From 9e8672f1c36d7237508c537c0a1db6c473c2be37 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Thu, 12 Sep 2013 10:21:25 +0100 Subject: [PATCH] tools: remove xend and associated python modules I've retained xen.lowlevel.{xc,xs} since they seem more widely useful. I also kept xen.lowlevel.xl even though it is disabled by default and IMHO useless in its current form. I've tried to clean up the various associated bits like example configs, init scripts, udev rules etc but no doubt I have missed something, those can easily be cleaned up later. I've also removed xm-test since although it could in theory be reworked to test xl it hasn't been touched for years. If someone wants to resurrect it then they could do so via the git history. This has been built but not runtime tested. Signed-off-by: Ian Campbell --- v2: Clean out some .*ignore cruft Remove some xm/xend docs. --- .gitignore | 14 - .hgignore | 12 - MAINTAINERS | 2 - config/Tools.mk.in | 1 - docs/man/xend-config.sxp.pod.5 | 158 - docs/man/xl.pod.1 | 1 - docs/man/xm.pod.1 | 1004 ---- docs/man/xmdomain.cfg.pod.5 | 358 -- tools/configure | 48 - tools/configure.ac | 13 - tools/examples/Makefile | 12 - tools/examples/xend-config.sxp | 304 -- tools/examples/xend-pci-permissive.sxp | 27 - tools/examples/xend-pci-quirks.sxp | 96 - tools/examples/xm-config.xml | 45 - tools/examples/xmexample.hvm | 373 -- tools/examples/xmexample.hvm-stubdom | 317 -- tools/examples/xmexample.nbd | 26 - tools/examples/xmexample.pv-grub | 172 - tools/examples/xmexample1 | 197 - tools/examples/xmexample2 | 232 - tools/examples/xmexample3 | 218 - tools/hotplug/Linux/Makefile | 5 - tools/hotplug/Linux/init.d/xend | 82 - tools/hotplug/Linux/xend.rules | 4 - tools/hotplug/NetBSD/Makefile | 3 +- tools/hotplug/NetBSD/rc.d/xend | 71 - tools/libxl/xl.c | 16 - tools/python/Makefile | 18 +- tools/python/logging/logging-0.4.9.2/PKG-INFO | 25 - .../python/logging/logging-0.4.9.2/README.txt | 311 -- .../logging/logging-0.4.9.2/default.css | 32 - .../logging/logging-0.4.9.2/liblogging.tex | 1281 ----- .../logging-0.4.9.2/logging/__init__.py | 1225 ----- .../logging/logging-0.4.9.2/logging/config.py | 301 -- .../logging-0.4.9.2/logging/handlers.py | 787 --- .../logging-0.4.9.2/python_logging.html | 1183 ----- tools/python/logging/logging-0.4.9.2/setup.py | 29 - .../logging/logging-0.4.9.2/test/app.py | 5 - .../logging/logging-0.4.9.2/test/critical.ini | 60 - .../logging/logging-0.4.9.2/test/debug.ini | 60 - .../logging/logging-0.4.9.2/test/error.ini | 60 - .../logging/logging-0.4.9.2/test/events.xml | 31 - .../logging/logging-0.4.9.2/test/log_test.py | 158 - .../logging/logging-0.4.9.2/test/log_test0.py | 118 - .../logging/logging-0.4.9.2/test/log_test1.py | 85 - .../logging-0.4.9.2/test/log_test10.py | 87 - .../logging-0.4.9.2/test/log_test11.py | 72 - .../logging-0.4.9.2/test/log_test12.py | 47 - .../logging-0.4.9.2/test/log_test13.py | 106 - .../logging-0.4.9.2/test/log_test14.py | 108 - .../logging-0.4.9.2/test/log_test15.py | 70 - .../logging-0.4.9.2/test/log_test16.py | 73 - .../logging-0.4.9.2/test/log_test17.py | 111 - .../logging-0.4.9.2/test/log_test18.py | 102 - .../logging-0.4.9.2/test/log_test19.py | 57 - .../logging/logging-0.4.9.2/test/log_test2.py | 119 - .../logging-0.4.9.2/test/log_test20.py | 84 - .../logging-0.4.9.2/test/log_test21.py | 141 - .../logging-0.4.9.2/test/log_test22.py | 50 - .../logging-0.4.9.2/test/log_test3.ini | 95 - .../logging/logging-0.4.9.2/test/log_test3.py | 70 - .../logging/logging-0.4.9.2/test/log_test4.py | 168 - .../logging/logging-0.4.9.2/test/log_test5.py | 44 - .../logging/logging-0.4.9.2/test/log_test6.py | 47 - .../logging/logging-0.4.9.2/test/log_test7.py | 48 - .../logging/logging-0.4.9.2/test/log_test8.py | 69 - .../logging/logging-0.4.9.2/test/log_test9.py | 71 - .../logging/logging-0.4.9.2/test/logconf.ini | 180 - .../logging/logging-0.4.9.2/test/logconf.py | 1738 ------- .../logging/logging-0.4.9.2/test/logging.dtd | 19 - .../logging/logging-0.4.9.2/test/logging.xml | 5 - .../logging/logging-0.4.9.2/test/logrecv.ini | 36 - .../logging/logging-0.4.9.2/test/logrecv.py | 443 -- .../logging/logging-0.4.9.2/test/myapp.py | 13 - .../logging/logging-0.4.9.2/test/mymodule.py | 8 - .../logging/logging-0.4.9.2/test/stderr.exp | 566 --- .../logging/logging-0.4.9.2/test/stdout.exp | 24 - .../logging/logging-0.4.9.2/test/warn.ini | 60 - tools/python/logging/setup.py | 11 - tools/python/ptsname/ptsname.c | 44 - tools/python/setup.py | 95 +- .../xen/lowlevel/checkpoint/checkpoint.c | 371 -- .../xen/lowlevel/checkpoint/checkpoint.h | 61 - .../xen/lowlevel/checkpoint/libcheckpoint.c | 850 ---- tools/python/xen/lowlevel/flask/flask.c | 292 -- .../python/xen/lowlevel/netlink/libnetlink.c | 585 --- .../python/xen/lowlevel/netlink/libnetlink.h | 58 - tools/python/xen/lowlevel/netlink/netlink.c | 215 - tools/python/xen/lowlevel/process/process.c | 164 - tools/python/xen/lowlevel/scf/scf.c | 156 - tools/python/xen/remus/__init__.py | 0 tools/python/xen/remus/blkdev.py | 31 - tools/python/xen/remus/device.py | 397 -- tools/python/xen/remus/image.py | 227 - tools/python/xen/remus/netlink.py | 318 -- tools/python/xen/remus/profile.py | 56 - tools/python/xen/remus/qdisc.py | 189 - tools/python/xen/remus/save.py | 186 - tools/python/xen/remus/tapdisk.py | 4 - tools/python/xen/remus/util.py | 82 - tools/python/xen/remus/vbd.py | 9 - tools/python/xen/remus/vdi.py | 121 - tools/python/xen/remus/vif.py | 18 - tools/python/xen/remus/vm.py | 168 - tools/python/xen/util/Brctl.py | 186 - tools/python/xen/util/SSHTransport.py | 102 - tools/python/xen/util/__init__.py | 1 - tools/python/xen/util/acmpolicy.py | 1622 ------ tools/python/xen/util/asserts.py | 27 - tools/python/xen/util/auxbin.py | 47 - tools/python/xen/util/blkif.py | 107 - tools/python/xen/util/bootloader.py | 626 --- tools/python/xen/util/bugtool.py | 234 - tools/python/xen/util/diagnose.py | 185 - tools/python/xen/util/dictio.py | 50 - tools/python/xen/util/fileuri.py | 156 - tools/python/xen/util/ip.py | 121 - tools/python/xen/util/mac.py | 11 - tools/python/xen/util/mkdir.py | 44 - tools/python/xen/util/oshelp.py | 33 - tools/python/xen/util/pci.py | 1416 ------ tools/python/xen/util/rwlock.py | 137 - tools/python/xen/util/sxputils.py | 64 - tools/python/xen/util/utils.py | 78 - tools/python/xen/util/vscsi_util.py | 307 -- tools/python/xen/util/vusb_util.py | 338 -- tools/python/xen/util/xmlrpcclient.py | 129 - tools/python/xen/util/xmlrpclib2.py | 220 - tools/python/xen/util/xpopen.py | 182 - tools/python/xen/util/xsconstants.py | 115 - tools/python/xen/util/xsm/__init__.py | 2 - tools/python/xen/util/xsm/acm/__init__.py | 1 - tools/python/xen/util/xsm/acm/acm.py | 1627 ------ tools/python/xen/util/xsm/dummy/__init__.py | 1 - tools/python/xen/util/xsm/dummy/dummy.py | 136 - tools/python/xen/util/xsm/flask/__init__.py | 1 - tools/python/xen/util/xsm/flask/flask.py | 65 - tools/python/xen/util/xsm/xsm.py | 20 - tools/python/xen/util/xsm/xsm_core.py | 7 - tools/python/xen/util/xspolicy.py | 66 - tools/python/xen/web/SrvBase.py | 98 - tools/python/xen/web/SrvDir.py | 126 - tools/python/xen/web/__init__.py | 17 - tools/python/xen/web/connection.py | 333 -- tools/python/xen/web/http.py | 518 -- tools/python/xen/web/httpserver.py | 367 -- tools/python/xen/web/protocol.py | 40 - tools/python/xen/web/resource.py | 108 - tools/python/xen/web/static.py | 61 - tools/python/xen/web/tcp.py | 212 - tools/python/xen/web/unix.py | 69 - tools/python/xen/xend/Args.py | 166 - tools/python/xen/xend/MemoryPool.py | 118 - tools/python/xen/xend/PrettyPrint.py | 323 -- tools/python/xen/xend/Vifctl.py | 35 - tools/python/xen/xend/XendAPI.py | 2812 ----------- tools/python/xen/xend/XendAPIConstants.py | 82 - tools/python/xen/xend/XendAPIStore.py | 83 - tools/python/xen/xend/XendAPIVersion.py | 22 - tools/python/xen/xend/XendAuthSessions.py | 131 - tools/python/xen/xend/XendBase.py | 126 - tools/python/xen/xend/XendBootloader.py | 230 - tools/python/xen/xend/XendCPUPool.py | 910 ---- tools/python/xen/xend/XendCheckpoint.py | 425 -- tools/python/xen/xend/XendClient.py | 40 - tools/python/xen/xend/XendConfig.py | 2265 --------- tools/python/xen/xend/XendConstants.py | 164 - tools/python/xen/xend/XendDPCI.py | 165 - tools/python/xen/xend/XendDSCSI.py | 299 -- tools/python/xen/xend/XendDevices.py | 85 - tools/python/xen/xend/XendDmesg.py | 41 - tools/python/xen/xend/XendDomain.py | 1958 -------- tools/python/xen/xend/XendDomainInfo.py | 4429 ----------------- tools/python/xen/xend/XendError.py | 252 - tools/python/xen/xend/XendLocalStorageRepo.py | 93 - tools/python/xen/xend/XendLogging.py | 149 - tools/python/xen/xend/XendMonitor.py | 340 -- tools/python/xen/xend/XendNetwork.py | 238 - tools/python/xen/xend/XendNode.py | 1173 ----- tools/python/xen/xend/XendOptions.py | 567 --- tools/python/xen/xend/XendPBD.py | 99 - tools/python/xen/xend/XendPIF.py | 390 -- tools/python/xen/xend/XendPIFMetrics.py | 59 - tools/python/xen/xend/XendPPCI.py | 160 - tools/python/xen/xend/XendPSCSI.py | 211 - tools/python/xen/xend/XendProtocol.py | 225 - tools/python/xen/xend/XendQCoWStorageRepo.py | 340 -- tools/python/xen/xend/XendSXPDev.py | 13 - tools/python/xen/xend/XendStateStore.py | 234 - .../python/xen/xend/XendStorageRepository.py | 118 - tools/python/xen/xend/XendTask.py | 224 - tools/python/xen/xend/XendTaskManager.py | 110 - tools/python/xen/xend/XendVDI.py | 214 - tools/python/xen/xend/XendVMMetrics.py | 146 - tools/python/xen/xend/XendVnet.py | 181 - tools/python/xen/xend/XendXSPolicy.py | 305 -- tools/python/xen/xend/XendXSPolicyAdmin.py | 386 -- tools/python/xen/xend/__init__.py | 1 - tools/python/xen/xend/arch.py | 31 - tools/python/xen/xend/balloon.py | 244 - tools/python/xen/xend/encode.py | 180 - tools/python/xen/xend/image.py | 1047 ---- tools/python/xen/xend/osdep.py | 268 - .../xen/xend/server/BlktapController.py | 313 -- .../xen/xend/server/ConsoleController.py | 38 - tools/python/xen/xend/server/DevConstants.py | 49 - tools/python/xen/xend/server/DevController.py | 677 --- .../python/xen/xend/server/SSLXMLRPCServer.py | 103 - tools/python/xen/xend/server/SrvDaemon.py | 420 -- tools/python/xen/xend/server/SrvDmesg.py | 52 - tools/python/xen/xend/server/SrvDomain.py | 329 -- tools/python/xen/xend/server/SrvDomainDir.py | 222 - tools/python/xen/xend/server/SrvNode.py | 64 - tools/python/xen/xend/server/SrvRoot.py | 43 - tools/python/xen/xend/server/SrvServer.py | 261 - tools/python/xen/xend/server/SrvVnetDir.py | 128 - tools/python/xen/xend/server/SrvXendLog.py | 37 - tools/python/xen/xend/server/XMLRPCServer.py | 273 - tools/python/xen/xend/server/__init__.py | 1 - tools/python/xen/xend/server/blkif.py | 221 - tools/python/xen/xend/server/iopif.py | 102 - tools/python/xen/xend/server/irqif.py | 95 - tools/python/xen/xend/server/netif.py | 218 - tools/python/xen/xend/server/netif2.py | 163 - tools/python/xen/xend/server/params.py | 46 - tools/python/xen/xend/server/pciif.py | 596 --- tools/python/xen/xend/server/pciquirk.py | 149 - tools/python/xen/xend/server/relocate.py | 173 - .../python/xen/xend/server/tests/__init__.py | 1 - .../xen/xend/server/tests/test_controllers.py | 81 - tools/python/xen/xend/server/udevevent.py | 92 - tools/python/xen/xend/server/vfbif.py | 91 - tools/python/xen/xend/server/vscsiif.py | 246 - tools/python/xen/xend/server/vusbif.py | 126 - tools/python/xen/xend/sxp.py | 765 --- tools/python/xen/xend/tests/__init__.py | 1 - .../python/xen/xend/tests/test_XendConfig.py | 42 - tools/python/xen/xend/tests/test_sxp.py | 39 - tools/python/xen/xend/tests/test_uuid.py | 30 - tools/python/xen/xend/tests/xend-config.sxp | 131 - tools/python/xen/xend/uuid.py | 69 - tools/python/xen/xend/xend | 110 - tools/python/xen/xend/xenstore/__init__.py | 16 - .../xen/xend/xenstore/tests/__init__.py | 2 - .../xen/xend/xenstore/tests/stress_xs.py | 121 - tools/python/xen/xend/xenstore/xstransact.py | 368 -- tools/python/xen/xend/xenstore/xsutil.py | 32 - tools/python/xen/xend/xenstore/xswatch.py | 80 - tools/python/xen/xm/XenAPI.py | 206 - tools/python/xen/xm/__init__.py | 0 tools/python/xen/xm/addlabel.py | 274 - tools/python/xen/xm/console.py | 88 - tools/python/xen/xm/cpupool-create.py | 51 - tools/python/xen/xm/cpupool-new.py | 50 - tools/python/xen/xm/cpupool.py | 236 - tools/python/xen/xm/create.dtd | 154 - tools/python/xen/xm/create.py | 1529 ------ tools/python/xen/xm/dry-run.py | 161 - tools/python/xen/xm/dumppolicy.py | 69 - tools/python/xen/xm/getenforce.py | 66 - tools/python/xen/xm/getlabel.py | 157 - tools/python/xen/xm/getpolicy.py | 135 - tools/python/xen/xm/help.py | 100 - tools/python/xen/xm/labels.py | 89 - tools/python/xen/xm/main.py | 4030 --------------- tools/python/xen/xm/migrate.py | 87 - tools/python/xen/xm/new.py | 79 - tools/python/xen/xm/opts.py | 627 --- tools/python/xen/xm/resetpolicy.py | 106 - tools/python/xen/xm/resources.py | 65 - tools/python/xen/xm/rmlabel.py | 216 - tools/python/xen/xm/setenforce.py | 74 - tools/python/xen/xm/setpolicy.py | 181 - tools/python/xen/xm/shutdown.py | 164 - tools/python/xen/xm/tests/__init__.py | 2 - tools/python/xen/xm/tests/test_create.py | 206 - tools/python/xen/xm/xenapi_create.py | 1129 ----- tools/python/xen/xm/xm | 20 - tools/xcutils/Makefile | 10 +- tools/xcutils/xc_restore.c | 73 - tools/xcutils/xc_save.c | 227 - tools/xm-test/COPYING | 340 -- tools/xm-test/ChangeLog | 11 - tools/xm-test/Makefile.am | 18 - tools/xm-test/README | 310 -- tools/xm-test/TODO | 3 - tools/xm-test/Writing_Tests_HOWTO | 136 - tools/xm-test/autogen | 9 - tools/xm-test/configure.ac | 155 - tools/xm-test/grouptest/cpupool | 1 - tools/xm-test/grouptest/create | 1 - tools/xm-test/grouptest/default | 30 - tools/xm-test/grouptest/medium | 24 - tools/xm-test/grouptest/quick | 4 - tools/xm-test/grouptest/xapi | 1 - tools/xm-test/lib/XmTestLib/Console.py | 302 -- tools/xm-test/lib/XmTestLib/DomainTracking.py | 61 - tools/xm-test/lib/XmTestLib/NetConfig.py | 268 - tools/xm-test/lib/XmTestLib/Test.py | 203 - tools/xm-test/lib/XmTestLib/XenAPIDomain.py | 183 - tools/xm-test/lib/XmTestLib/XenDevice.py | 275 - tools/xm-test/lib/XmTestLib/XenDomain.py | 385 -- tools/xm-test/lib/XmTestLib/XenMemory.py | 68 - tools/xm-test/lib/XmTestLib/Xm.py | 245 - tools/xm-test/lib/XmTestLib/__init__.py | 27 - tools/xm-test/lib/XmTestLib/arch.py | 118 - tools/xm-test/lib/XmTestLib/block_utils.py | 53 - tools/xm-test/lib/XmTestLib/config.py.in | 7 - tools/xm-test/lib/XmTestLib/network_utils.py | 60 - tools/xm-test/lib/XmTestLib/xapi.py | 54 - tools/xm-test/lib/XmTestReport/OSReport.py | 248 - tools/xm-test/lib/XmTestReport/ProgReport.py | 119 - tools/xm-test/lib/XmTestReport/Report.py | 156 - .../xm-test/lib/XmTestReport/ResultReport.py | 157 - tools/xm-test/lib/XmTestReport/arch.py | 42 - tools/xm-test/lib/XmTestReport/utils.py | 31 - tools/xm-test/lib/XmTestReport/xmtest.py.in | 15 - tools/xm-test/mergereport | 25 - tools/xm-test/mkreport | 71 - tools/xm-test/ramdisk/Makefile.am | 126 - .../ramdisk/README-XenSource-initrd-0.7-img | 42 - .../ramdisk/README-XenSource-initrd-0.8-img | 42 - .../ramdisk/README-XenSource-initrd-1.0-img | 46 - .../ramdisk/README-XenSource-initrd-1.1-img | 45 - tools/xm-test/ramdisk/bin/create_disk_image | 384 -- tools/xm-test/ramdisk/configs/buildroot-i386 | 346 -- tools/xm-test/ramdisk/configs/busybox | 465 -- tools/xm-test/ramdisk/configs/uClibc | 172 - tools/xm-test/ramdisk/make-release.sh | 44 - .../patches/buildroot/add_xvd_devices.patch | 13 - .../ramdisk/patches/buildroot/hping.patch | 67 - tools/xm-test/ramdisk/skel/.profile | 3 - tools/xm-test/ramdisk/skel/etc/init.d/rcS | 19 - tools/xm-test/ramdisk/skel/etc/inittab | 5 - tools/xm-test/ramdisk/skel/root/.profile | 3 - tools/xm-test/runtest.sh | 337 -- tools/xm-test/tests/Makefile.am | 43 - tools/xm-test/tests/Makefile.am.template | 21 - tools/xm-test/tests/_sanity/01_domu_proc.py | 32 - tools/xm-test/tests/_sanity/Makefile.am | 21 - .../01_block_attach_device_pos.py | 49 - .../02_block_attach_file_device_pos.py | 49 - .../04_block_attach_device_repeatedly_pos.py | 46 - ...ttach_and_dettach_device_repeatedly_pos.py | 49 - .../06_block_attach_baddomain_neg.py | 18 - .../07_block_attach_baddevice_neg.py | 53 - .../08_block_attach_bad_filedevice_neg.py | 52 - ...ttach_and_dettach_device_check_data_pos.py | 66 - ...0_block_attach_dettach_multiple_devices.py | 100 - .../11_block_attach_shared_dom0.py | 38 - .../12_block_attach_shared_domU.py | 30 - tools/xm-test/tests/block-create/Makefile.am | 29 - .../01_block-destroy_btblock_pos.py | 44 - .../02_block-destroy_rtblock_pos.py | 41 - .../03_block-destroy_nonexist_neg.py | 17 - .../04_block-destroy_nonattached_neg.py | 33 - .../05_block-destroy_byname_pos.py | 43 - .../06_block-destroy_check_list_pos.py | 42 - tools/xm-test/tests/block-destroy/Makefile.am | 26 - .../01_block_device_read_verify.py | 62 - .../02_block_device_write_verify.py | 63 - .../xm-test/tests/block-integrity/Makefile.am | 22 - .../tests/block-list/01_block-list_pos.py | 42 - .../block-list/02_block-list_attachbd_pos.py | 46 - .../block-list/03_block-list_anotherbd_pos.py | 54 - .../block-list/04_block-list_nodb_pos.py | 28 - .../block-list/05_block-list_nonexist_neg.py | 18 - .../06_block-list_checkremove_pos.py | 61 - tools/xm-test/tests/block-list/Makefile.am | 26 - .../tests/console/01_console_badopt_neg.py | 21 - .../tests/console/02_console_baddom_neg.py | 27 - tools/xm-test/tests/console/Makefile.am | 22 - .../tests/cpupool/01_cpupool_basic_pos.py | 72 - .../tests/cpupool/02_cpupool_manage_pos.py | 152 - .../tests/cpupool/03_cpupool_domain.py | 126 - .../tests/cpupool/04_cpupool_migrate.py | 84 - tools/xm-test/tests/cpupool/Makefile.am | 22 - tools/xm-test/tests/cpupool/pool1.cfg | 1 - tools/xm-test/tests/cpupool/pools.py | 78 - .../tests/create/01_create_basic_pos.py | 49 - .../tests/create/02_create_noparm_neg.py | 17 - .../tests/create/03_create_badparm_neg.py | 19 - .../create/04_create_conflictname_neg.py | 41 - .../xm-test/tests/create/06_create_mem_neg.py | 53 - .../tests/create/07_create_mem64_pos.py | 49 - .../tests/create/08_create_mem128_pos.py | 49 - .../tests/create/09_create_mem256_pos.py | 49 - .../tests/create/10_create_fastdestroy.py | 43 - .../tests/create/11_create_concurrent_pos.py | 78 - .../create/12_create_concurrent_stress_pos.py | 59 - .../tests/create/13_create_multinic_pos.py | 27 - .../tests/create/14_create_blockroot_pos.py | 44 - .../tests/create/15_create_smallmem_pos.py | 27 - .../tests/create/16_create_smallmem_neg.py | 30 - tools/xm-test/tests/create/Makefile.am | 33 - .../tests/destroy/01_destroy_basic_pos.py | 40 - .../tests/destroy/02_destroy_noparm_neg.py | 16 - .../tests/destroy/03_destroy_nonexist_neg.py | 16 - .../tests/destroy/04_destroy_badparm_neg.py | 16 - .../tests/destroy/05_destroy_byid_pos.py | 33 - .../tests/destroy/06_destroy_dom0_neg.py | 14 - .../tests/destroy/07_destroy_stale_pos.py | 133 - tools/xm-test/tests/destroy/Makefile.am | 27 - .../xm-test/tests/dmesg/01_dmesg_basic_pos.py | 15 - .../xm-test/tests/dmesg/02_dmesg_basic_neg.py | 17 - tools/xm-test/tests/dmesg/Makefile.am | 21 - .../xm-test/tests/domid/01_domid_basic_pos.py | 16 - .../xm-test/tests/domid/02_domid_basic_neg.py | 15 - tools/xm-test/tests/domid/Makefile.am | 21 - .../tests/domname/01_domname_basic_pos.py | 17 - .../tests/domname/02_domname_basic_neg.py | 15 - tools/xm-test/tests/domname/Makefile.am | 21 - .../01_enforce_dom0_cpus_basic_pos.py | 126 - .../tests/enforce_dom0_cpus/Makefile.am | 21 - tools/xm-test/tests/help/01_help_basic_pos.py | 14 - tools/xm-test/tests/help/02_help_basic_neg.py | 14 - .../xm-test/tests/help/03_help_badparm_neg.py | 14 - tools/xm-test/tests/help/04_help_long_pos.py | 16 - .../xm-test/tests/help/05_help_nonroot_pos.py | 17 - tools/xm-test/tests/help/06_help_allcmds.py | 44 - tools/xm-test/tests/help/Makefile.am | 26 - tools/xm-test/tests/info/01_info_basic_pos.py | 11 - .../tests/info/02_info_compiledata_pos.py | 42 - tools/xm-test/tests/info/Makefile.am | 22 - tools/xm-test/tests/list/01_list_basic_pos.py | 14 - .../xm-test/tests/list/02_list_badparm_neg.py | 16 - .../tests/list/03_list_nonexist_neg.py | 17 - .../tests/list/04_list_goodparm_pos.py | 28 - tools/xm-test/tests/list/05_list_long_pos.py | 22 - tools/xm-test/tests/list/06_list_nonroot.py | 15 - tools/xm-test/tests/list/Makefile.am | 27 - .../tests/memmax/01_memmax_badparm_neg.py | 29 - tools/xm-test/tests/memmax/Makefile.am | 21 - .../tests/memset/01_memset_basic_pos.py | 82 - .../tests/memset/02_memset_badparm_neg.py | 56 - .../tests/memset/03_memset_random_pos.py | 64 - .../tests/memset/04_memset_smallmem_pos.py | 55 - tools/xm-test/tests/memset/Makefile.am | 24 - .../tests/migrate/01_migrate_localhost_pos.py | 86 - tools/xm-test/tests/migrate/Makefile.am | 20 - .../network-attach/01_network_attach_pos.py | 43 - .../02_network_attach_detach_pos.py | 49 - .../03_network_attach_detach_multiple_pos.py | 51 - .../04_network_attach_baddomain_neg.py | 15 - .../xm-test/tests/network-attach/Makefile.am | 24 - .../network/02_network_local_ping_pos.py | 71 - .../tests/network/03_network_local_tcp_pos.py | 75 - .../tests/network/04_network_local_udp_pos.py | 76 - .../tests/network/05_network_dom0_ping_pos.py | 54 - .../tests/network/06_network_dom0_tcp_pos.py | 57 - .../tests/network/07_network_dom0_udp_pos.py | 56 - .../tests/network/11_network_domU_ping_pos.py | 62 - .../tests/network/12_network_domU_tcp_pos.py | 64 - .../tests/network/13_network_domU_udp_pos.py | 76 - tools/xm-test/tests/network/Makefile.am | 34 - .../xm-test/tests/pause/01_pause_basic_pos.py | 63 - .../tests/pause/02_pause_badopt_neg.py | 32 - .../tests/pause/03_pause_badname_neg.py | 18 - .../xm-test/tests/pause/04_pause_badid_neg.py | 18 - tools/xm-test/tests/pause/Makefile.am | 22 - .../tests/reboot/01_reboot_basic_pos.py | 52 - .../tests/reboot/02_reboot_badopt_neg.py | 32 - .../tests/reboot/03_reboot_badname_neg.py | 18 - tools/xm-test/tests/reboot/Makefile.am | 23 - .../tests/restore/01_restore_basic_pos.py | 82 - .../tests/restore/02_restore_badparm_neg.py | 28 - .../restore/03_restore_badfilename_neg.py | 28 - .../restore/04_restore_withdevices_pos.py | 130 - tools/xm-test/tests/restore/Makefile.am | 24 - tools/xm-test/tests/save/01_save_basic_pos.py | 37 - .../xm-test/tests/save/02_save_badparm_neg.py | 28 - .../tests/save/03_save_bogusfile_neg.py | 39 - tools/xm-test/tests/save/Makefile.am | 24 - .../01_sched_credit_weight_cap_pos.py | 72 - tools/xm-test/tests/sched-credit/Makefile.am | 20 - .../tests/sedf/01_sedf_period_slice_pos.py | 62 - .../tests/sedf/02_sedf_period_lower_neg.py | 44 - .../tests/sedf/03_sedf_slice_lower_neg.py | 40 - .../tests/sedf/04_sedf_slice_upper_neg.py | 48 - .../tests/sedf/05_sedf_extratime_pos.py | 63 - .../sedf/06_sedf_extratime_disable_neg.py | 71 - tools/xm-test/tests/sedf/Makefile.am | 25 - .../tests/shutdown/01_shutdown_basic_pos.py | 54 - .../tests/shutdown/02_shutdown_badparm_neg.py | 39 - .../shutdown/03_shutdown_nonexist_neg.py | 22 - tools/xm-test/tests/shutdown/Makefile.am | 21 - .../xm-test/tests/sysrq/01_sysrq_basic_neg.py | 20 - .../xm-test/tests/sysrq/02_sysrq_sync_pos.py | 52 - .../tests/sysrq/03_sysrq_withreboot_pos.py | 40 - tools/xm-test/tests/sysrq/Makefile.am | 23 - .../tests/unpause/01_unpause_basic_pos.py | 76 - tools/xm-test/tests/unpause/Makefile.am | 20 - .../vcpu-disable/01_vcpu-disable_basic_pos.py | 82 - tools/xm-test/tests/vcpu-disable/Makefile.am | 21 - .../tests/vcpu-pin/01_vcpu-pin_basic_pos.py | 50 - tools/xm-test/tests/vcpu-pin/Makefile.am | 21 - tools/xm-test/tests/xapi/01_xapi-vm_basic.py | 61 - tools/xm-test/tests/xapi/02_xapi-vbd_basic.py | 122 - .../xm-test/tests/xapi/03_xapi-network_pos.py | 123 - .../tests/xapi/04_xapi-data_uri_handling.py | 65 - .../tests/xapi/20_xapi-cpu_pool_basic.py | 157 - tools/xm-test/tests/xapi/Makefile.am | 23 - 503 files changed, 7 insertions(+), 83858 deletions(-) delete mode 100644 docs/man/xend-config.sxp.pod.5 delete mode 100644 docs/man/xm.pod.1 delete mode 100644 docs/man/xmdomain.cfg.pod.5 delete mode 100644 tools/examples/xend-config.sxp delete mode 100644 tools/examples/xend-pci-permissive.sxp delete mode 100644 tools/examples/xend-pci-quirks.sxp delete mode 100644 tools/examples/xm-config.xml delete mode 100644 tools/examples/xmexample.hvm delete mode 100644 tools/examples/xmexample.hvm-stubdom delete mode 100644 tools/examples/xmexample.nbd delete mode 100644 tools/examples/xmexample.pv-grub delete mode 100644 tools/examples/xmexample1 delete mode 100644 tools/examples/xmexample2 delete mode 100644 tools/examples/xmexample3 delete mode 100755 tools/hotplug/Linux/init.d/xend delete mode 100644 tools/hotplug/Linux/xend.rules delete mode 100644 tools/hotplug/NetBSD/rc.d/xend delete mode 100644 tools/python/logging/logging-0.4.9.2/PKG-INFO delete mode 100644 tools/python/logging/logging-0.4.9.2/README.txt delete mode 100644 tools/python/logging/logging-0.4.9.2/default.css delete mode 100644 tools/python/logging/logging-0.4.9.2/liblogging.tex delete mode 100644 tools/python/logging/logging-0.4.9.2/logging/__init__.py delete mode 100644 tools/python/logging/logging-0.4.9.2/logging/config.py delete mode 100644 tools/python/logging/logging-0.4.9.2/logging/handlers.py delete mode 100644 tools/python/logging/logging-0.4.9.2/python_logging.html delete mode 100644 tools/python/logging/logging-0.4.9.2/setup.py delete mode 100644 tools/python/logging/logging-0.4.9.2/test/app.py delete mode 100644 tools/python/logging/logging-0.4.9.2/test/critical.ini delete mode 100644 tools/python/logging/logging-0.4.9.2/test/debug.ini delete mode 100644 tools/python/logging/logging-0.4.9.2/test/error.ini delete mode 100644 tools/python/logging/logging-0.4.9.2/test/events.xml delete mode 100755 tools/python/logging/logging-0.4.9.2/test/log_test.py delete mode 100755 tools/python/logging/logging-0.4.9.2/test/log_test0.py delete mode 100755 tools/python/logging/logging-0.4.9.2/test/log_test1.py delete mode 100755 tools/python/logging/logging-0.4.9.2/test/log_test10.py delete mode 100755 tools/python/logging/logging-0.4.9.2/test/log_test11.py delete mode 100755 tools/python/logging/logging-0.4.9.2/test/log_test12.py delete mode 100755 tools/python/logging/logging-0.4.9.2/test/log_test13.py delete mode 100755 tools/python/logging/logging-0.4.9.2/test/log_test14.py delete mode 100755 tools/python/logging/logging-0.4.9.2/test/log_test15.py delete mode 100755 tools/python/logging/logging-0.4.9.2/test/log_test16.py delete mode 100755 tools/python/logging/logging-0.4.9.2/test/log_test17.py delete mode 100755 tools/python/logging/logging-0.4.9.2/test/log_test18.py delete mode 100755 tools/python/logging/logging-0.4.9.2/test/log_test19.py delete mode 100755 tools/python/logging/logging-0.4.9.2/test/log_test2.py delete mode 100755 tools/python/logging/logging-0.4.9.2/test/log_test20.py delete mode 100755 tools/python/logging/logging-0.4.9.2/test/log_test21.py delete mode 100755 tools/python/logging/logging-0.4.9.2/test/log_test22.py delete mode 100644 tools/python/logging/logging-0.4.9.2/test/log_test3.ini delete mode 100755 tools/python/logging/logging-0.4.9.2/test/log_test3.py delete mode 100755 tools/python/logging/logging-0.4.9.2/test/log_test4.py delete mode 100755 tools/python/logging/logging-0.4.9.2/test/log_test5.py delete mode 100755 tools/python/logging/logging-0.4.9.2/test/log_test6.py delete mode 100755 tools/python/logging/logging-0.4.9.2/test/log_test7.py delete mode 100755 tools/python/logging/logging-0.4.9.2/test/log_test8.py delete mode 100755 tools/python/logging/logging-0.4.9.2/test/log_test9.py delete mode 100644 tools/python/logging/logging-0.4.9.2/test/logconf.ini delete mode 100755 tools/python/logging/logging-0.4.9.2/test/logconf.py delete mode 100644 tools/python/logging/logging-0.4.9.2/test/logging.dtd delete mode 100644 tools/python/logging/logging-0.4.9.2/test/logging.xml delete mode 100644 tools/python/logging/logging-0.4.9.2/test/logrecv.ini delete mode 100755 tools/python/logging/logging-0.4.9.2/test/logrecv.py delete mode 100644 tools/python/logging/logging-0.4.9.2/test/myapp.py delete mode 100644 tools/python/logging/logging-0.4.9.2/test/mymodule.py delete mode 100644 tools/python/logging/logging-0.4.9.2/test/stderr.exp delete mode 100644 tools/python/logging/logging-0.4.9.2/test/stdout.exp delete mode 100644 tools/python/logging/logging-0.4.9.2/test/warn.ini delete mode 100644 tools/python/logging/setup.py delete mode 100644 tools/python/ptsname/ptsname.c delete mode 100644 tools/python/xen/lowlevel/checkpoint/checkpoint.c delete mode 100644 tools/python/xen/lowlevel/checkpoint/checkpoint.h delete mode 100644 tools/python/xen/lowlevel/checkpoint/libcheckpoint.c delete mode 100644 tools/python/xen/lowlevel/flask/flask.c delete mode 100644 tools/python/xen/lowlevel/netlink/libnetlink.c delete mode 100644 tools/python/xen/lowlevel/netlink/libnetlink.h delete mode 100644 tools/python/xen/lowlevel/netlink/netlink.c delete mode 100644 tools/python/xen/lowlevel/process/process.c delete mode 100644 tools/python/xen/lowlevel/scf/scf.c delete mode 100644 tools/python/xen/remus/__init__.py delete mode 100644 tools/python/xen/remus/blkdev.py delete mode 100644 tools/python/xen/remus/device.py delete mode 100644 tools/python/xen/remus/image.py delete mode 100644 tools/python/xen/remus/netlink.py delete mode 100644 tools/python/xen/remus/profile.py delete mode 100644 tools/python/xen/remus/qdisc.py delete mode 100644 tools/python/xen/remus/save.py delete mode 100644 tools/python/xen/remus/tapdisk.py delete mode 100644 tools/python/xen/remus/util.py delete mode 100644 tools/python/xen/remus/vbd.py delete mode 100644 tools/python/xen/remus/vdi.py delete mode 100644 tools/python/xen/remus/vif.py delete mode 100644 tools/python/xen/remus/vm.py delete mode 100644 tools/python/xen/util/Brctl.py delete mode 100644 tools/python/xen/util/SSHTransport.py delete mode 100644 tools/python/xen/util/__init__.py delete mode 100644 tools/python/xen/util/acmpolicy.py delete mode 100644 tools/python/xen/util/asserts.py delete mode 100644 tools/python/xen/util/auxbin.py delete mode 100644 tools/python/xen/util/blkif.py delete mode 100644 tools/python/xen/util/bootloader.py delete mode 100644 tools/python/xen/util/bugtool.py delete mode 100644 tools/python/xen/util/diagnose.py delete mode 100644 tools/python/xen/util/dictio.py delete mode 100644 tools/python/xen/util/fileuri.py delete mode 100644 tools/python/xen/util/ip.py delete mode 100644 tools/python/xen/util/mac.py delete mode 100644 tools/python/xen/util/mkdir.py delete mode 100644 tools/python/xen/util/oshelp.py delete mode 100644 tools/python/xen/util/pci.py delete mode 100644 tools/python/xen/util/rwlock.py delete mode 100644 tools/python/xen/util/sxputils.py delete mode 100644 tools/python/xen/util/utils.py delete mode 100644 tools/python/xen/util/vscsi_util.py delete mode 100644 tools/python/xen/util/vusb_util.py delete mode 100644 tools/python/xen/util/xmlrpcclient.py delete mode 100644 tools/python/xen/util/xmlrpclib2.py delete mode 100644 tools/python/xen/util/xpopen.py delete mode 100644 tools/python/xen/util/xsconstants.py delete mode 100644 tools/python/xen/util/xsm/__init__.py delete mode 100644 tools/python/xen/util/xsm/acm/__init__.py delete mode 100644 tools/python/xen/util/xsm/acm/acm.py delete mode 100644 tools/python/xen/util/xsm/dummy/__init__.py delete mode 100644 tools/python/xen/util/xsm/dummy/dummy.py delete mode 100644 tools/python/xen/util/xsm/flask/__init__.py delete mode 100644 tools/python/xen/util/xsm/flask/flask.py delete mode 100644 tools/python/xen/util/xsm/xsm.py delete mode 100644 tools/python/xen/util/xsm/xsm_core.py delete mode 100644 tools/python/xen/util/xspolicy.py delete mode 100644 tools/python/xen/web/SrvBase.py delete mode 100644 tools/python/xen/web/SrvDir.py delete mode 100644 tools/python/xen/web/__init__.py delete mode 100644 tools/python/xen/web/connection.py delete mode 100644 tools/python/xen/web/http.py delete mode 100644 tools/python/xen/web/httpserver.py delete mode 100644 tools/python/xen/web/protocol.py delete mode 100644 tools/python/xen/web/resource.py delete mode 100644 tools/python/xen/web/static.py delete mode 100644 tools/python/xen/web/tcp.py delete mode 100644 tools/python/xen/web/unix.py delete mode 100644 tools/python/xen/xend/Args.py delete mode 100644 tools/python/xen/xend/MemoryPool.py delete mode 100644 tools/python/xen/xend/PrettyPrint.py delete mode 100644 tools/python/xen/xend/Vifctl.py delete mode 100644 tools/python/xen/xend/XendAPI.py delete mode 100644 tools/python/xen/xend/XendAPIConstants.py delete mode 100644 tools/python/xen/xend/XendAPIStore.py delete mode 100644 tools/python/xen/xend/XendAPIVersion.py delete mode 100644 tools/python/xen/xend/XendAuthSessions.py delete mode 100644 tools/python/xen/xend/XendBase.py delete mode 100644 tools/python/xen/xend/XendBootloader.py delete mode 100644 tools/python/xen/xend/XendCPUPool.py delete mode 100644 tools/python/xen/xend/XendCheckpoint.py delete mode 100644 tools/python/xen/xend/XendClient.py delete mode 100644 tools/python/xen/xend/XendConfig.py delete mode 100644 tools/python/xen/xend/XendConstants.py delete mode 100644 tools/python/xen/xend/XendDPCI.py delete mode 100644 tools/python/xen/xend/XendDSCSI.py delete mode 100644 tools/python/xen/xend/XendDevices.py delete mode 100644 tools/python/xen/xend/XendDmesg.py delete mode 100644 tools/python/xen/xend/XendDomain.py delete mode 100644 tools/python/xen/xend/XendDomainInfo.py delete mode 100644 tools/python/xen/xend/XendError.py delete mode 100644 tools/python/xen/xend/XendLocalStorageRepo.py delete mode 100644 tools/python/xen/xend/XendLogging.py delete mode 100644 tools/python/xen/xend/XendMonitor.py delete mode 100644 tools/python/xen/xend/XendNetwork.py delete mode 100644 tools/python/xen/xend/XendNode.py delete mode 100644 tools/python/xen/xend/XendOptions.py delete mode 100644 tools/python/xen/xend/XendPBD.py delete mode 100644 tools/python/xen/xend/XendPIF.py delete mode 100644 tools/python/xen/xend/XendPIFMetrics.py delete mode 100644 tools/python/xen/xend/XendPPCI.py delete mode 100644 tools/python/xen/xend/XendPSCSI.py delete mode 100644 tools/python/xen/xend/XendProtocol.py delete mode 100644 tools/python/xen/xend/XendQCoWStorageRepo.py delete mode 100644 tools/python/xen/xend/XendSXPDev.py delete mode 100644 tools/python/xen/xend/XendStateStore.py delete mode 100644 tools/python/xen/xend/XendStorageRepository.py delete mode 100644 tools/python/xen/xend/XendTask.py delete mode 100644 tools/python/xen/xend/XendTaskManager.py delete mode 100644 tools/python/xen/xend/XendVDI.py delete mode 100644 tools/python/xen/xend/XendVMMetrics.py delete mode 100644 tools/python/xen/xend/XendVnet.py delete mode 100644 tools/python/xen/xend/XendXSPolicy.py delete mode 100644 tools/python/xen/xend/XendXSPolicyAdmin.py delete mode 100644 tools/python/xen/xend/__init__.py delete mode 100644 tools/python/xen/xend/arch.py delete mode 100644 tools/python/xen/xend/balloon.py delete mode 100644 tools/python/xen/xend/encode.py delete mode 100644 tools/python/xen/xend/image.py delete mode 100644 tools/python/xen/xend/osdep.py delete mode 100644 tools/python/xen/xend/server/BlktapController.py delete mode 100644 tools/python/xen/xend/server/ConsoleController.py delete mode 100644 tools/python/xen/xend/server/DevConstants.py delete mode 100644 tools/python/xen/xend/server/DevController.py delete mode 100644 tools/python/xen/xend/server/SSLXMLRPCServer.py delete mode 100644 tools/python/xen/xend/server/SrvDaemon.py delete mode 100644 tools/python/xen/xend/server/SrvDmesg.py delete mode 100644 tools/python/xen/xend/server/SrvDomain.py delete mode 100644 tools/python/xen/xend/server/SrvDomainDir.py delete mode 100644 tools/python/xen/xend/server/SrvNode.py delete mode 100644 tools/python/xen/xend/server/SrvRoot.py delete mode 100644 tools/python/xen/xend/server/SrvServer.py delete mode 100644 tools/python/xen/xend/server/SrvVnetDir.py delete mode 100644 tools/python/xen/xend/server/SrvXendLog.py delete mode 100644 tools/python/xen/xend/server/XMLRPCServer.py delete mode 100644 tools/python/xen/xend/server/__init__.py delete mode 100644 tools/python/xen/xend/server/blkif.py delete mode 100644 tools/python/xen/xend/server/iopif.py delete mode 100644 tools/python/xen/xend/server/irqif.py delete mode 100644 tools/python/xen/xend/server/netif.py delete mode 100644 tools/python/xen/xend/server/netif2.py delete mode 100644 tools/python/xen/xend/server/params.py delete mode 100644 tools/python/xen/xend/server/pciif.py delete mode 100644 tools/python/xen/xend/server/pciquirk.py delete mode 100644 tools/python/xen/xend/server/relocate.py delete mode 100644 tools/python/xen/xend/server/tests/__init__.py delete mode 100644 tools/python/xen/xend/server/tests/test_controllers.py delete mode 100644 tools/python/xen/xend/server/udevevent.py delete mode 100644 tools/python/xen/xend/server/vfbif.py delete mode 100644 tools/python/xen/xend/server/vscsiif.py delete mode 100644 tools/python/xen/xend/server/vusbif.py delete mode 100644 tools/python/xen/xend/sxp.py delete mode 100644 tools/python/xen/xend/tests/__init__.py delete mode 100644 tools/python/xen/xend/tests/test_XendConfig.py delete mode 100644 tools/python/xen/xend/tests/test_sxp.py delete mode 100644 tools/python/xen/xend/tests/test_uuid.py delete mode 100644 tools/python/xen/xend/tests/xend-config.sxp delete mode 100644 tools/python/xen/xend/uuid.py delete mode 100644 tools/python/xen/xend/xend delete mode 100644 tools/python/xen/xend/xenstore/__init__.py delete mode 100644 tools/python/xen/xend/xenstore/tests/__init__.py delete mode 100644 tools/python/xen/xend/xenstore/tests/stress_xs.py delete mode 100644 tools/python/xen/xend/xenstore/xstransact.py delete mode 100644 tools/python/xen/xend/xenstore/xsutil.py delete mode 100644 tools/python/xen/xend/xenstore/xswatch.py delete mode 100644 tools/python/xen/xm/XenAPI.py delete mode 100644 tools/python/xen/xm/__init__.py delete mode 100644 tools/python/xen/xm/addlabel.py delete mode 100644 tools/python/xen/xm/console.py delete mode 100644 tools/python/xen/xm/cpupool-create.py delete mode 100644 tools/python/xen/xm/cpupool-new.py delete mode 100644 tools/python/xen/xm/cpupool.py delete mode 100644 tools/python/xen/xm/create.dtd delete mode 100644 tools/python/xen/xm/create.py delete mode 100644 tools/python/xen/xm/dry-run.py delete mode 100644 tools/python/xen/xm/dumppolicy.py delete mode 100644 tools/python/xen/xm/getenforce.py delete mode 100644 tools/python/xen/xm/getlabel.py delete mode 100644 tools/python/xen/xm/getpolicy.py delete mode 100644 tools/python/xen/xm/help.py delete mode 100644 tools/python/xen/xm/labels.py delete mode 100644 tools/python/xen/xm/main.py delete mode 100644 tools/python/xen/xm/migrate.py delete mode 100644 tools/python/xen/xm/new.py delete mode 100644 tools/python/xen/xm/opts.py delete mode 100644 tools/python/xen/xm/resetpolicy.py delete mode 100644 tools/python/xen/xm/resources.py delete mode 100644 tools/python/xen/xm/rmlabel.py delete mode 100644 tools/python/xen/xm/setenforce.py delete mode 100644 tools/python/xen/xm/setpolicy.py delete mode 100644 tools/python/xen/xm/shutdown.py delete mode 100644 tools/python/xen/xm/tests/__init__.py delete mode 100644 tools/python/xen/xm/tests/test_create.py delete mode 100644 tools/python/xen/xm/xenapi_create.py delete mode 100755 tools/python/xen/xm/xm delete mode 100644 tools/xcutils/xc_restore.c delete mode 100644 tools/xcutils/xc_save.c delete mode 100644 tools/xm-test/COPYING delete mode 100644 tools/xm-test/ChangeLog delete mode 100644 tools/xm-test/Makefile.am delete mode 100644 tools/xm-test/README delete mode 100644 tools/xm-test/TODO delete mode 100644 tools/xm-test/Writing_Tests_HOWTO delete mode 100755 tools/xm-test/autogen delete mode 100644 tools/xm-test/configure.ac delete mode 100644 tools/xm-test/grouptest/cpupool delete mode 100644 tools/xm-test/grouptest/create delete mode 100644 tools/xm-test/grouptest/default delete mode 100644 tools/xm-test/grouptest/medium delete mode 100644 tools/xm-test/grouptest/quick delete mode 100644 tools/xm-test/grouptest/xapi delete mode 100755 tools/xm-test/lib/XmTestLib/Console.py delete mode 100644 tools/xm-test/lib/XmTestLib/DomainTracking.py delete mode 100644 tools/xm-test/lib/XmTestLib/NetConfig.py delete mode 100644 tools/xm-test/lib/XmTestLib/Test.py delete mode 100644 tools/xm-test/lib/XmTestLib/XenAPIDomain.py delete mode 100644 tools/xm-test/lib/XmTestLib/XenDevice.py delete mode 100644 tools/xm-test/lib/XmTestLib/XenDomain.py delete mode 100644 tools/xm-test/lib/XmTestLib/XenMemory.py delete mode 100644 tools/xm-test/lib/XmTestLib/Xm.py delete mode 100644 tools/xm-test/lib/XmTestLib/__init__.py delete mode 100644 tools/xm-test/lib/XmTestLib/arch.py delete mode 100644 tools/xm-test/lib/XmTestLib/block_utils.py delete mode 100644 tools/xm-test/lib/XmTestLib/config.py.in delete mode 100644 tools/xm-test/lib/XmTestLib/network_utils.py delete mode 100644 tools/xm-test/lib/XmTestLib/xapi.py delete mode 100644 tools/xm-test/lib/XmTestReport/OSReport.py delete mode 100644 tools/xm-test/lib/XmTestReport/ProgReport.py delete mode 100644 tools/xm-test/lib/XmTestReport/Report.py delete mode 100644 tools/xm-test/lib/XmTestReport/ResultReport.py delete mode 100644 tools/xm-test/lib/XmTestReport/arch.py delete mode 100644 tools/xm-test/lib/XmTestReport/utils.py delete mode 100644 tools/xm-test/lib/XmTestReport/xmtest.py.in delete mode 100644 tools/xm-test/mergereport delete mode 100644 tools/xm-test/mkreport delete mode 100644 tools/xm-test/ramdisk/Makefile.am delete mode 100644 tools/xm-test/ramdisk/README-XenSource-initrd-0.7-img delete mode 100644 tools/xm-test/ramdisk/README-XenSource-initrd-0.8-img delete mode 100644 tools/xm-test/ramdisk/README-XenSource-initrd-1.0-img delete mode 100644 tools/xm-test/ramdisk/README-XenSource-initrd-1.1-img delete mode 100644 tools/xm-test/ramdisk/bin/create_disk_image delete mode 100644 tools/xm-test/ramdisk/configs/buildroot-i386 delete mode 100644 tools/xm-test/ramdisk/configs/busybox delete mode 100644 tools/xm-test/ramdisk/configs/uClibc delete mode 100644 tools/xm-test/ramdisk/make-release.sh delete mode 100644 tools/xm-test/ramdisk/patches/buildroot/add_xvd_devices.patch delete mode 100644 tools/xm-test/ramdisk/patches/buildroot/hping.patch delete mode 100644 tools/xm-test/ramdisk/skel/.profile delete mode 100644 tools/xm-test/ramdisk/skel/etc/init.d/rcS delete mode 100644 tools/xm-test/ramdisk/skel/etc/inittab delete mode 100644 tools/xm-test/ramdisk/skel/root/.profile delete mode 100755 tools/xm-test/runtest.sh delete mode 100644 tools/xm-test/tests/Makefile.am delete mode 100644 tools/xm-test/tests/Makefile.am.template delete mode 100644 tools/xm-test/tests/_sanity/01_domu_proc.py delete mode 100644 tools/xm-test/tests/_sanity/Makefile.am delete mode 100644 tools/xm-test/tests/block-create/01_block_attach_device_pos.py delete mode 100644 tools/xm-test/tests/block-create/02_block_attach_file_device_pos.py delete mode 100644 tools/xm-test/tests/block-create/04_block_attach_device_repeatedly_pos.py delete mode 100644 tools/xm-test/tests/block-create/05_block_attach_and_dettach_device_repeatedly_pos.py delete mode 100644 tools/xm-test/tests/block-create/06_block_attach_baddomain_neg.py delete mode 100644 tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py delete mode 100644 tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py delete mode 100644 tools/xm-test/tests/block-create/09_block_attach_and_dettach_device_check_data_pos.py delete mode 100644 tools/xm-test/tests/block-create/10_block_attach_dettach_multiple_devices.py delete mode 100644 tools/xm-test/tests/block-create/11_block_attach_shared_dom0.py delete mode 100644 tools/xm-test/tests/block-create/12_block_attach_shared_domU.py delete mode 100644 tools/xm-test/tests/block-create/Makefile.am delete mode 100644 tools/xm-test/tests/block-destroy/01_block-destroy_btblock_pos.py delete mode 100644 tools/xm-test/tests/block-destroy/02_block-destroy_rtblock_pos.py delete mode 100644 tools/xm-test/tests/block-destroy/03_block-destroy_nonexist_neg.py delete mode 100644 tools/xm-test/tests/block-destroy/04_block-destroy_nonattached_neg.py delete mode 100644 tools/xm-test/tests/block-destroy/05_block-destroy_byname_pos.py delete mode 100644 tools/xm-test/tests/block-destroy/06_block-destroy_check_list_pos.py delete mode 100644 tools/xm-test/tests/block-destroy/Makefile.am delete mode 100644 tools/xm-test/tests/block-integrity/01_block_device_read_verify.py delete mode 100644 tools/xm-test/tests/block-integrity/02_block_device_write_verify.py delete mode 100644 tools/xm-test/tests/block-integrity/Makefile.am delete mode 100644 tools/xm-test/tests/block-list/01_block-list_pos.py delete mode 100644 tools/xm-test/tests/block-list/02_block-list_attachbd_pos.py delete mode 100644 tools/xm-test/tests/block-list/03_block-list_anotherbd_pos.py delete mode 100644 tools/xm-test/tests/block-list/04_block-list_nodb_pos.py delete mode 100644 tools/xm-test/tests/block-list/05_block-list_nonexist_neg.py delete mode 100644 tools/xm-test/tests/block-list/06_block-list_checkremove_pos.py delete mode 100644 tools/xm-test/tests/block-list/Makefile.am delete mode 100644 tools/xm-test/tests/console/01_console_badopt_neg.py delete mode 100644 tools/xm-test/tests/console/02_console_baddom_neg.py delete mode 100644 tools/xm-test/tests/console/Makefile.am delete mode 100644 tools/xm-test/tests/cpupool/01_cpupool_basic_pos.py delete mode 100644 tools/xm-test/tests/cpupool/02_cpupool_manage_pos.py delete mode 100644 tools/xm-test/tests/cpupool/03_cpupool_domain.py delete mode 100644 tools/xm-test/tests/cpupool/04_cpupool_migrate.py delete mode 100644 tools/xm-test/tests/cpupool/Makefile.am delete mode 100644 tools/xm-test/tests/cpupool/pool1.cfg delete mode 100644 tools/xm-test/tests/cpupool/pools.py delete mode 100644 tools/xm-test/tests/create/01_create_basic_pos.py delete mode 100644 tools/xm-test/tests/create/02_create_noparm_neg.py delete mode 100644 tools/xm-test/tests/create/03_create_badparm_neg.py delete mode 100644 tools/xm-test/tests/create/04_create_conflictname_neg.py delete mode 100644 tools/xm-test/tests/create/06_create_mem_neg.py delete mode 100644 tools/xm-test/tests/create/07_create_mem64_pos.py delete mode 100644 tools/xm-test/tests/create/08_create_mem128_pos.py delete mode 100644 tools/xm-test/tests/create/09_create_mem256_pos.py delete mode 100644 tools/xm-test/tests/create/10_create_fastdestroy.py delete mode 100644 tools/xm-test/tests/create/11_create_concurrent_pos.py delete mode 100644 tools/xm-test/tests/create/12_create_concurrent_stress_pos.py delete mode 100644 tools/xm-test/tests/create/13_create_multinic_pos.py delete mode 100644 tools/xm-test/tests/create/14_create_blockroot_pos.py delete mode 100644 tools/xm-test/tests/create/15_create_smallmem_pos.py delete mode 100644 tools/xm-test/tests/create/16_create_smallmem_neg.py delete mode 100644 tools/xm-test/tests/create/Makefile.am delete mode 100644 tools/xm-test/tests/destroy/01_destroy_basic_pos.py delete mode 100644 tools/xm-test/tests/destroy/02_destroy_noparm_neg.py delete mode 100644 tools/xm-test/tests/destroy/03_destroy_nonexist_neg.py delete mode 100644 tools/xm-test/tests/destroy/04_destroy_badparm_neg.py delete mode 100644 tools/xm-test/tests/destroy/05_destroy_byid_pos.py delete mode 100644 tools/xm-test/tests/destroy/06_destroy_dom0_neg.py delete mode 100644 tools/xm-test/tests/destroy/07_destroy_stale_pos.py delete mode 100644 tools/xm-test/tests/destroy/Makefile.am delete mode 100644 tools/xm-test/tests/dmesg/01_dmesg_basic_pos.py delete mode 100644 tools/xm-test/tests/dmesg/02_dmesg_basic_neg.py delete mode 100644 tools/xm-test/tests/dmesg/Makefile.am delete mode 100644 tools/xm-test/tests/domid/01_domid_basic_pos.py delete mode 100644 tools/xm-test/tests/domid/02_domid_basic_neg.py delete mode 100644 tools/xm-test/tests/domid/Makefile.am delete mode 100644 tools/xm-test/tests/domname/01_domname_basic_pos.py delete mode 100644 tools/xm-test/tests/domname/02_domname_basic_neg.py delete mode 100644 tools/xm-test/tests/domname/Makefile.am delete mode 100644 tools/xm-test/tests/enforce_dom0_cpus/01_enforce_dom0_cpus_basic_pos.py delete mode 100644 tools/xm-test/tests/enforce_dom0_cpus/Makefile.am delete mode 100644 tools/xm-test/tests/help/01_help_basic_pos.py delete mode 100644 tools/xm-test/tests/help/02_help_basic_neg.py delete mode 100644 tools/xm-test/tests/help/03_help_badparm_neg.py delete mode 100644 tools/xm-test/tests/help/04_help_long_pos.py delete mode 100644 tools/xm-test/tests/help/05_help_nonroot_pos.py delete mode 100644 tools/xm-test/tests/help/06_help_allcmds.py delete mode 100644 tools/xm-test/tests/help/Makefile.am delete mode 100644 tools/xm-test/tests/info/01_info_basic_pos.py delete mode 100644 tools/xm-test/tests/info/02_info_compiledata_pos.py delete mode 100644 tools/xm-test/tests/info/Makefile.am delete mode 100644 tools/xm-test/tests/list/01_list_basic_pos.py delete mode 100644 tools/xm-test/tests/list/02_list_badparm_neg.py delete mode 100644 tools/xm-test/tests/list/03_list_nonexist_neg.py delete mode 100644 tools/xm-test/tests/list/04_list_goodparm_pos.py delete mode 100644 tools/xm-test/tests/list/05_list_long_pos.py delete mode 100644 tools/xm-test/tests/list/06_list_nonroot.py delete mode 100644 tools/xm-test/tests/list/Makefile.am delete mode 100644 tools/xm-test/tests/memmax/01_memmax_badparm_neg.py delete mode 100644 tools/xm-test/tests/memmax/Makefile.am delete mode 100644 tools/xm-test/tests/memset/01_memset_basic_pos.py delete mode 100644 tools/xm-test/tests/memset/02_memset_badparm_neg.py delete mode 100644 tools/xm-test/tests/memset/03_memset_random_pos.py delete mode 100644 tools/xm-test/tests/memset/04_memset_smallmem_pos.py delete mode 100644 tools/xm-test/tests/memset/Makefile.am delete mode 100644 tools/xm-test/tests/migrate/01_migrate_localhost_pos.py delete mode 100644 tools/xm-test/tests/migrate/Makefile.am delete mode 100644 tools/xm-test/tests/network-attach/01_network_attach_pos.py delete mode 100644 tools/xm-test/tests/network-attach/02_network_attach_detach_pos.py delete mode 100644 tools/xm-test/tests/network-attach/03_network_attach_detach_multiple_pos.py delete mode 100644 tools/xm-test/tests/network-attach/04_network_attach_baddomain_neg.py delete mode 100644 tools/xm-test/tests/network-attach/Makefile.am delete mode 100644 tools/xm-test/tests/network/02_network_local_ping_pos.py delete mode 100644 tools/xm-test/tests/network/03_network_local_tcp_pos.py delete mode 100644 tools/xm-test/tests/network/04_network_local_udp_pos.py delete mode 100644 tools/xm-test/tests/network/05_network_dom0_ping_pos.py delete mode 100644 tools/xm-test/tests/network/06_network_dom0_tcp_pos.py delete mode 100644 tools/xm-test/tests/network/07_network_dom0_udp_pos.py delete mode 100644 tools/xm-test/tests/network/11_network_domU_ping_pos.py delete mode 100644 tools/xm-test/tests/network/12_network_domU_tcp_pos.py delete mode 100644 tools/xm-test/tests/network/13_network_domU_udp_pos.py delete mode 100644 tools/xm-test/tests/network/Makefile.am delete mode 100644 tools/xm-test/tests/pause/01_pause_basic_pos.py delete mode 100644 tools/xm-test/tests/pause/02_pause_badopt_neg.py delete mode 100644 tools/xm-test/tests/pause/03_pause_badname_neg.py delete mode 100644 tools/xm-test/tests/pause/04_pause_badid_neg.py delete mode 100644 tools/xm-test/tests/pause/Makefile.am delete mode 100644 tools/xm-test/tests/reboot/01_reboot_basic_pos.py delete mode 100644 tools/xm-test/tests/reboot/02_reboot_badopt_neg.py delete mode 100644 tools/xm-test/tests/reboot/03_reboot_badname_neg.py delete mode 100644 tools/xm-test/tests/reboot/Makefile.am delete mode 100644 tools/xm-test/tests/restore/01_restore_basic_pos.py delete mode 100644 tools/xm-test/tests/restore/02_restore_badparm_neg.py delete mode 100644 tools/xm-test/tests/restore/03_restore_badfilename_neg.py delete mode 100644 tools/xm-test/tests/restore/04_restore_withdevices_pos.py delete mode 100644 tools/xm-test/tests/restore/Makefile.am delete mode 100644 tools/xm-test/tests/save/01_save_basic_pos.py delete mode 100644 tools/xm-test/tests/save/02_save_badparm_neg.py delete mode 100644 tools/xm-test/tests/save/03_save_bogusfile_neg.py delete mode 100644 tools/xm-test/tests/save/Makefile.am delete mode 100644 tools/xm-test/tests/sched-credit/01_sched_credit_weight_cap_pos.py delete mode 100644 tools/xm-test/tests/sched-credit/Makefile.am delete mode 100644 tools/xm-test/tests/sedf/01_sedf_period_slice_pos.py delete mode 100644 tools/xm-test/tests/sedf/02_sedf_period_lower_neg.py delete mode 100644 tools/xm-test/tests/sedf/03_sedf_slice_lower_neg.py delete mode 100644 tools/xm-test/tests/sedf/04_sedf_slice_upper_neg.py delete mode 100644 tools/xm-test/tests/sedf/05_sedf_extratime_pos.py delete mode 100644 tools/xm-test/tests/sedf/06_sedf_extratime_disable_neg.py delete mode 100644 tools/xm-test/tests/sedf/Makefile.am delete mode 100644 tools/xm-test/tests/shutdown/01_shutdown_basic_pos.py delete mode 100644 tools/xm-test/tests/shutdown/02_shutdown_badparm_neg.py delete mode 100644 tools/xm-test/tests/shutdown/03_shutdown_nonexist_neg.py delete mode 100644 tools/xm-test/tests/shutdown/Makefile.am delete mode 100644 tools/xm-test/tests/sysrq/01_sysrq_basic_neg.py delete mode 100644 tools/xm-test/tests/sysrq/02_sysrq_sync_pos.py delete mode 100644 tools/xm-test/tests/sysrq/03_sysrq_withreboot_pos.py delete mode 100644 tools/xm-test/tests/sysrq/Makefile.am delete mode 100644 tools/xm-test/tests/unpause/01_unpause_basic_pos.py delete mode 100644 tools/xm-test/tests/unpause/Makefile.am delete mode 100644 tools/xm-test/tests/vcpu-disable/01_vcpu-disable_basic_pos.py delete mode 100644 tools/xm-test/tests/vcpu-disable/Makefile.am delete mode 100644 tools/xm-test/tests/vcpu-pin/01_vcpu-pin_basic_pos.py delete mode 100644 tools/xm-test/tests/vcpu-pin/Makefile.am delete mode 100644 tools/xm-test/tests/xapi/01_xapi-vm_basic.py delete mode 100644 tools/xm-test/tests/xapi/02_xapi-vbd_basic.py delete mode 100644 tools/xm-test/tests/xapi/03_xapi-network_pos.py delete mode 100644 tools/xm-test/tests/xapi/04_xapi-data_uri_handling.py delete mode 100644 tools/xm-test/tests/xapi/20_xapi-cpu_pool_basic.py delete mode 100644 tools/xm-test/tests/xapi/Makefile.am diff --git a/.gitignore b/.gitignore index eb210ca9fc..af1d8267f2 100644 --- a/.gitignore +++ b/.gitignore @@ -245,8 +245,6 @@ tools/vtpm/tpm_emulator/* tools/vtpm/vtpm/* tools/vtpm_manager/manager/vtpm_managerd tools/xcutils/lsevtchn -tools/xcutils/xc_restore -tools/xcutils/xc_save tools/xcutils/readnotes tools/xenfb/sdlfb tools/xenfb/vncfb @@ -279,18 +277,6 @@ tools/xentrace/xentrace_setsize tools/xentrace/tbctl tools/xentrace/xenctx tools/xentrace/xentrace -tools/xm-test/ramdisk/buildroot -tools/xm-test/aclocal.m4 -tools/xm-test/autom4te -tools/xm-test/install-sh -tools/xm-test/mkinstalldirs -tools/xm-test/missing -tools/xm-test/config(ure|.log|.status|.guess|.sub) -tools/xm-test/Makefile(.in)* -tools/xm-test/*/Makefile(.in)* -tools/xm-test/lib/XmTestLib/config.py -tools/xm-test/lib/XmTestReport/xmtest.py -tools/xm-test/tests/*.test tools/ocaml-xenstored* xen/.banner xen/System.map diff --git a/.hgignore b/.hgignore index 9c9421e9bd..6d09b0904b 100644 --- a/.hgignore +++ b/.hgignore @@ -278,18 +278,6 @@ ^tools/xentrace/tbctl$ ^tools/xentrace/xenctx$ ^tools/xentrace/xentrace$ -^tools/xm-test/ramdisk/buildroot -^tools/xm-test/aclocal.m4$ -^tools/xm-test/autom4te -^tools/xm-test/install-sh$ -^tools/xm-test/mkinstalldirs$ -^tools/xm-test/missing$ -^tools/xm-test/config(ure|.log|.status|.guess|.sub)$ -^tools/xm-test/Makefile(.in)*$ -^tools/xm-test/.*/Makefile(.in)*$ -^tools/xm-test/lib/XmTestLib/config.py$ -^tools/xm-test/lib/XmTestReport/xmtest.py$ -^tools/xm-test/tests/.*\.test$ ^tools/firmware/ovmf-remote ^tools/firmware/ovmf$ ^tools/qemu-xen-traditional-dir-remote diff --git a/MAINTAINERS b/MAINTAINERS index 3f8810beb0..19dd49fb8f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -255,8 +255,6 @@ REMUS M: Shriram Rajagopalan S: Maintained F: tools/remus/ -F: tools/python/xen/remus/ -F: tools/python/xen/lowlevel/checkpoint/ F: tools/blktap2/drivers/block-remus.c F: tools/blktap2/drivers/hashtable* diff --git a/config/Tools.mk.in b/config/Tools.mk.in index d9d32398d8..85379b2964 100644 --- a/config/Tools.mk.in +++ b/config/Tools.mk.in @@ -54,7 +54,6 @@ CONFIG_ROMBIOS := @rombios@ CONFIG_SEABIOS := @seabios@ CONFIG_QEMU_TRAD := @qemu_traditional@ CONFIG_QEMU_XEN := @qemu_xen@ -CONFIG_XEND := @xend@ CONFIG_BLKTAP1 := @blktap1@ #System options diff --git a/docs/man/xend-config.sxp.pod.5 b/docs/man/xend-config.sxp.pod.5 deleted file mode 100644 index 9504c71fed..0000000000 --- a/docs/man/xend-config.sxp.pod.5 +++ /dev/null @@ -1,158 +0,0 @@ -=head1 NAME - -xend-config.sxp - Xen daemon configuration file - -=head1 SYNOPSIS - -/etc/xen/xend-config.sxp - -=head1 DESCRIPTION - -The xend(1) program requires xend-config.sxp to specify operating -parameters which determine the behavior of the daemon at runtime. - -The parameters are specified in S-expression format. See the example -configuration file in I for details. - -=head1 OPTIONS - -The following lists the daemon configuration parameters: - -=over 4 - -=item I - -The location of the file to record runtime log messages. Defaults to -I. - -=item I - -Filters out messages below the specified level. Possible values are -DEBUG, INFO, WARNING, ERROR, CRITICAL. Defaults to I. - -=item I - -A boolean value that tells xend whether or not to start the http -stream socket management server. Defaults to I. - -=item I - -A boolean value that tells xend whether or not to start the unix -domain socket management server. This is required for the CLI tools -to operate. Defaults to I. - -=item I - -A boolean value that tells xend whether or not to start the relocation -server. This is required for cross-machine migrations. Defaults to -I. - -=item I - -The location of the unix domain socket the xend-unix-server will use -to communicate with the management tools. Defaults to -I. - -=item I - -The port that will be used by the http management server. Defaults to -I<8000>. - -=item I - -The port that will be used by the relocation server. Defaults to -I<8002>. - -=item I - -The address to which the http management server will bind. Defaults -to I<''> which means "all interfaces". - -=item I - -The address to which the relocation server will bind. Defaults to -I<''> which means "all interfaces". - -=item I - -The kilobyte buffer limit that will be enforced by the console server. -This limit is set per-domain, and is needed to prevent a single domain -from overwhelming the console server with massive amounts of data. -Defaults to I<1024>. - -=item I - -The name of the script in I that will be run to -setup the networking environment. This can be any name, but in -general is either I or I. - -=item I - -The name of the script in I that will be run to -setup a virtual interface when it is created or destroyed. This needs -to (in general) work in unison with the I. - -=item I - -This specifies the minimum number of megabytes that will be reserved -for Domain0. If this value is positive, Domain0 will be automatically -ballooned down to this limit to make space for new domains. If this -is set to 0, Domain0 will not be automatically ballooned. - -=item I - -This specifies the number of CPUs that Domain0 will be allowed to use. -If the value is 0, all available CPUs will be used by Domain0. - -=item I - -A boolean value that tells xend whether or not core dumps of guest -domains should be saved when a crash occurs. Defaults to I. - -=item I - -The name of an application or script that can handle external device -migration, such as for example virtual TPM migration. An example -script is I. - -=item I - -Integer value that tells xend how long it should wait for a new device -to be created. Defaults to I<100>. - -=item I - -Integer value that tells xend how long it should wait for a device to -be destroyed. Defaults to I<100>. - -=back - -=head1 EXAMPLES - -An example configuration with relocation enabled for the local network: - -=over 4 - - (xend-relocation-server yes) - (xend-relocation-address 192.0.2.192) - (network-script network-bridge) - (vif-script vif-bridge) - (dom0-min-mem 0) - (dom0-cpus 0) - -=back - -=head1 CAVEATS - -Note that relocation is currently unsecured and is very dangerous if -left enabled. No authentication is performed, and very little sanity -checking takes place. Enable at your own risk. - -=head1 SEE ALSO - -B(1) - -=head1 AUTHOR - -Dan Smith - diff --git a/docs/man/xl.pod.1 b/docs/man/xl.pod.1 index f7ceaa848a..dae0718683 100644 --- a/docs/man/xl.pod.1 +++ b/docs/man/xl.pod.1 @@ -12,7 +12,6 @@ The B program is the new tool for managing Xen guest domains. The program can be used to create, pause, and shutdown domains. It can also be used to list current domains, enable or pin VCPUs, and attach or detach virtual block devices. -The old B tool is deprecated and should not be used. The basic structure of every B command is almost always: diff --git a/docs/man/xm.pod.1 b/docs/man/xm.pod.1 deleted file mode 100644 index 973de9543e..0000000000 --- a/docs/man/xm.pod.1 +++ /dev/null @@ -1,1004 +0,0 @@ -=head1 NAME - -xm - Obsolete xen management user interface - -=head1 SYNOPSIS - -B I [I] - -=head1 DESCRIPTION - -This program is now superseded by B, which should be largely -backwards-compatible with B. - -The B program is the main interface for managing Xen guest domains -when the obsolete Xend toolstack is in use. The program can be used to -create, pause, and shutdown domains. It can also be used to list -current domains, enable or pin VCPUs, and attach or detach virtual -block devices. - -The basic structure of every B command is almost always: - -=over 2 - -B I I [I] - -=back - -Where I is one of the subcommands listed below, I -is the numeric domain id, or the domain name (which will be internally -translated to domain id), and I are subcommand specific -options. There are a few exceptions to this rule in the cases where -the subcommand in question acts on all domains, the entire machine, -or directly on the Xen hypervisor. Those exceptions will be clear for -each of those subcommands. - -=head1 NOTES - -All B operations rely upon the Xen control daemon, aka B. -For any B commands to run, xend must also be running. For this -reason you should start xend as a service when your system first boots -using Xen. - -Most B commands require root privileges to run due to the -communications channels used to talk to the hypervisor. Running as -non root will return an error. - -Most B commands act synchronously, except maybe create, shutdown, -mem-set and vcpu-set. The fact that the B command returned doesn't -necessarily mean that the action is complete and you must poll through -xm list periodically to detect that the operation completed. - -=head1 DOMAIN SUBCOMMANDS - -The following subcommands manipulate domains directly. As stated -previously, most commands take I as the first parameter. - -=over 4 - -=item B I - -Attach to domain I's console. If you've set up your domains to -have a traditional log in console this will look much like a normal -text log in screen. - -This uses the back end xenconsole service which currently only -works for para-virtual domains. - -The attached console will perform much like a standard serial console, -so running curses based interfaces over the console B. Vi tends to get very odd when using it over this interface. - -Use the key combination Ctrl+] to detach the domain console. - -=item B I [I] [I].. - -The create subcommand requires a config file and can optionally take a -series of I that add to or override variables defined -in the config file. See L for full details of that file -format, and possible options used in either the configfile or for I. - -I can either be an absolute path to a file, or a relative -path to a file located in /etc/xen. - -Create will return B as the domain is started. This B mean the guest OS in the domain has actually booted, or is -available for input. - -B - -=over 4 - -=item B<--help_config> - -Print the available configuration variables I. These variables may be -used on the command line or in the configuration file I. - -=item B<-q>, B<--quiet> - -No console output. - -=item B<--path> - -Search path for configuration scripts. The value of PATH is a -colon-separated directory list. - -=item B<-f=FILE>, B<--defconfig=FILE> - -Use the given Python configuration script. The configuration -script is loaded after arguments have been processed. Each -command-line option sets a configuration variable named after -its long option name, and these variables are placed in the -environment of the script before it is loaded. Variables -for options that may be repeated have list values. Other -variables can be set using name=value on the command line. -After the script is loaded, option values that were not set -on the command line are replaced by the values set in the script. - -=item B<-F=FILE>, B<--config=FILE> - -Use the given SXP formatted configuration script. -SXP is the underlying configuration format used by Xen. -SXP configuration scripts can be hand-written or generated -from Python configuration scripts, using the -n -(dryrun) option to print the configuration. An SXP formatted -configuration file may also be generated for a given I by -redirecting the output from the the B> -to a file. - -=item B<-n>, B<--dryrun> - -Dry run - prints the resulting configuration in SXP -but does not create the domain. - -=item B<-x>, B<--xmldryrun> - -XML dry run - prints the resulting configuration in -XML but does not create the domain. - -=item B<-s>, B<--skipdtd> - -Skip DTD checking - skips checks on XML before -creating. Experimental. Can decrease create time. - -=item B<-p>, B<--paused> - -Leave the domain paused after it is created. - -=item B<-c>, B<--console_autoconnect> - -Attach console to the domain as soon as it has started. This is -useful for determining issues with crashing domains. - -=back - -B - -=over 4 - -=item I - - xm create Fedora4 - -This creates a domain with the file /etc/xen/Fedora4, and returns as -soon as it is run. - -=item I - - xm create /dev/null ramdisk=initrd.img \ - kernel=/boot/vmlinuz-2.6.12.6-xenU \ - name=ramdisk vif='' vcpus=1 \ - memory=64 root=/dev/ram0 - -This creates the domain without using a config file (more specifically -using /dev/null as an empty config file), kernel and ramdisk as -specified, setting the name of the domain to "ramdisk", also disabling -virtual networking. (This example comes from the xm-test test suite.) - -=back - -=item B - -Remove a domain from Xend domain management. The B command -shows the domain names. - -=item B I - -Immediately terminate the domain I. This doesn't give the -domain OS any chance to react, and is the equivalent of ripping the -power cord out on a physical machine. In most cases you will want to -use the B command instead. - -=item B I - -Converts a domain name to a domain id using xend's internal mapping. - -=item B I - -Converts a domain id to a domain name using xend's internal mapping. - -=item B [I] I [I] - -Dumps the virtual machine's memory for the specified domain to the -I specified. The dump file will be written to a distribution -specific directory for dump files. Such as: /var/lib/xen/dump or -/var/xen/dump Defaults to dumping the core without pausing the domain -if no I are specified. - -B - -=over 4 - -=item B<-L>, B<--live> - -Dump core without pausing the domain. - -=item B<-C>, B<--crash> - -Crash domain after dumping core. - -=back - -=item B [B<--long>] - -Displays the short help message (i.e. common commands). - -The B<--long> option prints out the complete set of B subcommands, -grouped by function. - -=item B [I] [I ...] - -Prints information about one or more domains. If no domains are -specified it prints out information about all domains. - - -B - -=over 4 - -=item B<-l>, B<--long> - -The output for B is not the table view shown below, but -instead presents the data in SXP format. - -=item B<--label> - -Security labels are added to the output of xm list and the lines -are sorted by the labels (ignoring case). -See the ACCESS CONTROL SUBCOMMAND section of this man page for more -information about labels. - -=item B<--state=> - -Output information for VMs in the specified state. - -=back - -B - -An example format for the list is as follows: - - Name ID Mem(MiB) VCPUs State Time(s) - Domain-0 0 98 1 r----- 5068.6 - Fedora3 164 128 1 r----- 7.6 - Fedora4 165 128 1 ------ 0.6 - Mandrake2006 166 128 1 -b---- 3.6 - Mandrake10.2 167 128 1 ------ 2.5 - Suse9.2 168 100 1 ------ 1.8 - -Name is the name of the domain. ID the numeric domain id. Mem is the -desired amount of memory to allocate to the domain (although it may -not be the currently allocated amount). VCPUs is the number of -virtual CPUs allocated to the domain. State is the run state (see -below). Time is the total run time of the domain as accounted for by -Xen. - -B - -The State field lists 6 states for a Xen domain, and which ones the -current domain is in. - -=over 4 - -=item B - -The domain is currently running on a CPU. - -=item B - -The domain is blocked, and not running or runnable. This can be caused -because the domain is waiting on IO (a traditional wait state) or has -gone to sleep because there was nothing else for it to do. - -=item B

- -The domain has been paused, usually occurring through the administrator -running B. When in a paused state the domain will still -consume allocated resources like memory, but will not be eligible for -scheduling by the Xen hypervisor. - -=item B - -FIXME: Why would you ever see this state? - -=item B - -The domain has crashed, which is always a violent ending. Usually -this state can only occur if the domain has been configured not to -restart on crash. See L for more info. - -=item B - -The domain is in process of dying, but hasn't completely shutdown or -crashed. - -FIXME: Is this right? - -=back - -B - -=over 4 - -The Time column is deceptive. Virtual IO (network and block devices) -used by domains requires coordination by Domain0, which means that -Domain0 is actually charged for much of the time that a DomainU is -doing IO. Use of this time value to determine relative utilizations -by domains is thus very suspect, as a high IO workload may show as -less utilized than a high CPU workload. Consider yourself warned. - -=back - -=item B I I - -Specify the maximum amount of memory the domain is able to use. I -is specified in megabytes. - -The mem-max value may not correspond to the actual memory used in the -domain, as it may balloon down its memory to give more back to the OS. - -=item B I I - -Set the domain's used memory using the balloon driver. - -Because this operation requires cooperation from the domain operating -system, there is no guarantee that it will succeed. This command will -definitely not work unless the domain has the required paravirt -driver. - -B There is no good way to know in advance how small of a -mem-set will make a domain unstable and cause it to crash. Be very -careful when using this command on running domains. - -=item B I I [I] - -Migrate a domain to another host machine. Xend must be running on -other host machine, it must be running the same version of Xen, it -must have the migration TCP port open and accepting connections from -the source host, and there must be sufficient resources for the domain -to run (memory, disk, etc). - -Migration is pretty complicated, and has many security implications. -Please read the Xen User's Guide to ensure you understand the -ramifications and limitations on migration before attempting it in -production. - -B - -=over 4 - -=item B<-l>, B<--live> - -Use live migration. This will migrate the domain between hosts -without shutting down the domain. See the Xen User's Guide for more -information. - -=item B<-r>, B<--resource> I - -Set maximum Mbs allowed for migrating the domain. This ensures that -the network link is not saturated with migration traffic while -attempting to do other useful work. - -=back - -=item B I [I] [I]... - -Adds a domain to Xend domain management. - -The new subcommand requires a config file and can optionally -take a series of I that add to or override variables -defined in the config file. See xmdomain.cfg for full details of that -file format, and possible options used in either the configfile or for -I. - -I can either be an absolute path to a file, or a relative -path to a file located in /etc/xen. - -The new subcommand will return without starting the domain. The -domain needs to be started using the B command. - -B - -=over 4 - -=item B<--help_config> - -Print the available configuration variables I. These variables may be -used on the command line or in the configuration file I. - -=item B<-q>, B<--quiet> - -No console output. - -=item B<--path> - -Search path for configuration scripts. The value of PATH is a -colon-separated directory list. - -=item B<-f=FILE>, B<--defconfig=FILE> - - -Use the given Python configuration script. The configuration -script is loaded after arguments have been processed. Each -command-line option sets a configuration variable named after -its long option name, and these variables are placed in the -environment of the script before it is loaded. Variables -for options that may be repeated have list values. Other -variables can be set using name=value on the command line. -After the script is loaded, option values that were not set -on the command line are replaced by the values set in the script. - -=item B<-F=FILE>, B<--config=FILE> - -Use the given SXP formatted configuration script. -SXP is the underlying configuration format used by Xen. -SXP configuration scripts can be hand-written or generated -from Python configuration scripts, using the -n -(dryrun) option to print the configuration. An SXP formatted -configuration file may also be generated for a given I by -redirecting the output from the the B> -to a file. - -=item B<-n>, B<--dryrun> - -Dry run - prints the resulting configuration in SXP -but does not create the domain. - -=item B<-x>, B<--xmldryrun> - -XML dry run - prints the resulting configuration in -XML but does not create the domain. - -=item B<-s>, B<--skipdtd> - -Skip DTD checking - skips checks on XML before -creating. Experimental. Can decrease create time. - -=item B<-p>, B<--paused> - -Leave the domain paused after it is created. - -=item B<-c>, B<--console_autoconnect> - -Attach console to the domain as soon as it has started. This is -useful for determining issues with crashing domains. - -=back - -=item B I - -Pause a domain. When in a paused state the domain will still consume -allocated resources such as memory, but will not be eligible for -scheduling by the Xen hypervisor. - -=item B [I] I - -Reboot a domain. This acts just as if the domain had the B -command run from the console. The command returns as soon as it has -executed the reboot action, which may be significantly before the -domain actually reboots. - -The behavior of what happens to a domain when it reboots is set by the -B parameter of the xmdomain.cfg file when the domain was -created. - -B - -=over 4 - -=item B<-a>, B<--all> - -Reboot all domains. - -=item B<-w>, B<--wait> - -Wait for reboot to complete before returning. This may take a while, -as all services in the domain will have to be shut down cleanly. - -=back - -=item B I - -Build a domain from an B state file. See B for more info. - -=item B I [I] - -Moves a domain out of the suspended state and back into memory. - -B - -=over 4 - -=item B<-p>, <--paused> - -Moves a domain back into memory but leaves the domain in a paused state. -The B subcommand may then be used to bring it out of the -paused state. - -=back - -=item B I I - -Saves a running domain to a state file so that it can be restored -later. Once saved, the domain will no longer be running on the -system, thus the memory allocated for the domain will be free for -other domains to use. B restores from this state file. - -This is roughly equivalent to doing a hibernate on a running computer, -with all the same limitations. Open network connections may be -severed upon restore, as TCP timeouts may have expired. - -=item B [I] I - -Gracefully shuts down a domain. This coordinates with the domain OS -to perform graceful shutdown, so there is no guarantee that it will -succeed, and may take a variable length of time depending on what -services must be shutdown in the domain. The command returns -immediately after signally the domain unless that B<-w> flag is used. - -The behavior of what happens to a domain when it reboots is set by the -B parameter of the xmdomain.cfg file when the domain was -created. - -B - -=over 4 - -=item B<-a> - -Shutdown B domains. Often used when doing a complete shutdown of -a Xen system. - -=item B<-w> - -Wait for the domain to complete shutdown before returning. - -=back - -=item B I [I] - -Start a Xend managed domain that was added using the B command. - - -B - -=over 4 - -=item B<-p>, B<--paused> - -Do not unpause domain after starting it. - -=item B<-c>, B<--console_autoconnect> - -Connect to the console after the domain is created. - -=back - -=item B I - -Suspend a domain to a state file so that it can be later -resumed using the B subcommand. Similar to the B -subcommand although the state file may not be specified. - -=item B I I - -Send a I signal to the domain. For more -information on available magic sys req operations, see sysrq.txt in -your Linux Kernel sources. - -=item B I - -Moves a domain out of the paused state. This will allow a previously -paused domain to now be eligible for scheduling by the Xen hypervisor. - -=item B I I - -Enables the I virtual CPUs for the domain in question. -Like mem-set, this command can only allocate up to the maximum virtual -CPU count configured at boot for the domain. - -If the I is smaller than the current number of active -VCPUs, the highest number VCPUs will be hotplug removed. This may be -important for pinning purposes. - -Attempting to set the VCPUs to a number larger than the initially -configured VCPU count is an error. Trying to set VCPUs to < 1 will be -quietly ignored. - -Because this operation requires cooperation from the domain operating -system, there is no guarantee that it will succeed. This command will -not work with a full virt domain. - -=item B [I] - -Lists VCPU information for a specific domain. If no domain is -specified, VCPU information for all domains will be provided. - -=item B I I I - -Pins the the VCPU to only run on the specific CPUs. The keyword -B can be used to apply the I list to all VCPUs in the -domain. - -Normally VCPUs can float between available CPUs whenever Xen deems a -different run state is appropriate. Pinning can be used to restrict -this, by ensuring certain VCPUs can only run on certain physical -CPUs. - -=back - -=head1 XEN HOST SUBCOMMANDS - -=over 4 - -=item B [B<-c>] - -Reads the Xen message buffer, similar to dmesg on a Linux system. The -buffer contains informational, warning, and error messages created -during Xen's boot process. If you are having problems with Xen, this -is one of the first places to look as part of problem determination. - -B - -=over 4 - -=item B<-c>, B<--clear> - -Clears Xen's message buffer. - -=back - -=item B - -Print information about the Xen host in I format. When -reporting a Xen bug, please provide this information as part of the -bug report. - -Sample output looks as follows (lines wrapped manually to make the man -page more readable): - - host : talon - release : 2.6.12.6-xen0 - version : #1 Mon Nov 14 14:26:26 EST 2005 - machine : i686 - nr_cpus : 2 - nr_nodes : 1 - cores_per_socket : 1 - threads_per_core : 1 - cpu_mhz : 696 - hw_caps : 0383fbff:00000000:00000000:00000040 - total_memory : 767 - free_memory : 37 - xen_major : 3 - xen_minor : 0 - xen_extra : -devel - xen_caps : xen-3.0-x86_32 - xen_scheduler : credit - xen_pagesize : 4096 - platform_params : virt_start=0xfc000000 - xen_changeset : Mon Nov 14 18:13:38 2005 +0100 - 7793:090e44133d40 - cc_compiler : gcc version 3.4.3 (Mandrakelinux - 10.2 3.4.3-7mdk) - cc_compile_by : sdague - cc_compile_domain : (none) - cc_compile_date : Mon Nov 14 14:16:48 EST 2005 - xend_config_format : 3 - -B - -Not all fields will be explained here, but some of the less obvious -ones deserve explanation: - -=over 4 - -=item B - -A vector showing what hardware capabilities are supported by your -processor. This is equivalent to, though more cryptic, the flags -field in /proc/cpuinfo on a normal Linux machine. - -=item B - -Available memory (in MB) not allocated to Xen, or any other domains. - -=item B - -The Xen version and architecture. Architecture values can be one of: -x86_32, x86_32p (i.e. PAE enabled), x86_64, ia64. - -=item B - -The Xen mercurial changeset id. Very useful for determining exactly -what version of code your Xen system was built from. - -=back - -=item B - -Print out the xend log. This log file can be found in -/var/log/xend.log. - -=item B - -Executes the B command, which provides real time monitoring of -domains. Xentop is a curses interface, and reasonably self -explanatory. - -=item B - -Prints the current uptime of the domains running. - -=back - -=head1 SCHEDULER SUBCOMMANDS - -Xen ships with a number of domain schedulers, which can be set at boot -time with the B parameter on the Xen command line. By -default B is used for scheduling. - -FIXME: we really need a scheduler expert to write up this section. - -=over 4 - -=item B [ B<-d> I [ B<-w>[B<=>I] | B<-c>[B<=>I] ] ] - -Set credit scheduler parameters. The credit scheduler is a -proportional fair share CPU scheduler built from the ground up to be -work conserving on SMP hosts. - -Each domain (including Domain0) is assigned a weight and a cap. - -B - -=over 4 - -=item I - -A domain with a weight of 512 will get twice as much CPU as a domain -with a weight of 256 on a contended host. Legal weights range from 1 -to 65535 and the default is 256. - -=item I - -The cap optionally fixes the maximum amount of CPU a domain will be -able to consume, even if the host system has idle CPU cycles. The cap -is expressed in percentage of one physical CPU: 100 is 1 physical CPU, -50 is half a CPU, 400 is 4 CPUs, etc. The default, 0, means there is -no upper cap. - -NB: Many systems have features that will scale down the computing -power of a cpu that is not 100% utilized. This can be in the -operating system, but can also sometimes be below the operating system -in the BIOS. If you set a cap such that individual cores are running -at less than 100%, this may have an impact on the performance of your -workload over and above the impact of the cap. For example, if your -processor runs at 2GHz, and you cap a vm at 50%, the power management -system may also reduce the clock speed to 1GHz; the effect will be -that your VM gets 25% of the available power (50% of 1GHz) rather than -50% (50% of 2GHz). If you are not getting the performance you expect, -look at performance and cpufreq options in your operating system and -your BIOS. - -=back - -=item B I I I I I - -Set Simple EDF (Earliest Deadline First) scheduler parameters. This -scheduler provides weighted CPU sharing in an intuitive way and uses -realtime-algorithms to ensure time guarantees. For more information -see docs/misc/sedf_scheduler_mini-HOWTO.txt in the Xen distribution. - -B - -=over 4 - -=item I - -The normal EDF scheduling usage in nanoseconds - -=item I - -The normal EDF scheduling usage in nanoseconds - -FIXME: these are lame, should explain more. - -=item I - -Scaled period if domain is doing heavy I/O. - -=item I - -Flag for allowing domain to run in extra time. - -=item I - -Another way of setting CPU slice. - -=back - -B - -I - - xm sched-sedf 20000000 5000000 0 0 0 - -I - - xm sched-sedf 20000000 0 0 1 0 - -I - - xm sched-sedf 20000000 5000000 0 1 0 - -I<4 domains with weights 2:3:4:2> - - xm sched-sedf 0 0 0 0 2 - xm sched-sedf 0 0 0 0 3 - xm sched-sedf 0 0 0 0 4 - xm sched-sedf 0 0 0 0 2 - -I<1 fully-specified (10ms/3ms) domain, 3 other domains share available -rest in 2:7:3 ratio:> - - xm sched-sedf 10000000 3000000 0 0 0 - xm sched-sedf 0 0 0 0 2 - xm sched-sedf 0 0 0 0 7 - xm sched-sedf 0 0 0 0 3 - -=back - -=head1 VIRTUAL DEVICE COMMANDS - -Most virtual devices can be added and removed while guests are -running. The effect to the guest OS is much the same as any hotplug -event. - -=head2 BLOCK DEVICES - -=over 4 - -=item B I I I I [I] - -Create a new virtual block device. This will trigger a hotplug event -for the guest. - -B - -=over 4 - -=item I - -The domain id of the guest domain that the device will be attached to. - -=item I - -The device in the backend domain (usually domain 0) to be exported. -This can be specified as a physical partition (phy:sda7) or as a file -mounted as loopback (file://path/to/loop.iso). - -=item I - -How the device should be presented to the guest domain. It can be -specified as either a symbolic name, such as /dev/hdc, for common -devices, or by device id, such as 0x1400 (/dev/hdc device id in hex). - -=item I - -The access mode for the device from the guest domain. Supported modes -are B (read/write) or B (read-only). - -=item I - -The back end domain hosting the device. This defaults to domain 0. - -=back - -B - -=over 4 - -=item I - -xm block-attach guestdomain file://path/to/dsl-2.0RC2.iso /dev/hdc r - -This will mount the dsl ISO as /dev/hdc in the guestdomain as a read -only device. This will probably not be detected as a CD-ROM by the -guest, but mounting /dev/hdc manually will work. - -=back - -=item B I I [B<--force>] - -Detach a domain's virtual block device. I may be the symbolic -name or the numeric device id given to the device by domain 0. You -will need to run B to determine that number. - -Detaching the device requires the cooperation of the domain. If the -domain fails to release the device (perhaps because the domain is hung -or is still using the device), the detach will fail. The B<--force> -parameter will forcefully detach the device, but may cause IO errors -in the domain. - -=item B [B<-l>|B<--long>] I - -List virtual block devices for a domain. The returned output is -formatted as a list or as an S-Expression if the B<--long> option was given. - -=back - -=head2 NETWORK DEVICES - -=over 4 - -=item B I [BI] [BI] -[BI] [BI] [BI] - -Creates a new network device in the domain specified by I. It -takes the following optional options: - -=back - -B - -=over 4 - -=item BI - -Use the specified script name to bring up the network. Defaults to -the default setting in xend-config.sxp for B. - -=item BI - -Passes the specified IP Address to the adapter on creation. - -FIXME: this currently appears to be B. I'm not sure under what -circumstances this should actually work. - -=item BI - -The MAC address that the domain will see on its Ethernet device. If -the device is not specified it will be randomly generated with the -00:16:3e vendor id prefix. - -=item BI - -The name of the bridge to attach the vif to, in case you have more -than one. This defaults to xenbr0. - -=item BI - -The backend domain id. By default this is domain 0. - -=back - -=over 4 - -=item B I I - -Removes the network device from the domain specified by I. -I is the virtual interface device number within the domain -(i.e. the 3 in vif22.3). - -FIXME: this is currently B. Network devices aren't completely -removed from domain 0. - -=item B [B<-l>|B<--long>]> I - -List virtual network interfaces for a domain. The returned output is -formatted as a list or as an S-Expression if the B<--long> option was given. - -=back - -=head1 SEE ALSO - -B(5), B(1) - -=head1 AUTHOR - - Sean Dague - Daniel Stekloff - Reiner Sailer - Stefan Berger - -=head1 BUGS diff --git a/docs/man/xmdomain.cfg.pod.5 b/docs/man/xmdomain.cfg.pod.5 deleted file mode 100644 index 2e73db4c71..0000000000 --- a/docs/man/xmdomain.cfg.pod.5 +++ /dev/null @@ -1,358 +0,0 @@ -=head1 NAME - -xmdomain.cfg - xm domain config file format - -=head1 SYNOPSIS - - /etc/xen/myxendomain - /etc/xen/myxendomain2 - /etc/xen/auto/myxenautostarted - -=head1 DESCRIPTION - -The B(1) program uses python executable config files to define -domains to create from scratch. Each of these config files needs to -contain a number of required options, and may specify many more. - -Domain configuration files live in /etc/xen by default, if you store -config files anywhere else the full path to the config file must be -specified in the I command. - -/etc/xen/auto is a special case. Domain config files in that -directory will be started automatically at system boot if the -xendomain init script is enabled. The contents of /etc/xen/auto -should be symlinks to files in /etc/xen to allow I to be -used without full paths. - -Options are specified by I statements in the -xmdomain.cfg files. - -=head1 OPTIONS - -The following lists the most commonly used options for a domain config -file. - -=over 4 - -=item B - -The kernel image for the domain. The format of the parameter is the -fully qualified path to the kernel image file, -i.e. I. - - -=item B - -The initial ramdisk for the domain. The format of the parameter is -the fully qualified path to the initrd, i.e. I. On -many Linux distros you will not need a ramdisk if using the default -xen kernel. - -=item B - -The amount of RAM, in megabytes, to allocate to the domain when it -starts. Allocating insufficient memory for a domain may produce -extremely bizarre behavior. If there isn't enough free memory left on -the machine to fulfil this request, the domain will fail to start. - -Xen does not support overcommit of memory, so the total memory of all -guests (+ 64 MB needed for Xen) must be less than or equal to the -physical RAM in the machine. - -=item B - -A unique name for the domain. Attempting to create two domains with -the same name will cause an error. - -=item B - -Specifies the root device for the domain. This is required for Linux -domains, and possibly other OSes. - -=item B - -The number of network interfaces allocated to the domain on boot. It -defaults to 1. - -=item B - -An array of block device stanzas, in the form: - - disk = [ "stanza1", "stanza2", ... ] - -Each stanza has 3 terms, separated by commas, -"backend-dev,frontend-dev,mode". - -=over 4 - -=item I - -The device in the backend domain that will be exported to the guest -(frontend) domain. Supported formats include: - -I - export the physical device listed. The device can be -in symbolic form, as in sda7, or as the hex major/minor number, as in -0x301 (which is hda1). - -I - export the file listed as a loopback device. -This will take care of the loopback setup before exporting the device. - -=item I - -How the device should appear in the guest domain. The device can be -in symbolic form, as in sda7, or as the hex major/minor number, as in -0x301 (which is hda1). - -=item I - -The access mode for the device. There are currently 2 valid options, -I (read-only), I (read/write). - -=back - -=item B - -An array of virtual interface stanzas in the form: - - vif = [ "stanza1", "stanza2", ... ] - -Each stanza specifies a set of I options separated by -commas, in the form: "name1=value1, name2=value2, ..." - -B - -=over 4 - -=item I - -The network bridge to be used for this device. This is especially -needed if multiple bridges exist on the machine. - -=item I - -The MAC address for the virtual interface. If mac is not specified, -one will be randomly chosen by xen with the 00:16:3e vendor id prefix. - -=back - -=item B - -A virtual frame buffer stanza in the form: - - vfb = [ "stanza" ] - -The stanza specifies a set of I options separated by -commas, in the form: "name1=value1, name2=value2, ..." - -B - -=over 4 - -=item I - -There are currently two valid options: I starts a VNC server that -lets you connect an external VNC viewer, and I starts an internal -viewer. - -=item I - -The VNC display number to use, defaults to the domain ID. The -VNC server listens on port 5900 + display number. - -=item I - -The listening address for the VNC server, default 127.0.0.1. - -=item I - -If non-zero, the VNC server listens on the first unused port above -5900. - -=item I - -Overrides the XenD configured default password. - -=item I - -Display to use for the internal viewer, defaults to environment -variable I. - -=item I - -Authority file to use for the internal viewer, defaults to environment -variable I. - -=back - -=back - -=head1 ADDITIONAL OPTIONS - -The following options are also supported in the config file, though -are far more rarely used. - -=over 4 - -=item B - -Which builder should be used to construct the domain. This defaults -to the I if not specified, which is the builder for -paravirtualized Linux domains. - -=item B - -Specifies which CPU the domain should be started on, where 0 specifies -the first cpu, 1 the second, and so on. This defaults to -1, which -means Xen is free to pick which CPU to start on. - -=item B - -Specifies a list of CPUs on which the domains' VCPUs are allowed to -execute upon. The syntax supports ranges (0-3), and negation, ^1. -For instance: - - cpus = "0-3,5,^1" - -Will result in CPUs 0, 2, 3, 5 being available for use by the domain. - -=item B - -Extra information to append to the end of the kernel parameter line. -The format is a string, the contents of which can be anything that the -kernel supports. For instance: - - extra = "4" - -Will cause the domain to boot to runlevel 4. - -=item B - -The IP address of the NFS server to use as the root device for the -domain. In order to do this you'll need to specify I, -and specify I. - -=item B - -The directory on the NFS server to be used as the root filesystem. -Specified as a fully qualified path, i.e. I. - -=item B - -The number of virtual cpus to allocate to the domain. In order to use -this the xen kernel must be compiled with SMP support. - -This defaults to 1, meaning running the domain as a UP. - -=back - -=head1 DOMAIN SHUTDOWN OPTIONS - -There are 3 options which control domain shutdown (both planned and -unplanned) under certain events. The 3 events currently captured are: - -=over 4 - -=item B - -Triggered on either an I or graceful shutdown from inside -the DomU. - -=item B - -Triggered on either an I or graceful reboot from inside the -DomU. - -=item B - -Triggered when a DomU goes to the crashed state for any reason. - -=back - -All of them take one of 4 valid states listed below. - -=over 4 - -=item B - -The domain will be cleaned up completely. No attempt at respawning -will occur. This is what a typical shutdown would look like. - -=item B - -The domain will be restarted with the same name as the old domain. -This is what a typical reboot would look like. - -=item B - -The domain will not be cleaned up at all. This is often useful for -crash state domains which ensures that enough evidence is to debug the -real issue. - -=item B - -The old domain will not be cleaned up, but will be renamed so a new -domain can be restarted in it's place. The old domain will be renamed with -a suffix -1, -2, etc, and assigned a new random UUID; the new domain will -keep the original name and UUID. The old domain will release the devices that -it holds, so that the new one may take them. - -=back - -Additionally, the "on_crash" event can also take: - -=over 4 - -=item B - -Dump the crashed domain's core and then destroy it. - -=item B - -Dump the crashed domain's core and then restart it. - -=back - -=head1 EXAMPLES - -The following are quick examples of ways that domains might be -configured. They should not be considered an exhaustive set. - -=over 4 - -=item I - - kernel = "/boot/vmlinuz-2.6-xenU" - memory = 128 - name = "MyLinux" - root = "/dev/hda1 ro" - disk = [ "file:/var/xen/mylinux.img,hda1,w" ] - -This creates a domain called MyLinux with 128 MB of memory using a -default xen kernel, and the file /var/xen/mylinux.img loopback mounted -at hda1, which is the root filesystem. - -=item I - -FIXME: write me - -=item I - -FIXME: write me - -=item I - -FIXME: write me - -=back - -=head1 SEE ALSO - -B(1) - -=head1 AUTHOR - - Sean Dague - -=head1 BUGS - -Not all options are currently documented diff --git a/tools/configure b/tools/configure index 5c2fa142bf..7a445054ca 100755 --- a/tools/configure +++ b/tools/configure @@ -688,7 +688,6 @@ seabios_path qemu_xen qemu_traditional blktap1 -xend debug seabios rombios @@ -765,7 +764,6 @@ enable_ovmf enable_rombios enable_seabios enable_debug -enable_xend enable_blktap1 enable_qemu_traditional with_system_qemu @@ -1427,7 +1425,6 @@ Optional Features: --disable-rombios Disable ROM BIOS (default is ENABLED) --disable-seabios Disable SeaBIOS (default is ENABLED) --disable-debug Disable debug build of tools (default is ENABLED) - --enable-xend Enable xend toolstack (default is DISABLED) --enable-blktap1 Enable blktap1 tools (default is DISABLED) --enable-qemu-traditional Enable qemu traditional device model, (DEFAULT is on @@ -3747,29 +3744,6 @@ debug=$ax_cv_debug -# Check whether --enable-xend was given. -if test "${enable_xend+set}" = set; then : - enableval=$enable_xend; -fi - - -if test "x$enable_xend" = "xno"; then : - - ax_cv_xend="n" - -elif test "x$enable_xend" = "xyes"; then : - - ax_cv_xend="y" - -elif test -z $ax_cv_xend; then : - - ax_cv_xend="n" - -fi -xend=$ax_cv_xend - - - # Check whether --enable-blktap1 was given. if test "${enable_blktap1+set}" = set; then : enableval=$enable_blktap1; @@ -9480,25 +9454,3 @@ $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi -if test "x$xend" = "xy" ; then : - - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You have enabled the xend toolstack. - -xend is deprecated and scheduled for removal. Please migrate to another -toolstack ASAP. - -See http://wiki.xen.org/wiki/Choice_of_Toolstacks for information on -other alternatives, including xl which is designed to be a drop in -replacement for xm (http://wiki.xen.org/wiki/XL). -" >&5 -$as_echo "$as_me: WARNING: You have enabled the xend toolstack. - -xend is deprecated and scheduled for removal. Please migrate to another -toolstack ASAP. - -See http://wiki.xen.org/wiki/Choice_of_Toolstacks for information on -other alternatives, including xl which is designed to be a drop in -replacement for xm (http://wiki.xen.org/wiki/XL). -" >&2;} - -fi diff --git a/tools/configure.ac b/tools/configure.ac index a62faf8057..e1f7527136 100644 --- a/tools/configure.ac +++ b/tools/configure.ac @@ -58,7 +58,6 @@ AX_ARG_DEFAULT_DISABLE([ovmf], [Enable OVMF]) AX_ARG_DEFAULT_ENABLE([rombios], [Disable ROM BIOS]) AX_ARG_DEFAULT_ENABLE([seabios], [Disable SeaBIOS]) AX_ARG_DEFAULT_ENABLE([debug], [Disable debug build of tools]) -AX_ARG_DEFAULT_DISABLE([xend], [Enable xend toolstack]) AX_ARG_DEFAULT_DISABLE([blktap1], [Enable blktap1 tools]) AC_ARG_ENABLE([qemu-traditional], @@ -245,15 +244,3 @@ AC_CHECK_HEADERS([yajl/yajl_version.h sys/eventfd.h]) AC_OUTPUT() -AS_IF([test "x$xend" = "xy" ], [ - AC_MSG_WARN( -[You have enabled the xend toolstack. - -xend is deprecated and scheduled for removal. Please migrate to another -toolstack ASAP. - -See http://wiki.xen.org/wiki/Choice_of_Toolstacks for information on -other alternatives, including xl which is designed to be a drop in -replacement for xm (http://wiki.xen.org/wiki/XL). -]) -]) diff --git a/tools/examples/Makefile b/tools/examples/Makefile index df24e387d1..86d9cc1b1f 100644 --- a/tools/examples/Makefile +++ b/tools/examples/Makefile @@ -5,18 +5,6 @@ include $(XEN_ROOT)/tools/Rules.mk XEN_READMES = README XEN_READMES += README.incompatibilities -XEN_CONFIGS-$(CONFIG_XEND) += xend-config.sxp -XEN_CONFIGS-$(CONFIG_XEND) += xm-config.xml -XEN_CONFIGS-$(CONFIG_XEND) += xmexample1 -XEN_CONFIGS-$(CONFIG_XEND) += xmexample2 -XEN_CONFIGS-$(CONFIG_XEND) += xmexample3 -XEN_CONFIGS-$(CONFIG_XEND) += xmexample.hvm -XEN_CONFIGS-$(CONFIG_XEND) += xmexample.hvm-stubdom -XEN_CONFIGS-$(CONFIG_XEND) += xmexample.pv-grub -XEN_CONFIGS-$(CONFIG_XEND) += xmexample.nbd -XEN_CONFIGS-$(CONFIG_XEND) += xend-pci-quirks.sxp -XEN_CONFIGS-$(CONFIG_XEND) += xend-pci-permissive.sxp - XEN_CONFIGS += xlexample.hvm XEN_CONFIGS += xlexample.pvlinux XEN_CONFIGS += xl.conf diff --git a/tools/examples/xend-config.sxp b/tools/examples/xend-config.sxp deleted file mode 100644 index 0896a27645..0000000000 --- a/tools/examples/xend-config.sxp +++ /dev/null @@ -1,304 +0,0 @@ -# -*- sh -*- - -# -# Xend configuration file. -# - -# This example configuration is appropriate for an installation that -# utilizes a bridged network configuration. Access to xend via http -# is disabled. - -# Commented out entries show the default for that entry, unless otherwise -# specified. - -#(logfile /var/log/xen/xend.log) -#(loglevel DEBUG) - -# Uncomment the line below. Set the value to flask, acm, or dummy to -# select a security module. - -#(xsm_module_name dummy) - -# The Xen-API server configuration. -# -# This value configures the ports, interfaces, and access controls for the -# Xen-API server. Each entry in the list starts with either unix, a port -# number, or an address:port pair. If this is "unix", then a UDP socket is -# opened, and this entry applies to that. If it is a port, then Xend will -# listen on all interfaces on that TCP port, and if it is an address:port -# pair, then Xend will listen on the specified port, using the interface with -# the specified address. -# -# The subsequent string configures the user-based access control for the -# listener in question. This can be one of "none" or "pam", indicating either -# that users should be allowed access unconditionally, or that the local -# Pluggable Authentication Modules configuration should be used. If this -# string is missing or empty, then "pam" is used. -# -# The final string gives the host-based access control for that listener. If -# this is missing or empty, then all connections are accepted. Otherwise, -# this should be a space-separated sequence of regular expressions; any host -# with a fully-qualified domain name or an IP address that matches one of -# these regular expressions will be accepted. -# -# Example: listen on TCP port 9363 on all interfaces, accepting connections -# only from machines in example.com or localhost, and allow access through -# the unix domain socket unconditionally: -# -# (xen-api-server ((9363 pam '^localhost$ example\\.com$') -# (unix none))) -# -# Optionally, the TCP Xen-API server can use SSL by specifying the private -# key and certificate location: -# -# (9367 pam '' xen-api.key xen-api.crt) -# -# Default: -# (xen-api-server ((unix))) - - -#(xend-http-server no) -#(xend-unix-server no) -#(xend-tcp-xmlrpc-server no) -#(xend-unix-xmlrpc-server yes) -#(xend-relocation-server no) -(xend-relocation-server yes) -#(xend-relocation-ssl-server no) -#(xend-udev-event-server no) - -#(xend-unix-path /var/lib/xend/xend-socket) - - -# Address and port xend should use for the legacy TCP XMLRPC interface, -# if xend-tcp-xmlrpc-server is set. -#(xend-tcp-xmlrpc-server-address 'localhost') -#(xend-tcp-xmlrpc-server-port 8006) - -# SSL key and certificate to use for the legacy TCP XMLRPC interface. -# Setting these will mean that this port serves only SSL connections as -# opposed to plaintext ones. -#(xend-tcp-xmlrpc-server-ssl-key-file xmlrpc.key) -#(xend-tcp-xmlrpc-server-ssl-cert-file xmlrpc.crt) - - -# Port xend should use for the HTTP interface, if xend-http-server is set. -#(xend-port 8000) - -# Port xend should use for the relocation interface, if xend-relocation-server -# is set. -#(xend-relocation-port 8002) - -# Port xend should use for the ssl relocation interface, if -# xend-relocation-ssl-server is set. -#(xend-relocation-ssl-port 8003) - -# SSL key and certificate to use for the ssl relocation interface, if -# xend-relocation-ssl-server is set. -#(xend-relocation-server-ssl-key-file xmlrpc.key) -#(xend-relocation-server-ssl-cert-file xmlrpc.crt) - -# Whether to use ssl as default when relocating. -#(xend-relocation-ssl no) - -# Address xend should listen on for HTTP connections, if xend-http-server is -# set. -# Specifying 'localhost' prevents remote connections. -# Specifying the empty string '' (the default) allows all connections. -#(xend-address '') -#(xend-address localhost) - -# Address xend should listen on for relocation-socket connections, if -# xend-relocation-server is set. -# Meaning and default as for xend-address above. -# Also, interface name is allowed (e.g. eth0) there to get the -# relocation address to be bound on. -#(xend-relocation-address '') - -# The hosts allowed to talk to the relocation port. If this is empty (the -# default), then all connections are allowed (assuming that the connection -# arrives on a port and interface on which we are listening; see -# xend-relocation-port and xend-relocation-address above). Otherwise, this -# should be a space-separated sequence of regular expressions. Any host with -# a fully-qualified domain name or an IP address that matches one of these -# regular expressions will be accepted. -# -# For example: -# (xend-relocation-hosts-allow '^localhost$ ^.*\\.example\\.org$') -# -#(xend-relocation-hosts-allow '') -(xend-relocation-hosts-allow '^localhost$ ^localhost\\.localdomain$') - -# The limit (in kilobytes) on the size of the console buffer -#(console-limit 1024) - -## -# To bridge network traffic, like this: -# -# dom0: ----------------- bridge -> real eth0 -> the network -# | -# domU: fake eth0 -> vifN.0 -+ -# -# use -# -# (network-script network-bridge) -# -# Your default ethernet device is used as the outgoing interface, by default. -# To use a different one (e.g. eth1) use -# -# (network-script 'network-bridge netdev=eth1') -# -# The bridge is named eth0, by default (yes, really!) -# - -# It is normally much better to create the bridge yourself in -# /etc/network/interfaces. network-bridge start does nothing if you -# already have a bridge, and network-bridge stop does nothing if the -# default bridge name (normally eth0) is not a bridge. See -# bridge-utils-interfaces(5) for full information on the syntax in -# /etc/network/interfaces, but you probably want something like this: -# iface xenbr0 inet static -# address [etc] -# netmask [etc] -# [etc] -# bridge_ports eth0 -# -# To have network-bridge create a differently-named bridge, use: -# (network-script 'network-bridge bridge=') -# -# It is possible to use the network-bridge script in more complicated -# scenarios, such as having two outgoing interfaces, with two bridges, and -# two fake interfaces per guest domain. To do things like this, write -# yourself a wrapper script, and call network-bridge from it, as appropriate. -# -(network-script network-bridge) - -# The script used to control virtual interfaces. This can be overridden on a -# per-vif basis when creating a domain or a configuring a new vif. The -# vif-bridge script is designed for use with the network-bridge script, or -# similar configurations. -# -# If you have overridden the bridge name using -# (network-script 'network-bridge bridge=') then you may wish to do the -# same here. The bridge name can also be set when creating a domain or -# configuring a new vif, but a value specified here would act as a default. -# -# If you are using only one bridge, the vif-bridge script will discover that, -# so there is no need to specify it explicitly. The default is to use -# the bridge which is listed first in the output from brctl. -# -(vif-script vif-bridge) - - -## Use the following if network traffic is routed, as an alternative to the -# settings for bridged networking given above. -#(network-script network-route) -#(vif-script vif-route) - - -## Use the following if network traffic is routed with NAT, as an alternative -# to the settings for bridged networking given above. -#(network-script network-nat) -#(vif-script vif-nat) - -# dom0-min-mem is the lowest permissible memory level (in MB) for dom0. -# This is a minimum both for auto-ballooning (as enabled by -# enable-dom0-ballooning below) and for xm mem-set when applied to dom0. -(dom0-min-mem 196) - -# Whether to enable auto-ballooning of dom0 to allow domUs to be created. -# If enable-dom0-ballooning = no, dom0 will never balloon out. -(enable-dom0-ballooning yes) - -# 32-bit paravirtual domains can only consume physical -# memory below 168GB. On systems with memory beyond that address, -# they'll be confined to memory below 128GB. -# Using total_available_memory (in GB) to specify the amount of memory reserved -# in the memory pool exclusively for 32-bit paravirtual domains. -# Additionally you should use dom0_mem = <-Value> as a parameter in -# xen kernel to reserve the memory for 32-bit paravirtual domains, default -# is "0" (0GB). -(total_available_memory 0) - -# In SMP system, dom0 will use dom0-cpus # of CPUS -# If dom0-cpus = 0, dom0 will take all cpus available -(dom0-cpus 0) - -# Whether to enable core-dumps when domains crash. -#(enable-dump no) - -# The tool used for initiating virtual TPM migration -#(external-migration-tool '') - -# The interface for VNC servers to listen on. Defaults -# to 127.0.0.1 To restore old 'listen everywhere' behaviour -# set this to 0.0.0.0 -#(vnc-listen '127.0.0.1') - -# The default password for VNC console on HVM domain. -# Empty string is no authentication. -(vncpasswd '') - -# The VNC server can be told to negotiate a TLS session -# to encryption all traffic, and provide x509 cert to -# clients enabling them to verify server identity. The -# GTK-VNC widget, virt-viewer, virt-manager and VeNCrypt -# all support the VNC extension for TLS used in QEMU. The -# TightVNC/RealVNC/UltraVNC clients do not. -# -# To enable this create x509 certificates / keys in the -# directory ${XEN_CONFIG_DIR} + vnc -# -# ca-cert.pem - The CA certificate -# server-cert.pem - The Server certificate signed by the CA -# server-key.pem - The server private key -# -# and then uncomment this next line -# (vnc-tls 1) - -# The certificate dir can be pointed elsewhere.. -# -# (vnc-x509-cert-dir vnc) - -# The server can be told to request & validate an x509 -# certificate from the client. Only clients with a cert -# signed by the trusted CA will be able to connect. This -# is more secure the password auth alone. Passwd auth can -# used at the same time if desired. To enable client cert -# checking uncomment this: -# -# (vnc-x509-verify 1) - -# The default keymap to use for the VM's virtual keyboard -# when not specififed in VM's configuration -#(keymap 'en-us') - -# Script to run when the label of a resource has changed. -#(resource-label-change-script '') - -# Rotation count of qemu-dm log file. -#(qemu-dm-logrotate-count 10) - -# Path where persistent domain configuration is stored. -# Default is /var/lib/xend/domains/ -#(xend-domains-path /var/lib/xend/domains) - -# Number of seconds xend will wait for device creation and -# destruction -#(device-create-timeout 100) -#(device-destroy-timeout 100) - -# When assigning device to HVM guest, we use the strict check for HVM guest by -# default. (For PV guest, we use loose check automatically if necessary.) -# When we assign device to HVM guest, if we meet with the co-assignment -# issues or the ACS issue, we could try changing the option to 'no' -- however, -# we have to realize this may incur security issue and we can't make sure the -# device assignment could really work properly even after we do this. -#(pci-passthrough-strict-check yes) - -# If we have a very big scsi device configuration, start of xend is slow, -# because xend scans all the device paths to build its internal PSCSI device -# list. If we need only a few devices for assigning to a guest, we can reduce -# the scan to this device. Set list list of device paths in same syntax like in -# command lsscsi, e.g. ('16:0:0:0' '15:0') -# (pscsi-device-mask ('*')) - diff --git a/tools/examples/xend-pci-permissive.sxp b/tools/examples/xend-pci-permissive.sxp deleted file mode 100644 index 1a3fb90a04..0000000000 --- a/tools/examples/xend-pci-permissive.sxp +++ /dev/null @@ -1,27 +0,0 @@ -############################################################################### -# Configuration file for granting quiry PCI devices full write access to their -# configuration space. This file should only be used when you are unable to -# determine the exact registers required by your device. Even so, it should -# be used only temporarily. -# -# SEND A MESSAGE TO xen-devel@lists.xensource.com IF YOU USE THIS FILE. -# -# Using this file should NOT be necessary. If you must use it to make some -# device work, send a message to the above list with as much information about -# your device as possible so the developers can make accomodations for it. -# Once developers make the necessary updates you can remove the corresponding -# entry for your device. -############################################################################### -# Entries are formated as follows: :[::] -# -# Example: Appending to an existing list -# -# (unconstrained_dev_ids -# ('XXXX:XXXX:XXXX:XXXX' # existing entry -# 'YYYY:YYYY:YYYY:YYYY' # new entry 1 -# 'ZZZZ:ZZZZ') # new entry 2 -# ) -############################################################################### -(unconstrained_dev_ids - #('0123:4567:89AB:CDEF') -) diff --git a/tools/examples/xend-pci-quirks.sxp b/tools/examples/xend-pci-quirks.sxp deleted file mode 100644 index 6bce4b8a78..0000000000 --- a/tools/examples/xend-pci-quirks.sxp +++ /dev/null @@ -1,96 +0,0 @@ -############################################################################### -# Configuration file for quirky PCI devices that require write-access to -# parts of the configuration space. Use this file to specific PCI device -# IDs and the configuration space fields to which those devices must be -# able to write. -# -# Length is important, so be sure to match new entries with the -# lengths of comparable existing entries. -# -# Additions to this file take effect as soon as a new domain with a -# matching device is started. However, to remove a field that was -# previously applied to a device you must unbind the device from -# pciback. -############################################################################### -# This is a bogus entry to show how a new device would be added to the list -# -# (new_quirky_dev_name -# (pci_ids -# ('0123:4567:890A:BCEF') -# ) -# -# (pci_config_space_fields -# ('12345678:1:00000000') -# ) -# ) -############################################################################### - -(tg3 - (pci_ids - # Entries are formated as follows: - # :[::] - ('14e4:1644' # Broadcom Tigon3 5700 - '14e4:1645' # Broadcom Tigon3 5701 - '14e4:1646' # Broadcom Tigon3 5702 - '14e4:1647' # Broadcom Tigon3 5703 - '14e4:1648' # Broadcom Tigon3 5704 - '14e4:164d' # Broadcom Tigon3 5702FE - '14e4:1653' # Broadcom Tigon3 5705 - '14e4:1654' # Broadcom Tigon3 5705_2 - '14e4:165d' # Broadcom Tigon3 5705M - '14e4:165e' # Broadcom Tigon3 5705M_2 - '14e4:16a6' # Broadcom Tigon3 5702X - '14e4:16a7' # Broadcom Tigon3 5703X - '14e4:16a8' # Broadcom Tigon3 5704S - '14e4:16c6' # Broadcom Tigon3 5702A3 - '14e4:16c7' # Broadcom Tigon3 5703A3 - '14e4:1696' # Broadcom Tigon3 5782 - '14e4:169c' # Broadcom Tigon3 5788 - '14e4:169d' # Broadcom Tigon3 5789 - '14e4:170d' # Broadcom Tigon3 5901 - '14e4:1649' # Broadcom Tigon3 5704S_2 - '14e4:166e' # Broadcom Tigon3 5705F - '14e4:1658' # Broadcom Tigon3 5720 - '14e4:1659' # Broadcom Tigon3 5721 - '14e4:1676' # Broadcom Tigon3 5750 - '14e4:1677' # Broadcom Tigon3 5751 - '14e4:167c' # Broadcom Tigon3 5750M - '14e4:167d' # Broadcom Tigon3 5751M - '14e4:167e' # Broadcom Tigon3 5751F - '14e4:1600' # Broadcom Tigon3 5752 - '14e4:1601' # Broadcom Tigon3 5752M - '14e4:16f7' # Broadcom Tigon3 5753 - '14e4:16fd' # Broadcom Tigon3 5753M - '14e4:16fe' # Broadcom Tigon3 5753F - '14e4:1668' # Broadcom Tigon3 5714 - '14e4:1678' # Broadcom Tigon3 5715 - '14e4:166a' # Broadcom Tigon3 5780 - '14e4:166b' # Broadcom Tigon3 5780S - '14e4:16dd' # Broadcom Tigon3 5781 - '1148:4400' # Syskonnect 9DXX - '1148:4500' # Syskonnect 9MXX - '173b:03e8' # Altima AC1000 - '173b:03e9' # Altima AC1001 - '173b:03eb' # Altima AC1003 - '173b:03ea' # Altima AC9100 - '106b:1645') # Apple Tigon3 - ) - - (pci_config_space_fields - # Entries are formated as follows: - # :: - # size is measured in bytes (1,2,4 are valid sizes) - # mask is currently unused; use all zero's - ('00000078:4:00000000' # TG3PCI_REG_BASE_ADDR - '0000007c:4:00000000' # TG3PCI_MEM_WIN_BASE_ADDR - '00000080:4:00000000' # TG3PCI_REG_DATA - '00000084:4:00000000' # TG3PCI_MEM_WIN_DATA - '00000090:4:00000000' # TG3PCI_MISC_LOCAL_CTRL - '00000068:4:00000000' # TG3PCI_MISC_HOST_CTRL - '0000009C:4:00000000' # TG3PCI_STD_RING_PROD_IDX + TG3_64BIT_REG_LOW - '00000098:4:00000000' # TG3PCI_STD_RING_PROD_IDX + TG3_64BIT_REG_HIGH - '000000a4:4:00000000' # TG3PCI_RCV_RET_RING_CON_IDX + TG3_64BIT_REG_LOW - '000000a0:4:00000000' # TG3PCI_RCV_RET_RING_CON_IDX + TG3_64BIT_REG_HIGH - '00000070:4:00000000') # TG3PCI_PCISTATE - ) -) diff --git a/tools/examples/xm-config.xml b/tools/examples/xm-config.xml deleted file mode 100644 index 943b74d297..0000000000 --- a/tools/examples/xm-config.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - diff --git a/tools/examples/xmexample.hvm b/tools/examples/xmexample.hvm deleted file mode 100644 index 96b6cc44bb..0000000000 --- a/tools/examples/xmexample.hvm +++ /dev/null @@ -1,373 +0,0 @@ -# -*- mode: python; -*- -#============================================================================ -# Python configuration setup for 'xm create'. -# This script sets the parameters used when a domain is created using 'xm create'. -# You use a separate script for each domain you want to create, or -# you can set the parameters for the domain on the xm command line. -#============================================================================ - -#---------------------------------------------------------------------------- -# Kernel image file. -kernel = "hvmloader" - -# The domain build function. HVM domain uses 'hvm'. -builder='hvm' - -# Initial memory allocation (in megabytes) for the new domain. -# -# WARNING: Creating a domain with insufficient memory may cause out of -# memory errors. The domain needs enough memory to boot kernel -# and modules. Allocating less than 32MBs is not recommended. -memory = 128 - -# Shadow pagetable memory for the domain, in MB. -# If not explicictly set, xend will pick an appropriate value. -# Should be at least 2KB per MB of domain memory, plus a few MB per vcpu. -# shadow_memory = 8 - -# Whether to transparently share this domain's memory with other domains. -# default = 0 -# memory_sharing = 0 - -# A name for your domain. All domains must have different names. -name = "ExampleHVMDomain" - -# 128-bit UUID for the domain. The default behavior is to generate a new UUID -# on each call to 'xm create'. -#uuid = "06ed00fe-1162-4fc4-b5d8-11993ee4a8b9" - -#----------------------------------------------------------------------------- -# The number of cpus guest platform has, default=1 -#vcpus=1 - -# Enable/disable HVM guest PAE, default=1 (enabled) -#pae=1 - -# Enable/disable HVM guest ACPI, default=1 (enabled) -#acpi=1 - -# Enable/disable HVM APIC mode, default=1 (enabled) -# Note that this option is ignored if vcpus > 1 -#apic=1 - -# Enable/disable extended power management support within HVM guest, i.e., beyond -# S3, S4, S5 within guest like exposing battery meter. -# 0 (default option, extended power management support disabled) -# 1 (pass-through mode; uses pass-through as needed; efficient but limited in scope) -# 2 (non pass-through mode; extended scope, likely to work on all applicable environment -# but comparitively less efficient than pass-through mode) -# xen_extended_power_mgmt=0 - -# List of which CPUS this domain is allowed to use, default Xen picks -#cpus = "" # leave to Xen to pick -#cpus = "0" # all vcpus run on CPU0 -#cpus = "0-3,5,^1" # all vcpus run on cpus 0,2,3,5 -#cpus = ["2", "3"] # VCPU0 runs on CPU2, VCPU1 runs on CPU3 - -# Optionally define mac and/or bridge for the network interfaces. -# Random MACs are assigned if not given. -#vif = [ 'type=ioemu, mac=00:16:3e:00:00:11, bridge=xenbr0, model=ne2k_pci' ] -# type=ioemu specify the NIC is an ioemu device not netfront -vif = [ 'type=ioemu, bridge=xenbr0' ] - -#---------------------------------------------------------------------------- -# Define the disk devices you want the domain to have access to, and -# what you want them accessible as. -# Each disk entry is of the form phy:UNAME,DEV,MODE -# where UNAME is the device, DEV is the device name the domain will see, -# and MODE is r for read-only, w for read-write. - -#disk = [ 'phy:hda1,hda1,r' ] -disk = [ 'file:/var/images/min-el3-i386.img,hda,w', ',hdc:cdrom,r' ] - -#---------------------------------------------------------------------------- -# Configure the behaviour when a domain exits. There are three 'reasons' -# for a domain to stop: poweroff, reboot, and crash. For each of these you -# may specify: -# -# "destroy", meaning that the domain is cleaned up as normal; -# "restart", meaning that a new domain is started in place of the old -# one; -# "preserve", meaning that no clean-up is done until the domain is -# manually destroyed (using xm destroy, for example); or -# "rename-restart", meaning that the old domain is not cleaned up, but is -# renamed and a new domain started in its place. -# -# In the event a domain stops due to a crash, you have the additional options: -# -# "coredump-destroy", meaning dump the crashed domain's core and then destroy; -# "coredump-restart', meaning dump the crashed domain's core and the restart. -# -# The default is -# -# on_poweroff = 'destroy' -# on_reboot = 'restart' -# on_crash = 'restart' -# -# For backwards compatibility we also support the deprecated option restart -# -# restart = 'onreboot' means on_poweroff = 'destroy' -# on_reboot = 'restart' -# on_crash = 'destroy' -# -# restart = 'always' means on_poweroff = 'restart' -# on_reboot = 'restart' -# on_crash = 'restart' -# -# restart = 'never' means on_poweroff = 'destroy' -# on_reboot = 'destroy' -# on_crash = 'destroy' - -#on_poweroff = 'destroy' -#on_reboot = 'restart' -#on_crash = 'restart' - -#============================================================================ - -# Device Model to be used -device_model = 'qemu-dm' - -#----------------------------------------------------------------------------- -# boot on floppy (a), hard disk (c), Network (n) or CD-ROM (d) -# default: hard disk, cd-rom, floppy -#boot="cda" - -#----------------------------------------------------------------------------- -# write to temporary files instead of disk image files -#snapshot=1 - -#---------------------------------------------------------------------------- -# enable SDL library for graphics, default = 0 -sdl=0 - -#---------------------------------------------------------------------------- -# enable OpenGL for texture rendering inside the SDL window, default = 1 -# valid only if sdl is enabled. -opengl=1 - -#---------------------------------------------------------------------------- -# enable VNC library for graphics, default = 1 -vnc=1 - -#---------------------------------------------------------------------------- -# address that should be listened on for the VNC server if vnc is set. -# default is to use 'vnc-listen' setting from -# auxbin.xen_configdir() + /xend-config.sxp -#vnclisten="127.0.0.1" - -#---------------------------------------------------------------------------- -# set VNC display number, default = domid -#vncdisplay=1 - -#---------------------------------------------------------------------------- -# try to find an unused port for the VNC server, default = 1 -#vncunused=1 - -#---------------------------------------------------------------------------- -# set password for domain's VNC console -# default is depents on vncpasswd in xend-config.sxp -vncpasswd='' - -#---------------------------------------------------------------------------- -# no graphics, use serial port -#nographic=0 - -#---------------------------------------------------------------------------- -# enable stdvga, default = 0 (use cirrus logic device model) -stdvga=0 - -#----------------------------------------------------------------------------- -# serial port re-direct to pty deivce, /dev/pts/n -# then xm console or minicom can connect -serial='pty' - -#---------------------------------------------------------------------------- -# tsc_mode : TSC mode (0=default, 1=native TSC, 2=never emulate, 3=pvrdtscp) -# emulate TSC provides synced TSC for all vcpus, but lose perfomrance. -# native TSC leverages hardware's TSC(no perf loss), but vcpu's TSC may lose -# sync due to hardware's unreliable/unsynced TSC between CPUs. -# default intelligently uses native TSC on machines where it is safe, but -# switches to emulated if necessary after save/restore/migration -# pvrdtscp is for intelligent apps that use special Xen-only paravirtualized -# cpuid instructions to obtain offset/scaling/migration info and maximize -# performance within pools of machines that support the rdtscp instruction -tsc_mode=0 - -#----------------------------------------------------------------------------- -# Qemu Monitor, default is disable -# Use ctrl-alt-2 to connect -#monitor=1 - - -#----------------------------------------------------------------------------- -# enable sound card support, [sb16|es1370|all|..,..], default none -#soundhw='sb16' - - -#----------------------------------------------------------------------------- -# set the real time clock to local time [default=0 i.e. set to utc] -#localtime=1 - - -#----------------------------------------------------------------------------- -# set the real time clock offset in seconds [default=0 i.e. same as dom0] -#rtc_timeoffset=3600 - -#----------------------------------------------------------------------------- -# start in full screen -#full-screen=1 - - -#----------------------------------------------------------------------------- -# Enable USB support (specific devices specified at runtime through the -# monitor window) -#usb=1 - -# Enable USB mouse support (only enable one of the following, `mouse' for -# PS/2 protocol relative mouse, `tablet' for -# absolute mouse) -#usbdevice='mouse' -#usbdevice='tablet' - -#----------------------------------------------------------------------------- -# Set keyboard layout, default is en-us keyboard. -#keymap='ja' - -#----------------------------------------------------------------------------- -# Enable/disable xen platform PCI device, default=1 (enabled) -#xen_platform_pci=1 - -#----------------------------------------------------------------------------- -# Configure guest CPUID responses: -# -#cpuid=[ '1:ecx=xxxxxxxxxxx00xxxxxxxxxxxxxxxxxxx, -# eax=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' ] -# - Unset the SSE4 features (CPUID.1[ECX][20-19]) -# - Default behaviour for all other bits in ECX And EAX registers. -# -# Each successive character represent a lesser-significant bit: -# '1' -> force the corresponding bit to 1 -# '0' -> force to 0 -# 'x' -> Get a safe value (pass through and mask with the default policy) -# 'k' -> pass through the host bit value -# 's' -> as 'k' but preserve across save/restore and migration -# -# Expose to the guest multi-core cpu instead of multiple processors -# Example for intel, expose a 8-core processor : -#cpuid=['1:edx=xxx1xxxxxxxxxxxxxxxxxxxxxxxxxxxx, -# ebx=xxxxxxxx00010000xxxxxxxxxxxxxxxx', -# '4,0:eax=001111xxxxxxxxxxxxxxxxxxxxxxxxxx'] -# - CPUID.1[EDX][HT] : Enable HT -# - CPUID.1[EBX] : Number of vcpus * 2 -# - CPUID.4,0[EAX] : Number of vcpus * 2 - 1 -#vcpus=8 -# -# Example for amd, expose a 5-core processor : -# cpuid = ['1:ebx=xxxxxxxx00001010xxxxxxxxxxxxxxxx, -# edx=xxx1xxxxxxxxxxxxxxxxxxxxxxxxxxxx', -# '0x80000001:ecx=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1x', -# '0x80000008:ecx=xxxxxxxxxxxxxxxxxxxxxxxxxx001001'] -# - CPUID.1[EBX] : Threads per Core * Cores per Socket (2 * #vcpus) -# - CPUID.1[EDX][HT] : Enable HT -# - CPUID.0x80000001[CmpLegacy] : Use legacy method -# - CPUID.0x80000008[ECX] : #vcpus * 2 - 1 -#vcpus=5 -# -# Downgrade the cpuid to make a better compatibility for migration : -# Look like a generic 686 : -# cpuid = [ '0:eax=0x3,ebx=0x0,ecx=0x0,edx=0x0', -# '1:eax=0x06b1, -# ecx=xxxxxxxxxxx0000xx00xxx0000000xx0, -# edx=xxx00000xxxxxxx0xxxxxxxxx0xxxxxx', -# '4:eax=0x3,ebx=0x0,ecx=0x0,edx=0x0', -# '0x80000000:eax=0x3,ebx=0x0,ecx=0x0,edx=0x0'] -# with the highest leaf -# - CPUID.0[EAX] : Set the highest leaf -# - CPUID.1[EAX] : 686 -# - CPUID.1[ECX] : Mask some features -# - CPUID.1[EDX] : Mask some features -# - CPUID.4 : Reply like the highest leaf, in our case CPUID.3 -# - CPUID.0x80000000 : No extension we are on a Pentium III, reply like the -# highest leaf (CPUID.3). -# -# Configure host CPUID consistency checks, which must be satisfied for this -# VM to be allowed to run on this host's processor type: -#cpuid_check=[ '1:ecx=xxxxxxxxxxxxxxxxxxxxxxxxxx1xxxxx' ] -# - Host must have VMX feature flag set -# -# The format is similar to the above for 'cpuid': -# '1' -> the bit must be '1' -# '0' -> the bit must be '0' -# 'x' -> we don't care (do not check) -# 's' -> the bit must be the same as on the host that started this VM - -#----------------------------------------------------------------------------- -# Configure passthrough PCI{,-X,e} devices: -# -# pci=[ '[SSSS:]BB:DD.F[,option1[,option2[...]]]', ... ] -# -# [SSSS]:BB:DD.F "bus segment:bus:device.function"(1) of the device to -# be assigned, bus segment is optional. All fields are -# in hexadecimal and no field should be longer than that -# as shown in the pattern. Successful assignment may need -# certain hardware support and additional configurations -# (e.g. VT-d, see docs/misc/vtd.txt for more details). -# -# (1) bus segment is sometimes also referred to as the PCI "domain", -# not to be confused with Xen domain. -# -# -# optionN per-device options in "key=val" format. Current -# available options are: -# - msitranslate=0|1 -# per-device overriden of pci_msitranslate, see below -# - power_mgmt=0|1 -# per-device overriden of pci_power_mgmt, see below -# -#pci=[ '07:00.0', '07:00.1' ] - -# MSI-INTx translation for MSI capable devices: -# -# If it's set, Xen will enable MSI for the device that supports it even -# if the guest don't use MSI. In the case, an IO-APIC type interrupt will -# be injected to the guest every time a corresponding MSI message is -# received. -# If the guest enables MSI or MSI-X, the translation is automatically -# turned off. -# -#pci_msitranslate=1 - -# PCI Power Management: -# -# If it's set, the guest OS will be able to program D0-D3hot states of the -# PCI device for the purpose of low power consumption. -# -#pci_power_mgmt=0 - -# Enable graphics passthrough: -# -# If it's set, and specify graphics device BDF in pci passthrough option, -# like pci=['xx:xx.x'], it enables graphics passthrough, default=0 (disabled) -#gfx_passthru=0 - -#----------------------------------------------------------------------------- -# Configure PVSCSI devices: -# -#vscsi=[ 'PDEV, VDEV' ] -# -# PDEV gives physical SCSI device to be attached to specified guest -# domain by one of the following identifier format. -# - XX:XX:XX:XX (4-tuples with decimal notation which shows -# "host:channel:target:lun") -# - /dev/sdxx or sdx -# - /dev/stxx or stx -# - /dev/sgxx or sgx -# - result of 'scsi_id -gu -s'. -# ex. # scsi_id -gu -s /block/sdb -# 36000b5d0006a0000006a0257004c0000 -# -# VDEV gives virtual SCSI device by 4-tuples (XX:XX:XX:XX) as -# which the specified guest domain recognize. -# - -#vscsi = [ '/dev/sdx, 0:0:0:0' ] diff --git a/tools/examples/xmexample.hvm-stubdom b/tools/examples/xmexample.hvm-stubdom deleted file mode 100644 index a425e83e7c..0000000000 --- a/tools/examples/xmexample.hvm-stubdom +++ /dev/null @@ -1,317 +0,0 @@ -# -*- mode: python; -*- -#============================================================================ -# Python configuration setup for 'xm create'. -# This script sets the parameters used when a domain is created using 'xm create'. -# You use a separate script for each domain you want to create, or -# you can set the parameters for the domain on the xm command line. -#============================================================================ -# -# This is a version using a stubdomain for device model -# The differences with xmexample.hvm are marked with "STUBDOM" - -#---------------------------------------------------------------------------- -# Kernel image file. -kernel = "hvmloader" - -# The domain build function. HVM domain uses 'hvm'. -builder='hvm' - -# Initial memory allocation (in megabytes) for the new domain. -# -# WARNING: Creating a domain with insufficient memory may cause out of -# memory errors. The domain needs enough memory to boot kernel -# and modules. Allocating less than 32MBs is not recommended. -memory = 128 - -# Shadow pagetable memory for the domain, in MB. -# If not explicictly set, xend will pick an appropriate value. -# Should be at least 2KB per MB of domain memory, plus a few MB per vcpu. -# shadow_memory = 8 - -# A name for your domain. All domains must have different names. -name = "xmexample.hvm" - -# 128-bit UUID for the domain. The default behavior is to generate a new UUID -# on each call to 'xm create'. -#uuid = "06ed00fe-1162-4fc4-b5d8-11993ee4a8b9" - -#----------------------------------------------------------------------------- -# The number of cpus guest platform has, default=1 -#vcpus=1 - -# Enable/disable HVM guest PAE, default=1 (enabled) -#pae=1 - -# Enable/disable HVM guest ACPI, default=1 (enabled) -#acpi=1 - -# Enable/disable HVM APIC mode, default=1 (enabled) -# Note that this option is ignored if vcpus > 1 -#apic=1 - -# List of which CPUS this domain is allowed to use, default Xen picks -#cpus = "" # leave to Xen to pick -#cpus = "0" # all vcpus run on CPU0 -#cpus = "0-3,5,^1" # all vcpus run on cpus 0,2,3,5 -#cpus = ["2", "3"] # VCPU0 runs on CPU2, VCPU1 runs on CPU3 - -# Optionally define mac and/or bridge for the network interfaces. -# Random MACs are assigned if not given. -#vif = [ 'type=ioemu, mac=00:16:3e:00:00:11, bridge=xenbr0, model=ne2k_pci' ] -# type=ioemu specify the NIC is an ioemu device not netfront -vif = [ 'type=ioemu, bridge=xenbr0' ] - -#---------------------------------------------------------------------------- -# Define the disk devices you want the domain to have access to, and -# what you want them accessible as. -# Each disk entry is of the form phy:UNAME,DEV,MODE -# where UNAME is the device, DEV is the device name the domain will see, -# and MODE is r for read-only, w for read-write. - -disk = [ 'file:/var/images/min-el3-i386.img,hda,w', 'phy:/dev/cdrom,hdc:cdrom,r' ] - -#---------------------------------------------------------------------------- -# Configure the behaviour when a domain exits. There are three 'reasons' -# for a domain to stop: poweroff, reboot, and crash. For each of these you -# may specify: -# -# "destroy", meaning that the domain is cleaned up as normal; -# "restart", meaning that a new domain is started in place of the old -# one; -# "preserve", meaning that no clean-up is done until the domain is -# manually destroyed (using xm destroy, for example); or -# "rename-restart", meaning that the old domain is not cleaned up, but is -# renamed and a new domain started in its place. -# -# In the event a domain stops due to a crash, you have the additional options: -# -# "coredump-destroy", meaning dump the crashed domain's core and then destroy; -# "coredump-restart', meaning dump the crashed domain's core and the restart. -# -# The default is -# -# on_poweroff = 'destroy' -# on_reboot = 'restart' -# on_crash = 'restart' -# -# For backwards compatibility we also support the deprecated option restart -# -# restart = 'onreboot' means on_poweroff = 'destroy' -# on_reboot = 'restart' -# on_crash = 'destroy' -# -# restart = 'always' means on_poweroff = 'restart' -# on_reboot = 'restart' -# on_crash = 'restart' -# -# restart = 'never' means on_poweroff = 'destroy' -# on_reboot = 'destroy' -# on_crash = 'destroy' - -#on_poweroff = 'destroy' -#on_reboot = 'restart' -#on_crash = 'restart' - -#============================================================================ - -# Device Model to be used -# -# STUBDOM: this is a script that creates the stub domain running the device -# model -device_model = 'stubdom-dm' - -#----------------------------------------------------------------------------- -# boot on floppy (a), hard disk (c), Network (n) or CD-ROM (d) -# default: hard disk, cd-rom, floppy -boot="cda" - -#----------------------------------------------------------------------------- -# write to temporary files instead of disk image files -#snapshot=1 - -#---------------------------------------------------------------------------- -# enable SDL library for graphics, default = 0 -# -sdl=0 - -#---------------------------------------------------------------------------- -# enable OpenGL for texture rendering inside the SDL window, default = 1 -# valid only if sdl is enabled. -# -opengl=1 - -#---------------------------------------------------------------------------- -# enable VNC library for graphics, default = 1 -vnc=1 - -#---------------------------------------------------------------------------- -# address that should be listened on for the VNC server if vnc is set. -# default is to use 'vnc-listen' setting from -# auxbin.xen_configdir() + /xend-config.sxp -#vnclisten="127.0.0.1" - -#---------------------------------------------------------------------------- -# set VNC display number, default = domid -#vncdisplay=1 - -#---------------------------------------------------------------------------- -# try to find an unused port for the VNC server, default = 1 -#vncunused=1 - -#---------------------------------------------------------------------------- -# enable spawning vncviewer for domain's console -# (only valid when vnc=1), default = 0 -#vncconsole=0 - -#---------------------------------------------------------------------------- -# set password for domain's VNC console -# default is depents on vncpasswd in xend-config.sxp -vncpasswd='' - -#---------------------------------------------------------------------------- -# no graphics, use serial port -#nographic=0 - -#---------------------------------------------------------------------------- -# enable stdvga, default = 0 (use cirrus logic device model) -stdvga=0 - -#----------------------------------------------------------------------------- -# serial port re-direct to pty deivce, /dev/pts/n -# then xm console or minicom can connect -# -# In the stubdoms case this option adds a secondary console to the -# stubdom because there is always one for logging. -# To connect to the guest serial you can use "xm console -n 1" -# followed by the domain name of the stubdom. -#serial='pty' - - -#----------------------------------------------------------------------------- -# Qemu Monitor, default is disable -# Use ctrl-alt-2 to connect -#monitor=1 - - -#----------------------------------------------------------------------------- -# enable sound card support, [sb16|es1370|all|..,..], default none -# -# STUBDOM: not supported -#soundhw='sb16' - - -#----------------------------------------------------------------------------- -# set the real time clock to local time [default=0 i.e. set to utc] -#localtime=1 - - -#----------------------------------------------------------------------------- -# set the real time clock offset in seconds [default=0 i.e. same as dom0] -#rtc_timeoffset=3600 - -#----------------------------------------------------------------------------- -# start in full screen -#full-screen=1 - - -#----------------------------------------------------------------------------- -# Enable USB support (specific devices specified at runtime through the -# monitor window) -#usb=1 - -# Enable USB mouse support (only enable one of the following, `mouse' for -# PS/2 protocol relative mouse, `tablet' for -# absolute mouse) -#usbdevice='mouse' -#usbdevice='tablet' - -#----------------------------------------------------------------------------- -# Set keyboard layout, default is en-us keyboard. -#keymap='ja' - -#----------------------------------------------------------------------------- -# Configure guest CPUID responses: -# -#cpuid=[ '1:ecx=xxxxxxxxxxx00xxxxxxxxxxxxxxxxxxx, -# eax=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' ] -# - Unset the SSE4 features (CPUID.1[ECX][20-19]) -# - Default behaviour for all other bits in ECX And EAX registers. -# -# Each successive character represent a lesser-significant bit: -# '1' -> force the corresponding bit to 1 -# '0' -> force to 0 -# 'x' -> Get a safe value (pass through and mask with the default policy) -# 'k' -> pass through the host bit value -# 's' -> as 'k' but preserve across save/restore and migration -# -# Expose to the guest multi-core cpu instead of multiple processors -# Example for intel, expose a 8-core processor : -#cpuid=['1:edx=xxx1xxxxxxxxxxxxxxxxxxxxxxxxxxxx, -# ebx=xxxxxxxx00010000xxxxxxxxxxxxxxxx', -# '4,0:eax=001111xxxxxxxxxxxxxxxxxxxxxxxxxx'] -# - CPUID.1[EDX][HT] : Enable HT -# - CPUID.1[EBX] : Number of vcpus * 2 -# - CPUID.4,0[EAX] : Number of vcpus * 2 - 1 -#vcpus=8 -# -# Example for amd, expose a 5-core processor : -# cpuid = ['1:ebx=xxxxxxxx00001010xxxxxxxxxxxxxxxx, -# edx=xxx1xxxxxxxxxxxxxxxxxxxxxxxxxxxx', -# '0x80000001:ecx=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1x', -# '0x80000008:ecx=xxxxxxxxxxxxxxxxxxxxxxxxxx001001'] -# - CPUID.1[EBX] : Threads per Core * Cores per Socket (2 * #vcpus) -# - CPUID.1[EDX][HT] : Enable HT -# - CPUID.0x80000001[CmpLegacy] : Use legacy method -# - CPUID.0x80000008[ECX] : #vcpus * 2 - 1 -#vcpus=5 -# -# Downgrade the cpuid to make a better compatibility for migration : -# Look like a generic 686 : -# cpuid = [ '0:eax=0x3,ebx=0x0,ecx=0x0,edx=0x0', -# '1:eax=0x06b1, -# ecx=xxxxxxxxxx0000xx00xxx0000000xx0, -# edx=xx00000xxxxxxx0xxxxxxxxx0xxxxxx', -# '4:eax=0x3,ebx=0x0,ecx=0x0,edx=0x0', -# '0x80000000:eax=0x3,ebx=0x0,ecx=0x0,edx=0x0'] -# with the highest leaf -# - CPUID.0[EAX] : Set the highest leaf -# - CPUID.1[EAX] : 686 -# - CPUID.1[ECX] : Mask some features -# - CPUID.1[EDX] : Mask some features -# - CPUID.4 : Reply like the highest leaf, in our case CPUID.3 -# - CPUID.0x80000000 : No extension we are on a Pentium III, reply like the -# highest leaf (CPUID.3). -# -# Configure host CPUID consistency checks, which must be satisfied for this -# VM to be allowed to run on this host's processor type: -#cpuid_check=[ '1:ecx=xxxxxxxxxxxxxxxxxxxxxxxxxx1xxxxx' ] -# - Host must have VMX feature flag set -# -# The format is similar to the above for 'cpuid': -# '1' -> the bit must be '1' -# '0' -> the bit must be '0' -# 'x' -> we don't care (do not check) -# 's' -> the bit must be the same as on the host that started this VM - - -#----------------------------------------------------------------------------- -# Configure PVSCSI devices: -# -#vscsi=[ 'PDEV, VDEV' ] -# -# PDEV gives physical SCSI device to be attached to specified guest -# domain by one of the following identifier format. -# - XX:XX:XX:XX (4-tuples with decimal notation which shows -# "host:channel:target:lun") -# - /dev/sdxx or sdx -# - /dev/stxx or stx -# - /dev/sgxx or sgx -# - result of 'scsi_id -gu -s'. -# ex. # scsi_id -gu -s /block/sdb -# 36000b5d0006a0000006a0257004c0000 -# -# VDEV gives virtual SCSI device by 4-tuples (XX:XX:XX:XX) as -# which the specified guest domain recognize. -# - -#vscsi = [ '/dev/sdx, 0:0:0:0' ] diff --git a/tools/examples/xmexample.nbd b/tools/examples/xmexample.nbd deleted file mode 100644 index 7fdb74e0e0..0000000000 --- a/tools/examples/xmexample.nbd +++ /dev/null @@ -1,26 +0,0 @@ -# -*- mode: python; -*- -# -# xm create configuration example. -# -# This configuration is appropriate for using Network Block Device (NBD) -# filesystems. -# -# Each of these parameters will need changing to match your setup. -# - -kernel = "/boot/vmlinuz-2.6.13-15b-xen" -ramdisk = "/boot/initrd-2.6.13-15b-xen" - -# WARNING: Creating a domain with insufficient memory may cause out of -# memory errors. The domain needs enough memory to boot kernel -# and modules. Allocating less than 32MBs is not recommended. -memory = 128 - -name = "nbd4" -vif = [ '' ] -# Please change PORT -disk = [ 'nbd:134.100.233.115 20004,hda1,w' ] -dhcp = "dhcp" -hostname= "nbd4" -root = "/dev/hda1 ro" -extra = "3" diff --git a/tools/examples/xmexample.pv-grub b/tools/examples/xmexample.pv-grub deleted file mode 100644 index e04e6c1ea4..0000000000 --- a/tools/examples/xmexample.pv-grub +++ /dev/null @@ -1,172 +0,0 @@ -# -*- mode: python; -*- -#============================================================================ -# Python configuration setup for 'xm create'. -# This script sets the parameters used when a domain is created using 'xm create'. -# You use a separate script for each domain you want to create, or -# you can set the parameters for the domain on the xm command line. -#============================================================================ - -#---------------------------------------------------------------------------- -# PV GRUB image file. -kernel = "pv-grub.gz" - -# Optional provided menu.lst. -#ramdisk = "/boot/guests/menu.lst" - -# Sets path to menu.lst -extra = "(hd0,0)/boot/grub/menu.lst" -# can be a TFTP-served path (DHCP will automatically be run) -# extra = "(nd)/netboot/menu.lst" -# can be configured automatically by GRUB's DHCP option 150 (see grub manual) -# extra = "" - -# Initial memory allocation (in megabytes) for the new domain. -# -# WARNING: Creating a domain with insufficient memory may cause out of -# memory errors. The domain needs enough memory to boot kernel -# and modules. Allocating less than 32MBs is not recommended. -memory = 128 - -# A name for your domain. All domains must have different names. -name = "ExampleDomain" - -# 128-bit UUID for the domain. The default behavior is to generate a new UUID -# on each call to 'xm create'. -#uuid = "06ed00fe-1162-4fc4-b5d8-11993ee4a8b9" - -# List of which CPUS this domain is allowed to use, default Xen picks -#cpus = "" # leave to Xen to pick -#cpus = "0" # all vcpus run on CPU0 -#cpus = "0-3,5,^1" # all vcpus run on cpus 0,2,3,5 -#cpus = ["2", "3"] # VCPU0 runs on CPU2, VCPU1 runs on CPU3 - -# Number of Virtual CPUS to use, default is 1 -#vcpus = 1 - -#---------------------------------------------------------------------------- -# Define network interfaces. - -# By default, no network interfaces are configured. You may have one created -# with sensible defaults using an empty vif clause: -# -# vif = [ '' ] -# -# or optionally override backend, bridge, ip, mac, script, type, or vifname: -# -# vif = [ 'mac=00:16:3e:00:00:11, bridge=xenbr0' ] -# -# or more than one interface may be configured: -# -# vif = [ '', 'bridge=xenbr1' ] - -vif = [ '' ] - -#---------------------------------------------------------------------------- -# Define the disk devices you want the domain to have access to, and -# what you want them accessible as. -# Each disk entry is of the form phy:UNAME,DEV,MODE -# where UNAME is the device, DEV is the device name the domain will see, -# and MODE is r for read-only, w for read-write. - -disk = [ 'phy:hda1,hda1,w' ] - -#---------------------------------------------------------------------------- -# Define frame buffer device. -# -# By default, no frame buffer device is configured. -# -# To create one using the SDL backend and sensible defaults: -# -# vfb = [ 'sdl=1' ] -# -# This uses environment variables XAUTHORITY and DISPLAY. You -# can override that: -# -# vfb = [ 'sdl=1,xauthority=/home/bozo/.Xauthority,display=:1' ] -# -# To create one using the VNC backend and sensible defaults: -# -# vfb = [ 'vnc=1' ] -# -# The backend listens on 127.0.0.1 port 5900+N by default, where N is -# the domain ID. You can override both address and N: -# -# vfb = [ 'vnc=1,vnclisten=127.0.0.1,vncdisplay=1' ] -# -# Or you can bind the first unused port above 5900: -# -# vfb = [ 'vnc=1,vnclisten=0.0.0.0,vncunused=1' ] -# -# You can override the password: -# -# vfb = [ 'vnc=1,vncpasswd=MYPASSWD' ] -# -# Empty password disables authentication. Defaults to the vncpasswd -# configured in xend-config.sxp. - -#---------------------------------------------------------------------------- -# Configure the behaviour when a domain exits. There are three 'reasons' -# for a domain to stop: poweroff, reboot, and crash. For each of these you -# may specify: -# -# "destroy", meaning that the domain is cleaned up as normal; -# "restart", meaning that a new domain is started in place of the old -# one; -# "preserve", meaning that no clean-up is done until the domain is -# manually destroyed (using xm destroy, for example); or -# "rename-restart", meaning that the old domain is not cleaned up, but is -# renamed and a new domain started in its place. -# -# In the event a domain stops due to a crash, you have the additional options: -# -# "coredump-destroy", meaning dump the crashed domain's core and then destroy; -# "coredump-restart', meaning dump the crashed domain's core and the restart. -# -# The default is -# -# on_poweroff = 'destroy' -# on_reboot = 'restart' -# on_crash = 'restart' -# -# For backwards compatibility we also support the deprecated option restart -# -# restart = 'onreboot' means on_poweroff = 'destroy' -# on_reboot = 'restart' -# on_crash = 'destroy' -# -# restart = 'always' means on_poweroff = 'restart' -# on_reboot = 'restart' -# on_crash = 'restart' -# -# restart = 'never' means on_poweroff = 'destroy' -# on_reboot = 'destroy' -# on_crash = 'destroy' - -#on_poweroff = 'destroy' -#on_reboot = 'restart' -#on_crash = 'restart' - -#----------------------------------------------------------------------------- -# Configure PVSCSI devices: -# -#vscsi=[ 'PDEV, VDEV' ] -# -# PDEV gives physical SCSI device to be attached to specified guest -# domain by one of the following identifier format. -# - XX:XX:XX:XX (4-tuples with decimal notation which shows -# "host:channel:target:lun") -# - /dev/sdxx or sdx -# - /dev/stxx or stx -# - /dev/sgxx or sgx -# - result of 'scsi_id -gu -s'. -# ex. # scsi_id -gu -s /block/sdb -# 36000b5d0006a0000006a0257004c0000 -# -# VDEV gives virtual SCSI device by 4-tuples (XX:XX:XX:XX) as -# which the specified guest domain recognize. -# - -#vscsi = [ '/dev/sdx, 0:0:0:0' ] - -#============================================================================ - diff --git a/tools/examples/xmexample1 b/tools/examples/xmexample1 deleted file mode 100644 index c95120014c..0000000000 --- a/tools/examples/xmexample1 +++ /dev/null @@ -1,197 +0,0 @@ -# -*- mode: python; -*- -#============================================================================ -# Python configuration setup for 'xm create'. -# This script sets the parameters used when a domain is created using 'xm create'. -# You use a separate script for each domain you want to create, or -# you can set the parameters for the domain on the xm command line. -#============================================================================ - -#---------------------------------------------------------------------------- -# Kernel image file. -kernel = "/boot/vmlinuz-2.6.10-xenU" - -# Optional ramdisk. -#ramdisk = "/boot/initrd.gz" - -# The domain build function. Default is 'linux'. -#builder='linux' - -# Initial memory allocation (in megabytes) for the new domain. -# -# WARNING: Creating a domain with insufficient memory may cause out of -# memory errors. The domain needs enough memory to boot kernel -# and modules. Allocating less than 32MBs is not recommended. -memory = 64 - -# A name for your domain. All domains must have different names. -name = "ExampleDomain" - -# 128-bit UUID for the domain. The default behavior is to generate a new UUID -# on each call to 'xm create'. -#uuid = "06ed00fe-1162-4fc4-b5d8-11993ee4a8b9" - -# List of which CPUS this domain is allowed to use, default Xen picks -#cpus = "" # leave to Xen to pick -#cpus = "0" # all vcpus run on CPU0 -#cpus = "0-3,5,^1" # all vcpus run on cpus 0,2,3,5 -#cpus = ["2", "3"] # VCPU0 runs on CPU2, VCPU1 runs on CPU3 - -# Number of Virtual CPUS to use, default is 1 -#vcpus = 1 - -#---------------------------------------------------------------------------- -# Define network interfaces. - -# By default, no network interfaces are configured. You may have one created -# with sensible defaults using an empty vif clause: -# -# vif = [ '' ] -# -# or optionally override backend, bridge, ip, mac, script, type, or vifname: -# -# vif = [ 'mac=00:16:3e:00:00:11, bridge=xenbr0' ] -# -# or more than one interface may be configured: -# -# vif = [ '', 'bridge=xenbr1' ] - -vif = [ '' ] - -#---------------------------------------------------------------------------- -# Define the disk devices you want the domain to have access to, and -# what you want them accessible as. -# Each disk entry is of the form phy:UNAME,DEV,MODE -# where UNAME is the device, DEV is the device name the domain will see, -# and MODE is r for read-only, w for read-write. - -disk = [ 'phy:hda1,hda1,w' ] - -#---------------------------------------------------------------------------- -# Define frame buffer device. -# -# By default, no frame buffer device is configured. -# -# To create one using the SDL backend and sensible defaults: -# -# vfb = [ 'sdl=1' ] -# -# This uses environment variables XAUTHORITY and DISPLAY. You -# can override that: -# -# vfb = [ 'sdl=1,xauthority=/home/bozo/.Xauthority,display=:1' ] -# -# To create one using the VNC backend and sensible defaults: -# -# vfb = [ 'vnc=1' ] -# -# The backend listens on 127.0.0.1 port 5900+N by default, where N is -# the domain ID. You can override both address and N: -# -# vfb = [ 'vnc=1,vnclisten=127.0.0.1,vncdisplay=1' ] -# -# Or you can bind the first unused port above 5900: -# -# vfb = [ 'vnc=1,vnclisten=0.0.0.0,vncunused=1' ] -# -# You can override the password: -# -# vfb = [ 'vnc=1,vncpasswd=MYPASSWD' ] -# -# Empty password disables authentication. Defaults to the vncpasswd -# configured in xend-config.sxp. - -#---------------------------------------------------------------------------- -# Set the kernel command line for the new domain. -# You only need to define the IP parameters and hostname if the domain's -# IP config doesn't, e.g. in ifcfg-eth0 or via DHCP. -# You can use 'extra' to set the runlevel and custom environment -# variables used by custom rc scripts (e.g. VMID=, usr= ). - -# Set if you want dhcp to allocate the IP address. -#dhcp="dhcp" -# Set netmask. -#netmask= -# Set default gateway. -#gateway= -# Set the hostname. -#hostname= "vm%d" % vmid - -# Set root device. -root = "/dev/hda1 ro" - -# Root device for nfs. -#root = "/dev/nfs" -# The nfs server. -#nfs_server = '192.0.2.1' -# Root directory on the nfs server. -#nfs_root = '/full/path/to/root/directory' - -# Sets runlevel 4. -extra = "4" - -#---------------------------------------------------------------------------- -# Configure the behaviour when a domain exits. There are three 'reasons' -# for a domain to stop: poweroff, reboot, and crash. For each of these you -# may specify: -# -# "destroy", meaning that the domain is cleaned up as normal; -# "restart", meaning that a new domain is started in place of the old -# one; -# "preserve", meaning that no clean-up is done until the domain is -# manually destroyed (using xm destroy, for example); or -# "rename-restart", meaning that the old domain is not cleaned up, but is -# renamed and a new domain started in its place. -# -# In the event a domain stops due to a crash, you have the additional options: -# -# "coredump-destroy", meaning dump the crashed domain's core and then destroy; -# "coredump-restart', meaning dump the crashed domain's core and the restart. -# -# The default is -# -# on_poweroff = 'destroy' -# on_reboot = 'restart' -# on_crash = 'restart' -# -# For backwards compatibility we also support the deprecated option restart -# -# restart = 'onreboot' means on_poweroff = 'destroy' -# on_reboot = 'restart' -# on_crash = 'destroy' -# -# restart = 'always' means on_poweroff = 'restart' -# on_reboot = 'restart' -# on_crash = 'restart' -# -# restart = 'never' means on_poweroff = 'destroy' -# on_reboot = 'destroy' -# on_crash = 'destroy' - -#on_poweroff = 'destroy' -#on_reboot = 'restart' -#on_crash = 'restart' - -#----------------------------------------------------------------------------- -# Configure PVSCSI devices: -# -#vscsi=[ 'PDEV, VDEV' ] -# -# PDEV gives physical SCSI device to be attached to specified guest -# domain by one of the following identifier format. -# - XX:XX:XX:XX (4-tuples with decimal notation which shows -# "host:channel:target:lun") -# - /dev/sdxx or sdx -# - /dev/stxx or stx -# - /dev/sgxx or sgx -# - result of 'scsi_id -gu -s'. -# ex. # scsi_id -gu -s /block/sdb -# 36000b5d0006a0000006a0257004c0000 -# -# VDEV gives virtual SCSI device by 4-tuples (XX:XX:XX:XX) as -# which the specified guest domain recognize. -# - -#vscsi = [ '/dev/sdx, 0:0:0:0' ] - -#============================================================================ - diff --git a/tools/examples/xmexample2 b/tools/examples/xmexample2 deleted file mode 100644 index 8c5137ed85..0000000000 --- a/tools/examples/xmexample2 +++ /dev/null @@ -1,232 +0,0 @@ -# -*- mode: python; -*- -#============================================================================ -# Example Python setup script for 'xm create'. -# This script sets the parameters used when a domain is created using 'xm create'. -# -# This is a relatively advanced script that uses a parameter, vmid, to control -# the settings. So this script can be used to start a set of domains by -# setting the vmid parameter on the 'xm create' command line. For example: -# -# xm create vmid=1 -# xm create vmid=2 -# xm create vmid=3 -# -# The vmid is purely a script variable, and has no effect on the the domain -# id assigned to the new domain. -#============================================================================ - -# Define script variables here. -# xm_vars is defined automatically, use xm_vars.var() to define a variable. - -# This function checks that 'vmid' has been given a valid value. -# It is called automatically by 'xm create'. -def vmid_check(var, val): - val = int(val) - if val <= 0: - raise ValueError - return val - -# Define the 'vmid' variable so that 'xm create' knows about it. -xm_vars.var('vmid', - use="Virtual machine id. Integer greater than 0.", - check=vmid_check) - -# Check the defined variables have valid values.. -xm_vars.check() - -#---------------------------------------------------------------------------- -# Kernel image file. -kernel = "/boot/vmlinuz-2.6.10-xenU" - -# Optional ramdisk. -#ramdisk = "/boot/initrd.gz" - -# The domain build function. Default is 'linux'. -#builder='linux' - -# Initial memory allocation (in megabytes) for the new domain. -# -# WARNING: Creating a domain with insufficient memory may cause out of -# memory errors. The domain needs enough memory to boot kernel -# and modules. Allocating less than 32MBs is not recommended. -memory = 64 - -# A name for the new domain. All domains have to have different names, -# so we use the vmid to create a name. -name = "VM%d" % vmid - -# 128-bit UUID for the domain. The default behavior is to generate a new UUID -# on each call to 'xm create'. -#uuid = "06ed00fe-1162-4fc4-b5d8-11993ee4a8b9" - -# List of which CPUS this domain is allowed to use, default Xen picks -#cpus = "" # leave to Xen to pick -#cpus = "0" # all vcpus run on CPU0 -#cpus = "0-3,5,^1" # all vcpus run on cpus 0,2,3,5 -#cpus = ["2", "3"] # VCPU0 runs on CPU2, VCPU1 runs on CPU3 -#cpus = "%s" % vmid # set based on vmid (mod number of CPUs) - -# Number of Virtual CPUS to use, default is 1 -#vcpus = 1 -vcpus = 4 # make your domain a 4-way - -#---------------------------------------------------------------------------- -# Define network interfaces. - -# By default, no network interfaces are configured. You may have one created -# with sensible defaults using an empty vif clause: -# -# vif = [ '' ] -# -# or optionally override backend, bridge, ip, mac, script, type, or vifname: -# -# vif = [ 'mac=00:16:3e:00:00:11, bridge=xenbr0' ] -# -# or more than one interface may be configured: -# -# vif = [ '', 'bridge=xenbr1' ] - -vif = [ '' ] - -#---------------------------------------------------------------------------- -# Define the disk devices you want the domain to have access to, and -# what you want them accessible as. -# Each disk entry is of the form phy:UNAME,DEV,MODE -# where UNAME is the device, DEV is the device name the domain will see, -# and MODE is r for read-only, w for read-write. - -# This makes the disk device depend on the vmid - assuming -# that devices sda7, sda8 etc. exist. The device is exported -# to all domains as sda1. -# All domains get sda6 read-only (to use for /usr, see below). -disk = [ 'phy:sda%d,sda1,w' % (7+vmid), - 'phy:sda6,sda6,r' ] - -#---------------------------------------------------------------------------- -# Define frame buffer device. -# -# By default, no frame buffer device is configured. -# -# To create one using the SDL backend and sensible defaults: -# -# vfb = [ 'sdl=1' ] -# -# This uses environment variables XAUTHORITY and DISPLAY. You -# can override that: -# -# vfb = [ 'sdl=1,xauthority=/home/bozo/.Xauthority,display=:1' ] -# -# To create one using the VNC backend and sensible defaults: -# -# vfb = [ 'vnc=1' ] -# -# The backend listens on 127.0.0.1 port 5900+N by default, where N is -# the domain ID. You can override both address and N: -# -# vfb = [ 'vnc=1,vnclisten=127.0.0.1,vncdisplay=%d' % vmid ] -# -# Or you can bind the first unused port above 5900: -# -# vfb = [ 'vnc=1,vnclisten=0.0.0.0,vncunused=1' ] -# -# You can override the password: -# -# vfb = [ 'vnc=1,vncpasswd=MYPASSWD' ] -# -# Empty password disables authentication. Defaults to the vncpasswd -# configured in xend-config.sxp. - -#---------------------------------------------------------------------------- -# Set the kernel command line for the new domain. -# You only need to define the IP parameters and hostname if the domain's -# IP config doesn't, e.g. in ifcfg-eth0 or via DHCP. -# You can use 'extra' to set the runlevel and custom environment -# variables used by custom rc scripts (e.g. VMID=, usr= ). - -# Set if you want dhcp to allocate the IP address. -#dhcp="dhcp" -# Set netmask. -#netmask= -# Set default gateway. -#gateway= -# Set the hostname. -#hostname= "vm%d" % vmid - -# Set root device. -root = "/dev/sda1 ro" - -# Root device for nfs. -#root = "/dev/nfs" -# The nfs server. -#nfs_server = '192.0.2.1' -# Root directory on the nfs server. -#nfs_root = '/full/path/to/root/directory' - -# Sets runlevel 4 and the device for /usr. -extra = "4 VMID=%d usr=/dev/sda6" % vmid - -#---------------------------------------------------------------------------- -# Configure the behaviour when a domain exits. There are three 'reasons' -# for a domain to stop: poweroff, reboot, and crash. For each of these you -# may specify: -# -# "destroy", meaning that the domain is cleaned up as normal; -# "restart", meaning that a new domain is started in place of the old -# one; -# "preserve", meaning that no clean-up is done until the domain is -# manually destroyed (using xm destroy, for example); or -# "rename-restart", meaning that the old domain is not cleaned up, but is -# renamed and a new domain started in its place. -# -# In the event a domain stops due to a crash, you have the additional options: -# -# "coredump-destroy", meaning dump the crashed domain's core and then destroy; -# "coredump-restart', meaning dump the crashed domain's core and the restart. -# -# The default is -# -# on_poweroff = 'destroy' -# on_reboot = 'restart' -# on_crash = 'restart' -# -# For backwards compatibility we also support the deprecated option restart -# -# restart = 'onreboot' means on_poweroff = 'destroy' -# on_reboot = 'restart' -# on_crash = 'destroy' -# -# restart = 'always' means on_poweroff = 'restart' -# on_reboot = 'restart' -# on_crash = 'restart' -# -# restart = 'never' means on_poweroff = 'destroy' -# on_reboot = 'destroy' -# on_crash = 'destroy' - -#on_poweroff = 'destroy' -#on_reboot = 'restart' -#on_crash = 'restart' - -#----------------------------------------------------------------------------- -# Configure PVSCSI devices: -# -#vscsi=[ 'PDEV, VDEV' ] -# -# PDEV gives physical SCSI device to be attached to specified guest -# domain by one of the following identifier format. -# - XX:XX:XX:XX (4-tuples with decimal notation which shows -# "host:channel:target:lun") -# - /dev/sdxx or sdx -# - /dev/stxx or stx -# - /dev/sgxx or sgx -# - result of 'scsi_id -gu -s'. -# ex. # scsi_id -gu -s /block/sdb -# 36000b5d0006a0000006a0257004c0000 -# -# VDEV gives virtual SCSI device by 4-tuples (XX:XX:XX:XX) as -# which the specified guest domain recognize. -# - -#vscsi = [ '/dev/sdx, 0:0:0:0' ] - -#============================================================================ diff --git a/tools/examples/xmexample3 b/tools/examples/xmexample3 deleted file mode 100644 index ae799f9088..0000000000 --- a/tools/examples/xmexample3 +++ /dev/null @@ -1,218 +0,0 @@ -# -*- mode: python; -*- -#============================================================================ -# Example Python setup script for 'xm create'. -# This script sets the parameters used when a domain is created using 'xm create'. -# -# This is a relatively advanced script that uses a parameter, vmid, to control -# the settings. So this script can be used to start a set of domains by -# setting the vmid parameter on the 'xm create' command line. For example: -# -# xm create vmid=1 -# xm create vmid=2 -# xm create vmid=3 -# -# The vmid is purely a script variable, and has no effect on the the domain -# id assigned to the new domain. -#============================================================================ - -# Define script variables here. -# xm_vars is defined automatically, use xm_vars.var() to define a variable. - -# This function checks that 'vmid' has been given a valid value. -# It is called automatically by 'xm create'. -def vmid_check(var, val): - val = int(val) - if val <= 0: - raise ValueError - return val - -# Define the 'vmid' variable so that 'xm create' knows about it. -xm_vars.var('vmid', - use="Virtual machine id. Integer greater than 0.", - check=vmid_check) - -# Check the defined variables have valid values.. -xm_vars.check() - -#---------------------------------------------------------------------------- -# Kernel image file. -kernel = "/path/to/domU/kernel" - -# Optional ramdisk. -#ramdisk = "/boot/initrd.gz" - -# The domain build function. Default is 'linux'. -#builder='linux' - -# Initial memory allocation (in megabytes) for the new domain. -# -# WARNING: Creating a domain with insufficient memory may cause out of -# memory errors. The domain needs enough memory to boot kernel -# and modules. Allocating less than 32MBs is not recommended. -memory = 64 - -# A name for the new domain. All domains have to have different names, -# so we use the vmid to create a name. -name = "VM%d" % vmid - -# 128-bit UUID for the domain. The default behavior is to generate a new UUID -# on each call to 'xm create'. -#uuid = "06ed00fe-1162-4fc4-b5d8-11993ee4a8b9" - -# List of which CPUS this domain is allowed to use, default Xen picks -#cpus = "" # leave to Xen to pick -#cpus = "0" # all vcpus run on CPU0 -#cpus = "0-3,5,^1" # all vcpus run on cpus 0,2,3,5 -#cpus = ["2", "3"] # VCPU0 runs on CPU2, VCPU1 runs on CPU3 -cpus = "%s" % vmid # set based on vmid (mod number of CPUs) - -#---------------------------------------------------------------------------- -# Define network interfaces. - -# Optionally define mac and/or bridge for the network interfaces. -# Random MACs are assigned if not given. - -vif = [ 'ip=192.168.%d.1/24' % (vmid)] - -#---------------------------------------------------------------------------- -# Define the disk devices you want the domain to have access to, and -# what you want them accessible as. -# Each disk entry is of the form phy:UNAME,DEV,MODE -# where UNAME is the device, DEV is the device name the domain will see, -# and MODE is r for read-only, w for read-write. - -# This makes the disk device depend on the vmid - assuming -# tHat devices sda7, sda8 etc. exist. The device is exported -# to all domains as sda1. -# All domains get sda6 read-only (to use for /usr, see below). -disk = [ 'phy:hda%d,hda1,w' % (vmid)] - -#---------------------------------------------------------------------------- -# Define frame buffer device. -# -# By default, no frame buffer device is configured. -# -# To create one using the SDL backend and sensible defaults: -# -# vfb = [ 'sdl=1' ] -# -# This uses environment variables XAUTHORITY and DISPLAY. You -# can override that: -# -# vfb = [ 'sdl=1,xauthority=/home/bozo/.Xauthority,display=:1' ] -# -# To create one using the VNC backend and sensible defaults: -# -# vfb = [ 'vnc=1' ] -# -# The backend listens on 127.0.0.1 port 5900+N by default, where N is -# the domain ID. You can override both address and N: -# -# vfb = [ 'vnc=1,vnclisten=127.0.0.1,vncdisplay=%d' % vmid ] -# -# Or you can bind the first unused port above 5900: -# -# vfb = [ 'vnc=1,vnclisten=0.0.0.0,vncunused=1' ] -# -# You can override the password: -# -# vfb = [ 'vnc=1,vncpasswd=MYPASSWD' ] -# -# Empty password disables authentication. Defaults to the vncpasswd -# configured in xend-config.sxp. - -#---------------------------------------------------------------------------- -# Set the kernel command line for the new domain. -# You only need to define the IP parameters and hostname if the domain's -# IP config doesn't, e.g. in ifcfg-eth0 or via DHCP. -# You can use 'extra' to set the runlevel and custom environment -# variables used by custom rc scripts (e.g. VMID=, usr= ). - -# Set if you want dhcp to allocate the IP address. -dhcp="off" -ip="192.168.%d.2" % (vmid) -# Set netmask. -netmask="255.255.255.0" -# Set default gateway. -gateway="192.168.%d.1" % (vmid) -# Set the hostname. -hostname= "domain-%d.xeno" % vmid - -# Set root device. -root = "/dev/hda1 ro" - -# Root device for nfs. -#root = "/dev/nfs" -# The nfs server. -#nfs_server = "10.212.4.103" -# Root directory on the nfs server. -#nfs_root = "/path/to/root/filesystem" - -# Sets runlevel 4 and the device for /usr. -extra = "4 VMID=%d" % vmid - -#---------------------------------------------------------------------------- -# Configure the behaviour when a domain exits. There are three 'reasons' -# for a domain to stop: poweroff, reboot, and crash. For each of these you -# may specify: -# -# "destroy", meaning that the domain is cleaned up as normal; -# "restart", meaning that a new domain is started in place of the old -# one; -# "preserve", meaning that no clean-up is done until the domain is -# manually destroyed (using xm destroy, for example); or -# "rename-restart", meaning that the old domain is not cleaned up, but is -# renamed and a new domain started in its place. -# -# In the event a domain stops due to a crash, you have the additional options: -# -# "coredump-destroy", meaning dump the crashed domain's core and then destroy; -# "coredump-restart', meaning dump the crashed domain's core and the restart. -# -# The default is -# -# on_poweroff = 'destroy' -# on_reboot = 'restart' -# on_crash = 'restart' -# -# For backwards compatibility we also support the deprecated option restart -# -# restart = 'onreboot' means on_poweroff = 'destroy' -# on_reboot = 'restart' -# on_crash = 'destroy' -# -# restart = 'always' means on_poweroff = 'restart' -# on_reboot = 'restart' -# on_crash = 'restart' -# -# restart = 'never' means on_poweroff = 'destroy' -# on_reboot = 'destroy' -# on_crash = 'destroy' - -#on_poweroff = 'destroy' -#on_reboot = 'restart' -#on_crash = 'restart' - -#----------------------------------------------------------------------------- -# Configure PVSCSI devices: -# -#vscsi=[ 'PDEV, VDEV' ] -# -# PDEV gives physical SCSI device to be attached to specified guest -# domain by one of the following identifier format. -# - XX:XX:XX:XX (4-tuples with decimal notation which shows -# "host:channel:target:lun") -# - /dev/sdxx or sdx -# - /dev/stxx or stx -# - /dev/sgxx or sgx -# - result of 'scsi_id -gu -s'. -# ex. # scsi_id -gu -s /block/sdb -# 36000b5d0006a0000006a0257004c0000 -# -# VDEV gives virtual SCSI device by 4-tuples (XX:XX:XX:XX) as -# which the specified guest domain recognize. -# - -#vscsi = [ '/dev/sdx, 0:0:0:0' ] - -#============================================================================ diff --git a/tools/hotplug/Linux/Makefile b/tools/hotplug/Linux/Makefile index 47655f691a..a14cb42d4f 100644 --- a/tools/hotplug/Linux/Makefile +++ b/tools/hotplug/Linux/Makefile @@ -2,7 +2,6 @@ XEN_ROOT = $(CURDIR)/../../.. include $(XEN_ROOT)/tools/Rules.mk # Init scripts. -XEND_INITD = init.d/xend XENDOMAINS_INITD = init.d/xendomains XENDOMAINS_SYSCONFIG = init.d/sysconfig.xendomains @@ -30,7 +29,6 @@ XEN_SCRIPT_DATA += xen-hotplug-common.sh xen-network-common.sh vif-common.sh XEN_SCRIPT_DATA += block-common.sh UDEV_RULES_DIR = $(CONFIG_DIR)/udev -UDEV_RULES-$(CONFIG_XEND) = xend.rules UDEV_RULES = xen-backend.rules $(UDEV_RULES-y) .PHONY: all @@ -47,9 +45,6 @@ install: all install-initd install-scripts install-udev install-initd: [ -d $(DESTDIR)$(INITD_DIR) ] || $(INSTALL_DIR) $(DESTDIR)$(INITD_DIR) [ -d $(DESTDIR)$(SYSCONFIG_DIR) ] || $(INSTALL_DIR) $(DESTDIR)$(SYSCONFIG_DIR) -ifeq ($(CONFIG_XEND),y) - $(INSTALL_PROG) $(XEND_INITD) $(DESTDIR)$(INITD_DIR) -endif $(INSTALL_PROG) $(XENDOMAINS_INITD) $(DESTDIR)$(INITD_DIR) $(INSTALL_DATA) $(XENDOMAINS_SYSCONFIG) $(DESTDIR)$(SYSCONFIG_DIR)/xendomains $(INSTALL_PROG) $(XENCOMMONS_INITD) $(DESTDIR)$(INITD_DIR) diff --git a/tools/hotplug/Linux/init.d/xend b/tools/hotplug/Linux/init.d/xend deleted file mode 100755 index 8921383f1b..0000000000 --- a/tools/hotplug/Linux/init.d/xend +++ /dev/null @@ -1,82 +0,0 @@ -#!/bin/bash -# -# xend Script to start and stop the Xen control daemon. -# -# Author: Keir Fraser -# -# chkconfig: 2345 98 01 -# description: Starts and stops the Xen control daemon. -### BEGIN INIT INFO -# Provides: xend -# Required-Start: $syslog $remote_fs xenstored xenconsoled -# Should-Start: -# Required-Stop: $syslog $remote_fs xenstored xenconsoled -# Should-Stop: -# Default-Start: 2 3 5 -# Default-Stop: 0 1 6 -# Short-Description: Start/stop xend -# Description: Starts and stops the Xen control daemon. -### END INIT INFO - -. /etc/xen/scripts/hotplugpath.sh - -shopt -s extglob - -# Wait for Xend to be up -function await_daemons_up -{ - i=1 - rets=10 - ${SBINDIR}/xend status - while [ $? -ne 0 -a $i -lt $rets ]; do - sleep 1 - echo -n . - i=$(($i + 1)) - ${SBINDIR}/xend status - done -} - -case "$1" in - start) - echo "WARNING: Enabling the xend toolstack." - echo "xend is deprecated and scheduled for removal. Please migrate" - echo "to another toolstack ASAP." - - if [ -z "`ps -C xenconsoled -o pid=`" ]; then - echo "xencommons should be started first." - exit 1 - fi - # mkdir shouldn't be needed as most distros have this already created. Default to using subsys. - # See docs/misc/distro_mapping.txt - mkdir -p /var/lock - if [ -d /var/lock/subsys ] ; then - touch /var/lock/subsys/xend - else - touch /var/lock/xend - fi - ${SBINDIR}/xend start - await_daemons_up - ;; - stop) - ${SBINDIR}/xend stop - rm -f /var/lock/subsys/xend /var/lock/xend - ;; - status) - ${SBINDIR}/xend status - ;; - reload) - ${SBINDIR}/xend reload - ;; - restart|force-reload) - ${SBINDIR}/xend restart - await_daemons_up - ;; - *) - # do not advertise unreasonable commands that there is no reason - # to use with this device - echo $"Usage: $0 {start|stop|status|restart|reload|force-reload}" - exit 1 -esac - -exit $? - diff --git a/tools/hotplug/Linux/xend.rules b/tools/hotplug/Linux/xend.rules deleted file mode 100644 index 4d79ac0c99..0000000000 --- a/tools/hotplug/Linux/xend.rules +++ /dev/null @@ -1,4 +0,0 @@ -SUBSYSTEM=="pci", RUN+="socket:/org/xen/xend/udev_event" -SUBSYSTEM=="scsi", RUN+="socket:/org/xen/xend/udev_event" -SUBSYSTEM=="usb", RUN+="socket:/org/xen/xend/udev_event" -#SUBSYSTEM=="net", KERNEL!="vif[0-9]*.[0-9]*|tap[0-9]*.[0-9]*", RUN+="socket:/org/xen/xend/udev_event" diff --git a/tools/hotplug/NetBSD/Makefile b/tools/hotplug/NetBSD/Makefile index 3d7f2222c9..fc61162df8 100644 --- a/tools/hotplug/NetBSD/Makefile +++ b/tools/hotplug/NetBSD/Makefile @@ -8,8 +8,7 @@ XEN_SCRIPTS += vif-bridge XEN_SCRIPTS += vif-ip XEN_SCRIPT_DATA = -XEN_RCD_PROG-$(CONFIG_XEND) = rc.d/xend -XEN_RCD_PROG = rc.d/xencommons $(XEN_RCD_PROG-y) rc.d/xendomains rc.d/xen-watchdog +XEN_RCD_PROG = rc.d/xencommons rc.d/xendomains rc.d/xen-watchdog .PHONY: all all: diff --git a/tools/hotplug/NetBSD/rc.d/xend b/tools/hotplug/NetBSD/rc.d/xend deleted file mode 100644 index ac5f2ca1d8..0000000000 --- a/tools/hotplug/NetBSD/rc.d/xend +++ /dev/null @@ -1,71 +0,0 @@ -#!/bin/sh -# -# PROVIDE: xend -# REQUIRE: xencommons - -. /etc/rc.subr - -DIR=$(dirname "$0") -. "${DIR}/xen-hotplugpath.sh" - -LD_LIBRARY_PATH="${LIBDIR}" -export LD_LIBRARY_PATH PYTHONPATH -PATH="${PATH}:${SBINDIR}" -export PATH - -name="xend" -rcvar=$name -start_precmd="xend_precmd" -start_cmd="xend_startcmd" -stop_cmd="xend_stop" -status_cmd="xend_status" -extra_commands="status" -required_files="/kern/xen/privcmd" - -XENBACKENDD_PIDFILE="/var/run/xenbackendd.pid" -#XENBACKENDD_DEBUG=1 - -xend_precmd() -{ - mkdir -p /var/run/xend || exit 1 - mkdir -p /var/run/xend/boot || exit 1 -} - -xend_startcmd() -{ - printf "Starting xenbackendd.\n" - - XENBACKENDD_ARGS="" - if [ -n "${XENBACKENDD_DEBUG}" ]; then - XENBACKENDD_ARGS="${XENBACKENDD_ARGS} -d" - fi - - ${SBINDIR}/xenbackendd ${XENBACKENDD_ARGS} - - printf "Starting xend.\n" - ${SBINDIR}/xend start >/dev/null 2>&1 -} - -xend_stop() -{ - printf "Stopping xenbackendd, xend\n" - xb_pid=$(check_pidfile ${XENBACKENDD_PIDFILE} ${SBINDIR}/xenbackendd) - if test -n "$xb_pid"; - then - kill -${sig_stop:-TERM} $xb_pid - fi - while pgrep -f ${SBINDIR}/xend >/dev/null 2>&1; do - pkill -${sig_stop:-KILL} -f ${SBINDIR}/xend - done - wait_for_pids $xb_pid - rm -f /var/lock/subsys/xend /var/lock/xend /var/run/xenbackendd.pid -} - -xend_status() -{ - ${SBINDIR}/xend status -} - -load_rc_config $name -run_rc_command "$1" - diff --git a/tools/libxl/xl.c b/tools/libxl/xl.c index 527b4c5965..4c5a5ee472 100644 --- a/tools/libxl/xl.c +++ b/tools/libxl/xl.c @@ -33,8 +33,6 @@ #include "libxlutil.h" #include "xl.h" -#define XEND_LOCK { "/var/lock/subsys/xend", "/var/lock/xend" } - xentoollog_logger_stdiostream *logger; int dryrun_only; int force_execution; @@ -299,7 +297,6 @@ int main(int argc, char **argv) int ret; void *config_data = 0; int config_len = 0; - const char *locks[] = XEND_LOCK; while ((opt = getopt(argc, argv, "+vftN")) >= 0) { switch (opt) { @@ -357,19 +354,6 @@ int main(int argc, char **argv) ret = 1; goto xit; } - if (cspec->modifies && !dryrun_only) { - for (int i = 0; i < sizeof(locks)/sizeof(locks[0]); i++) { - if (!access(locks[i], F_OK) && !force_execution) { - fprintf(stderr, -"xend is running, which may cause unpredictable results when using\n" -"this xl command. Please shut down xend before continuing.\n\n" -"(This check can be overridden with the -f option.)\n" - ); - ret = 1; - goto xit; - } - } - } ret = cspec->cmd_impl(argc, argv); } else if (!strcmp(cmd, "help")) { help(argv[1]); diff --git a/tools/python/Makefile b/tools/python/Makefile index 3d0f8f0678..74ed027460 100644 --- a/tools/python/Makefile +++ b/tools/python/Makefile @@ -16,26 +16,14 @@ build: genpath genwrap.py $(XEN_ROOT)/tools/libxl/libxl_types.idl \ $(XEN_ROOT)/tools/libxl/libxl_types.idl \ xen/lowlevel/xl/_pyxl_types.h \ xen/lowlevel/xl/_pyxl_types.c - CC="$(CC)" CFLAGS="$(CFLAGS)" $(PYTHON) setup.py build --xend=$(CONFIG_XEND) + CC="$(CC)" CFLAGS="$(CFLAGS)" $(PYTHON) setup.py build .PHONY: install -install: install-dtd +install: CC="$(CC)" CFLAGS="$(CFLAGS)" $(PYTHON) setup.py install \ - $(PYTHON_PREFIX_ARG) --root="$(DESTDIR)" --force --xend=$(CONFIG_XEND) + $(PYTHON_PREFIX_ARG) --root="$(DESTDIR)" --force $(INSTALL_DIR) $(DESTDIR)$(SBINDIR) -ifeq ($(CONFIG_XEND),y) - $(INSTALL_PYTHON_PROG) xen/xm/xm $(DESTDIR)$(SBINDIR)/xm - $(INSTALL_PYTHON_PROG) xen/xend/xend $(DESTDIR)$(SBINDIR)/xend -endif - -install-dtd: all -ifeq ($(CONFIG_XEND),y) - $(INSTALL_DIR) $(DESTDIR)$(SHAREDIR)/xen - $(INSTALL_DATA) xen/xm/create.dtd $(DESTDIR)$(SHAREDIR)/xen -else - : -endif .PHONY: test test: diff --git a/tools/python/logging/logging-0.4.9.2/PKG-INFO b/tools/python/logging/logging-0.4.9.2/PKG-INFO deleted file mode 100644 index 6f7ee38e83..0000000000 --- a/tools/python/logging/logging-0.4.9.2/PKG-INFO +++ /dev/null @@ -1,25 +0,0 @@ -Metadata-Version: 1.0 -Name: logging -Version: 0.4.9.2 -Summary: A logging module for Python -Home-page: http://www.red-dove.com/python_logging.html -Author: Vinay Sajip -Author-email: vinay_sajip@red-dove.com -License: Copyright (C) 2001-2004 by Vinay Sajip. All Rights Reserved. - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Vinay Sajip -not be used in advertising or publicity pertaining to distribution -of the software without specific, written prior permission. - -VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN -AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -Description: This module is intended to provide a standard error logging mechanism in Python as per PEP 282. -Platform: UNKNOWN diff --git a/tools/python/logging/logging-0.4.9.2/README.txt b/tools/python/logging/logging-0.4.9.2/README.txt deleted file mode 100644 index 3d38889629..0000000000 --- a/tools/python/logging/logging-0.4.9.2/README.txt +++ /dev/null @@ -1,311 +0,0 @@ -This module is intended to provide error logging functionality for Python -programs. It aims to be aligned with Python Enhancement Proposal (PEP) 282. - -For more information on the package itself, see python_logging.html. In it, -there is a description of each file in the distribution. -You can also use pydoc to browse the interfaces. - -Change History --------------- - -Version Date Description -============================================================================= -0.4.9.2 28 Feb 2004 Traceback text is now cached. - Tracebacks can be propagated across sockets as text. - Added makeLogRecord() to allow a LogRecord to be - created from a dictionary. - Closing a handler now removes it from the internal list - used by shutdown(). - Made close() call flush() for handlers where this makes - sense (thanks to Jim Jewett). - The exc_info keyword parameter can be used to pass an - exception tuple as well as a flag indicating that the - current exception should be logged. - A shutdown hook is registered to call shutdown() on - application (Python) exit (thanks to Jim Jewett). - Removed redundant error check in setLoggerClass(). - Added RESET_ERROR to logging.config. - SocketHandler now uses an exponential backoff strategy - (thanks to Robert Olson). - Minor documentation corrections. ------------------------------------------------------------------------------ -0.4.8 22 Apr 2003 Made _listener global in stopListening(). - Made listen() correctly pass the specified port. - Removed some redundant imports in __init__.py. - Added the record being processed as a parameter to - handleError (thanks to Gordon den Otter for the idea). - Handler.handle returns the result of applying the - filter to the record (thanks to Gordon den Otter for - the idea). - Added a seek(0, 2) in RotatingFileHandler before the - tell() call. This is because under Windows, tell() - returns 0 until the first actual write (thanks to - Gordon den Otter for the patch). - Altered findCaller to not use inspect (thanks to - Jeremy Hylton for the patch). - Renamed warn and WARN to warning and WARNING. This may - break existing code, but the standard Python module - will use warning/WARNING rather than warn/WARN. The - fatal and FATAL synonyms for critical and CRITICAL - have also been removed. - Added defaultEncoding and some support for encoding - Unicode messages (thanks to Stéphane Bidoul for the - suggestion). - Added process ID to the list of LogRecord attributes. - Modified Logger.removeHandler so that it does not - close the handler on removal. - Modified SMTPHandler to treat a single "to address" - correctly (thanks to Anthony Baxter). - Modified SMTPHandler to add a date header to the SMTP - message (thanks to David Driver for the suggestion). - Modified HTTPHandler to factor out the mapping of - a LogRecord to a dictionary (thanks to Franz Glasner - for the patch). ------------------------------------------------------------------------------ -0.4.7 15 Nov 2002 Made into a package with three modules: __init__ (the - core code), handlers (all handlers other than - FileHandler and its bases) and config (all the config - stuff). Before doing this: - Updated docstrings to include a short line, then a - blank line, then more descriptive text. - Renamed 'lvl' to 'level' in various functions. - Changed FileHandler to use "a" and "w" instead of "a+" - and "w+". - Moved log file rotation functionality from FileHandler - to a new class RotatingFileHandler. - Improved docstring describing rollover. - Updated makePickle to use 4-byte length and struct - module, likewise logrecv.py. Also updated on-the-fly - config reader to use 4-byte length/struct module. - Altered ConfigParser test to look at 'readline' rather - than 'read'. - Added optional "defaults" argument to fileConfig, to - be passed to ConfigParser. - Renamed ALL to NOTSET to avoid confusion. - Commented out getRootLogger(), as obsolete. - To do regression testing, run log_test.py and compare - the created files stdout.log and stderr.log against - the files stdout.exp and stderr.exp. They should match - except fir a couple of exception messages which give - absolute file paths. - Updated python_logging.html to remove links to - logging_pydoc.html, which has been removed from the - distribution. - Changed default for raiseExceptions to 1. ------------------------------------------------------------------------------ -0.4.6 08 Jul 2002 Added raiseExceptions to allow conditional propagation - of exceptions which occur during handling. - Added converter to Formatter to allow use of any - function to convert time from seconds to a tuple. It - still defaults to time.localtime but now you can also - use time.gmtime. - Added log_test22.py to test the conversion feature. - Changed rootlogger default level to WARN - was DEBUG. - Updated some docstrings. - Moved import of threading to where thread is imported. - If either is unavailable, threading support is off. - Updated minor defects in python_logging.html. - Check to see if ConfigParser has readfp method; if it - does and an object with a 'read' method is passed in, - assumes a file-like object and uses readfp to read it - in. ------------------------------------------------------------------------------ -0.4.5 04 Jun 2002 Fixed bug which caused problem if no args to message - (suggested by Hye-Shik Chang). - Fixed bug in _fixupParents (thanks to Nicholas Veeser) - and added log_test19.py as a test case for this bug. - Added getMessage to LogRecord (code was moved here from - Formatter.format) - Applied str() to record.msg to allow arbitrary classes - to determine the formatting (as msg can now be a class - instance). - Table of Contents added to python_logging.html, the - section on Loggers updated, and the logconf.ini file - section annotated. - Added log_test20.py which demonstrates how to use - class instances to provide alternatives to numeric - severities as mechanisms for control of logging. - Added log_test21.py which builds on log_test20.py to - show how you can use a regular expression-based Filter - for flexible matching similar to e.g. Protomatter - Syslog, where you can filter on e.g. "a.*" or "*.b" or - "a.*.c". - _levelNames changed to contain reverse mappings as well - as forward mappings (leveltext->level as well as level - -> leveltext). The reverse mappings are used by - fileConfig(). - fileConfig() now more forgiving of missing options in - .ini file - sensible defaults now used when some - options are absent. Also, eval() is used less when - interpreting .ini file contents - int() and dict lookup - are used in more places. ------------------------------------------------------------------------------ -0.4.4 02 May 2002 getEffectiveLevel() returns ALL instead of None when - nothing found. Modified references to level=0 to - level=ALL in a couple of places. - SocketHandler now inherits from Handler (it used to - inherit from StreamHandler, for no good reason). - getLock() renamed to createLock(). - Docstring tidy-ups, and some tidying up of - DatagramHandler. - Factored out unpickling in logrecv.py. - Added log_test18.py to illustrate MatchFilter, which is - a general matching filter. - Improved FileHandler.doRollover() so that the base - file name is always the most recent, then .1, then .2 - etc. up to the maximum backup count. Renamed formal - args and attributes used in rollover. - Changed LogRecord attributes lvl -> levelno, level -> - levelname (less ambiguity) - Formatter.format searches for "%(asctime)" rather than - "(asctime)" - Renamed _start_time to _startTime - Formatter.formatTime now returns the time - Altered logrecv.py to support stopping servers - programmatically - Added log_test.py as overall test harness - basicConfig() can now be safely called more than once - Modified test scripts to make it easier to call them - from log_test.py - Moved SOAPHandler from core to log_test13.py. It's not - general enough to be in the core; most production use - will have differing RPC signatures. ------------------------------------------------------------------------------ -0.4.3 14 Apr 2002 Bug fix one-off error message to go to sys.stderr - rather than sys.stdout. - logrecv.py fix TCP for busy network. - Thread safety - added locking to Handler and for shared - data in module, and log_test16.py to test it. - Added socket listener to allow on-the-fly configuration - and added log_test17.py to test it. ------------------------------------------------------------------------------ -0.4.2 11 Apr 2002 Bug fix fileConfig() - setup of MemoryHandler target - and errors when loggers have no handlers set or - handlers have no formatters set - logconf.py - seems to hang if window closed when combo - dropdown is showing - added code to close popup on exit - Some tweaks to _srcfile computation (normpath added) - findCaller() optimized, now a lot faster! - Logger.removeHandler now closes the handler before - removing it - fileConfig() removes existing handlers before adding - the new set, to avoid memory leakage when repeated - calls are made - Fixed logrecv.py bug which hogged CPU time when TCP - connection was closed from the client - Added log_test14.py to demonstrate/test a DBHandler - which writes logging records into an RDBMS using the - Python Database API 2.0 (to run, you need something - which supports this already installed - I tested with - mxODBC) - Made getLogger name argument optional - returns root - logger if omitted - Altered Filter to take a string initializer, filtering - a sub-hierarchy rooted at a particular point (idea from - Denis S. Otkidach). - Added log_test15.py to test Filter initializer - Minor docstring changes ------------------------------------------------------------------------------ -0.4.1 03 Apr 2002 Bug fix SMTPHandler - extra \r\n needed (Oleg Orlov) - Added BufferingHandler, BufferingFormatter - Renamed getChainedPriority to getEffectiveLevel - Removed Logger.getRoot as it is redundant - Added log_test9.py to test Buffering classes and - to show an XMLFormatter example. - Added setLoggerClass. - Added log_test10.py to test setLoggerClass, using an - example Logger-derived class which outputs exception - info even for DEBUG level logging calls - Added log_test11.py to test a buffering implementation - of SMTPHandler - Changed logging call implementation to allow keyword - arguments (Kevin Butler and others) - Changed default SysLogHandler implementation. - Renamed "additive" to "propagate" as it better - describes the attribute. - Added HTTPHandler. - Modified logrecv.py to remove "both" option and to add - "HTTP" and "SOAP" options (SOAP option needs you to - have PyXML-0.6.6 and ZSI installed - for logrecv.py - only, and not for the core logging module itself). - Added log_test12.py to test HTTPHandler. - Added log_test13.py to test SOAPHandler. - Formatted to Python source guidelines (spaces, indent - of 4, within 80 columns). - More method renamings (result of feedback) - _handle() - renamed to emit(), _logRecord() renamed to handle(). - Renamed FATAL to CRITICAL (David Goodger), but left - fatal() and FATAL in (until PEP is changed) - Changed configuration file format to ConfigParser - format. - Factored filter application functionality out to a new - Filterer class. The isLoggable() method is renamed to - filter() in both Filter and Filterer classes. - Altered SMTPHandler __init__ to accept (host, port) - for the mail internet address. - Added GUI configurator which uses Tkinter and the new - configuration file format. (See logconf.py and an - example configuration file in logconf.ini) - Altered log_test3.py to test with the new file format. ------------------------------------------------------------------------------ -0.4 21 Mar 2002 Incorporated comments/patches from Ollie Rutherfurd: - -Added level filtering for handlers. - -Return root logger if no name specified in getLogger. - Incorporated comments from Greg Ward: - -Added distutils setup.py script. - Added formatter initialization in Handler.__init__. - Tidied up docstrings. - Added removeHandler to Logger. - Added removeFilter to Logger and Handler. - logrecv.py modified to keep connection alive until - client closes it. - SocketHandler modified to not reset connection after - each logging event. - Added shutdown function which closes open sockets - Renamed DEFAULT_LOGGING_PORT->DEFAULT_TCP_LOGGING_PORT - Added DEFAULT_UDP_LOGGING_PORT - Added log_test4.py (example of arbitrary levels) - Added addLevelName, changed behaviour of getLevelName - Fixed bugs in DatagramHandler - Added SMTPHandler implementation - Added log_test5.py to test SMTPHandler - Added SysLogHandler (contribution from Nicolas Untz - based on Sam Rushing's syslog.py) - Modified log_test1.py to add a SysLogHandler - Added rollover functionality to FileHandler - Added NTEventLogHandler (based on Win32 extensions) - Added MemoryHandler implementation - Added log_test7.py to test MemoryHandler - Added log_test8.py to test FileHandler rollover - Added logException method to Logger - Added formatException method to Formatter - Added log_test6.py to test NTEventHandler and - logException - Numerous internal method renamings (sorry - but better - to do this now, rather than when we enter beta status). ------------------------------------------------------------------------------ -0.3 14 Mar 2002 First public release, for early feedback ------------------------------------------------------------------------------ -0.2 Consolidated into single file (for internal use only) ------------------------------------------------------------------------------ -0.1 Initial implementation (for internal use only) ------------------------------------------------------------------------------ - ------------------------------------------------------------------------------ -COPYRIGHT ------------------------------------------------------------------------------ -Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Vinay Sajip -not be used in advertising or publicity pertaining to distribution -of the software without specific, written prior permission. -VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN -AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/tools/python/logging/logging-0.4.9.2/default.css b/tools/python/logging/logging-0.4.9.2/default.css deleted file mode 100644 index 0c7ce5b7b0..0000000000 --- a/tools/python/logging/logging-0.4.9.2/default.css +++ /dev/null @@ -1,32 +0,0 @@ -BODY, P, UL, OL {font-family: Verdana, Arial, Helvetica, Geneva, sans-serif ; background: white; color: black; font-size: 10pt; } -CODE {font-family: "Courier New", Courier, Monaco, monospace ; } -PRE {font-family: "Courier New", Courier, Monaco, monospace ; } -.program { color: navy; font-family: "Courier New", Courier, Monaco, monospace } -.output { color: maroon } -HR {color: gray ; } -.navbar { font-family: Verdana, Arial, Helvetica, Geneva, sans-serif; background: #FFFF66 ; border-style: none none solid none; border-width: thin; padding: 2px;} -.navarea { background: #FFFF66 ; } -TR { font-size: 10pt } -.red { color: #FF0000 } -.maroon { color: #800000 } -.comment { color: green } -.optional { color: silver } -.strong { font-weight: bold } -TR.tblheading { background: silver ; } -.notrecommended {color: #666666 ; } -.deemphasized {color: #666666 ; } -TABLE.densetable {font-size: 80% ; } -TH { text-align: left; background: silver } -TR.summaryrow { font-size: 90%; background: #00FFFF ; } -CAPTION {font-size: 100% ; } -.embeddedfloat {float: right; margin-left: 3em} -.bigtd { font-size: 18pt } -TD, .normaltd { vertical-align: top; background: #EEEEEE; font-family: Verdana, Arial, Helvetica, Geneva, sans-serif; font-size: 10pt } -H1, H2, H3, H4, H5, H6 {font-family: Verdana, Arial, Helvetica, Geneva, sans-serif ; } -H4 {margin-bottom: 0.5em } -H5, H6 {margin-bottom: 0.1em } -A:link {color: blue ; } -A:visited {color: purple ; } -A:active {color: red ; } -A { font-family: Verdana, Arial, Helvetica, Geneva, sans-serif; font-size: 10pt } -.warning { color: red } \ No newline at end of file diff --git a/tools/python/logging/logging-0.4.9.2/liblogging.tex b/tools/python/logging/logging-0.4.9.2/liblogging.tex deleted file mode 100644 index bc39ab21fb..0000000000 --- a/tools/python/logging/logging-0.4.9.2/liblogging.tex +++ /dev/null @@ -1,1281 +0,0 @@ -\section{\module{logging} --- - Logging facility for Python} - -\declaremodule{standard}{logging} - -% These apply to all modules, and may be given more than once: - -\moduleauthor{Vinay Sajip}{vinay_sajip@red-dove.com} -\sectionauthor{Vinay Sajip}{vinay_sajip@red-dove.com} - -\modulesynopsis{Logging module for Python based on \pep{282}.} - -\indexii{Errors}{logging} - -\versionadded{2.3} -This module defines functions and classes which implement a flexible -error logging system for applications. - -Logging is performed by calling methods on instances of the -\class{Logger} class (hereafter called \dfn{loggers}). Each instance has a -name, and they are conceptually arranged in a name space hierarchy -using dots (periods) as separators. For example, a logger named -"scan" is the parent of loggers "scan.text", "scan.html" and "scan.pdf". -Logger names can be anything you want, and indicate the area of an -application in which a logged message originates. - -Logged messages also have levels of importance associated with them. -The default levels provided are \constant{DEBUG}, \constant{INFO}, -\constant{WARNING}, \constant{ERROR} and \constant{CRITICAL}. As a -convenience, you indicate the importance of a logged message by calling -an appropriate method of \class{Logger}. The methods are -\method{debug()}, \method{info()}, \method{warning()}, \method{error()} and -\method{critical()}, which mirror the default levels. You are not -constrained to use these levels: you can specify your own and use a -more general \class{Logger} method, \method{log()}, which takes an -explicit level argument. - -Levels can also be associated with loggers, being set either by the -developer or through loading a saved logging configuration. When a -logging method is called on a logger, the logger compares its own -level with the level associated with the method call. If the logger's -level is higher than the method call's, no logging message is actually -generated. This is the basic mechanism controlling the verbosity of -logging output. - -Logging messages are encoded as instances of the \class{LogRecord} class. -When a logger decides to actually log an event, an \class{LogRecord} -instance is created from the logging message. - -Logging messages are subjected to a dispatch mechanism through the -use of \dfn{handlers}, which are instances of subclasses of the -\class{Handler} class. Handlers are responsible for ensuring that a logged -message (in the form of a \class{LogRecord}) ends up in a particular -location (or set of locations) which is useful for the target audience for -that message (such as end users, support desk staff, system administrators, -developers). Handlers are passed \class{LogRecord} instances intended for -particular destinations. Each logger can have zero, one or more handlers -associated with it (via the \method{addHandler} method of \class{Logger}). -In addition to any handlers directly associated with a logger, -\emph{all handlers associated with all ancestors of the logger} are -called to dispatch the message. - -Just as for loggers, handlers can have levels associated with them. -A handler's level acts as a filter in the same way as a logger's level does. -If a handler decides to actually dispatch an event, the \method{emit()} method -is used to send the message to its destination. Most user-defined subclasses -of \class{Handler} will need to override this \method{emit()}. - -In addition to the base \class{Handler} class, many useful subclasses -are provided: - -\begin{enumerate} - -\item \class{StreamHandler} instances send error messages to -streams (file-like objects). - -\item \class{FileHandler} instances send error messages to disk -files. - -\item \class{RotatingFileHandler} instances send error messages to disk -files, with support for maximum log file sizes and log file rotation. - -\item \class{SocketHandler} instances send error messages to -TCP/IP sockets. - -\item \class{DatagramHandler} instances send error messages to UDP -sockets. - -\item \class{SMTPHandler} instances send error messages to a -designated email address. - -\item \class{SysLogHandler} instances send error messages to a -\UNIX{} syslog daemon, possibly on a remote machine. - -\item \class{NTEventLogHandler} instances send error messages to a -Windows NT/2000/XP event log. - -\item \class{MemoryHandler} instances send error messages to a -buffer in memory, which is flushed whenever specific criteria are -met. - -\item \class{HTTPHandler} instances send error messages to an -HTTP server using either \samp{GET} or \samp{POST} semantics. - -\end{enumerate} - -The \class{StreamHandler} and \class{FileHandler} classes are defined -in the core logging package. The other handlers are defined in a sub- -module, \module{logging.handlers}. (There is also another sub-module, -\module{logging.config}, for configuration functionality.) - -Logged messages are formatted for presentation through instances of the -\class{Formatter} class. They are initialized with a format string -suitable for use with the \% operator and a dictionary. - -For formatting multiple messages in a batch, instances of -\class{BufferingFormatter} can be used. In addition to the format string -(which is applied to each message in the batch), there is provision for -header and trailer format strings. - -When filtering based on logger level and/or handler level is not enough, -instances of \class{Filter} can be added to both \class{Logger} and -\class{Handler} instances (through their \method{addFilter()} method). -Before deciding to process a message further, both loggers and handlers -consult all their filters for permission. If any filter returns a false -value, the message is not processed further. - -The basic \class{Filter} functionality allows filtering by specific logger -name. If this feature is used, messages sent to the named logger and its -children are allowed through the filter, and all others dropped. - -In addition to the classes described above, there are a number of module- -level functions. - -\begin{funcdesc}{getLogger}{\optional{name}} -Return a logger with the specified name or, if no name is specified, return -a logger which is the root logger of the hierarchy. - -All calls to this function with a given name return the same logger instance. -This means that logger instances never need to be passed between different -parts of an application. -\end{funcdesc} - -\begin{funcdesc}{debug}{msg\optional{, *args\optional{, **kwargs}}} -Logs a message with level \constant{DEBUG} on the root logger. -The \var{msg} is the message format string, and the \var{args} are the -arguments which are merged into \var{msg}. The only keyword argument in -\var{kwargs} which is inspected is \var{exc_info} which, if it does not -evaluate as false, causes exception information (via a call to -\function{sys.exc_info()}) to be added to the logging message. -\end{funcdesc} - -\begin{funcdesc}{info}{msg\optional{, *args\optional{, **kwargs}}} -Logs a message with level \constant{INFO} on the root logger. -The arguments are interpreted as for \function{debug()}. -\end{funcdesc} - -\begin{funcdesc}{warning}{msg\optional{, *args\optional{, **kwargs}}} -Logs a message with level \constant{WARNING} on the root logger. -The arguments are interpreted as for \function{debug()}. -\end{funcdesc} - -\begin{funcdesc}{error}{msg\optional{, *args\optional{, **kwargs}}} -Logs a message with level \constant{ERROR} on the root logger. -The arguments are interpreted as for \function{debug()}. -\end{funcdesc} - -\begin{funcdesc}{critical}{msg\optional{, *args\optional{, **kwargs}}} -Logs a message with level \constant{CRITICAL} on the root logger. -The arguments are interpreted as for \function{debug()}. -\end{funcdesc} - -\begin{funcdesc}{exception}{msg\optional{, *args}} -Logs a message with level \constant{ERROR} on the root logger. -The arguments are interpreted as for \function{debug()}. Exception info -is added to the logging message. This function should only be called -from an exception handler. -\end{funcdesc} - -\begin{funcdesc}{disable}{lvl} -Provides an overriding level \var{lvl} for all loggers which takes -precedence over the logger's own level. When the need arises to -temporarily throttle logging output down across the whole application, -this function can be useful. -\end{funcdesc} - -\begin{funcdesc}{addLevelName}{lvl, levelName} -Associates level \var{lvl} with text \var{levelName} in an internal -dictionary, which is used to map numeric levels to a textual -representation, for example when a \class{Formatter} formats a message. -This function can also be used to define your own levels. The only -constraints are that all levels used must be registered using this -function, levels should be positive integers and they should increase -in increasing order of severity. -\end{funcdesc} - -\begin{funcdesc}{getLevelName}{lvl} -Returns the textual representation of logging level \var{lvl}. If the -level is one of the predefined levels \constant{CRITICAL}, -\constant{ERROR}, \constant{WARNING}, \constant{INFO} or \constant{DEBUG} -then you get the corresponding string. If you have associated levels -with names using \function{addLevelName()} then the name you have associated -with \var{lvl} is returned. Otherwise, the string "Level \%s" \% lvl is -returned. -\end{funcdesc} - -\begin{funcdesc}{makeLogRecord}{attrdict} -Creates and returns a new \class{LogRecord} instance whose attributes are -defined by \var{attrdict}. This function is useful for taking a pickled -\class{LogRecord} attribute dictionary, sent over a socket, and reconstituting -it as a \class{LogRecord} instance at the receiving end. -\end{funcdesc} - -\begin{funcdesc}{basicConfig}{} -Does basic configuration for the logging system by creating a -\class{StreamHandler} with a default \class{Formatter} and adding it to -the root logger. The functions \function{debug()}, \function{info()}, -\function{warning()}, \function{error()} and \function{critical()} will call -\function{basicConfig()} automatically if no handlers are defined for the -root logger. -\end{funcdesc} - -\begin{funcdesc}{shutdown}{} -Informs the logging system to perform an orderly shutdown by flushing and -closing all handlers. -\end{funcdesc} - -\begin{funcdesc}{setLoggerClass}{klass} -Tells the logging system to use the class \var{klass} when instantiating a -logger. The class should define \method{__init__()} such that only a name -argument is required, and the \method{__init__()} should call -\method{Logger.__init__()}. This function is typically called before any -loggers are instantiated by applications which need to use custom logger -behavior. -\end{funcdesc} - - -\begin{seealso} - \seepep{282}{A Logging System} - {The proposal which described this feature for inclusion in - the Python standard library.} - \seelink{http://www.red-dove.com/python_logging.html} - {Original Python \module{logging} package} - {This is the original source for the \module{logging} - package. The version of the package available from this - site is suitable for use with Python 1.5.2, 2.1.x and 2.2.x, which - do not include the \module{logging} package in the standard - library.} -\end{seealso} - - -\subsection{Logger Objects} - -Loggers have the following attributes and methods. Note that Loggers are -never instantiated directly, but always through the module-level function -\function{logging.getLogger(name)}. - -\begin{datadesc}{propagate} -If this evaluates to false, logging messages are not passed by this -logger or by child loggers to higher level (ancestor) loggers. The -constructor sets this attribute to 1. -\end{datadesc} - -\begin{methoddesc}{setLevel}{lvl} -Sets the threshold for this logger to \var{lvl}. Logging messages -which are less severe than \var{lvl} will be ignored. When a logger is -created, the level is set to \constant{NOTSET} (which causes all messages -to be processed in the root logger, or delegation to the parent in non-root -loggers). -\end{methoddesc} - -\begin{methoddesc}{isEnabledFor}{lvl} -Indicates if a message of severity \var{lvl} would be processed by -this logger. This method checks first the module-level level set by -\function{logging.disable(lvl)} and then the logger's effective level as -determined by \method{getEffectiveLevel()}. -\end{methoddesc} - -\begin{methoddesc}{getEffectiveLevel}{} -Indicates the effective level for this logger. If a value other than -\constant{NOTSET} has been set using \method{setLevel()}, it is returned. -Otherwise, the hierarchy is traversed towards the root until a value -other than \constant{NOTSET} is found, and that value is returned. -\end{methoddesc} - -\begin{methoddesc}{debug}{msg\optional{, *args\optional{, **kwargs}}} -Logs a message with level \constant{DEBUG} on this logger. -The \var{msg} is the message format string, and the \var{args} are the -arguments which are merged into \var{msg}. The only keyword argument in -\var{kwargs} which is inspected is \var{exc_info} which, if it does not -evaluate as false, causes exception information (via a call to -\function{sys.exc_info()}) to be added to the logging message. -\end{methoddesc} - -\begin{methoddesc}{info}{msg\optional{, *args\optional{, **kwargs}}} -Logs a message with level \constant{INFO} on this logger. -The arguments are interpreted as for \method{debug()}. -\end{methoddesc} - -\begin{methoddesc}{warning}{msg\optional{, *args\optional{, **kwargs}}} -Logs a message with level \constant{WARNING} on this logger. -The arguments are interpreted as for \method{debug()}. -\end{methoddesc} - -\begin{methoddesc}{error}{msg\optional{, *args\optional{, **kwargs}}} -Logs a message with level \constant{ERROR} on this logger. -The arguments are interpreted as for \method{debug()}. -\end{methoddesc} - -\begin{methoddesc}{critical}{msg\optional{, *args\optional{, **kwargs}}} -Logs a message with level \constant{CRITICAL} on this logger. -The arguments are interpreted as for \method{debug()}. -\end{methoddesc} - -\begin{methoddesc}{log}{lvl, msg\optional{, *args\optional{, **kwargs}}} -Logs a message with level \var{lvl} on this logger. -The other arguments are interpreted as for \method{debug()}. -\end{methoddesc} - -\begin{methoddesc}{exception}{msg\optional{, *args}} -Logs a message with level \constant{ERROR} on this logger. -The arguments are interpreted as for \method{debug()}. Exception info -is added to the logging message. This method should only be called -from an exception handler. -\end{methoddesc} - -\begin{methoddesc}{addFilter}{filt} -Adds the specified filter \var{filt} to this logger. -\end{methoddesc} - -\begin{methoddesc}{removeFilter}{filt} -Removes the specified filter \var{filt} from this logger. -\end{methoddesc} - -\begin{methoddesc}{filter}{record} -Applies this logger's filters to the record and returns a true value if -the record is to be processed. -\end{methoddesc} - -\begin{methoddesc}{addHandler}{hdlr} -Adds the specified handler \var{hdlr} to this logger. -\end{methoddesc} - -\begin{methoddesc}{removeHandler}{hdlr} -Removes the specified handler \var{hdlr} from this logger. -\end{methoddesc} - -\begin{methoddesc}{findCaller}{} -Finds the caller's source filename and line number. Returns the filename -and line number as a 2-element tuple. -\end{methoddesc} - -\begin{methoddesc}{handle}{record} -Handles a record by passing it to all handlers associated with this logger -and its ancestors (until a false value of \var{propagate} is found). -This method is used for unpickled records received from a socket, as well -as those created locally. Logger-level filtering is applied using -\method{filter()}. -\end{methoddesc} - -\begin{methoddesc}{makeRecord}{name, lvl, fn, lno, msg, args, exc_info} -This is a factory method which can be overridden in subclasses to create -specialized \class{LogRecord} instances. -\end{methoddesc} - -\subsection{Handler Objects} - -Handlers have the following attributes and methods. Note that -\class{Handler} is never instantiated directly; this class acts as a -base for more useful subclasses. However, the \method{__init__()} -method in subclasses needs to call \method{Handler.__init__()}. - -\begin{methoddesc}{__init__}{level=\constant{NOTSET}} -Initializes the \class{Handler} instance by setting its level, setting -the list of filters to the empty list and creating a lock (using -\method{createLock()}) for serializing access to an I/O mechanism. -\end{methoddesc} - -\begin{methoddesc}{createLock}{} -Initializes a thread lock which can be used to serialize access to -underlying I/O functionality which may not be threadsafe. -\end{methoddesc} - -\begin{methoddesc}{acquire}{} -Acquires the thread lock created with \method{createLock()}. -\end{methoddesc} - -\begin{methoddesc}{release}{} -Releases the thread lock acquired with \method{acquire()}. -\end{methoddesc} - -\begin{methoddesc}{setLevel}{lvl} -Sets the threshold for this handler to \var{lvl}. Logging messages which are -less severe than \var{lvl} will be ignored. When a handler is created, the -level is set to \constant{NOTSET} (which causes all messages to be processed). -\end{methoddesc} - -\begin{methoddesc}{setFormatter}{form} -Sets the \class{Formatter} for this handler to \var{form}. -\end{methoddesc} - -\begin{methoddesc}{addFilter}{filt} -Adds the specified filter \var{filt} to this handler. -\end{methoddesc} - -\begin{methoddesc}{removeFilter}{filt} -Removes the specified filter \var{filt} from this handler. -\end{methoddesc} - -\begin{methoddesc}{filter}{record} -Applies this handler's filters to the record and returns a true value if -the record is to be processed. -\end{methoddesc} - -\begin{methoddesc}{flush}{} -Ensure all logging output has been flushed. This version does -nothing and is intended to be implemented by subclasses. -\end{methoddesc} - -\begin{methoddesc}{close}{} -Tidy up any resources used by the handler. This version does -nothing and is intended to be implemented by subclasses. -\end{methoddesc} - -\begin{methoddesc}{handle}{record} -Conditionally emits the specified logging record, depending on -filters which may have been added to the handler. Wraps the actual -emission of the record with acquisition/release of the I/O thread -lock. -\end{methoddesc} - -\begin{methoddesc}{handleError}{record} -This method should be called from handlers when an exception is -encountered during an \method{emit()} call. By default it does nothing, -which means that exceptions get silently ignored. This is what is -mostly wanted for a logging system - most users will not care -about errors in the logging system, they are more interested in -application errors. You could, however, replace this with a custom -handler if you wish. The specified record is the one which was being -processed when the exception occurred. -\end{methoddesc} - -\begin{methoddesc}{format}{record} -Do formatting for a record - if a formatter is set, use it. -Otherwise, use the default formatter for the module. -\end{methoddesc} - -\begin{methoddesc}{emit}{record} -Do whatever it takes to actually log the specified logging record. -This version is intended to be implemented by subclasses and so -raises a \exception{NotImplementedError}. -\end{methoddesc} - -\subsubsection{StreamHandler} - -The \class{StreamHandler} class sends logging output to streams such as -\var{sys.stdout}, \var{sys.stderr} or any file-like object (or, more -precisely, any object which supports \method{write()} and \method{flush()} -methods). - -\begin{classdesc}{StreamHandler}{\optional{strm}} -Returns a new instance of the \class{StreamHandler} class. If \var{strm} is -specified, the instance will use it for logging output; otherwise, -\var{sys.stderr} will be used. -\end{classdesc} - -\begin{methoddesc}{emit}{record} -If a formatter is specified, it is used to format the record. -The record is then written to the stream with a trailing newline. -If exception information is present, it is formatted using -\function{traceback.print_exception()} and appended to the stream. -\end{methoddesc} - -\begin{methoddesc}{flush}{} -Flushes the stream by calling its \method{flush()} method. Note that -the \method{close()} method is inherited from \class{Handler} and -so does nothing, so an explicit \method{flush()} call may be needed -at times. -\end{methoddesc} - -\subsubsection{FileHandler} - -The \class{FileHandler} class sends logging output to a disk file. -It inherits the output functionality from \class{StreamHandler}. - -\begin{classdesc}{FileHandler}{filename\optional{, mode}} -Returns a new instance of the \class{FileHandler} class. The specified -file is opened and used as the stream for logging. If \var{mode} is -not specified, \constant{'a'} is used. By default, the file grows -indefinitely. -\end{classdesc} - -\begin{methoddesc}{close}{} -Closes the file. -\end{methoddesc} - -\begin{methoddesc}{emit}{record} -Outputs the record to the file. -\end{methoddesc} - -\subsubsection{RotatingFileHandler} - -The \class{RotatingFileHandler} class supports rotation of disk log files. - -\begin{classdesc}{RotatingFileHandler}{filename\optional{, mode\optional{, - maxBytes\optional{, backupCount}}}} -Returns a new instance of the \class{RotatingFileHandler} class. The -specified file is opened and used as the stream for logging. If -\var{mode} is not specified, \code{'a'} is used. By default, the -file grows indefinitely. - -You can use the \var{maxBytes} and -\var{backupCount} values to allow the file to \dfn{rollover} at a -predetermined size. When the size is about to be exceeded, the file is -closed and a new file is silently opened for output. Rollover occurs -whenever the current log file is nearly \var{maxBytes} in length; if -\var{maxBytes} is zero, rollover never occurs. If \var{backupCount} -is non-zero, the system will save old log files by appending the -extensions ".1", ".2" etc., to the filename. For example, with -a \var{backupCount} of 5 and a base file name of -\file{app.log}, you would get \file{app.log}, -\file{app.log.1}, \file{app.log.2}, up to \file{app.log.5}. The file being -written to is always \file{app.log}. When this file is filled, it is -closed and renamed to \file{app.log.1}, and if files \file{app.log.1}, -\file{app.log.2}, etc. exist, then they are renamed to \file{app.log.2}, -\file{app.log.3} etc. respectively. -\end{classdesc} - -\begin{methoddesc}{doRollover}{} -Does a rollover, as described above. -\end{methoddesc} - -\begin{methoddesc}{emit}{record} -Outputs the record to the file, catering for rollover as described -in \method{setRollover()}. -\end{methoddesc} - -\subsubsection{SocketHandler} - -The \class{SocketHandler} class sends logging output to a network -socket. The base class uses a TCP socket. - -\begin{classdesc}{SocketHandler}{host, port} -Returns a new instance of the \class{SocketHandler} class intended to -communicate with a remote machine whose address is given by \var{host} -and \var{port}. -\end{classdesc} - -\begin{methoddesc}{close}{} -Closes the socket. -\end{methoddesc} - -\begin{methoddesc}{handleError}{} -\end{methoddesc} - -\begin{methoddesc}{emit}{} -Pickles the record's attribute dictionary and writes it to the socket in -binary format. If there is an error with the socket, silently drops the -packet. If the connection was previously lost, re-establishes the connection. -To unpickle the record at the receiving end into a LogRecord, use the -\function{makeLogRecord} function. -\end{methoddesc} - -\begin{methoddesc}{handleError}{} -Handles an error which has occurred during \method{emit()}. The -most likely cause is a lost connection. Closes the socket so that -we can retry on the next event. -\end{methoddesc} - -\begin{methoddesc}{makeSocket}{} -This is a factory method which allows subclasses to define the precise -type of socket they want. The default implementation creates a TCP -socket (\constant{socket.SOCK_STREAM}). -\end{methoddesc} - -\begin{methoddesc}{makePickle}{record} -Pickles the record's attribute dictionary in binary format with a length -prefix, and returns it ready for transmission across the socket. -\end{methoddesc} - -\begin{methoddesc}{send}{packet} -Send a pickled string \var{packet} to the socket. This function allows -for partial sends which can happen when the network is busy. -\end{methoddesc} - -\subsubsection{DatagramHandler} - -The \class{DatagramHandler} class inherits from \class{SocketHandler} -to support sending logging messages over UDP sockets. - -\begin{classdesc}{DatagramHandler}{host, port} -Returns a new instance of the \class{DatagramHandler} class intended to -communicate with a remote machine whose address is given by \var{host} -and \var{port}. -\end{classdesc} - -\begin{methoddesc}{emit}{} -Pickles the record's attribute dictionary and writes it to the socket in -binary format. If there is an error with the socket, silently drops the -packet. -To unpickle the record at the receiving end into a LogRecord, use the -\function{makeLogRecord} function. -\end{methoddesc} - -\begin{methoddesc}{makeSocket}{} -The factory method of \class{SocketHandler} is here overridden to create -a UDP socket (\constant{socket.SOCK_DGRAM}). -\end{methoddesc} - -\begin{methoddesc}{send}{s} -Send a pickled string to a socket. -\end{methoddesc} - -\subsubsection{SysLogHandler} - -The \class{SysLogHandler} class supports sending logging messages to a -remote or local \UNIX{} syslog. - -\begin{classdesc}{SysLogHandler}{\optional{address\optional{, facility}}} -Returns a new instance of the \class{SysLogHandler} class intended to -communicate with a remote \UNIX{} machine whose address is given by -\var{address} in the form of a \code{(\var{host}, \var{port})} -tuple. If \var{address} is not specified, \code{('localhost', 514)} is -used. The address is used to open a UDP socket. If \var{facility} is -not specified, \constant{LOG_USER} is used. -\end{classdesc} - -\begin{methoddesc}{close}{} -Closes the socket to the remote host. -\end{methoddesc} - -\begin{methoddesc}{emit}{record} -The record is formatted, and then sent to the syslog server. If -exception information is present, it is \emph{not} sent to the server. -\end{methoddesc} - -\begin{methoddesc}{encodePriority}{facility, priority} -Encodes the facility and priority into an integer. You can pass in strings -or integers - if strings are passed, internal mapping dictionaries are used -to convert them to integers. -\end{methoddesc} - -\subsubsection{NTEventLogHandler} - -The \class{NTEventLogHandler} class supports sending logging messages -to a local Windows NT, Windows 2000 or Windows XP event log. Before -you can use it, you need Mark Hammond's Win32 extensions for Python -installed. - -\begin{classdesc}{NTEventLogHandler}{appname\optional{, - dllname\optional{, logtype}}} -Returns a new instance of the \class{NTEventLogHandler} class. The -\var{appname} is used to define the application name as it appears in the -event log. An appropriate registry entry is created using this name. -The \var{dllname} should give the fully qualified pathname of a .dll or .exe -which contains message definitions to hold in the log (if not specified, -\code{'win32service.pyd'} is used - this is installed with the Win32 -extensions and contains some basic placeholder message definitions. -Note that use of these placeholders will make your event logs big, as the -entire message source is held in the log. If you want slimmer logs, you have -to pass in the name of your own .dll or .exe which contains the message -definitions you want to use in the event log). The \var{logtype} is one of -\code{'Application'}, \code{'System'} or \code{'Security'}, and -defaults to \code{'Application'}. -\end{classdesc} - -\begin{methoddesc}{close}{} -At this point, you can remove the application name from the registry as a -source of event log entries. However, if you do this, you will not be able -to see the events as you intended in the Event Log Viewer - it needs to be -able to access the registry to get the .dll name. The current version does -not do this (in fact it doesn't do anything). -\end{methoddesc} - -\begin{methoddesc}{emit}{record} -Determines the message ID, event category and event type, and then logs the -message in the NT event log. -\end{methoddesc} - -\begin{methoddesc}{getEventCategory}{record} -Returns the event category for the record. Override this if you -want to specify your own categories. This version returns 0. -\end{methoddesc} - -\begin{methoddesc}{getEventType}{record} -Returns the event type for the record. Override this if you want -to specify your own types. This version does a mapping using the -handler's typemap attribute, which is set up in \method{__init__()} -to a dictionary which contains mappings for \constant{DEBUG}, -\constant{INFO}, \constant{WARNING}, \constant{ERROR} and -\constant{CRITICAL}. If you are using your own levels, you will either need -to override this method or place a suitable dictionary in the -handler's \var{typemap} attribute. -\end{methoddesc} - -\begin{methoddesc}{getMessageID}{record} -Returns the message ID for the record. If you are using your -own messages, you could do this by having the \var{msg} passed to the -logger being an ID rather than a format string. Then, in here, -you could use a dictionary lookup to get the message ID. This -version returns 1, which is the base message ID in -\file{win32service.pyd}. -\end{methoddesc} - -\subsubsection{SMTPHandler} - -The \class{SMTPHandler} class supports sending logging messages to an email -address via SMTP. - -\begin{classdesc}{SMTPHandler}{mailhost, fromaddr, toaddrs, subject} -Returns a new instance of the \class{SMTPHandler} class. The -instance is initialized with the from and to addresses and subject -line of the email. The \var{toaddrs} should be a list of strings without -domain names (That's what the \var{mailhost} is for). To specify a -non-standard SMTP port, use the (host, port) tuple format for the -\var{mailhost} argument. If you use a string, the standard SMTP port -is used. -\end{classdesc} - -\begin{methoddesc}{emit}{record} -Formats the record and sends it to the specified addressees. -\end{methoddesc} - -\begin{methoddesc}{getSubject}{record} -If you want to specify a subject line which is record-dependent, -override this method. -\end{methoddesc} - -\subsubsection{MemoryHandler} - -The \class{MemoryHandler} supports buffering of logging records in memory, -periodically flushing them to a \dfn{target} handler. Flushing occurs -whenever the buffer is full, or when an event of a certain severity or -greater is seen. - -\class{MemoryHandler} is a subclass of the more general -\class{BufferingHandler}, which is an abstract class. This buffers logging -records in memory. Whenever each record is added to the buffer, a -check is made by calling \method{shouldFlush()} to see if the buffer -should be flushed. If it should, then \method{flush()} is expected to -do the needful. - -\begin{classdesc}{BufferingHandler}{capacity} -Initializes the handler with a buffer of the specified capacity. -\end{classdesc} - -\begin{methoddesc}{emit}{record} -Appends the record to the buffer. If \method{shouldFlush()} returns true, -calls \method{flush()} to process the buffer. -\end{methoddesc} - -\begin{methoddesc}{flush}{} -You can override this to implement custom flushing behavior. This version -just zaps the buffer to empty. -\end{methoddesc} - -\begin{methoddesc}{shouldFlush}{record} -Returns true if the buffer is up to capacity. This method can be -overridden to implement custom flushing strategies. -\end{methoddesc} - -\begin{classdesc}{MemoryHandler}{capacity\optional{, flushLevel -\optional{, target}}} -Returns a new instance of the \class{MemoryHandler} class. The -instance is initialized with a buffer size of \var{capacity}. If -\var{flushLevel} is not specified, \constant{ERROR} is used. If no -\var{target} is specified, the target will need to be set using -\method{setTarget()} before this handler does anything useful. -\end{classdesc} - -\begin{methoddesc}{close}{} -Calls \method{flush()}, sets the target to \constant{None} and -clears the buffer. -\end{methoddesc} - -\begin{methoddesc}{flush}{} -For a \class{MemoryHandler}, flushing means just sending the buffered -records to the target, if there is one. Override if you want -different behavior. -\end{methoddesc} - -\begin{methoddesc}{setTarget}{target} -Sets the target handler for this handler. -\end{methoddesc} - -\begin{methoddesc}{shouldFlush}{record} -Checks for buffer full or a record at the \var{flushLevel} or higher. -\end{methoddesc} - -\subsubsection{HTTPHandler} - -The \class{HTTPHandler} class supports sending logging messages to a -Web server, using either \samp{GET} or \samp{POST} semantics. - -\begin{classdesc}{HTTPHandler}{host, url\optional{, method}} -Returns a new instance of the \class{HTTPHandler} class. The -instance is initialized with a host address, url and HTTP method. -If no \var{method} is specified, \samp{GET} is used. -\end{classdesc} - -\begin{methoddesc}{emit}{record} -Sends the record to the Web server as an URL-encoded dictionary. -\end{methoddesc} - -\subsection{Formatter Objects} - -\class{Formatter}s have the following attributes and methods. They are -responsible for converting a \class{LogRecord} to (usually) a string -which can be interpreted by either a human or an external system. The -base -\class{Formatter} allows a formatting string to be specified. If none is -supplied, the default value of \code{'\%(message)s\e'} is used. - -A Formatter can be initialized with a format string which makes use of -knowledge of the \class{LogRecord} attributes - such as the default value -mentioned above making use of the fact that the user's message and -arguments are pre-formatted into a LogRecord's \var{message} -attribute. This format string contains standard python \%-style -mapping keys. See section \ref{typesseq-strings}, ``String Formatting -Operations,'' for more information on string formatting. - -Currently, the useful mapping keys in a LogRecord are: - -\begin{tableii}{l|l}{code}{Format}{Description} -\lineii{\%(name)s} {Name of the logger (logging channel).} -\lineii{\%(levelno)s} {Numeric logging level for the message - (\constant{DEBUG}, \constant{INFO}, - \constant{WARNING}, \constant{ERROR}, - \constant{CRITICAL}).} -\lineii{\%(levelname)s}{Text logging level for the message - (\code{'DEBUG'}, \code{'INFO'}, - \code{'WARNING'}, \code{'ERROR'}, - \code{'CRITICAL'}).} -\lineii{\%(pathname)s} {Full pathname of the source file where the logging - call was issued (if available).} -\lineii{\%(filename)s} {Filename portion of pathname.} -\lineii{\%(module)s} {Module (name portion of filename).} -\lineii{\%(lineno)d} {Source line number where the logging call was issued - (if available).} -\lineii{\%(created)f} {Time when the LogRecord was created (as - returned by \function{time.time()}).} -\lineii{\%(asctime)s} {Human-readable time when the LogRecord was created. - By default this is of the form - ``2003-07-08 16:49:45,896'' (the numbers after the - comma are millisecond portion of the time).} -\lineii{\%(msecs)d} {Millisecond portion of the time when the - \class{LogRecord} was created.} -\lineii{\%(thread)d} {Thread ID (if available).} -\lineii{\%(process)d} {Process ID (if available).} -\lineii{\%(message)s} {The logged message, computed as \code{msg \% args}.} -\end{tableii} - -\begin{classdesc}{Formatter}{\optional{fmt\optional{, datefmt}}} -Returns a new instance of the \class{Formatter} class. The -instance is initialized with a format string for the message as a whole, -as well as a format string for the date/time portion of a message. If -no \var{fmt} is specified, \code{'\%(message)s'} is used. If no \var{datefmt} -is specified, the ISO8601 date format is used. -\end{classdesc} - -\begin{methoddesc}{format}{record} -The record's attribute dictionary is used as the operand to a -string formatting operation. Returns the resulting string. -Before formatting the dictionary, a couple of preparatory steps -are carried out. The \var{message} attribute of the record is computed -using \var{msg} \% \var{args}. If the formatting string contains -\code{'(asctime)'}, \method{formatTime()} is called to format the -event time. If there is exception information, it is formatted using -\method{formatException()} and appended to the message. -\end{methoddesc} - -\begin{methoddesc}{formatTime}{record\optional{, datefmt}} -This method should be called from \method{format()} by a formatter which -wants to make use of a formatted time. This method can be overridden -in formatters to provide for any specific requirement, but the -basic behavior is as follows: if \var{datefmt} (a string) is specified, -it is used with \function{time.strftime()} to format the creation time of the -record. Otherwise, the ISO8601 format is used. The resulting -string is returned. -\end{methoddesc} - -\begin{methoddesc}{formatException}{exc_info} -Formats the specified exception information (a standard exception tuple -as returned by \function{sys.exc_info()}) as a string. This default -implementation just uses \function{traceback.print_exception()}. -The resulting string is returned. -\end{methoddesc} - -\subsection{Filter Objects} - -\class{Filter}s can be used by \class{Handler}s and \class{Logger}s for -more sophisticated filtering than is provided by levels. The base filter -class only allows events which are below a certain point in the logger -hierarchy. For example, a filter initialized with "A.B" will allow events -logged by loggers "A.B", "A.B.C", "A.B.C.D", "A.B.D" etc. but not "A.BB", -"B.A.B" etc. If initialized with the empty string, all events are passed. - -\begin{classdesc}{Filter}{\optional{name}} -Returns an instance of the \class{Filter} class. If \var{name} is specified, -it names a logger which, together with its children, will have its events -allowed through the filter. If no name is specified, allows every event. -\end{classdesc} - -\begin{methoddesc}{filter}{record} -Is the specified record to be logged? Returns zero for no, nonzero for -yes. If deemed appropriate, the record may be modified in-place by this -method. -\end{methoddesc} - -\subsection{LogRecord Objects} - -LogRecord instances are created every time something is logged. They -contain all the information pertinent to the event being logged. The -main information passed in is in msg and args, which are combined -using msg \% args to create the message field of the record. The record -also includes information such as when the record was created, the -source line where the logging call was made, and any exception -information to be logged. - -LogRecord has no methods; it's just a repository for information about the -logging event. The only reason it's a class rather than a dictionary is to -facilitate extension. - -\begin{classdesc}{LogRecord}{name, lvl, pathname, lineno, msg, args, - exc_info} -Returns an instance of \class{LogRecord} initialized with interesting -information. The \var{name} is the logger name; \var{lvl} is the -numeric level; \var{pathname} is the absolute pathname of the source -file in which the logging call was made; \var{lineno} is the line -number in that file where the logging call is found; \var{msg} is the -user-supplied message (a format string); \var{args} is the tuple -which, together with \var{msg}, makes up the user message; and -\var{exc_info} is the exception tuple obtained by calling -\function{sys.exc_info() }(or \constant{None}, if no exception information -is available). -\end{classdesc} - -\subsection{Thread Safety} - -The logging module is intended to be thread-safe without any special work -needing to be done by its clients. It achieves this though using threading -locks; there is one lock to serialize access to the module's shared data, -and each handler also creates a lock to serialize access to its underlying -I/O. - -\subsection{Configuration} - - -\subsubsection{Configuration functions} - -The following functions allow the logging module to be -configured. Before they can be used, you must import -\module{logging.config}. Their use is optional --- you can configure -the logging module entirely by making calls to the main API (defined -in \module{logging} itself) and defining handlers which are declared -either in \module{logging} or \module{logging.handlers}. - -\begin{funcdesc}{fileConfig}{fname\optional{, defaults}} -Reads the logging configuration from a ConfigParser-format file named -\var{fname}. This function can be called several times from an application, -allowing an end user the ability to select from various pre-canned -configurations (if the developer provides a mechanism to present the -choices and load the chosen configuration). Defaults to be passed to -ConfigParser can be specified in the \var{defaults} argument. -\end{funcdesc} - -\begin{funcdesc}{listen}{\optional{port}} -Starts up a socket server on the specified port, and listens for new -configurations. If no port is specified, the module's default -\constant{DEFAULT_LOGGING_CONFIG_PORT} is used. Logging configurations -will be sent as a file suitable for processing by \function{fileConfig()}. -Returns a \class{Thread} instance on which you can call \method{start()} -to start the server, and which you can \method{join()} when appropriate. -To stop the server, call \function{stopListening()}. -\end{funcdesc} - -\begin{funcdesc}{stopListening}{} -Stops the listening server which was created with a call to -\function{listen()}. This is typically called before calling \method{join()} -on the return value from \function{listen()}. -\end{funcdesc} - -\subsubsection{Configuration file format} - -The configuration file format understood by \function{fileConfig} is -based on ConfigParser functionality. The file must contain sections -called \code{[loggers]}, \code{[handlers]} and \code{[formatters]} -which identify by name the entities of each type which are defined in -the file. For each such entity, there is a separate section which -identified how that entity is configured. Thus, for a logger named -\code{log01} in the \code{[loggers]} section, the relevant -configuration details are held in a section -\code{[logger_log01]}. Similarly, a handler called \code{hand01} in -the \code{[handlers]} section will have its configuration held in a -section called \code{[handler_hand01]}, while a formatter called -\code{form01} in the \code{[formatters]} section will have its -configuration specified in a section called -\code{[formatter_form01]}. The root logger configuration must be -specified in a section called \code{[logger_root]}. - -Examples of these sections in the file are given below. - -\begin{verbatim} -[loggers] -keys=root,log02,log03,log04,log05,log06,log07 - -[handlers] -keys=hand01,hand02,hand03,hand04,hand05,hand06,hand07,hand08,hand09 - -[formatters] -keys=form01,form02,form03,form04,form05,form06,form07,form08,form09 -\end{verbatim} - -The root logger must specify a level and a list of handlers. An -example of a root logger section is given below. - -\begin{verbatim} -[logger_root] -level=NOTSET -handlers=hand01 -\end{verbatim} - -The \code{level} entry can be one of \code{DEBUG, INFO, WARNING, -ERROR, CRITICAL} or \code{NOTSET}. For the root logger only, -\code{NOTSET} means that all messages will be logged. Level values are -\function{eval()}uated in the context of the \code{logging} package's -namespace. - -The \code{handlers} entry is a comma-separated list of handler names, -which must appear in the \code{[handlers]} section. These names must -appear in the \code{[handlers]} section and have corresponding -sections in the configuration file. - -For loggers other than the root logger, some additional information is -required. This is illustrated by the following example. - -\begin{verbatim} -[logger_parser] -level=DEBUG -handlers=hand01 -propagate=1 -qualname=compiler.parser -\end{verbatim} - -The \code{level} and \code{handlers} entries are interpreted as for -the root logger, except that if a non-root logger's level is specified -as \code{NOTSET}, the system consults loggers higher up the hierarchy -to determine the effective level of the logger. The \code{propagate} -entry is set to 1 to indicate that messages must propagate to handlers -higher up the logger hierarchy from this logger, or 0 to indicate that -messages are \strong{not} propagated to handlers up the hierarchy. The -\code{qualname} entry is the hierarchical channel name of the logger, -that is to say the name used by the application to get the logger. - -Sections which specify handler configuration are exemplified by the -following. - -\begin{verbatim} -[handler_hand01] -class=StreamHandler -level=NOTSET -formatter=form01 -args=(sys.stdout,) -\end{verbatim} - -The \code{class} entry indicates the handler's class (as determined by -\function{eval()} in the \code{logging} package's namespace). The -\code{level} is interpreted as for loggers, and \code{NOTSET} is taken -to mean "log everything". - -The \code{formatter} entry indicates the key name of the formatter for -this handler. If blank, a default formatter -(\code{logging._defaultFormatter}) is used. If a name is specified, it -must appear in the \code{[formatters]} section and have a -corresponding section in the configuration file. - -The \code{args} entry, when \function{eval()}uated in the context of -the \code{logging} package's namespace, is the list of arguments to -the constructor for the handler class. Refer to the constructors for -the relevant handlers, or to the examples below, to see how typical -entries are constructed. - -\begin{verbatim} -[handler_hand02] -class=FileHandler -level=DEBUG -formatter=form02 -args=('python.log', 'w') - -[handler_hand03] -class=handlers.SocketHandler -level=INFO -formatter=form03 -args=('localhost', handlers.DEFAULT_TCP_LOGGING_PORT) - -[handler_hand04] -class=handlers.DatagramHandler -level=WARN -formatter=form04 -args=('localhost', handlers.DEFAULT_UDP_LOGGING_PORT) - -[handler_hand05] -class=handlers.SysLogHandler -level=ERROR -formatter=form05 -args=(('localhost', handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER) - -[handler_hand06] -class=NTEventLogHandler -level=CRITICAL -formatter=form06 -args=('Python Application', '', 'Application') - -[handler_hand07] -class=SMTPHandler -level=WARN -formatter=form07 -args=('localhost', 'from@abc', ['user1@abc', 'user2@xyz'], 'Logger Subject') - -[handler_hand08] -class=MemoryHandler -level=NOTSET -formatter=form08 -target= -args=(10, ERROR) - -[handler_hand09] -class=HTTPHandler -level=NOTSET -formatter=form09 -args=('localhost:9022', '/log', 'GET') -\end{verbatim} - -Sections which specify formatter configuration are typified by the following. - -\begin{verbatim} -[formatter_form01] -format=F1 %(asctime)s %(levelname)s %(message)s -datefmt= -\end{verbatim} - -The \code{format} entry is the overall format string, and the -\code{datefmt} entry is the \function{strftime()}-compatible date/time format -string. If empty, the package substitutes ISO8601 format date/times, which -is almost equivalent to specifying the date format string "%Y-%m-%d %H:%M:%S". -The ISO8601 format also specifies milliseconds, which are appended to the -result of using the above format string, with a comma separator. An example -time in ISO8601 format is \code{2003-01-23 00:29:50,411}. - -\subsection{Using the logging package} - -\subsubsection{Simplest usage} - -Here's a simple example which shows the most casual usage of the logging -package. - -\begin{verbatim} -import logging -logging.debug("Houston, we have a %s", "thorny problem") -logging.info("Houston, we have a %s", "interesting problem") -logging.warning("Houston, we have a %s", "bit of a problem") -logging.error("Houston, we have a %s", "major problem") -logging.critical("Houston, we have a %s", "major disaster") -try: - infinity = 1 / 0 -except: - logging.exception("Houston, we have an %s", "unexpected problem") -\end{verbatim} - -If you run the above example, this will produce: - -\begin{verbatim} -WARNING:root:Houston, we have a bit of a problem -ERROR:root:Houston, we have a major problem -CRITICAL:root:Houston, we have a major disaster -ERROR:root:Houston, we have an unexpected problem -Traceback (most recent call last): - File "C:\Projects\RDC\Python\packages\logging\test\tmp.py", line 8, in ? - infinity = 1 / 0 -ZeroDivisionError: integer division or modulo by zero -\end{verbatim} - -The reason you get this output is that the default format is - -\begin{verbatim} -"%(levelname)s:%(name)s:%(message)s". -\end{verbatim} - -When you invoke functions \function{info()}, \function{warning()} etc. in the -logging package itself, these calls are delegated to the correspondingly -named methods in the root logger. This is why the logger name shown in the above -logging output is "root". If the root logger has no handlers configured, the -logging package creates a console handler and adds it to the root logger -automatically. (It does this by calling the \function{basicConfig()}, which you -can also call directly from your own code.) - -By default, events with a severity below WARNING are suppressed. Notice -that the \function{exception()} function acts like \function{error()}, except -that a traceback is appended to the log entry. - -\subsubsection{Logging to the console} - -Here's a simple example which logs all messages to the console. We use a named -logger: - -\begin{verbatim} -import logging -logging.basicConfig() -logger = logging.getLogger('myapp') -logger.setLevel(logging.DEBUG) -logger.debug("Houston, we have a %s", "thorny problem") -logger.info("Houston, we have a %s", "interesting problem") -logger.warning("Houston, we have a %s", "bit of a problem") -logger.error("Houston, we have a %s", "major problem") -logger.critical("Houston, we have a %s", "major disaster") -try: - infinity = 1 / 0 -except: - logger.exception("Houston, we have an %s", "unexpected problem") -\end{verbatim} - -Here's the corresponding output: - -\begin{verbatim} -DEBUG:myapp:Houston, we have a thorny problem -INFO:myapp:Houston, we have a interesting problem -WARNING:myapp:Houston, we have a bit of a problem -ERROR:myapp:Houston, we have a major problem -CRITICAL:myapp:Houston, we have a major disaster -ERROR:myapp:Houston, we have an unexpected problem -Traceback (most recent call last): - File "C:\Projects\RDC\Python\packages\logging\test\tmp.py", line 11, in ? - infinity = 1 / 0 -ZeroDivisionError: integer division or modulo by zero -\end{verbatim} - -As you can see, the specified logger name now appears in the output, and -DEBUG and INFO messages are included in the output because we explicitly -asked for them via the call to \method{setLevel()}. - -\subsubsection{Logging to a file} - -Here's a simple logging example that just logs to a file. In order, -it creates a \class{Logger} instance, then a \class{FileHandler} -and a \class{Formatter}. It attaches the \class{Formatter} to the -\class{FileHandler}, then the \class{FileHandler} to the \class{Logger}. -Finally, it sets a debug level for the logger. - -\begin{verbatim} -import logging -logger = logging.getLogger('myapp') -hdlr = logging.FileHandler('/var/tmp/myapp.log') -formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s') -hdlr.setFormatter(formatter) -logger.addHandler(hdlr) -logger.setLevel(logging.WARNING) -\end{verbatim} - -We can use this logger object now to write entries to the log file: - -\begin{verbatim} -logger.error('We have a problem') -logger.info('While this is just chatty') -\end{verbatim} - -If we look in the file that was created, we'll see something like this: -\begin{verbatim} -2003-07-08 16:49:45,896 ERROR We have a problem -\end{verbatim} - -The info message was not written to the file - we called the \method{setLevel} -method to say we only wanted \code{WARNING} or worse, so the info message is -discarded. - -The timestamp is of the form -``year-month-day hour:minutes:seconds,milliseconds.'' -Note that despite the three digits of precision in the milliseconds field, -not all systems provide time with this much precision. - -\subsubsection{Logging to a rotating set of files} - diff --git a/tools/python/logging/logging-0.4.9.2/logging/__init__.py b/tools/python/logging/logging-0.4.9.2/logging/__init__.py deleted file mode 100644 index 75946e04e7..0000000000 --- a/tools/python/logging/logging-0.4.9.2/logging/__init__.py +++ /dev/null @@ -1,1225 +0,0 @@ -# Copyright 2001-2004 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -""" -Logging package for Python. Based on PEP 282 and comments thereto in -comp.lang.python, and influenced by Apache's log4j system. - -Should work under Python versions >= 1.5.2, except that source line -information is not available unless 'sys._getframe()' is. - -Copyright (C) 2001-2004 Vinay Sajip. All Rights Reserved. - -To use, simply 'import logging' and log away! -""" - -import sys, os, types, time, string, cStringIO - -try: - import thread - import threading -except ImportError: - thread = None - -__author__ = "Vinay Sajip " -__status__ = "beta" -__version__ = "0.4.9.2" -__date__ = "28 February 2004" - -#--------------------------------------------------------------------------- -# Miscellaneous module data -#--------------------------------------------------------------------------- - -# -#_srcfile is used when walking the stack to check when we've got the first -# caller stack frame. -# -if string.lower(__file__[-4:]) in ['.pyc', '.pyo']: - _srcfile = __file__[:-4] + '.py' -else: - _srcfile = __file__ -_srcfile = os.path.normcase(_srcfile) - -# _srcfile is only used in conjunction with sys._getframe(). -# To provide compatibility with older versions of Python, set _srcfile -# to None if _getframe() is not available; this value will prevent -# findCaller() from being called. -if not hasattr(sys, "_getframe"): - _srcfile = None - -# -#_startTime is used as the base when calculating the relative time of events -# -_startTime = time.time() - -# -#raiseExceptions is used to see if exceptions during handling should be -#propagated -# -raiseExceptions = 1 - -#--------------------------------------------------------------------------- -# Level related stuff -#--------------------------------------------------------------------------- -# -# Default levels and level names, these can be replaced with any positive set -# of values having corresponding names. There is a pseudo-level, NOTSET, which -# is only really there as a lower limit for user-defined levels. Handlers and -# loggers are initialized with NOTSET so that they will log all messages, even -# at user-defined levels. -# -CRITICAL = 50 -FATAL = CRITICAL -ERROR = 40 -WARNING = 30 -WARN = WARNING -INFO = 20 -DEBUG = 10 -NOTSET = 0 - -_levelNames = { - CRITICAL : 'CRITICAL', - ERROR : 'ERROR', - WARNING : 'WARNING', - INFO : 'INFO', - DEBUG : 'DEBUG', - NOTSET : 'NOTSET', - 'CRITICAL' : CRITICAL, - 'ERROR' : ERROR, - 'WARN' : WARNING, - 'WARNING' : WARNING, - 'INFO' : INFO, - 'DEBUG' : DEBUG, - 'NOTSET' : NOTSET, -} - -def getLevelName(level): - """ - Return the textual representation of logging level 'level'. - - If the level is one of the predefined levels (CRITICAL, ERROR, WARNING, - INFO, DEBUG) then you get the corresponding string. If you have - associated levels with names using addLevelName then the name you have - associated with 'level' is returned. Otherwise, the string - "Level %s" % level is returned. - """ - return _levelNames.get(level, ("Level %s" % level)) - -def addLevelName(level, levelName): - """ - Associate 'levelName' with 'level'. - - This is used when converting levels to text during message formatting. - """ - _acquireLock() - try: #unlikely to cause an exception, but you never know... - _levelNames[level] = levelName - _levelNames[levelName] = level - finally: - _releaseLock() - -#--------------------------------------------------------------------------- -# Thread-related stuff -#--------------------------------------------------------------------------- - -# -#_lock is used to serialize access to shared data structures in this module. -#This needs to be an RLock because fileConfig() creates Handlers and so -#might arbitrary user threads. Since Handler.__init__() updates the shared -#dictionary _handlers, it needs to acquire the lock. But if configuring, -#the lock would already have been acquired - so we need an RLock. -#The same argument applies to Loggers and Manager.loggerDict. -# -_lock = None - -def _acquireLock(): - """ - Acquire the module-level lock for serializing access to shared data. - - This should be released with _releaseLock(). - """ - global _lock - if (not _lock) and thread: - _lock = threading.RLock() - if _lock: - _lock.acquire() - -def _releaseLock(): - """ - Release the module-level lock acquired by calling _acquireLock(). - """ - if _lock: - _lock.release() - -#--------------------------------------------------------------------------- -# The logging record -#--------------------------------------------------------------------------- - -class LogRecord: - """ - A LogRecord instance represents an event being logged. - - LogRecord instances are created every time something is logged. They - contain all the information pertinent to the event being logged. The - main information passed in is in msg and args, which are combined - using str(msg) % args to create the message field of the record. The - record also includes information such as when the record was created, - the source line where the logging call was made, and any exception - information to be logged. - """ - def __init__(self, name, level, pathname, lineno, msg, args, exc_info): - """ - Initialize a logging record with interesting information. - """ - ct = time.time() - self.name = name - self.msg = msg - self.args = args - self.levelname = getLevelName(level) - self.levelno = level - self.pathname = pathname - try: - self.filename = os.path.basename(pathname) - self.module = os.path.splitext(self.filename)[0] - except: - self.filename = pathname - self.module = "Unknown module" - self.exc_info = exc_info - self.exc_text = None # used to cache the traceback text - self.lineno = lineno - self.created = ct - self.msecs = (ct - long(ct)) * 1000 - self.relativeCreated = (self.created - _startTime) * 1000 - if thread: - self.thread = thread.get_ident() - else: - self.thread = None - if hasattr(os, 'getpid'): - self.process = os.getpid() - else: - self.process = None - - def __str__(self): - return ''%(self.name, self.levelno, - self.pathname, self.lineno, self.msg) - - def getMessage(self): - """ - Return the message for this LogRecord. - - Return the message for this LogRecord after merging any user-supplied - arguments with the message. - """ - if not hasattr(types, "UnicodeType"): #if no unicode support... - msg = str(self.msg) - else: - try: - msg = str(self.msg) - except UnicodeError: - msg = self.msg #Defer encoding till later - if self.args: - msg = msg % self.args - return msg - -def makeLogRecord(dict): - """ - Make a LogRecord whose attributes are defined by the specified dictionary, - This function is useful for converting a logging event received over - a socket connection (which is sent as a dictionary) into a LogRecord - instance. - """ - rv = LogRecord(None, None, "", 0, "", (), None) - rv.__dict__.update(dict) - return rv - -#--------------------------------------------------------------------------- -# Formatter classes and functions -#--------------------------------------------------------------------------- - -class Formatter: - """ - Formatter instances are used to convert a LogRecord to text. - - Formatters need to know how a LogRecord is constructed. They are - responsible for converting a LogRecord to (usually) a string which can - be interpreted by either a human or an external system. The base Formatter - allows a formatting string to be specified. If none is supplied, the - default value of "%s(message)\\n" is used. - - The Formatter can be initialized with a format string which makes use of - knowledge of the LogRecord attributes - e.g. the default value mentioned - above makes use of the fact that the user's message and arguments are pre- - formatted into a LogRecord's message attribute. Currently, the useful - attributes in a LogRecord are described by: - - %(name)s Name of the logger (logging channel) - %(levelno)s Numeric logging level for the message (DEBUG, INFO, - WARNING, ERROR, CRITICAL) - %(levelname)s Text logging level for the message ("DEBUG", "INFO", - "WARNING", "ERROR", "CRITICAL") - %(pathname)s Full pathname of the source file where the logging - call was issued (if available) - %(filename)s Filename portion of pathname - %(module)s Module (name portion of filename) - %(lineno)d Source line number where the logging call was issued - (if available) - %(created)f Time when the LogRecord was created (time.time() - return value) - %(asctime)s Textual time when the LogRecord was created - %(msecs)d Millisecond portion of the creation time - %(relativeCreated)d Time in milliseconds when the LogRecord was created, - relative to the time the logging module was loaded - (typically at application startup time) - %(thread)d Thread ID (if available) - %(process)d Process ID (if available) - %(message)s The result of record.getMessage(), computed just as - the record is emitted - """ - - converter = time.localtime - - def __init__(self, fmt=None, datefmt=None): - """ - Initialize the formatter with specified format strings. - - Initialize the formatter either with the specified format string, or a - default as described above. Allow for specialized date formatting with - the optional datefmt argument (if omitted, you get the ISO8601 format). - """ - if fmt: - self._fmt = fmt - else: - self._fmt = "%(message)s" - self.datefmt = datefmt - - def formatTime(self, record, datefmt=None): - """ - Return the creation time of the specified LogRecord as formatted text. - - This method should be called from format() by a formatter which - wants to make use of a formatted time. This method can be overridden - in formatters to provide for any specific requirement, but the - basic behaviour is as follows: if datefmt (a string) is specified, - it is used with time.strftime() to format the creation time of the - record. Otherwise, the ISO8601 format is used. The resulting - string is returned. This function uses a user-configurable function - to convert the creation time to a tuple. By default, time.localtime() - is used; to change this for a particular formatter instance, set the - 'converter' attribute to a function with the same signature as - time.localtime() or time.gmtime(). To change it for all formatters, - for example if you want all logging times to be shown in GMT, - set the 'converter' attribute in the Formatter class. - """ - ct = self.converter(record.created) - if datefmt: - s = time.strftime(datefmt, ct) - else: - t = time.strftime("%Y-%m-%d %H:%M:%S", ct) - s = "%s,%03d" % (t, record.msecs) - return s - - def formatException(self, ei): - """ - Format and return the specified exception information as a string. - - This default implementation just uses - traceback.print_exception() - """ - import traceback - sio = cStringIO.StringIO() - traceback.print_exception(ei[0], ei[1], ei[2], None, sio) - s = sio.getvalue() - sio.close() - if s[-1] == "\n": - s = s[:-1] - return s - - def format(self, record): - """ - Format the specified record as text. - - The record's attribute dictionary is used as the operand to a - string formatting operation which yields the returned string. - Before formatting the dictionary, a couple of preparatory steps - are carried out. The message attribute of the record is computed - using LogRecord.getMessage(). If the formatting string contains - "%(asctime)", formatTime() is called to format the event time. - If there is exception information, it is formatted using - formatException() and appended to the message. - """ - record.message = record.getMessage() - if string.find(self._fmt,"%(asctime)") >= 0: - record.asctime = self.formatTime(record, self.datefmt) - s = self._fmt % record.__dict__ - if record.exc_info: - # Cache the traceback text to avoid converting it multiple times - # (it's constant anyway) - if not record.exc_text: - record.exc_text = self.formatException(record.exc_info) - if record.exc_text: - if s[-1] != "\n": - s = s + "\n" - s = s + record.exc_text - return s - -# -# The default formatter to use when no other is specified -# -_defaultFormatter = Formatter() - -class BufferingFormatter: - """ - A formatter suitable for formatting a number of records. - """ - def __init__(self, linefmt=None): - """ - Optionally specify a formatter which will be used to format each - individual record. - """ - if linefmt: - self.linefmt = linefmt - else: - self.linefmt = _defaultFormatter - - def formatHeader(self, records): - """ - Return the header string for the specified records. - """ - return "" - - def formatFooter(self, records): - """ - Return the footer string for the specified records. - """ - return "" - - def format(self, records): - """ - Format the specified records and return the result as a string. - """ - rv = "" - if len(records) > 0: - rv = rv + self.formatHeader(records) - for record in records: - rv = rv + self.linefmt.format(record) - rv = rv + self.formatFooter(records) - return rv - -#--------------------------------------------------------------------------- -# Filter classes and functions -#--------------------------------------------------------------------------- - -class Filter: - """ - Filter instances are used to perform arbitrary filtering of LogRecords. - - Loggers and Handlers can optionally use Filter instances to filter - records as desired. The base filter class only allows events which are - below a certain point in the logger hierarchy. For example, a filter - initialized with "A.B" will allow events logged by loggers "A.B", - "A.B.C", "A.B.C.D", "A.B.D" etc. but not "A.BB", "B.A.B" etc. If - initialized with the empty string, all events are passed. - """ - def __init__(self, name=''): - """ - Initialize a filter. - - Initialize with the name of the logger which, together with its - children, will have its events allowed through the filter. If no - name is specified, allow every event. - """ - self.name = name - self.nlen = len(name) - - def filter(self, record): - """ - Determine if the specified record is to be logged. - - Is the specified record to be logged? Returns 0 for no, nonzero for - yes. If deemed appropriate, the record may be modified in-place. - """ - if self.nlen == 0: - return 1 - elif self.name == record.name: - return 1 - elif string.find(record.name, self.name, 0, self.nlen) != 0: - return 0 - return (record.name[self.nlen] == ".") - -class Filterer: - """ - A base class for loggers and handlers which allows them to share - common code. - """ - def __init__(self): - """ - Initialize the list of filters to be an empty list. - """ - self.filters = [] - - def addFilter(self, filter): - """ - Add the specified filter to this handler. - """ - if not (filter in self.filters): - self.filters.append(filter) - - def removeFilter(self, filter): - """ - Remove the specified filter from this handler. - """ - if filter in self.filters: - self.filters.remove(filter) - - def filter(self, record): - """ - Determine if a record is loggable by consulting all the filters. - - The default is to allow the record to be logged; any filter can veto - this and the record is then dropped. Returns a zero value if a record - is to be dropped, else non-zero. - """ - rv = 1 - for f in self.filters: - if not f.filter(record): - rv = 0 - break - return rv - -#--------------------------------------------------------------------------- -# Handler classes and functions -#--------------------------------------------------------------------------- - -_handlers = {} #repository of handlers (for flushing when shutdown called) - -class Handler(Filterer): - """ - Handler instances dispatch logging events to specific destinations. - - The base handler class. Acts as a placeholder which defines the Handler - interface. Handlers can optionally use Formatter instances to format - records as desired. By default, no formatter is specified; in this case, - the 'raw' message as determined by record.message is logged. - """ - def __init__(self, level=NOTSET): - """ - Initializes the instance - basically setting the formatter to None - and the filter list to empty. - """ - Filterer.__init__(self) - self.level = level - self.formatter = None - #get the module data lock, as we're updating a shared structure. - _acquireLock() - try: #unlikely to raise an exception, but you never know... - _handlers[self] = 1 - finally: - _releaseLock() - self.createLock() - - def createLock(self): - """ - Acquire a thread lock for serializing access to the underlying I/O. - """ - if thread: - self.lock = thread.allocate_lock() - else: - self.lock = None - - def acquire(self): - """ - Acquire the I/O thread lock. - """ - if self.lock: - self.lock.acquire() - - def release(self): - """ - Release the I/O thread lock. - """ - if self.lock: - self.lock.release() - - def setLevel(self, level): - """ - Set the logging level of this handler. - """ - self.level = level - - def format(self, record): - """ - Format the specified record. - - If a formatter is set, use it. Otherwise, use the default formatter - for the module. - """ - if self.formatter: - fmt = self.formatter - else: - fmt = _defaultFormatter - return fmt.format(record) - - def emit(self, record): - """ - Do whatever it takes to actually log the specified logging record. - - This version is intended to be implemented by subclasses and so - raises a NotImplementedError. - """ - raise NotImplementedError, 'emit must be implemented '\ - 'by Handler subclasses' - - def handle(self, record): - """ - Conditionally emit the specified logging record. - - Emission depends on filters which may have been added to the handler. - Wrap the actual emission of the record with acquisition/release of - the I/O thread lock. Returns whether the filter passed the record for - emission. - """ - rv = self.filter(record) - if rv: - self.acquire() - try: - self.emit(record) - finally: - self.release() - return rv - - def setFormatter(self, fmt): - """ - Set the formatter for this handler. - """ - self.formatter = fmt - - def flush(self): - """ - Ensure all logging output has been flushed. - - This version does nothing and is intended to be implemented by - subclasses. - """ - pass - - def close(self): - """ - Tidy up any resources used by the handler. - - This version does removes the handler from an internal list - of handlers which is closed when shutdown() is called. Subclasses - should ensure that this gets called from overridden close() - methods. - """ - #get the module data lock, as we're updating a shared structure. - _acquireLock() - try: #unlikely to raise an exception, but you never know... - del _handlers[self] - finally: - _releaseLock() - - def handleError(self, record): - """ - Handle errors which occur during an emit() call. - - This method should be called from handlers when an exception is - encountered during an emit() call. If raiseExceptions is false, - exceptions get silently ignored. This is what is mostly wanted - for a logging system - most users will not care about errors in - the logging system, they are more interested in application errors. - You could, however, replace this with a custom handler if you wish. - The record which was being processed is passed in to this method. - """ - if raiseExceptions: - import traceback - ei = sys.exc_info() - traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr) - del ei - -class StreamHandler(Handler): - """ - A handler class which writes logging records, appropriately formatted, - to a stream. Note that this class does not close the stream, as - sys.stdout or sys.stderr may be used. - """ - def __init__(self, strm=None): - """ - Initialize the handler. - - If strm is not specified, sys.stderr is used. - """ - Handler.__init__(self) - if not strm: - strm = sys.stderr - self.stream = strm - self.formatter = None - - def flush(self): - """ - Flushes the stream. - """ - self.stream.flush() - - def emit(self, record): - """ - Emit a record. - - If a formatter is specified, it is used to format the record. - The record is then written to the stream with a trailing newline - [N.B. this may be removed depending on feedback]. If exception - information is present, it is formatted using - traceback.print_exception and appended to the stream. - """ - try: - msg = self.format(record) - if not hasattr(types, "UnicodeType"): #if no unicode support... - self.stream.write("%s\n" % msg) - else: - try: - self.stream.write("%s\n" % msg) - except UnicodeError: - self.stream.write("%s\n" % msg.encode("UTF-8")) - self.flush() - except: - self.handleError(record) - -class FileHandler(StreamHandler): - """ - A handler class which writes formatted logging records to disk files. - """ - def __init__(self, filename, mode="a"): - """ - Open the specified file and use it as the stream for logging. - """ - StreamHandler.__init__(self, open(filename, mode)) - self.baseFilename = filename - self.mode = mode - - def close(self): - """ - Closes the stream. - """ - self.flush() - self.stream.close() - StreamHandler.close(self) - -#--------------------------------------------------------------------------- -# Manager classes and functions -#--------------------------------------------------------------------------- - -class PlaceHolder: - """ - PlaceHolder instances are used in the Manager logger hierarchy to take - the place of nodes for which no loggers have been defined. This class is - intended for internal use only and not as part of the public API. - """ - def __init__(self, alogger): - """ - Initialize with the specified logger being a child of this placeholder. - """ - self.loggers = [alogger] - - def append(self, alogger): - """ - Add the specified logger as a child of this placeholder. - """ - if alogger not in self.loggers: - self.loggers.append(alogger) - -# -# Determine which class to use when instantiating loggers. -# -_loggerClass = None - -def setLoggerClass(klass): - """ - Set the class to be used when instantiating a logger. The class should - define __init__() such that only a name argument is required, and the - __init__() should call Logger.__init__() - """ - if klass != Logger: - if not issubclass(klass, Logger): - raise TypeError, "logger not derived from logging.Logger: " + \ - klass.__name__ - global _loggerClass - _loggerClass = klass - -class Manager: - """ - There is [under normal circumstances] just one Manager instance, which - holds the hierarchy of loggers. - """ - def __init__(self, rootnode): - """ - Initialize the manager with the root node of the logger hierarchy. - """ - self.root = rootnode - self.disable = 0 - self.emittedNoHandlerWarning = 0 - self.loggerDict = {} - - def getLogger(self, name): - """ - Get a logger with the specified name (channel name), creating it - if it doesn't yet exist. - - If a PlaceHolder existed for the specified name [i.e. the logger - didn't exist but a child of it did], replace it with the created - logger and fix up the parent/child references which pointed to the - placeholder to now point to the logger. - """ - rv = None - _acquireLock() - try: - if self.loggerDict.has_key(name): - rv = self.loggerDict[name] - if isinstance(rv, PlaceHolder): - ph = rv - rv = _loggerClass(name) - rv.manager = self - self.loggerDict[name] = rv - self._fixupChildren(ph, rv) - self._fixupParents(rv) - else: - rv = _loggerClass(name) - rv.manager = self - self.loggerDict[name] = rv - self._fixupParents(rv) - finally: - _releaseLock() - return rv - - def _fixupParents(self, alogger): - """ - Ensure that there are either loggers or placeholders all the way - from the specified logger to the root of the logger hierarchy. - """ - name = alogger.name - i = string.rfind(name, ".") - rv = None - while (i > 0) and not rv: - substr = name[:i] - if not self.loggerDict.has_key(substr): - self.loggerDict[substr] = PlaceHolder(alogger) - else: - obj = self.loggerDict[substr] - if isinstance(obj, Logger): - rv = obj - else: - assert isinstance(obj, PlaceHolder) - obj.append(alogger) - i = string.rfind(name, ".", 0, i - 1) - if not rv: - rv = self.root - alogger.parent = rv - - def _fixupChildren(self, ph, alogger): - """ - Ensure that children of the placeholder ph are connected to the - specified logger. - """ - for c in ph.loggers: - if string.find(c.parent.name, alogger.name) <> 0: - alogger.parent = c.parent - c.parent = alogger - -#--------------------------------------------------------------------------- -# Logger classes and functions -#--------------------------------------------------------------------------- - -class Logger(Filterer): - """ - Instances of the Logger class represent a single logging channel. A - "logging channel" indicates an area of an application. Exactly how an - "area" is defined is up to the application developer. Since an - application can have any number of areas, logging channels are identified - by a unique string. Application areas can be nested (e.g. an area - of "input processing" might include sub-areas "read CSV files", "read - XLS files" and "read Gnumeric files"). To cater for this natural nesting, - channel names are organized into a namespace hierarchy where levels are - separated by periods, much like the Java or Python package namespace. So - in the instance given above, channel names might be "input" for the upper - level, and "input.csv", "input.xls" and "input.gnu" for the sub-levels. - There is no arbitrary limit to the depth of nesting. - """ - def __init__(self, name, level=NOTSET): - """ - Initialize the logger with a name and an optional level. - """ - Filterer.__init__(self) - self.name = name - self.level = level - self.parent = None - self.propagate = 1 - self.handlers = [] - self.disabled = 0 - - def setLevel(self, level): - """ - Set the logging level of this logger. - """ - self.level = level - -# def getRoot(self): -# """ -# Get the root of the logger hierarchy. -# """ -# return Logger.root - - def debug(self, msg, *args, **kwargs): - """ - Log 'msg % args' with severity 'DEBUG'. - - To pass exception information, use the keyword argument exc_info with - a true value, e.g. - - logger.debug("Houston, we have a %s", "thorny problem", exc_info=1) - """ - if self.manager.disable >= DEBUG: - return - if DEBUG >= self.getEffectiveLevel(): - apply(self._log, (DEBUG, msg, args), kwargs) - - def info(self, msg, *args, **kwargs): - """ - Log 'msg % args' with severity 'INFO'. - - To pass exception information, use the keyword argument exc_info with - a true value, e.g. - - logger.info("Houston, we have a %s", "interesting problem", exc_info=1) - """ - if self.manager.disable >= INFO: - return - if INFO >= self.getEffectiveLevel(): - apply(self._log, (INFO, msg, args), kwargs) - - def warning(self, msg, *args, **kwargs): - """ - Log 'msg % args' with severity 'WARNING'. - - To pass exception information, use the keyword argument exc_info with - a true value, e.g. - - logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1) - """ - if self.manager.disable >= WARNING: - return - if self.isEnabledFor(WARNING): - apply(self._log, (WARNING, msg, args), kwargs) - - warn = warning - - def error(self, msg, *args, **kwargs): - """ - Log 'msg % args' with severity 'ERROR'. - - To pass exception information, use the keyword argument exc_info with - a true value, e.g. - - logger.error("Houston, we have a %s", "major problem", exc_info=1) - """ - if self.manager.disable >= ERROR: - return - if self.isEnabledFor(ERROR): - apply(self._log, (ERROR, msg, args), kwargs) - - def exception(self, msg, *args): - """ - Convenience method for logging an ERROR with exception information. - """ - apply(self.error, (msg,) + args, {'exc_info': 1}) - - def critical(self, msg, *args, **kwargs): - """ - Log 'msg % args' with severity 'CRITICAL'. - - To pass exception information, use the keyword argument exc_info with - a true value, e.g. - - logger.critical("Houston, we have a %s", "major disaster", exc_info=1) - """ - if self.manager.disable >= CRITICAL: - return - if CRITICAL >= self.getEffectiveLevel(): - apply(self._log, (CRITICAL, msg, args), kwargs) - - fatal = critical - - def log(self, level, msg, *args, **kwargs): - """ - Log 'msg % args' with the severity 'level'. - - To pass exception information, use the keyword argument exc_info with - a true value, e.g. - - logger.log(level, "We have a %s", "mysterious problem", exc_info=1) - """ - if self.manager.disable >= level: - return - if self.isEnabledFor(level): - apply(self._log, (level, msg, args), kwargs) - - def findCaller(self): - """ - Find the stack frame of the caller so that we can note the source - file name and line number. - """ - f = sys._getframe(1) - while 1: - co = f.f_code - filename = os.path.normcase(co.co_filename) - if filename == _srcfile: - f = f.f_back - continue - return filename, f.f_lineno - - def makeRecord(self, name, level, fn, lno, msg, args, exc_info): - """ - A factory method which can be overridden in subclasses to create - specialized LogRecords. - """ - return LogRecord(name, level, fn, lno, msg, args, exc_info) - - def _log(self, level, msg, args, exc_info=None): - """ - Low-level logging routine which creates a LogRecord and then calls - all the handlers of this logger to handle the record. - """ - if _srcfile: - fn, lno = self.findCaller() - else: - fn, lno = "", 0 - if exc_info: - if type(exc_info) != types.TupleType: - exc_info = sys.exc_info() - record = self.makeRecord(self.name, level, fn, lno, msg, args, exc_info) - self.handle(record) - - def handle(self, record): - """ - Call the handlers for the specified record. - - This method is used for unpickled records received from a socket, as - well as those created locally. Logger-level filtering is applied. - """ - if (not self.disabled) and self.filter(record): - self.callHandlers(record) - - def addHandler(self, hdlr): - """ - Add the specified handler to this logger. - """ - if not (hdlr in self.handlers): - self.handlers.append(hdlr) - - def removeHandler(self, hdlr): - """ - Remove the specified handler from this logger. - """ - if hdlr in self.handlers: - #hdlr.close() - self.handlers.remove(hdlr) - - def callHandlers(self, record): - """ - Pass a record to all relevant handlers. - - Loop through all handlers for this logger and its parents in the - logger hierarchy. If no handler was found, output a one-off error - message to sys.stderr. Stop searching up the hierarchy whenever a - logger with the "propagate" attribute set to zero is found - that - will be the last logger whose handlers are called. - """ - c = self - found = 0 - while c: - for hdlr in c.handlers: - found = found + 1 - if record.levelno >= hdlr.level: - hdlr.handle(record) - if not c.propagate: - c = None #break out - else: - c = c.parent - if (found == 0) and not self.manager.emittedNoHandlerWarning: - sys.stderr.write("No handlers could be found for logger" - " \"%s\"\n" % self.name) - self.manager.emittedNoHandlerWarning = 1 - - def getEffectiveLevel(self): - """ - Get the effective level for this logger. - - Loop through this logger and its parents in the logger hierarchy, - looking for a non-zero logging level. Return the first one found. - """ - logger = self - while logger: - if logger.level: - return logger.level - logger = logger.parent - return NOTSET - - def isEnabledFor(self, level): - """ - Is this logger enabled for level 'level'? - """ - if self.manager.disable >= level: - return 0 - return level >= self.getEffectiveLevel() - -class RootLogger(Logger): - """ - A root logger is not that different to any other logger, except that - it must have a logging level and there is only one instance of it in - the hierarchy. - """ - def __init__(self, level): - """ - Initialize the logger with the name "root". - """ - Logger.__init__(self, "root", level) - -_loggerClass = Logger - -root = RootLogger(WARNING) -Logger.root = root -Logger.manager = Manager(Logger.root) - -#--------------------------------------------------------------------------- -# Configuration classes and functions -#--------------------------------------------------------------------------- - -BASIC_FORMAT = "%(levelname)s:%(name)s:%(message)s" - -def basicConfig(): - """ - Do basic configuration for the logging system by creating a - StreamHandler with a default Formatter and adding it to the - root logger. - """ - if len(root.handlers) == 0: - hdlr = StreamHandler() - fmt = Formatter(BASIC_FORMAT) - hdlr.setFormatter(fmt) - root.addHandler(hdlr) - -#--------------------------------------------------------------------------- -# Utility functions at module level. -# Basically delegate everything to the root logger. -#--------------------------------------------------------------------------- - -def getLogger(name=None): - """ - Return a logger with the specified name, creating it if necessary. - - If no name is specified, return the root logger. - """ - if name: - return Logger.manager.getLogger(name) - else: - return root - -#def getRootLogger(): -# """ -# Return the root logger. -# -# Note that getLogger('') now does the same thing, so this function is -# deprecated and may disappear in the future. -# """ -# return root - -def critical(msg, *args, **kwargs): - """ - Log a message with severity 'CRITICAL' on the root logger. - """ - if len(root.handlers) == 0: - basicConfig() - apply(root.critical, (msg,)+args, kwargs) - -fatal = critical - -def error(msg, *args, **kwargs): - """ - Log a message with severity 'ERROR' on the root logger. - """ - if len(root.handlers) == 0: - basicConfig() - apply(root.error, (msg,)+args, kwargs) - -def exception(msg, *args): - """ - Log a message with severity 'ERROR' on the root logger, - with exception information. - """ - apply(error, (msg,)+args, {'exc_info': 1}) - -def warning(msg, *args, **kwargs): - """ - Log a message with severity 'WARNING' on the root logger. - """ - if len(root.handlers) == 0: - basicConfig() - apply(root.warning, (msg,)+args, kwargs) - -warn = warning - -def info(msg, *args, **kwargs): - """ - Log a message with severity 'INFO' on the root logger. - """ - if len(root.handlers) == 0: - basicConfig() - apply(root.info, (msg,)+args, kwargs) - -def debug(msg, *args, **kwargs): - """ - Log a message with severity 'DEBUG' on the root logger. - """ - if len(root.handlers) == 0: - basicConfig() - apply(root.debug, (msg,)+args, kwargs) - -def disable(level): - """ - Disable all logging calls less severe than 'level'. - """ - root.manager.disable = level - -def shutdown(): - """ - Perform any cleanup actions in the logging system (e.g. flushing - buffers). - - Should be called at application exit. - """ - for h in _handlers.keys(): - h.flush() - h.close() - -#Let's try and shutdown automatically on application exit... -try: - import atexit - atexit.register(shutdown) -except ImportError: # for Python versions < 2.0 - def exithook(status, old_exit=sys.exit): - try: - shutdown() - finally: - old_exit(status) - - sys.exit = exithook diff --git a/tools/python/logging/logging-0.4.9.2/logging/config.py b/tools/python/logging/logging-0.4.9.2/logging/config.py deleted file mode 100644 index c9ffab03e5..0000000000 --- a/tools/python/logging/logging-0.4.9.2/logging/config.py +++ /dev/null @@ -1,301 +0,0 @@ -# Copyright 2001-2004 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -""" -Configuration functions for the logging package for Python. The core package -is based on PEP 282 and comments thereto in comp.lang.python, and influenced -by Apache's log4j system. - -Should work under Python versions >= 1.5.2, except that source line -information is not available unless 'sys._getframe()' is. - -Copyright (C) 2001-2004 Vinay Sajip. All Rights Reserved. - -To use, simply 'import logging' and log away! -""" - -import sys, logging, logging.handlers, string, thread, threading, socket, struct, os - -from SocketServer import ThreadingTCPServer, StreamRequestHandler - - -DEFAULT_LOGGING_CONFIG_PORT = 9030 - -if sys.platform == "win32": - RESET_ERROR = 10054 #WSAECONNRESET -else: - RESET_ERROR = 104 #ECONNRESET - -# -# The following code implements a socket listener for on-the-fly -# reconfiguration of logging. -# -# _listener holds the server object doing the listening -_listener = None - -def fileConfig(fname, defaults=None): - """ - Read the logging configuration from a ConfigParser-format file. - - This can be called several times from an application, allowing an end user - the ability to select from various pre-canned configurations (if the - developer provides a mechanism to present the choices and load the chosen - configuration). - In versions of ConfigParser which have the readfp method [typically - shipped in 2.x versions of Python], you can pass in a file-like object - rather than a filename, in which case the file-like object will be read - using readfp. - """ - import ConfigParser - - cp = ConfigParser.ConfigParser(defaults) - if hasattr(cp, 'readfp') and hasattr(fname, 'readline'): - cp.readfp(fname) - else: - cp.read(fname) - #first, do the formatters... - flist = cp.get("formatters", "keys") - if len(flist): - flist = string.split(flist, ",") - formatters = {} - for form in flist: - sectname = "formatter_%s" % form - opts = cp.options(sectname) - if "format" in opts: - fs = cp.get(sectname, "format", 1) - else: - fs = None - if "datefmt" in opts: - dfs = cp.get(sectname, "datefmt", 1) - else: - dfs = None - f = logging.Formatter(fs, dfs) - formatters[form] = f - #next, do the handlers... - #critical section... - logging._acquireLock() - try: - try: - #first, lose the existing handlers... - logging._handlers.clear() - #now set up the new ones... - hlist = cp.get("handlers", "keys") - if len(hlist): - hlist = string.split(hlist, ",") - handlers = {} - fixups = [] #for inter-handler references - for hand in hlist: - sectname = "handler_%s" % hand - klass = cp.get(sectname, "class") - opts = cp.options(sectname) - if "formatter" in opts: - fmt = cp.get(sectname, "formatter") - else: - fmt = "" - klass = eval(klass, vars(logging)) - args = cp.get(sectname, "args") - args = eval(args, vars(logging)) - h = apply(klass, args) - if "level" in opts: - level = cp.get(sectname, "level") - h.setLevel(logging._levelNames[level]) - if len(fmt): - h.setFormatter(formatters[fmt]) - #temporary hack for FileHandler and MemoryHandler. - if klass == logging.handlers.MemoryHandler: - if "target" in opts: - target = cp.get(sectname,"target") - else: - target = "" - if len(target): #the target handler may not be loaded yet, so keep for later... - fixups.append((h, target)) - handlers[hand] = h - #now all handlers are loaded, fixup inter-handler references... - for fixup in fixups: - h = fixup[0] - t = fixup[1] - h.setTarget(handlers[t]) - #at last, the loggers...first the root... - llist = cp.get("loggers", "keys") - llist = string.split(llist, ",") - llist.remove("root") - sectname = "logger_root" - root = logging.root - log = root - opts = cp.options(sectname) - if "level" in opts: - level = cp.get(sectname, "level") - log.setLevel(logging._levelNames[level]) - for h in root.handlers[:]: - root.removeHandler(h) - hlist = cp.get(sectname, "handlers") - if len(hlist): - hlist = string.split(hlist, ",") - for hand in hlist: - log.addHandler(handlers[hand]) - #and now the others... - #we don't want to lose the existing loggers, - #since other threads may have pointers to them. - #existing is set to contain all existing loggers, - #and as we go through the new configuration we - #remove any which are configured. At the end, - #what's left in existing is the set of loggers - #which were in the previous configuration but - #which are not in the new configuration. - existing = root.manager.loggerDict.keys() - #now set up the new ones... - for log in llist: - sectname = "logger_%s" % log - qn = cp.get(sectname, "qualname") - opts = cp.options(sectname) - if "propagate" in opts: - propagate = cp.getint(sectname, "propagate") - else: - propagate = 1 - logger = logging.getLogger(qn) - if qn in existing: - existing.remove(qn) - if "level" in opts: - level = cp.get(sectname, "level") - logger.setLevel(logging._levelNames[level]) - for h in logger.handlers[:]: - logger.removeHandler(h) - logger.propagate = propagate - logger.disabled = 0 - hlist = cp.get(sectname, "handlers") - if len(hlist): - hlist = string.split(hlist, ",") - for hand in hlist: - logger.addHandler(handlers[hand]) - #Disable any old loggers. There's no point deleting - #them as other threads may continue to hold references - #and by disabling them, you stop them doing any logging. - for log in existing: - root.manager.loggerDict[log].disabled = 1 - except: - import traceback - ei = sys.exc_info() - traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr) - del ei - finally: - logging._releaseLock() - -def listen(port=DEFAULT_LOGGING_CONFIG_PORT): - """ - Start up a socket server on the specified port, and listen for new - configurations. - - These will be sent as a file suitable for processing by fileConfig(). - Returns a Thread object on which you can call start() to start the server, - and which you can join() when appropriate. To stop the server, call - stopListening(). - """ - if not thread: - raise NotImplementedError, "listen() needs threading to work" - - class ConfigStreamHandler(StreamRequestHandler): - """ - Handler for a logging configuration request. - - It expects a completely new logging configuration and uses fileConfig - to install it. - """ - def handle(self): - """ - Handle a request. - - Each request is expected to be a 4-byte length, - followed by the config file. Uses fileConfig() to do the - grunt work. - """ - import tempfile - try: - conn = self.connection - chunk = conn.recv(4) - if len(chunk) == 4: - slen = struct.unpack(">L", chunk)[0] - chunk = self.connection.recv(slen) - while len(chunk) < slen: - chunk = chunk + conn.recv(slen - len(chunk)) - #Apply new configuration. We'd like to be able to - #create a StringIO and pass that in, but unfortunately - #1.5.2 ConfigParser does not support reading file - #objects, only actual files. So we create a temporary - #file and remove it later. - file = tempfile.mktemp(".ini") - f = open(file, "w") - f.write(chunk) - f.close() - fileConfig(file) - os.remove(file) - except socket.error, e: - if type(e.args) != types.TupleType: - raise - else: - errcode = e.args[0] - if errcode != RESET_ERROR: - raise - - class ConfigSocketReceiver(ThreadingTCPServer): - """ - A simple TCP socket-based logging config receiver. - """ - - allow_reuse_address = 1 - - def __init__(self, host='localhost', port=DEFAULT_LOGGING_CONFIG_PORT, - handler=None): - ThreadingTCPServer.__init__(self, (host, port), handler) - logging._acquireLock() - self.abort = 0 - logging._releaseLock() - self.timeout = 1 - - def serve_until_stopped(self): - import select - abort = 0 - while not abort: - rd, wr, ex = select.select([self.socket.fileno()], - [], [], - self.timeout) - if rd: - self.handle_request() - logging._acquireLock() - abort = self.abort - logging._releaseLock() - - def serve(rcvr, hdlr, port): - server = rcvr(port=port, handler=hdlr) - global _listener - logging._acquireLock() - _listener = server - logging._releaseLock() - server.serve_until_stopped() - - return threading.Thread(target=serve, - args=(ConfigSocketReceiver, - ConfigStreamHandler, port)) - -def stopListening(): - """ - Stop the listening server which was created with a call to listen(). - """ - global _listener - if _listener: - logging._acquireLock() - _listener.abort = 1 - _listener = None - logging._releaseLock() diff --git a/tools/python/logging/logging-0.4.9.2/logging/handlers.py b/tools/python/logging/logging-0.4.9.2/logging/handlers.py deleted file mode 100644 index 99a543e5db..0000000000 --- a/tools/python/logging/logging-0.4.9.2/logging/handlers.py +++ /dev/null @@ -1,787 +0,0 @@ -# Copyright 2001-2004 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -""" -Additional handlers for the logging package for Python. The core package is -based on PEP 282 and comments thereto in comp.lang.python, and influenced by -Apache's log4j system. - -Should work under Python versions >= 1.5.2, except that source line -information is not available unless 'sys._getframe()' is. - -Copyright (C) 2001-2004 Vinay Sajip. All Rights Reserved. - -To use, simply 'import logging' and log away! -""" - -import sys, logging, socket, types, os, string, cPickle, struct, time - -from SocketServer import ThreadingTCPServer, StreamRequestHandler - -# -# Some constants... -# - -DEFAULT_TCP_LOGGING_PORT = 9020 -DEFAULT_UDP_LOGGING_PORT = 9021 -DEFAULT_HTTP_LOGGING_PORT = 9022 -DEFAULT_SOAP_LOGGING_PORT = 9023 -SYSLOG_UDP_PORT = 514 - - -class RotatingFileHandler(logging.FileHandler): - def __init__(self, filename, mode="a", maxBytes=0, backupCount=0): - """ - Open the specified file and use it as the stream for logging. - - By default, the file grows indefinitely. You can specify particular - values of maxBytes and backupCount to allow the file to rollover at - a predetermined size. - - Rollover occurs whenever the current log file is nearly maxBytes in - length. If backupCount is >= 1, the system will successively create - new files with the same pathname as the base file, but with extensions - ".1", ".2" etc. appended to it. For example, with a backupCount of 5 - and a base file name of "app.log", you would get "app.log", - "app.log.1", "app.log.2", ... through to "app.log.5". The file being - written to is always "app.log" - when it gets filled up, it is closed - and renamed to "app.log.1", and if files "app.log.1", "app.log.2" etc. - exist, then they are renamed to "app.log.2", "app.log.3" etc. - respectively. - - If maxBytes is zero, rollover never occurs. - """ - logging.FileHandler.__init__(self, filename, mode) - self.maxBytes = maxBytes - self.backupCount = backupCount - if maxBytes > 0: - self.mode = "a" - - def doRollover(self): - """ - Do a rollover, as described in __init__(). - """ - - self.stream.close() - if self.backupCount > 0: - for i in range(self.backupCount - 1, 0, -1): - sfn = "%s.%d" % (self.baseFilename, i) - dfn = "%s.%d" % (self.baseFilename, i + 1) - if os.path.exists(sfn): - #print "%s -> %s" % (sfn, dfn) - if os.path.exists(dfn): - os.remove(dfn) - os.rename(sfn, dfn) - dfn = self.baseFilename + ".1" - if os.path.exists(dfn): - os.remove(dfn) - os.rename(self.baseFilename, dfn) - #print "%s -> %s" % (self.baseFilename, dfn) - self.stream = open(self.baseFilename, "w") - - def emit(self, record): - """ - Emit a record. - - Output the record to the file, catering for rollover as described - in doRollover(). - """ - if self.maxBytes > 0: # are we rolling over? - msg = "%s\n" % self.format(record) - self.stream.seek(0, 2) #due to non-posix-compliant Windows feature - if self.stream.tell() + len(msg) >= self.maxBytes: - self.doRollover() - logging.FileHandler.emit(self, record) - - -class SocketHandler(logging.Handler): - """ - A handler class which writes logging records, in pickle format, to - a streaming socket. The socket is kept open across logging calls. - If the peer resets it, an attempt is made to reconnect on the next call. - The pickle which is sent is that of the LogRecord's attribute dictionary - (__dict__), so that the receiver does not need to have the logging module - installed in order to process the logging event. - - To unpickle the record at the receiving end into a LogRecord, use the - makeLogRecord function. - """ - - def __init__(self, host, port): - """ - Initializes the handler with a specific host address and port. - - The attribute 'closeOnError' is set to 1 - which means that if - a socket error occurs, the socket is silently closed and then - reopened on the next logging call. - """ - logging.Handler.__init__(self) - self.host = host - self.port = port - self.sock = None - self.closeOnError = 0 - self.retryTime = None - # - # Exponential backoff parameters. - # - self.retryStart = 1.0 - self.retryMax = 30.0 - self.retryFactor = 2.0 - - def makeSocket(self): - """ - A factory method which allows subclasses to define the precise - type of socket they want. - """ - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.connect((self.host, self.port)) - return s - - def createSocket(self): - """ - Try to create a socket, using an exponential backoff with - a max retry time. Thanks to Robert Olson for the original patch - (SF #815911) which has been slightly refactored. - """ - now = time.time() - # Either retryTime is None, in which case this - # is the first time back after a disconnect, or - # we've waited long enough. - if self.retryTime is None: - attempt = 1 - else: - attempt = (now >= self.retryTime) - if attempt: - try: - self.sock = self.makeSocket() - self.retryTime = None # next time, no delay before trying - except: - #Creation failed, so set the retry time and return. - if self.retryTime is None: - self.retryPeriod = self.retryStart - else: - self.retryPeriod = self.retryPeriod * self.retryFactor - if self.retryPeriod > self.retryMax: - self.retryPeriod = self.retryMax - self.retryTime = now + self.retryPeriod - - def send(self, s): - """ - Send a pickled string to the socket. - - This function allows for partial sends which can happen when the - network is busy. - """ - if self.sock is None: - self.createSocket() - #self.sock can be None either because we haven't reached the retry - #time yet, or because we have reached the retry time and retried, - #but are still unable to connect. - if self.sock: - try: - if hasattr(self.sock, "sendall"): - self.sock.sendall(s) - else: - sentsofar = 0 - left = len(s) - while left > 0: - sent = self.sock.send(s[sentsofar:]) - sentsofar = sentsofar + sent - left = left - sent - except socket.error: - self.sock.close() - self.sock = None # so we can call createSocket next time - - def makePickle(self, record): - """ - Pickles the record in binary format with a length prefix, and - returns it ready for transmission across the socket. - """ - ei = record.exc_info - if ei: - dummy = self.format(record) # just to get traceback text into record.exc_text - record.exc_info = None # to avoid Unpickleable error - s = cPickle.dumps(record.__dict__, 1) - if ei: - record.exc_info = ei # for next handler - slen = struct.pack(">L", len(s)) - return slen + s - - def handleError(self, record): - """ - Handle an error during logging. - - An error has occurred during logging. Most likely cause - - connection lost. Close the socket so that we can retry on the - next event. - """ - if self.closeOnError and self.sock: - self.sock.close() - self.sock = None #try to reconnect next time - else: - logging.Handler.handleError(self, record) - - def emit(self, record): - """ - Emit a record. - - Pickles the record and writes it to the socket in binary format. - If there is an error with the socket, silently drop the packet. - If there was a problem with the socket, re-establishes the - socket. - """ - try: - s = self.makePickle(record) - self.send(s) - except: - self.handleError(record) - - def close(self): - """ - Closes the socket. - """ - if self.sock: - self.sock.close() - self.sock = None - logging.Handler.close(self) - -class DatagramHandler(SocketHandler): - """ - A handler class which writes logging records, in pickle format, to - a datagram socket. The pickle which is sent is that of the LogRecord's - attribute dictionary (__dict__), so that the receiver does not need to - have the logging module installed in order to process the logging event. - - To unpickle the record at the receiving end into a LogRecord, use the - makeLogRecord function. - - """ - def __init__(self, host, port): - """ - Initializes the handler with a specific host address and port. - """ - SocketHandler.__init__(self, host, port) - self.closeOnError = 0 - - def makeSocket(self): - """ - The factory method of SocketHandler is here overridden to create - a UDP socket (SOCK_DGRAM). - """ - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - return s - - def send(self, s): - """ - Send a pickled string to a socket. - - This function no longer allows for partial sends which can happen - when the network is busy - UDP does not guarantee delivery and - can deliver packets out of sequence. - """ - self.sock.sendto(s, (self.host, self.port)) - -class SysLogHandler(logging.Handler): - """ - A handler class which sends formatted logging records to a syslog - server. Based on Sam Rushing's syslog module: - http://www.nightmare.com/squirl/python-ext/misc/syslog.py - Contributed by Nicolas Untz (after which minor refactoring changes - have been made). - """ - - # from : - # ====================================================================== - # priorities/facilities are encoded into a single 32-bit quantity, where - # the bottom 3 bits are the priority (0-7) and the top 28 bits are the - # facility (0-big number). Both the priorities and the facilities map - # roughly one-to-one to strings in the syslogd(8) source code. This - # mapping is included in this file. - # - # priorities (these are ordered) - - LOG_EMERG = 0 # system is unusable - LOG_ALERT = 1 # action must be taken immediately - LOG_CRIT = 2 # critical conditions - LOG_ERR = 3 # error conditions - LOG_WARNING = 4 # warning conditions - LOG_NOTICE = 5 # normal but significant condition - LOG_INFO = 6 # informational - LOG_DEBUG = 7 # debug-level messages - - # facility codes - LOG_KERN = 0 # kernel messages - LOG_USER = 1 # random user-level messages - LOG_MAIL = 2 # mail system - LOG_DAEMON = 3 # system daemons - LOG_AUTH = 4 # security/authorization messages - LOG_SYSLOG = 5 # messages generated internally by syslogd - LOG_LPR = 6 # line printer subsystem - LOG_NEWS = 7 # network news subsystem - LOG_UUCP = 8 # UUCP subsystem - LOG_CRON = 9 # clock daemon - LOG_AUTHPRIV = 10 # security/authorization messages (private) - - # other codes through 15 reserved for system use - LOG_LOCAL0 = 16 # reserved for local use - LOG_LOCAL1 = 17 # reserved for local use - LOG_LOCAL2 = 18 # reserved for local use - LOG_LOCAL3 = 19 # reserved for local use - LOG_LOCAL4 = 20 # reserved for local use - LOG_LOCAL5 = 21 # reserved for local use - LOG_LOCAL6 = 22 # reserved for local use - LOG_LOCAL7 = 23 # reserved for local use - - priority_names = { - "alert": LOG_ALERT, - "crit": LOG_CRIT, - "critical": LOG_CRIT, - "debug": LOG_DEBUG, - "emerg": LOG_EMERG, - "err": LOG_ERR, - "error": LOG_ERR, # DEPRECATED - "info": LOG_INFO, - "notice": LOG_NOTICE, - "panic": LOG_EMERG, # DEPRECATED - "warn": LOG_WARNING, # DEPRECATED - "warning": LOG_WARNING, - } - - facility_names = { - "auth": LOG_AUTH, - "authpriv": LOG_AUTHPRIV, - "cron": LOG_CRON, - "daemon": LOG_DAEMON, - "kern": LOG_KERN, - "lpr": LOG_LPR, - "mail": LOG_MAIL, - "news": LOG_NEWS, - "security": LOG_AUTH, # DEPRECATED - "syslog": LOG_SYSLOG, - "user": LOG_USER, - "uucp": LOG_UUCP, - "local0": LOG_LOCAL0, - "local1": LOG_LOCAL1, - "local2": LOG_LOCAL2, - "local3": LOG_LOCAL3, - "local4": LOG_LOCAL4, - "local5": LOG_LOCAL5, - "local6": LOG_LOCAL6, - "local7": LOG_LOCAL7, - } - - def __init__(self, address=('localhost', SYSLOG_UDP_PORT), facility=LOG_USER): - """ - Initialize a handler. - - If address is specified as a string, UNIX socket is used. - If facility is not specified, LOG_USER is used. - """ - logging.Handler.__init__(self) - - self.address = address - self.facility = facility - if type(address) == types.StringType: - self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) - # syslog may require either DGRAM or STREAM sockets - try: - self.socket.connect(address) - except socket.error: - self.socket.close() - self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - self.socket.connect(address) - self.unixsocket = 1 - else: - self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - self.unixsocket = 0 - - self.formatter = None - - # curious: when talking to the unix-domain '/dev/log' socket, a - # zero-terminator seems to be required. this string is placed - # into a class variable so that it can be overridden if - # necessary. - log_format_string = '<%d>%s\000' - - def encodePriority (self, facility, priority): - """ - Encode the facility and priority. You can pass in strings or - integers - if strings are passed, the facility_names and - priority_names mapping dictionaries are used to convert them to - integers. - """ - if type(facility) == types.StringType: - facility = self.facility_names[facility] - if type(priority) == types.StringType: - priority = self.priority_names[priority] - return (facility << 3) | priority - - def close (self): - """ - Closes the socket. - """ - if self.unixsocket: - self.socket.close() - logging.Handler.close(self) - - def emit(self, record): - """ - Emit a record. - - The record is formatted, and then sent to the syslog server. If - exception information is present, it is NOT sent to the server. - """ - msg = self.format(record) - """ - We need to convert record level to lowercase, maybe this will - change in the future. - """ - msg = self.log_format_string % ( - self.encodePriority(self.facility, - string.lower(record.levelname)), - msg) - try: - if self.unixsocket: - self.socket.send(msg) - else: - self.socket.sendto(msg, self.address) - except: - self.handleError(record) - -class SMTPHandler(logging.Handler): - """ - A handler class which sends an SMTP email for each logging event. - """ - def __init__(self, mailhost, fromaddr, toaddrs, subject): - """ - Initialize the handler. - - Initialize the instance with the from and to addresses and subject - line of the email. To specify a non-standard SMTP port, use the - (host, port) tuple format for the mailhost argument. - """ - logging.Handler.__init__(self) - if type(mailhost) == types.TupleType: - host, port = mailhost - self.mailhost = host - self.mailport = port - else: - self.mailhost = mailhost - self.mailport = None - self.fromaddr = fromaddr - if type(toaddrs) == types.StringType: - toaddrs = [toaddrs] - self.toaddrs = toaddrs - self.subject = subject - - def getSubject(self, record): - """ - Determine the subject for the email. - - If you want to specify a subject line which is record-dependent, - override this method. - """ - return self.subject - - weekdayname = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] - - monthname = [None, - 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', - 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] - - def date_time(self): - """Return the current date and time formatted for a MIME header.""" - year, month, day, hh, mm, ss, wd, y, z = time.gmtime(time.time()) - s = "%s, %02d %3s %4d %02d:%02d:%02d GMT" % ( - self.weekdayname[wd], - day, self.monthname[month], year, - hh, mm, ss) - return s - - def emit(self, record): - """ - Emit a record. - - Format the record and send it to the specified addressees. - """ - try: - import smtplib - port = self.mailport - if not port: - port = smtplib.SMTP_PORT - smtp = smtplib.SMTP(self.mailhost, port) - msg = self.format(record) - msg = "From: %s\r\nTo: %s\r\nSubject: %s\r\nDate: %s\r\n\r\n%s" % ( - self.fromaddr, - string.join(self.toaddrs, ","), - self.getSubject(record), - self.date_time(), msg) - smtp.sendmail(self.fromaddr, self.toaddrs, msg) - smtp.quit() - except: - self.handleError(record) - -class NTEventLogHandler(logging.Handler): - """ - A handler class which sends events to the NT Event Log. Adds a - registry entry for the specified application name. If no dllname is - provided, win32service.pyd (which contains some basic message - placeholders) is used. Note that use of these placeholders will make - your event logs big, as the entire message source is held in the log. - If you want slimmer logs, you have to pass in the name of your own DLL - which contains the message definitions you want to use in the event log. - """ - def __init__(self, appname, dllname=None, logtype="Application"): - logging.Handler.__init__(self) - try: - import win32evtlogutil, win32evtlog - self.appname = appname - self._welu = win32evtlogutil - if not dllname: - dllname = os.path.split(self._welu.__file__) - dllname = os.path.split(dllname[0]) - dllname = os.path.join(dllname[0], r'win32service.pyd') - self.dllname = dllname - self.logtype = logtype - self._welu.AddSourceToRegistry(appname, dllname, logtype) - self.deftype = win32evtlog.EVENTLOG_ERROR_TYPE - self.typemap = { - logging.DEBUG : win32evtlog.EVENTLOG_INFORMATION_TYPE, - logging.INFO : win32evtlog.EVENTLOG_INFORMATION_TYPE, - logging.WARNING : win32evtlog.EVENTLOG_WARNING_TYPE, - logging.ERROR : win32evtlog.EVENTLOG_ERROR_TYPE, - logging.CRITICAL: win32evtlog.EVENTLOG_ERROR_TYPE, - } - except ImportError: - print "The Python Win32 extensions for NT (service, event "\ - "logging) appear not to be available." - self._welu = None - - def getMessageID(self, record): - """ - Return the message ID for the event record. If you are using your - own messages, you could do this by having the msg passed to the - logger being an ID rather than a formatting string. Then, in here, - you could use a dictionary lookup to get the message ID. This - version returns 1, which is the base message ID in win32service.pyd. - """ - return 1 - - def getEventCategory(self, record): - """ - Return the event category for the record. - - Override this if you want to specify your own categories. This version - returns 0. - """ - return 0 - - def getEventType(self, record): - """ - Return the event type for the record. - - Override this if you want to specify your own types. This version does - a mapping using the handler's typemap attribute, which is set up in - __init__() to a dictionary which contains mappings for DEBUG, INFO, - WARNING, ERROR and CRITICAL. If you are using your own levels you will - either need to override this method or place a suitable dictionary in - the handler's typemap attribute. - """ - return self.typemap.get(record.levelno, self.deftype) - - def emit(self, record): - """ - Emit a record. - - Determine the message ID, event category and event type. Then - log the message in the NT event log. - """ - if self._welu: - try: - id = self.getMessageID(record) - cat = self.getEventCategory(record) - type = self.getEventType(record) - msg = self.format(record) - self._welu.ReportEvent(self.appname, id, cat, type, [msg]) - except: - self.handleError(record) - - def close(self): - """ - Clean up this handler. - - You can remove the application name from the registry as a - source of event log entries. However, if you do this, you will - not be able to see the events as you intended in the Event Log - Viewer - it needs to be able to access the registry to get the - DLL name. - """ - #self._welu.RemoveSourceFromRegistry(self.appname, self.logtype) - logging.Handler.close(self) - -class HTTPHandler(logging.Handler): - """ - A class which sends records to a Web server, using either GET or - POST semantics. - """ - def __init__(self, host, url, method="GET"): - """ - Initialize the instance with the host, the request URL, and the method - ("GET" or "POST") - """ - logging.Handler.__init__(self) - method = string.upper(method) - if method not in ["GET", "POST"]: - raise ValueError, "method must be GET or POST" - self.host = host - self.url = url - self.method = method - - def mapLogRecord(self, record): - """ - Default implementation of mapping the log record into a dict - that is sent as the CGI data. Overwrite in your class. - Contributed by Franz Glasner. - """ - return record.__dict__ - - def emit(self, record): - """ - Emit a record. - - Send the record to the Web server as an URL-encoded dictionary - """ - try: - import httplib, urllib - h = httplib.HTTP(self.host) - url = self.url - data = urllib.urlencode(self.mapLogRecord(record)) - if self.method == "GET": - if (string.find(url, '?') >= 0): - sep = '&' - else: - sep = '?' - url = url + "%c%s" % (sep, data) - h.putrequest(self.method, url) - if self.method == "POST": - h.putheader("Content-length", str(len(data))) - h.endheaders() - if self.method == "POST": - h.send(data) - h.getreply() #can't do anything with the result - except: - self.handleError(record) - -class BufferingHandler(logging.Handler): - """ - A handler class which buffers logging records in memory. Whenever each - record is added to the buffer, a check is made to see if the buffer should - be flushed. If it should, then flush() is expected to do what's needed. - """ - def __init__(self, capacity): - """ - Initialize the handler with the buffer size. - """ - logging.Handler.__init__(self) - self.capacity = capacity - self.buffer = [] - - def shouldFlush(self, record): - """ - Should the handler flush its buffer? - - Returns true if the buffer is up to capacity. This method can be - overridden to implement custom flushing strategies. - """ - return (len(self.buffer) >= self.capacity) - - def emit(self, record): - """ - Emit a record. - - Append the record. If shouldFlush() tells us to, call flush() to process - the buffer. - """ - self.buffer.append(record) - if self.shouldFlush(record): - self.flush() - - def flush(self): - """ - Override to implement custom flushing behaviour. - - This version just zaps the buffer to empty. - """ - self.buffer = [] - - def close(self): - """ - Close the handler. - - This version just flushes and chains to the parent class' close(). - """ - self.flush() - logging.Handler.close(self) - -class MemoryHandler(BufferingHandler): - """ - A handler class which buffers logging records in memory, periodically - flushing them to a target handler. Flushing occurs whenever the buffer - is full, or when an event of a certain severity or greater is seen. - """ - def __init__(self, capacity, flushLevel=logging.ERROR, target=None): - """ - Initialize the handler with the buffer size, the level at which - flushing should occur and an optional target. - - Note that without a target being set either here or via setTarget(), - a MemoryHandler is no use to anyone! - """ - BufferingHandler.__init__(self, capacity) - self.flushLevel = flushLevel - self.target = target - - def shouldFlush(self, record): - """ - Check for buffer full or a record at the flushLevel or higher. - """ - return (len(self.buffer) >= self.capacity) or \ - (record.levelno >= self.flushLevel) - - def setTarget(self, target): - """ - Set the target handler for this handler. - """ - self.target = target - - def flush(self): - """ - For a MemoryHandler, flushing means just sending the buffered - records to the target, if there is one. Override if you want - different behaviour. - """ - if self.target: - for record in self.buffer: - self.target.handle(record) - self.buffer = [] - - def close(self): - """ - Flush, set the target to None and lose the buffer. - """ - self.flush() - self.target = None - BufferingHandler.close(self) diff --git a/tools/python/logging/logging-0.4.9.2/python_logging.html b/tools/python/logging/logging-0.4.9.2/python_logging.html deleted file mode 100644 index b759ef9d03..0000000000 --- a/tools/python/logging/logging-0.4.9.2/python_logging.html +++ /dev/null @@ -1,1183 +0,0 @@ - - - - - - - - - - - -A Logging System for Python - - - - - - - - - - - - -
A Logging System for PythonHome
- Download
- Copyright & License
- Recent Changes
-
"Oh, I'm a lumberjack and I'm okay..." (Monty Python, The Lumberjack Song)
- -

Table of Contents

-Abstract
-Motivation
-Influences
-A Simple Example
-Control Flow
-Levels
-Loggers
-Handlers
-Formatters
-Filters
-Configuration
-The GUI Configurator
-Case Scenarios
-Thread Safety
-On-The-Fly Reconfiguration
-Module-Level Convenience Functions
-Performance
-Implementation Status
-Acknowledgements
-Still To Do
-Download and Installation
-Change History
-Copyright and License
- -

Abstract

- -

There is a need for a standard logging system in Python, as comprehensively documented -in PEP 282 and -enthusiastically endorsed by the BDFL in the Parade of the PEPs. By a happy -coincidence, the package described here was already in development and fairly close in -intent and design to the description in the aforementioned PEP, borrowing as it did -heavily from JSR-47 (now JDK 1.4's java.util.logging package) and log4j. This page describes it in more detail. -As I have tweaked the package to meet comments on PEP 282, I have structured this page in -the same way as the original PEP.

- -

Motivation

- -

The Python community has been incredibly helpful to me, a relative newcomer to the -language. Python and its community has certainly saved me much time and effort, and it -seems appropriate to give something back to the community by offering up this package for -people to try. Any feedback will be gratefully accepted.

- -

Influences

- -

This package owes its greatest debt to Apache log4j. Due notice was also taken of log4j's -comprehensive critique of -JSR47. This package bears a close resemblance to log4j, but is not a close translation -(as, for example, log4p appears to be). I have -attempted to be more minimalist (and hopefully more Pythonic) in my approach. You be the -judge!

- -

A Simple Example

- -

Using the package doesn't get much simpler. It is packaged as a standard Python package called (unsurprisingly) logging. You just need to import logging and you're ready to go. Minimal example:

- -
-# --- app.py --------------------------------------------------------------------
-import logging
-
-logging.warn("Hello")
-logging.error("Still here...")
-logging.warn("Goodbye")
-
- -

When you run app.py, the results are:

- -
-WARN:root:Hello
-ERROR:root:Still here...
-WARN:root:Goodbye
-
- -

Don't worry about the format of the output - it's all configurable. Here's a slightly -more involved example; if you've just looked at PEP 282 you will probably get a feeling of -dejà vu. (This is intentional.)

- -
-# --- mymodule.py --------------------------------------------------------------------
-import logging
-log = logging.getLogger("MyModule")
-
-def doIt():
-    log.debug("doin' stuff")
-    #do stuff...but suppose an error occurs?
-    raise TypeError, "bogus type error for testing"
-
-# --- myapp.py -----------------------------------------------------------------------
-import logging, mymodule
-
-logging.basicConfig()
-
-log = logging.getLogger("MyApp")
-log.setLevel(logging.DEBUG) #set verbosity to show all messages of severity >= DEBUG
-log.info("Starting my app")
-try:
-    mymodule.doIt()
-except Exception, e:
-    log.exception("There was a problem.")
-log.info("Ending my app")
-
- -

When you run myapp.py, the results are:

- -
-INFO:MyApp:Starting my app
-ERROR:MyApp:There was a problem.
-Traceback (most recent call last):
-  File "myapp.py", line 9, in ?
-    mymodule.doIt()
-  File "mymodule.py", line 7, in doIt
-    raise TypeError, "Bogus type error for testing"
-TypeError: Bogus type error for testing
-INFO:MyApp:Ending my app
-
- -

But don't worry - the above output is not hardcoded into the package. It's just an -example of what you can do with very little work. As you can see, exceptions are handled -as one would expect.

- -

Control Flow

- -

The package pretty much matches the PEP regarding control flow. The user of the package -makes logging calls on instances of Logger, which are organized into a -hierarchy based on a "dotted name" namespace. This hierarchy is embodied in an -encapsulated singleton Manager instance (which can be ignored by users of the -package, for most purposes). Based on the type of logging call and the logging -configuration (see below), the call may be passed through a set of Filter -instances to decide whether it should be dropped. If not, then the logger consults a set -of Handler instances which are associated with it, and asks each handler -instance to "handle" the logging event. By default, the system moves up the -namespace hierarchy and invokes handlers on all loggers at or above the level of the -logger on which the logging call was made. (You can override this by setting a logger's -"propagate" attribute to 0 - no traversal up the hierarchy is made from such a -logger. But I'm getting ahead of myself...)

- -

Handlers are passed LogRecord instances which (should) contain all the -information we're interested in logging. Handlers, too, can invoke filters to determine -whether a record should be dropped. If not, then the handler takes a handler-specific -action to actually log the record to a file, the console or whatever.

- -

Levels

- -

The following levels are implemented by default:

- -
-DEBUG
-INFO
-WARN
-ERROR
-CRITICAL
-
- -

The CRITICAL level replaces the earlier FATAL level. You can use either (for now), but CRITICAL is preferred since FATAL implies that the application is about to terminate. This is not true for many systems which use logging - for example, a Web server application which encounters a CRITICAL condition (e.g. running out of resources) will still try to keep going as best it can.

-

FATAL (and the corresponding fatal() methods) may be removed in future versions of the package. Currently, CRITICAL is synonymous with FATAL and critical() methods are synonymous with fatal().

-

Exceptions logged via exception() use the ERROR level for logging. If it is desired to log exception information with arbitrary logging levels, this can be done by passing a keyword argument exc_info with a true value to the logging methods (see the pydoc for more details).

-

The levels are not deeply hardcoded into the package - the number of levels, their numeric values and their textual representation are all configurable. The above levels represent the experience of the log4j community and so are provided as the default levels for users who do not have very specific requirements in this area.

-

The example script log_test4.py shows the use of bespoke logging levels (as well as filtering by level at logger and handler, as well as use of filter classes).

- -

Loggers

- -

The package implements loggers pretty much as mentioned in the PEP, except that the manager class is called Manager rather than LogManager.

-

Each Logger instance represents "an area" of the application. This somewhat nebulous definition is needed because it's entirely up to each application developer to define an application's "areas".

For example, an application which reads and processes spreadsheet-type data in different formats might have an overall area "input", concerned with reading input files; and areas "input.csv", "input.xls" and "input.gnu", related to processing comma-separated-value, Excel and Gnumeric input files. Logging messages relating to the overall input function (e.g. deciding which files to process) might be logged used the logger named "input"; logging messages relating to reading individual files might be sent to any of "input.csv", "input.xls" or "input.gnu" depending on the type of file being read.

The advantage of the hierarchical structure is that logging verbosity may be controlled either at the high level or the low level. The levels are loosely coupled and new levels can easily be added at a later date, e.g."input.wks" for reading Lotus-123 format files. It's also possible to do things like routing messages relating to Excel file input to whoever is working on Excel imports, messages related to Gnumeric file processing to a different developer, and so on. Even if the same person works on both, they can at different times focus logging verbosity on particular areas of interest - for example, when debugging Excel imports, they can set the "input.xls" logger's verbosity to DEBUG and others to CRITICAL, and when moving to debug Gnumeric imports, they can reduce the "input.xls" verbosity by setting the level to CRITICAL, while increasing "input.gnu"'s verbosity by setting the level to DEBUG.

- -

Handlers

- -

The following handlers are implemented. I guess they could use more testing ;-) - -

    -
  • StreamHandler - logging to a stream, defaulting to sys.stderr.
  • -
  • FileHandler - logging to disk files.
  • -
  • RotatingFileHandler - logging to disk files with support for rollover, rotating files.
  • -
  • SocketHandler - logging to a streaming socket.
  • -
  • DatagramHandler - logging to a UDP socket.
  • -
  • SMTPHandler - logging to an email address.
  • -
  • SysLogHandler - logging to Unix syslog. Contributed by Nicolas Untz, based on Sam Rushing's syslog module.
  • -
  • MemoryHandler - buffering records in memory until a specific trigger occurs (or until the buffer gets full).
  • -
  • NTEventLogHandler - writes events to the NT event log. For this to work, you need to have Mark Hammond's Win32 extensions installed. (Though of course you can still log to NT from other platforms - just use SocketHandler to redirect to an NT machine).
  • -
  • HTTPHandler - sends events to a Web server using either GET or POST semantics.
  • -
-

All of these except the first two are defined in a sub-module, handlers.py. (To use these handlers, you'll need to import logging.handlers. In addition to the above list, there are example implementations of XMLHandler (see log_test9.py), BufferingSMTPHandler (see log_test11.py) and DBHandler (see log_test14.py) in the test harnesses, on which you can base more specific classes. There is also a class called SLHandler (see log_test1.py) which implements an alternative SysLogHandler - one which uses the syslog module in the standard library (and which is therefore only available on Unix).

-

SOAPHandler, which sends events to a SOAP server, has moved (as of release 0.4.4) from the core to an example script (log_test13.py). The SOAP message is packaged as a function call to a single log() function on the remote server, which takes each relevant member of the LogRecord as a positional parameter. This is perhaps not ideal - but then this SOAPHandler is just a proof-of-concept example to get you started ;-)

-

Note that the handlers are specifically intended not to raise exceptions when errors occur at runtime. This is to avoid error messages from the logging infrastructure polluting logging messages from the application being logged. If, for example, a SocketHandler sees a connection reset by the remote endpoint, it will silently drop all records passed to it (but it will try to connect each time). It may be that due to bugs there are some exceptions incorrectly raised by the logging system, I will try to rectify this kind of problem as soon as it is found and reported!

- -

Formatters

- -

A basic Formatter has been implemented, which should cater for most immediate -requirements. You basically initialize the Formatter with a format string which knows how the attribute dictionary of a LogRecord looks. For example, the output in the example above was produced -with a format string of "%(asctime)s %(name)-19s %(levelname)-5s - -%(message)s". Note that the "message" attribute of the LogRecord -is derived from "msg % args" where msg and args -are passed by the the user in a logging call.

- -

Filters

- -

Filters are used to refine logging output at either logger or handler level with a finer control than is available by just using logging levels. The basic Filter class takes an optional name argument and passes all logging records from loggers which are at or below the specified name.

-

For example, a Filter initialized with "A.B" will allow events logged by loggers "A.B", "A.B.C", "A.B.C.D", "A.B.D" but not "A.BB", "B.A.B". If no name is specified, all events are passed by the filter.

- -

Configuration

- -

A basic configuration is provided via a module-level function, basicConfig(). -If you want to use very simple logging, you can just call the module-level -convenience functions and they will call basicConfig() for you if -necessary. It (basically) adds a StreamHandler (which writes to sys.stderr)to the root Logger.

- -

There are numerous examples of configuration in the test/example scripts included in the distribution. For example, log_test8.py has an example of using a file-based logger.

-

An alternative using ConfigParser-based configuration files is also available (the older, dict-based function is no more). To use this functionality, you'll need to import logging.config. Here is an example of such a config file - it's a bit long, but a full working example so bear with me. I've annotated it as best I can :-):

-

-In the listing below, some values are used by both the logging configuration API -and the GUI configurator, while others are used only by the GUI configurator. To -make it clearer which values you absolutely need to have in the .ini file for it to be useful even if you hand-code it, the values used by the configuration API are shown -like this. (The other ones are used by the GUI configurator, but ignored by the configuration API.) -

-
-# --- logconf.ini -----------------------------------------------------------
-#The "loggers" section contains the key names for all the loggers in this
-#configuration. These are not the actual channel names, but values used to
-#identify where the parameters for each logger are found in this file.
-#The section for an individual logger is named "logger_xxx" where the "key"
-#for a logger is "xxx". So ... "logger_root", "logger_log02", etc. further
-#down the file, indicate how the root logger is set up, logger "log_02" is set
-#up, and so on.
-#Logger key names can be any identifier, except "root" which is reserved for
-#the root logger. (The names "lognn" are generated by the GUI configurator.)
-
-[loggers]
-keys=root,log02,log03,log04,log05,log06,log07
-
-#The "handlers" section contains the key names for all the handlers in this
-#configuration. Just as for loggers above, the key names are values used to
-#identify where the parameters for each handler are found in this file.
-#The section for an individual handler is named "handler_xxx" where the "key"
-#for a handler is "xxx". So sections "handler_hand01", "handler_hand02", etc.
-#further down the file, indicate how the handlers "hand01", "hand02" etc.
-#are set up.
-#Handler key names can be any identifier. (The names "handnn" are generated
-#by the GUI configurator.)
-
-[handlers]
-keys=hand01,hand02,hand03,hand04,hand05,hand06,hand07,hand08,hand09
-
-#The "formatters" section contains the key names for all the formatters in
-#this configuration. Just as for loggers and handlers above, the key names
-#are values used to identify where the parameters for each formatter are found
-#in this file.
-#The section for an individual formatter is named "formatter_xxx" where the
-#"key" for a formatter is "xxx". So sections "formatter_form01",
-#"formatter_form02", etc. further down the file indicate how the formatters
-#"form01", "form02" etc. are set up.
-#Formatter key names can be any identifier. (The names "formnn" are generated
-#by the GUI configurator.)
-
-[formatters]
-keys=form01,form02,form03,form04,form05,form06,form07,form08,form09
-
-#The section below indicates the information relating to the root logger.
-#
-#The level value needs to be one of DEBUG, INFO, WARN, ERROR, CRITICAL or NOTSET.
-#In the root logger, NOTSET indicates that all messages will be logged.
-#Level values are eval()'d in the context of the logging package's namespace.
-#
-#The propagate value indicates whether or not parents of this loggers will
-#be traversed when looking for handlers. It doesn't really make sense in the
-#root logger - it's just there because a root logger is almost like any other
-#logger.
-#
-#The channel value indicates the lowest portion of the channel name of the
-#logger. For a logger called "a.b.c", this value would be "c".
-#
-#The parent value indicates the key name of the parent logger, except that
-#root is shown as "(root)" rather than "root".
-#
-#The qualname value is the fully qualified channel name of the logger. For a
-#logger called "a.b.c", this value would be "a.b.c".
-#
-#The handlers value is a comma-separated list of the key names of the handlers
-#attached to this logger.
-#
-[logger_root]
-level=NOTSET
-handlers=hand01
-qualname=(root) # note - this is used in non-root loggers
-propagate=1 # note - this is used in non-root loggers
-channel=
-parent=
-
-#
-#The explanation for the values in this section is analogous to the above. The
-#logger is named "log02" and coincidentally has a key name of "log02". It has
-#a level of DEBUG and handler with key name "hand02". (See section
-#"handler_hand02" for handler details.) If the level value were NOTSET, this tells
-#the logging package to consult the parent (as long as propagate is 1) for the
-#effective level of this logger. If propagate is 0, this level is treated as for
-#the root logger - a value of NOTSET means "pass everything", and other values are
-#interpreted at face value.
-#
-[logger_log02]
-level=DEBUG
-propagate=1
-qualname=log02
-handlers=hand02
-channel=log02
-parent=(root)
-
-#
-#The explanation for the values in this section is analogous to the above. The
-#logger is named "log02.log03" and has a key name of "log03".
-#It has a level of INFO and handler with key name "hand03".
-#
-[logger_log03]
-level=INFO
-propagate=1
-qualname=log02.log03
-handlers=hand03
-channel=log03
-parent=log02
-
-#
-#The explanations for the values in this section and subsequent logger sections
-#are analogous to the above.
-#
-[logger_log04]
-level=WARN
-propagate=0
-qualname=log02.log03.log04
-handlers=hand04
-channel=log04
-parent=log03
-
-[logger_log05]
-level=ERROR
-propagate=1
-qualname=log02.log03.log04.log05
-handlers=hand05
-channel=log05
-parent=log04
-
-[logger_log06]
-level=CRITICAL
-propagate=1
-qualname=log02.log03.log04.log05.log06
-handlers=hand06
-channel=log06
-parent=log05
-
-[logger_log07]
-level=WARN
-propagate=1
-qualname=log02.log03.log04.log05.log06.log07
-handlers=hand07
-channel=log07
-parent=log06
-
-#The section below indicates the information relating to handler "hand01".
-#The first three keys (class, level and formatter) are common to all handlers.
-#Any other values are handler-specific, except that "args", when eval()'ed,
-#is the list of arguments to the constructor for the handler class.
-#
-#The class value indicates the handler's class (as determined by eval() in
-#the logging package's namespace).
-#
-#The level value needs to be one of DEBUG, INFO, WARN, ERROR, CRITICAL or NOTSET.
-#NOTSET means "use the parent's level".
-#
-#The formatter value indicates the key name of the formatter for this handler.
-#If blank, a default formatter (logging._defaultFormatter) is used.
-#
-#The stream value indicates the stream for this StreamHandler. It is computed
-#by doing eval() on the string value in the context of the logging package's
-#namespace.
-#
-#The args value is a tuple of arguments which is passed to the constructor for
-#this handler's class in addition to the "self" argument.
-#
-[handler_hand01]
-class=StreamHandler
-level=NOTSET
-formatter=form01
-args=(sys.stdout,)
-stream=sys.stdout
-
-#The section below indicates the information relating to handler "hand02".
-#The first three keys are common to all handlers.
-#Any other values are handler-specific, except that "args", when eval()'ed,
-#is the list of arguments to the constructor for the handler class.
-#
-#The filename value is the name of the file to write logging information to.
-#The mode value is the mode used to open() the file. The maxsize and backcount
-#values control rollover as described in the package's pydoc.
-#
-[handler_hand02]
-class=FileHandler
-level=DEBUG
-formatter=form02
-args=('python.log', 'w')
-filename=python.log
-mode=w
-
-#The section below indicates the information relating to handler "hand03".
-#The first three keys are common to all handlers.
-#Any other values are handler-specific, except that "args", when eval()'ed,
-#is the list of arguments to the constructor for the handler class.
-#
-#The host value is the name of the host to send logging information to.
-#The port value is the port number to use for the socket connection.
-#
-[handler_hand03]
-class=handlers.SocketHandler
-level=INFO
-formatter=form03
-args=('localhost', handlers.DEFAULT_TCP_LOGGING_PORT)
-host=localhost
-port=DEFAULT_TCP_LOGGING_PORT
-
-#The section below indicates the information relating to handler "hand04".
-#The first three keys are common to all handlers.
-#Any other values are handler-specific, except that "args", when eval()'ed,
-#is the list of arguments to the constructor for the handler class.
-#
-#The host value is the name of the host to send logging information to.
-#The port value is the port number to use for the socket connection.
-#
-[handler_hand04]
-class=handlers.DatagramHandler
-level=WARN
-formatter=form04
-args=('localhost', handlers.DEFAULT_UDP_LOGGING_PORT)
-host=localhost
-port=DEFAULT_UDP_LOGGING_PORT
-
-#The section below indicates the information relating to handler "hand05".
-#The first three keys are common to all handlers.
-#Any other values are handler-specific, except that "args", when eval()'ed,
-#is the list of arguments to the constructor for the handler class.
-#
-#The host value is the name of the host to send logging information to.
-#The port value is the port number to use for the socket connection.
-#The facility is the syslog facility to use for logging.
-#
-[handler_hand05]
-class=handlers.SysLogHandler
-level=ERROR
-formatter=form05
-args=(('localhost', handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER)
-host=localhost
-port=SYSLOG_UDP_PORT
-facility=LOG_USER
-
-#The section below indicates the information relating to handler "hand06".
-#The first three keys are common to all handlers.
-#Any other values are handler-specific, except that "args", when eval()'ed,
-#is the list of arguments to the constructor for the handler class.
-#
-#The appname value is the name of the application which appears in the
-#NT event log.
-#The dllname value is the pathname of a DLL to use for message definitions.
-#The logtype is the type of NT event log to write to - Application, Security
-#or System.
-#
-[handler_hand06]
-class=NTEventLogHandler
-level=CRITICAL
-formatter=form06
-args=('Python Application', '', 'Application')
-appname=Python Application
-dllname=
-logtype=Application
-
-#The section below indicates the information relating to handler "hand07".
-#The first three keys are common to all handlers.
-#Any other values are handler-specific, except that "args", when eval()'ed,
-#is the list of arguments to the constructor for the handler class.
-#
-#The host value is the name of the SMTP server to connect to.
-#The port value is the port number to use for the SMTP connection.
-#The from value is the "From" value in emails.
-#The to value is a comma-separated list of email addresses.
-#The subject value is the subject of the email.
-#
-[handler_hand07]
-class=SMTPHandler
-level=WARN
-formatter=form07
-args=('localhost', 'from@abc', ['user1@abc', 'user2@xyz'], 'Logger Subject')
-host=localhost
-port=25
-from=from@abc
-to=user1@abc,user2@xyz
-subject=Logger Subject
-
-#The section below indicates the information relating to handler "hand08".
-#The first three keys are common to all handlers.
-#Any other values are handler-specific, except that "args", when eval()'ed,
-#is the list of arguments to the constructor for the handler class.
-#
-#The capacity value is the size of this handler's buffer.
-#The flushlevel value is the logging level at which the buffer is flushed.
-#The from value is the "From" value in emails.
-#The target value is the key name of the handler which messages are flushed
-#to (i.e. sent to when flushing).
-#
-[handler_hand08]
-class=MemoryHandler
-level=NOTSET
-formatter=form08
-target=
-args=(10, ERROR)
-capacity=10
-flushlevel=ERROR
-
-#The section below indicates the information relating to handler "hand09".
-#The first three keys are common to all handlers.
-#Any other values are handler-specific, except that "args", when eval()'ed,
-#is the list of arguments to the constructor for the handler class.
-#
-#The host value is the name of the HTTP server to connect to.
-#The port value is the port number to use for the HTTP connection.
-#The url value is the url to request from the server.
-#The method value is the HTTP request type (GET or POST).
-#
-[handler_hand09]
-class=HTTPHandler
-level=NOTSET
-formatter=form09
-args=('localhost:9022', '/log', 'GET')
-host=localhost
-port=9022
-url=/log
-method=GET
-
-#The sections below indicate the information relating to the various
-#formatters. The format value is the overall format string, and the
-#datefmt value is the strftime-compatible date/time format string. If
-#empty, the logging package substitutes ISO8601 format date/times where
-#needed. See the package pydoc for more details of the format string
-#structure.
-#
-[formatter_form01]
-format=F1 %(asctime)s %(levelname)s %(message)s
-datefmt=
-
-[formatter_form02]
-format=F2 %(asctime)s %(pathname)s(%(lineno)d): %(levelname)s %(message)s
-datefmt=
-
-[formatter_form03]
-format=F3 %(asctime)s %(levelname)s %(message)s
-datefmt=
-
-[formatter_form04]
-format=%(asctime)s %(levelname)s %(message)s
-datefmt=
-
-[formatter_form05]
-format=F5 %(asctime)s %(levelname)s %(message)s
-datefmt=
-
-[formatter_form06]
-format=F6 %(asctime)s %(levelname)s %(message)s
-datefmt=
-
-[formatter_form07]
-format=F7 %(asctime)s %(levelname)s %(message)s
-datefmt=
-
-[formatter_form08]
-format=F8 %(asctime)s %(levelname)s %(message)s
-datefmt=
-
-[formatter_form09]
-format=F9 %(asctime)s %(levelname)s %(message)s
-datefmt=
-
-# --- end of logconf.ini ----------------------------------------------------
-
- -

To use a file like this, you would call logging.config.fileConfig("logconf.ini") -whereupon the file is read in and processed. Note that evaluation happens in the context of the logging package (hence the unqualified class names). - - -

The GUI Configurator

- -To create a file like the above, you can use the new GUI configurator, logconf.py, which is invoked either with no arguments or with a single argument giving the name of a configuration file to read. (Or, if you're a masochist/don't have Tk, you can do it by hand. The configurator is a quick hack, which I hope is reasonably intuitive - have a play with it and see what you think. I've used it with 1.5.2 and 2.1.2 on Windows and 1.5.2 on Linux/x86. There's no validation, rudimentary error checking and the usability could be better, but it's something to build on, hey?)

- -

Here's a screenshot of the configurator:

- -

Here's a quick guide on how to use it: -

    -
  • The screen is laid out in three panels - for loggers, handlers and formatters (see the yellow rectangles in the screenshot).
  • -
  • Each panel consists of a listbox, New and Delete buttons and a "property editor" to set properties for each of the objects.
  • -
  • To create loggers, you need to first select the parent logger before clicking the New button. To create handlers and formatters, just click the appropriate New button.
  • -
  • To delete an item, just select it in the listbox and click the Delete button.
  • -
  • Whenever an item is selected in the listbox, its properties are displayed in the property editor section.
  • -
  • Whenever an item is deleted, the property editor section is cleared.
  • -
  • To edit a property, just click on the name or value. If the property is read-only, nothing happens. If it's a user-editable value, an entry field appears and you can type into it. If it's a user-selectable value (I mean selectable from a list), a button with ... appears. Clicking on it causes a pseudo-combobox to appear. All such boxes are single-selection, except for the "Handlers" property of loggers, for which several handlers can be selected.
  • -
  • To commit the changes, just click elsewhere in the property editor section, e.g. below the last property or on some other property.
  • -
  • Formatters are referred to by handlers, and handlers are referred to by loggers. Hence formatters and handlers have names generated for them automatically, for use in cross-referencing. The names of these cannot be changed. The name for loggers is, however, editable (except for the root logger), as it represents the position of the logger in the hierarchy.
  • -
  • The Load, Save, Save As and Reset buttons should be reasonably self-explanatory (except perhaps Reset, which just deletes all non-root loggers, handlers and formatters and starts with a clean slate).
  • -
  • Filters are not supported in this release, but will be as soon as time permits and if there is enough demand.
  • -

-

Case Scenarios

- -

With reference to the PEP, -here are my comments on the current state of play. - -

    -
  1. A short simple script. See the example app.py - above.
  2. -
  3. Medium sized app with C extension module. I have not specifically considered C extension - modules but I assume they can just use the standard Python C API to make logging calls.
  4. -
  5. Distutils. I would welcome more specific comments on what kind of configuration people - think would be useful. To a certain extent, controlling verbosity levels through setup.py - options is, I think, the domain of the app developer rather than the logging package.
  6. -
  7. Large applications. If users can restart a system after changing the logging settings - (via some user-friendly or support-desk-friendly interface) then present functionality - should cater for this. In the case where the logging behaviour of a (long-)running system needs - to be changed, then the functionality (new in 0.4.3) described below can be used.
  8. -
- -

Thread Safety

- -

The package is intended to be threadsafe. Although it makes no use of threads to provide its functionality (except for on-the-fly reconfiguration), shared data in the package is protected by a thread lock which is acquired before, and released after, modifications to shared data. In addition, the Handler class creates a per-handler instance I/O lock which is acquired before, and released after, calling emit(). If you define your own handlers, in most situations you should not need to take any special precautions, as long as your I/O is called only from emit(). The thread locks impose a slight performance penalty, but it's no worse than for any other use of thread locks in Python applications.

- -

On-The-Fly Reconfiguration

- -

The package also allows a program to permit changing of the logging configuration on the fly, i.e. while the program is still running. This should be a help for developers of long-running programs such as servers (e.g. Zope, Webware). At this stage, the on-the-fly configurability is fairly basic - to use it, two new module-level functions are provided (in the logging.config module). -

    -
  • listen([port]) is used to create a thread which, when started, opens a socket server which listens on the specified port for configuration requests. The socket protocol is very basic - a two-byte length followed by a string of that length is sent to the listener. The string should be in the same format as logging configuration files, i.e. ConfigParser files conforming to the scheme described above.
  • -
  • stopListening() tells the thread created by listening to terminate.
  • -
-Currently, you can't just change part of the logging configuration - the sent configuration completely replaces the existing configuration, and if previously existing loggers are not in the new configurations, they will be disabled after the new configuration takes effect. The script log_test17.py in the distribution illustrates the on-the-fly configuration feature. -

- -

Module-Level Convenience Functions

- -

For the casual user, there are module-level convenience functions which operate on the -root logger. Here is the pydoc for them.

- -

Performance

- -

The implementation has not been optimized for performance. This is planned to be done in a later phase, following feature stabilization and benchmarking.

- -

Implementation Status

- -

The implementation is what I have termed alpha - mainly because it has not had very wide exposure or extensive testing in many environments. Please try to use it/break it and give me -any feedback you can! There is no reason I can see why this package should not be ready in time for the Python 2.3 release :-)

- - -

Acknowledgements

-

The biggest thank you goes to the log4j developers, whom I am attempting to flatter sincerely by imitation ;-) Thanks also to Trent Mick for PEP 282, which prompted me to offer this implementation.

-

I'd also like to thank all of the people who have given me feedback, patches and encouragement. In particular (but in no particular order):

-
    -
  • Ollie Rutherfurd - patches and suggestions.
  • -
  • Greg Ward - for nudging me in the direction of distutils.
  • -
  • Hunter Matthews - questions about user-defined logging levels.
  • -
  • Nicolas Untz - SysLogHandler implementation.
  • -
  • Jeremy Hylton - discussions about logging exceptions.
  • -
  • Kevin Butler - discussions about logging exceptions.
  • -
  • Richard Jones - lots of positive feedback and ideas.
  • -
  • David Goodger - suggestion about using CRITICAL rather than FATAL.
  • -
  • Denis S. Otkidach - suggestions on filters and feedback on performance.
  • -
-

Still To Do

-

No rest for the wicked...

-
    -
  • Improvements to the GUI configurator. Feedback, anyone?
  • -
  • Overview-type documentation? The pydoc is reasonably comprehensive (I like to think). Perhaps a slightly formalized version of the information on this page?
  • -
  • Testing, and more testing (you could help with this, too ...)
  • -
-

If you can help with any of this, please email me.

-

Download and Installation

-

The current version is 0.4.7. Here is the latest tarball (also in zip format or Windows executable - the latter includes the logging package only). The distribution contains the following files: -


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Filename     Contents
 
README.txt Brief description and change history.
__init__.py The core logging package itself, including StreamHandler and FileHandler.
handlers.py The other handlers provided as part of the package.
config.py The code for configuring the package.
setup.py The distutils setup script.
logrecv.py A test server used for testing SocketHandler, DatagramHandler, HTTPHandler and SOAPHandler. Run it with an argument of one of "TCP", "UDP", "HTTP" or "SOAP" before running a test harness which logs to one of these handlers. Note that to use the SOAP handler, you need to have installed PyXML-0.6.6 and the Zolera Soap Infrastructure. This is needed for logrecv.py only, and not for the logging module itself. (Note that ZSI requires Python 2.x)
app.py The minimal example described above.
mymodule.py Another example described above.
myapp.py From the second example described above.
log_test.py A test script intended to work as a regression test harness. Runs a number of the other scripts and generates output to stdout.log and stderr.log.
log_test0.py A simple test script using basicConfig() only.
log_test1.py An example showing slightly more involved configuration and - exception handling, as well as a Unix syslog handler which uses the standard library's syslog module.
log_test2.py A version of log_test0.py which only logs to - a SocketHandler.
log_test3.py An example showing use of fileConfig() and - logging to various loggers.
log_test4.py An example showing use of bespoke levels, filtering by level at logger and handler, and use of filter classes (descendants of Filter).
log_test5.py An example showing use of SMTPHandler. Before running this script, be sure to change the bogus addresses it contains to real ones which you have access to.
log_test6.py An example showing use of NTEventLogHandler. This script needs to be run on an NT system.
log_test7.py An example showing use of MemoryHandler.
log_test8.py An example showing use of FileHandler with rollover across multiple files.
log_test9.py An example showing use of BufferingHandler and BufferingFormatter through implementing simple XMLFormatter and XMLHandler classes.
log_test10.py An example showing how to get the logging module to create loggers of your own class (though it needs to be a subclass of Logger).
log_test11.py An example SMTP handler, called BufferingSMTPHandler, which buffers events and sends them via email in batches.
log_test12.py An example showing the use of HTTPHandler, for use with logrecv.py.
log_test13.py An example showing the use of SOAPHandler, for use with logrecv.py.
log_test14.py An example showing an implementation of DBHandler, showing how to log requests to RDBMS tables using the Python Database API 2.0.
log_test15.py An example showing the use of the Filter class with a string initializer.
log_test16.py An example showing the use of logging in a multi-threaded program.
log_test17.py An example showing the use of logging in a multi-threaded program, together with reconfiguring logging on the fly through the use of listen() and stopListening(). This script serves as both server and client, depending on the arguments it's called with.
log_test18.py An example showing the use of an example filter, MatchFilter, which offers flexible match-based -filtering of LogRecords.
log_test19.py A basic test of logger parents.
log_test20.py Demonstrates the use of custom class instances for messages and filtering based on classes.
log_test21.py Demonstrates the use of a wildcard name-space filter with and without custom message classes.
log_test22.py Demonstrates the use of either localtime or gmtime to do date/time formatting.
debug.ini An example configuration for use with log_test17.py.
warn.ini An example configuration for use with log_test17.py.
error.ini An example configuration for use with log_test17.py.
critical.ini An example configuration for use with log_test17.py.
log_test3.ini An example configuration for use with log_test3.py.
stdout.exp The expected results of stdout.log after running log_test.py.
stderr.exp The expected results of stderr.log after running log_test.py.
logconf.py A Tkinter-based GUI configurator.
logconf.ini Example configuration file, in ConfigParser format, for use with logconf.py and log_test3.py.
logging.dtd A simple example DTD for use with log_test9.py.
logging.xml An example XML file for use with log_test9.py. It references events.xml as external data.
events.xml An example XML file for use with log_test9.py. It holds the actual events in XML format.
python_logging.html The page you're reading now.
default.css Stylesheet for use with the HTML pages.
 
-
-

To install, unpack the archive into any directory, and in that directory invoke the script "setup.py install" to install the module in the default location used by distutils.

-

To use, just put logging.py in your Python path, "import logging" and go. (The installation procedure described above will normally put the logging module in your Python path. If you want to use file-based configuration API, you'll also need to import logging.config. To use the more esoteric handlers, you'll also need to import logging.handlers.)

- -

Change History

- -

The change history is as follows.

- -
-Version   Date        Description
-=============================================================================
-0.4.7     15 Nov 2002 Made into a package with three modules: __init__ (the
-                      core code), handlers (all handlers other than
-                      FileHandler and its bases) and config (all the config
-                      stuff). Before doing this:
-                      Updated docstrings to include a short line, then a
-                      blank line, then more descriptive text.
-                      Renamed 'lvl' to 'level' in various functions.
-                      Changed FileHandler to use "a" and "w" instead of "a+"
-                      and "w+".
-                      Moved log file rotation functionality from FileHandler
-                      to a new class RotatingFileHandler.
-                      Improved docstring describing rollover.
-                      Updated makePickle to use 4-byte length and struct
-                      module, likewise logrecv.py. Also updated on-the-fly
-                      config reader to use 4-byte length/struct module.
-                      Altered ConfigParser test to look at 'readline' rather
-                      than 'read'.
-                      Added optional "defaults" argument to fileConfig, to
-                      be passed to ConfigParser.
-                      Renamed ALL to NOTSET to avoid confusion.
-                      Commented out getRootLogger(), as obsolete.
-                      To do regression testing, run log_test.py and compare
-                      the created files stdout.log and stderr.log against
-                      the files stdout.exp and stderr.exp. They should match
-                      except fir a couple of exception messages which give
-                      absolute file paths.
-                      Updated python_logging.html to remove links to
-                      logging_pydoc.html, which has been removed from the
-                      distribution.
-                      Changed default for raiseExceptions to 1.
------------------------------------------------------------------------------
-0.4.6     08 Jul 2002 Added raiseExceptions to allow conditional propagation
-                      of exceptions which occur during handling.
-                      Added converter to Formatter to allow use of any
-                      function to convert time from seconds to a tuple. It
-                      still defaults to time.localtime but now you can also
-                      use time.gmtime.
-                      Added log_test22.py to test the conversion feature.
-                      Changed rootlogger default level to WARN - was DEBUG.
-                      Updated some docstrings.
-                      Moved import of threading to where thread is imported.
-                      If either is unavailable, threading support is off.
-                      Updated minor defects in python_logging.html.
-                      Check to see if ConfigParser has readfp method; if it
-                      does and an object with a 'read' method is passed in,
-                      assumes a file-like object and uses readfp to read it
-                      in.
------------------------------------------------------------------------------
-0.4.5     04 Jun 2002 Fixed bug which caused problem if no args to message
-                      (suggested by Hye-Shik Chang).
-                      Fixed bug in _fixupParents (thanks to Nicholas Veeser)
-                      and added log_test19.py as a test case for this bug.
-                      Added getMessage to LogRecord (code was moved here from
-                      Formatter.format)
-                      Applied str() to record.msg to allow arbitrary classes
-                      to determine the formatting (as msg can now be a class
-                      instance).
-                      Table of Contents added to python_logging.html, the
-                      section on Loggers updated, and the logconf.ini file
-                      section annotated.
-                      Added log_test20.py which demonstrates how to use
-                      class instances to provide alternatives to numeric
-                      severities as mechanisms for control of logging.
-                      Added log_test21.py which builds on log_test20.py to
-                      show how you can use a regular expression-based Filter
-                      for flexible matching similar to e.g. Protomatter
-                      Syslog, where you can filter on e.g. "a.*" or "*.b" or
-                      "a.*.c".
-                      _levelNames changed to contain reverse mappings as well
-                      as forward mappings (leveltext->level as well as level
-                      -> leveltext). The reverse mappings are used by
-                      fileConfig().
-                      fileConfig() now more forgiving of missing options in
-                      .ini file - sensible defaults now used when some
-                      options are absent. Also, eval() is used less when
-                      interpreting .ini file contents - int() and dict lookup
-                      are used in more places. Altered log_test3.py and added
-                      log_test3.ini to show a hand-coded configuration file.
------------------------------------------------------------------------------
-0.4.4     02 May 2002 getEffectiveLevel() returns ALL instead of None when
-                      nothing found. Modified references to level=0 to
-                      level=ALL in a couple of places.
-                      SocketHandler now inherits from Handler (it used to
-                      inherit from StreamHandler, for no good reason).
-                      getLock() renamed to createLock().
-                      Docstring tidy-ups, and some tidying up of
-                      DatagramHandler.
-                      Factored out unpickling in logrecv.py.
-                      Added log_test18.py to illustrate MatchFilter, which is
-                      a general matching filter.
-                      Improved FileHandler.doRollover() so that the base
-                      file name is always the most recent, then .1, then .2
-                      etc. up to the maximum backup count. Renamed formal
-                      args and attributes used in rollover.
-                      Changed LogRecord attributes lvl -> levelno, level ->
-                      levelname (less ambiguity)
-                      Formatter.format searches for "%(asctime)" rather than
-                      "(asctime)"
-                      Renamed _start_time to _startTime
-                      Formatter.formatTime now returns the time
-                      Altered logrecv.py to support stopping servers
-                      programmatically
-                      Added log_test.py as overall test harness
-                      basicConfig() can now be safely called more than once
-                      Modified test scripts to make it easier to call them
-                      from log_test.py
-                      Moved SOAPHandler from core to log_test13.py. It's not
-                      general enough to be in the core; most production use
-                      will have differing RPC signatures.
------------------------------------------------------------------------------
-0.4.3     14 Apr 2002 Bug fix one-off error message to go to sys.stderr
-                      rather than sys.stdout.
-                      logrecv.py fix TCP for busy network.
-                      Thread safety - added locking to Handler and for shared
-                      data in module, and log_test16.py to test it.
-                      Added socket listener to allow on-the-fly configuration
-                      and added log_test17.py to test it.
------------------------------------------------------------------------------
-0.4.2     11 Apr 2002 Bug fix fileConfig() - setup of MemoryHandler target
-                      and errors when loggers have no handlers set or
-                      handlers have no formatters set
-                      logconf.py - seems to hang if window closed when combo
-                      dropdown is showing - added code to close popup on exit
-                      Some tweaks to _srcfile computation (normpath added)
-                      findCaller() optimized, now a lot faster!
-                      Logger.removeHandler now closes the handler before
-                      removing it
-                      fileConfig() removes existing handlers before adding
-                      the new set, to avoid memory leakage when repeated
-                      calls are made
-                      Fixed logrecv.py bug which hogged CPU time when TCP
-                      connection was closed from the client
-                      Added log_test14.py to demonstrate/test a DBHandler
-                      which writes logging records into an RDBMS using the
-                      Python Database API 2.0 (to run, you need something
-                      which supports this already installed - I tested with
-                      mxODBC)
-                      Made getLogger name argument optional - returns root
-                      logger if omitted
-                      Altered Filter to take a string initializer, filtering
-                      a sub-hierarchy rooted at a particular point (idea from
-                      Denis S. Otkidach).
-                      Added log_test15.py to test Filter initializer
------------------------------------------------------------------------------
-0.4.1     03 Apr 2002 Bug fix SMTPHandler - extra \r\n needed (Oleg Orlov)
-                      Added BufferingHandler, BufferingFormatter
-                      Renamed getChainedPriority to getEffectiveLevel
-                      Removed Logger.getRoot as it is redundant
-                      Added log_test9.py to test Buffering classes and
-                      to show an XMLFormatter example.
-                      Added setLoggerClass.
-                      Added log_test10.py to test setLoggerClass, using an
-                      example Logger-derived class which outputs exception
-                      info even for DEBUG level logging calls
-                      Added log_test11.py to test a buffering implementation
-                      of SMTPHandler
-                      Changed logging call implementation to allow keyword
-                      arguments (Kevin Butler and others)
-                      Changed default SysLogHandler implementation.
-                      Renamed "additive" to "propagate" as it better
-                      describes the attribute.
-                      Added HTTPHandler.
-                      Modified logrecv.py to remove "both" option and to add
-                      "HTTP" and "SOAP" options (SOAP option needs you to
-                      have PyXML-0.6.6 and ZSI installed - for logrecv.py
-                      only, and not for the core logging module itself).
-                      Added log_test12.py to test HTTPHandler.
-                      Added log_test13.py to test SOAPHandler.
-                      Formatted to Python source guidelines (spaces, indent
-                      of 4, within 80 columns).
-                      More method renamings (result of feedback) - _handle()
-                      renamed to emit(), _logRecord() renamed to handle().
-                      Renamed FATAL to CRITICAL (David Goodger), but left
-                      fatal() and FATAL in (until PEP is changed)
-                      Changed configuration file format to ConfigParser
-                      format.
-                      Factored filter application functionality out to a new
-                      Filterer class. The isLoggable() method is renamed to
-                      filter() in both Filter and Filterer classes.
-                      Altered SMTPHandler __init__ to accept (host, port)
-                      for the mail internet address.
-                      Added GUI configurator which uses Tkinter and the new
-                      configuration file format. (See logconf.py and an
-                      example configuration file in logconf.ini)
-                      Altered log_test3.py to test with the new file format.
------------------------------------------------------------------------------
-0.4       21 Mar 2002 Incorporated comments/patches from Ollie Rutherfurd:
-                      -Added level filtering for handlers.
-                      -Return root logger if no name specified in getLogger.
-                      Incorporated comments from Greg Ward:
-                      -Added distutils setup.py script.
-                      Added formatter initialization in Handler.__init__.
-                      Tidied up docstrings.
-                      Added removeHandler to Logger.
-                      Added removeFilter to Logger and Handler.
-                      logrecv.py modified to keep connection alive until
-                      client closes it.
-                      SocketHandler modified to not reset connection after
-                      each logging event.
-                      Added shutdown function which closes open sockets
-                      Renamed DEFAULT_LOGGING_PORT->DEFAULT_TCP_LOGGING_PORT
-                      Added DEFAULT_UDP_LOGGING_PORT
-                      Added log_test4.py (example of arbitrary levels)
-                      Added addLevelName, changed behaviour of getLevelName
-                      Fixed bugs in DatagramHandler
-                      Added SMTPHandler implementation
-                      Added log_test5.py to test SMTPHandler
-                      Added SysLogHandler (contribution from Nicolas Untz
-                      based on Sam Rushing's syslog.py)
-                      Modified log_test1.py to add a SysLogHandler
-                      Added rollover functionality to FileHandler
-                      Added NTEventLogHandler (based on Win32 extensions)
-                      Added MemoryHandler implementation
-                      Added log_test7.py to test MemoryHandler
-                      Added log_test8.py to test FileHandler rollover
-                      Added logException method to Logger
-                      Added formatException method to Formatter
-                      Added log_test6.py to test NTEventHandler and
-                      logException
-                      Numerous internal method renamings (sorry - but better
-                      to do this now, rather than when we enter beta status).
------------------------------------------------------------------------------
-0.3       14 Mar 2002 First public release, for early feedback
------------------------------------------------------------------------------
-0.2                   Consolidated into single file (for internal use only)
------------------------------------------------------------------------------
-0.1                   Initial implementation (for internal use only)
------------------------------------------------------------------------------
-
- -

Copyright and License

- -

The copyright statement follows.

- -
-Copyright 2001-2002 by Vinay Sajip. All Rights Reserved.
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Vinay Sajip
-not be used in advertising or publicity pertaining to distribution
-of the software without specific, written prior permission.
-VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
-VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
-AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
-IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - diff --git a/tools/python/logging/logging-0.4.9.2/setup.py b/tools/python/logging/logging-0.4.9.2/setup.py deleted file mode 100644 index 5bca563605..0000000000 --- a/tools/python/logging/logging-0.4.9.2/setup.py +++ /dev/null @@ -1,29 +0,0 @@ -from distutils.core import setup - -setup(name = "logging", - description="A logging module for Python", - long_description = """This module is intended to provide a standard error logging mechanism in Python as per PEP 282.""", - license="""Copyright (C) 2001-2004 by Vinay Sajip. All Rights Reserved. - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Vinay Sajip -not be used in advertising or publicity pertaining to distribution -of the software without specific, written prior permission. - -VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN -AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.""", - version = "0.4.9.2", - author = "Vinay Sajip", - author_email = "vinay_sajip@red-dove.com", - maintainer = "Vinay Sajip", - maintainer_email = "vinay_sajip@red-dove.com", - url = "http://www.red-dove.com/python_logging.html", - packages = ["logging"], - ) diff --git a/tools/python/logging/logging-0.4.9.2/test/app.py b/tools/python/logging/logging-0.4.9.2/test/app.py deleted file mode 100644 index e550a193ac..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/app.py +++ /dev/null @@ -1,5 +0,0 @@ -import logging - -logging.warning("Hello") -logging.error("Still here...") -logging.warning("Goodbye") \ No newline at end of file diff --git a/tools/python/logging/logging-0.4.9.2/test/critical.ini b/tools/python/logging/logging-0.4.9.2/test/critical.ini deleted file mode 100644 index 8cbaa8a57c..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/critical.ini +++ /dev/null @@ -1,60 +0,0 @@ -[loggers] -keys=root,log02,log03,log04,log05 - -[handlers] -keys=hand01 - -[formatters] -keys=form01 - -[logger_root] -level=WARN -propagate=1 -channel= -parent= -qualname=(root) -handlers=hand01 - -[logger_log02] -level=CRITICAL -propagate=1 -channel=A -parent=(root) -qualname=A -handlers= - -[logger_log03] -level=CRITICAL -propagate=1 -channel=B -parent=log02 -qualname=A.B -handlers= - -[logger_log04] -level=CRITICAL -propagate=1 -channel=C -parent=log03 -qualname=A.B.C -handlers= - -[logger_log05] -level=CRITICAL -propagate=1 -channel=D -parent=log04 -qualname=A.B.C.D -handlers= - -[handler_hand01] -class=StreamHandler -level=NOTSET -formatter=form01 -stream=sys.stderr -args=(sys.stderr,) - -[formatter_form01] -format=critical.ini %(name)s %(levelname)s %(message)s -datefmt= - diff --git a/tools/python/logging/logging-0.4.9.2/test/debug.ini b/tools/python/logging/logging-0.4.9.2/test/debug.ini deleted file mode 100644 index 6c8622f9c9..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/debug.ini +++ /dev/null @@ -1,60 +0,0 @@ -[loggers] -keys=root,log02,log03,log04,log05 - -[handlers] -keys=hand01 - -[formatters] -keys=form01 - -[logger_root] -level=WARN -propagate=1 -channel= -parent= -qualname=(root) -handlers=hand01 - -[logger_log02] -level=DEBUG -propagate=1 -channel=A -parent=(root) -qualname=A -handlers= - -[logger_log03] -level=DEBUG -propagate=1 -channel=B -parent=log02 -qualname=A.B -handlers= - -[logger_log04] -level=DEBUG -propagate=1 -channel=C -parent=log03 -qualname=A.B.C -handlers= - -[logger_log05] -level=DEBUG -propagate=1 -channel=D -parent=log04 -qualname=A.B.C.D -handlers= - -[handler_hand01] -class=StreamHandler -level=NOTSET -formatter=form01 -stream=sys.stderr -args=(sys.stderr,) - -[formatter_form01] -format=debug.ini %(name)s %(levelname)s %(message)s -datefmt= - diff --git a/tools/python/logging/logging-0.4.9.2/test/error.ini b/tools/python/logging/logging-0.4.9.2/test/error.ini deleted file mode 100644 index 49beea7545..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/error.ini +++ /dev/null @@ -1,60 +0,0 @@ -[loggers] -keys=root,log02,log03,log04,log05 - -[handlers] -keys=hand01 - -[formatters] -keys=form01 - -[logger_root] -level=WARN -propagate=1 -channel= -parent= -qualname=(root) -handlers=hand01 - -[logger_log02] -level=ERROR -propagate=1 -channel=A -parent=(root) -qualname=A -handlers= - -[logger_log03] -level=ERROR -propagate=1 -channel=B -parent=log02 -qualname=A.B -handlers= - -[logger_log04] -level=ERROR -propagate=1 -channel=C -parent=log03 -qualname=A.B.C -handlers= - -[logger_log05] -level=ERROR -propagate=1 -channel=D -parent=log04 -qualname=A.B.C.D -handlers= - -[handler_hand01] -class=StreamHandler -level=NOTSET -formatter=form01 -stream=sys.stderr -args=(sys.stderr,) - -[formatter_form01] -format=error.ini %(name)s %(levelname)s %(message)s -datefmt= - diff --git a/tools/python/logging/logging-0.4.9.2/test/events.xml b/tools/python/logging/logging-0.4.9.2/test/events.xml deleted file mode 100644 index f7f1092257..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/events.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - Info index = 90 - - - Info index = 91 - - - Info index = 92 - - - Info index = 93 - - - Info index = 94 - - - Info index = 95 - - - Info index = 96 - - - Info index = 97 - - - Info index = 98 - - - Info index = 99 - \ No newline at end of file diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test.py b/tools/python/logging/logging-0.4.9.2/test/log_test.py deleted file mode 100755 index 5d54b9b18c..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/log_test.py +++ /dev/null @@ -1,158 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# -"""Test harness for the logging module. Run all tests. - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. -""" - -import os, sys, logging, threading, time - -BANNER = "-- %-10s %-6s --------------------------------------------------------\n" - -def banner(nm, typ): - sep = BANNER % (nm, typ) - sys.stdout.write(sep) - sys.stdout.flush() - sys.stderr.write(sep) - sys.stderr.flush() - -def main(): - oldout = sys.stdout - olderr = sys.stderr - sys.stdout = open("stdout.log", "w") - sys.stderr = open("stderr.log", "w") - logging.basicConfig() - root = logging.getLogger("") - hdlr0 = root.handlers[0] - #Set up servers - import logrecv - threads = [] - tcpserver = logrecv.LogRecordSocketReceiver() - tcpserver.logname = "" - threads.append(threading.Thread(target=logrecv.runTCP, args=(tcpserver,))) - udpserver = logrecv.LogRecordDatagramReceiver() - udpserver.logname = "" - threads.append(threading.Thread(target=logrecv.runUDP, args=(udpserver,))) - httpserver = logrecv.LogRecordHTTPReceiver() - httpserver.logname = "" - threads.append(threading.Thread(target=logrecv.runHTTP, args=(httpserver,))) - soapserver = None - if logrecv.SOAPServer: - soapserver = logrecv.SOAPServer() - soapserver.modules = (sys.modules["logrecv"],) - soapserver.logname = "" - threads.append(threading.Thread(target=logrecv.runSOAP, args=(soapserver,))) - - for thread in threads: - thread.start() - try: - import log_test0 - banner("log_test0", "begin") - log_test0.main() - banner("log_test0", "end") - try: - import log_test1 - banner("log_test1", "begin") - log_test1.main() - banner("log_test1", "end") - except ImportError: - pass - - import log_test2 - banner("log_test2", "begin") - log_test2.main() - banner("log_test2", "end") - time.sleep(3) - - #Skip 3 as it tests fileConfig - - banner("log_test4", "begin") - import log_test4 - banner("log_test4", "end") - - #Skip 5 as it tests SMTPHandler, can't easily check results automatically - - #Skip 6 as it tests NTEventLogHandler, can't easily check results automatically - - banner("log_test7", "begin") - root.removeHandler(hdlr0) - import log_test7 - root.addHandler(hdlr0) - banner("log_test7", "end") - - banner("log_test8", "begin") - import log_test8 - root.removeHandler(hdlr0) - log_test8.main() - root.addHandler(hdlr0) - banner("log_test8", "end") - - banner("log_test9", "begin") - import log_test9 - root.removeHandler(hdlr0) - log_test9.main() - root.addHandler(hdlr0) - banner("log_test9", "end") - - banner("log_test10", "begin") - import log_test10 - log_test10.main() - banner("log_test10", "end") - - #Skip 11 as it tests SMTPHandler, can't easily check results automatically - - import log_test12 - banner("log_test12", "begin") - log_test12.main() - banner("log_test12", "end") - - import log_test13 - banner("log_test13", "begin") - log_test13.main() - banner("log_test13", "end") - - import log_test15 - banner("log_test15", "begin") - log_test15.test(log_test15.FILTER) - banner("log_test15", "end") - - time.sleep(3) - - finally: - #shut down servers - olderr.write("Tidying up...") - tcpserver.abort = 1 - udpserver.abort = 1 - httpserver.abort = 1 - if soapserver: - soapserver.abort = 1 - for thread in threads: - thread.join() - sys.stdout.close() - sys.stdout = oldout - #don't close this, as hdlr0 references it. hdlr0 will be closed at application exit - #sys.stderr.close() - sys.stderr = olderr - print "Test run completed." - -if __name__ == "__main__": - main() diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test0.py b/tools/python/logging/logging-0.4.9.2/test/log_test0.py deleted file mode 100755 index 3799841761..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/log_test0.py +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# -"""Test harness for the logging module. A basic test of levels. - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. -""" - -import logging -msgcount = 0 - -def nextmessage(): - global msgcount - rv = "Message %d" % msgcount - msgcount = msgcount + 1 - return rv - -def main(): - logging.basicConfig() - logging.getLogger("").setLevel(logging.DEBUG) - ERR = logging.getLogger("ERR") - ERR.setLevel(logging.ERROR) - INF = logging.getLogger("INF") - INF.setLevel(logging.INFO) - INF_ERR = logging.getLogger("INF.ERR") - INF_ERR.setLevel(logging.ERROR) - DEB = logging.getLogger("DEB") - DEB.setLevel(logging.DEBUG) - - INF_UNDEF = logging.getLogger("INF.UNDEF") - INF_ERR_UNDEF = logging.getLogger("INF.ERR.UNDEF") - UNDEF = logging.getLogger("UNDEF") - - GRANDCHILD = logging.getLogger("INF.BADPARENT.UNDEF") - CHILD = logging.getLogger("INF.BADPARENT") - - #These should log - ERR.log(logging.CRITICAL, nextmessage()) - ERR.error(nextmessage()) - - INF.log(logging.CRITICAL, nextmessage()) - INF.error(nextmessage()) - INF.warning(nextmessage()) - INF.info(nextmessage()) - - INF_UNDEF.log(logging.CRITICAL, nextmessage()) - INF_UNDEF.error(nextmessage()) - INF_UNDEF.warning(nextmessage()) - INF_UNDEF.info(nextmessage()) - - INF_ERR.log(logging.CRITICAL, nextmessage()) - INF_ERR.error(nextmessage()) - - INF_ERR_UNDEF.log(logging.CRITICAL, nextmessage()) - INF_ERR_UNDEF.error(nextmessage()) - - DEB.log(logging.CRITICAL, nextmessage()) - DEB.error(nextmessage()) - DEB.warning(nextmessage()) - DEB.info(nextmessage()) - DEB.debug(nextmessage()) - - UNDEF.log(logging.CRITICAL, nextmessage()) - UNDEF.error(nextmessage()) - UNDEF.warning(nextmessage()) - UNDEF.info(nextmessage()) - - GRANDCHILD.log(logging.CRITICAL, nextmessage()) - CHILD.log(logging.CRITICAL, nextmessage()) - - #These should not log - ERR.warning(nextmessage()) - ERR.info(nextmessage()) - ERR.debug(nextmessage()) - - INF.debug(nextmessage()) - INF_UNDEF.debug(nextmessage()) - - INF_ERR.warning(nextmessage()) - INF_ERR.info(nextmessage()) - INF_ERR.debug(nextmessage()) - INF_ERR_UNDEF.warning(nextmessage()) - INF_ERR_UNDEF.info(nextmessage()) - INF_ERR_UNDEF.debug(nextmessage()) - - INF.info("Messages should bear numbers 0 through 24.") - -if __name__ == "__main__": - import sys - #print sys.argv[0] - args = sys.argv[1:] - if "-profile" in args: - import profile, pstats - args.remove("-profile") - statf = "log_test0.pro" - profile.run("main()", statf) - stats = pstats.Stats(statf) - stats.strip_dirs().sort_stats('time').print_stats() - else: - main() diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test1.py b/tools/python/logging/logging-0.4.9.2/test/log_test1.py deleted file mode 100755 index 98b98743d3..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/log_test1.py +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# -"""Test harness for the logging module. A test showing exception handling and use of SysLogHandler. - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. -""" -import sys, logging -import syslog - -class SLHandler(logging.Handler): - def __init__(self, ident, logopt=0, facility=syslog.LOG_USER): - logging.Handler.__init__(self) - self.ident = ident - self.logopt = logopt - self.facility = facility - self.mappings = { - logging.DEBUG: syslog.LOG_DEBUG, - logging.INFO: syslog.LOG_INFO, - logging.WARNING: syslog.LOG_WARNING, - logging.ERROR: syslog.LOG_ERR, - logging.CRITICAL: syslog.LOG_CRIT, - } - - def encodeLevel(self, level): - return self.mappings.get(level, syslog.LOG_INFO) - - def emit(self, record): - syslog.openlog(self.ident, self.logopt, self.facility) - msg = self.format(record) - prio = self.encodeLevel(record.levelno) - syslog.syslog(prio, msg) - syslog.closelog() - -def config(): - logging.basicConfig() - logging.getLogger("").setLevel(logging.DEBUG) - if __name__ == "__main__": - fmt = logging.Formatter("%(asctime)s %(filename)s:%(lineno)d %(levelname)-5s - %(message)s") - hdlr = logging.FileHandler("tmp.tmp") - hdlr.setFormatter(fmt) - logging.getLogger("").addHandler(hdlr) - else: - fmt = None - hdlr = SLHandler("log_test1") - if fmt: - hdlr.setFormatter(fmt) - logging.getLogger("").addHandler(hdlr) - return hdlr - -def run(): - logging.info("Starting...") - try: - print "7" + 4 - except Exception, e: - logging.error("Problem %s (%d)", "ERROR", logging.ERROR, exc_info=1) - logging.debug("Problem %s (%d)", "DEBUG", logging.DEBUG, exc_info=1) - logging.info("Done.") - - -def main(): - hdlr = config() - run() - logging.getLogger("").removeHandler(hdlr) - -if __name__ == "__main__": - main() diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test10.py b/tools/python/logging/logging-0.4.9.2/test/log_test10.py deleted file mode 100755 index 839c08caea..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/log_test10.py +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# -"""Test harness for the logging module. Shows use of a user-defined Logger subclass. - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. -""" -import sys -import locale - -locale.setlocale(locale.LC_ALL, '') - -from logging import * - -LOG_FORMAT = "%(asctime)s %(levelname)-5s %(message)s" -DATE_FORMAT = "%x %X" - -class MyLogger(Logger): - """ - A simple example of a logger extension. - """ - def debug(self, msg, *args, **kwargs): - """ - This overridden method passes exception information for DEBUG level calls - """ - if self.manager.disable >= DEBUG: - return - if DEBUG >= self.getEffectiveLevel(): - exc_info = kwargs.get("exc_info", 0) - ei = None - if exc_info: - ei = sys.exc_info() - if not ei[1]: - ei = None - self._log(DEBUG, msg, args, ei) - del ei - -class NotALogger: - pass - -def config(): - try: - setLoggerClass(NotALogger) - except Exception, e: - sys.stderr.write("%s\n" % e) - setLoggerClass(MyLogger) - if __name__ == "__main__": - basicConfig() - if __name__ == "__main__": - getLogger("").handlers[0].setFormatter(Formatter(LOG_FORMAT, DATE_FORMAT)) - -def run(): - getLogger("").setLevel(DEBUG) - logger = getLogger("mylogger") - logger.info("Starting...") - logger.debug("Debug message not in exception handler (no traceback)") - logger.info("About to throw exception...") - try: - print "7" + 4 - except Exception, e: - logger.debug("Debug message inside exception handler (traceback)",exc_info=1) - logger.info("Done.") - -def main(): - config() - run() - -if __name__ == "__main__": - main() diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test11.py b/tools/python/logging/logging-0.4.9.2/test/log_test11.py deleted file mode 100755 index 0aae955148..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/log_test11.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# -"""Test harness for the logging module. Tests BufferingSMTPHandler, an alternative implementation -of SMTPHandler. - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. -""" -import string, logging, logging.handlers - -MAILHOST = 'beta' -FROM = 'log_test11@red-dove.com' -TO = ['arkadi_renko'] -SUBJECT = 'Test Logging email from Python logging module (buffering)' - -class BufferingSMTPHandler(logging.handlers.BufferingHandler): - def __init__(self, mailhost, fromaddr, toaddrs, subject, capacity): - logging.handlers.BufferingHandler.__init__(self, capacity) - self.mailhost = mailhost - self.mailport = None - self.fromaddr = fromaddr - self.toaddrs = toaddrs - self.subject = subject - self.setFormatter(logging.Formatter("%(asctime)s %(levelname)-5s %(message)s")) - - def flush(self): - if len(self.buffer) > 0: - try: - import smtplib - port = self.mailport - if not port: - port = smtplib.SMTP_PORT - smtp = smtplib.SMTP(self.mailhost, port) - msg = "From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n" % (self.fromaddr, string.join(self.toaddrs, ","), self.subject) - for record in self.buffer: - s = self.format(record) - print s - msg = msg + s + "\r\n" - smtp.sendmail(self.fromaddr, self.toaddrs, msg) - smtp.quit() - except: - self.handleError(None) # no particular record - self.buffer = [] - -def test(): - logger = logging.getLogger("") - logger.setLevel(logging.DEBUG) - logger.addHandler(BufferingSMTPHandler(MAILHOST, FROM, TO, SUBJECT, 10)) - for i in xrange(102): - logger.info("Info index = %d", i) - logging.shutdown() - -if __name__ == "__main__": - test() \ No newline at end of file diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test12.py b/tools/python/logging/logging-0.4.9.2/test/log_test12.py deleted file mode 100755 index e5e9be3923..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/log_test12.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# -""" -A test harness for the logging module. Tests HTTPHandler. - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. -""" -import sys, string, logging, logging.handlers - -def main(): - import pdb - host = "localhost:%d" % logging.handlers.DEFAULT_HTTP_LOGGING_PORT - gh = logging.handlers.HTTPHandler(host, '/log', 'GET') - ph = logging.handlers.HTTPHandler(host, '/log', 'POST') - logger = logging.getLogger("log_test12") - logger.propagate = 0 - logger.addHandler(gh) - logger.addHandler(ph) - logging.getLogger("").setLevel(logging.DEBUG) - logger.info("Jackdaws love my big %s of %s", "sphinx", "quartz") - logger.debug("Pack my %s with twelve dozen %s", "box", "liquor jugs") - gh.close() - ph.close() - logger.removeHandler(gh) - logger.removeHandler(ph) - -if __name__ == "__main__": - main() diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test13.py b/tools/python/logging/logging-0.4.9.2/test/log_test13.py deleted file mode 100755 index c054f2997d..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/log_test13.py +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# -""" -A test harness for the logging module. Implements a SOAPHandler class which -can be used to form the basis of extended SOAP functionality. - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. -""" -import string, logging, logging.handlers, types - -SOAP_MESSAGE = """ - - -%s - - - -""" - -class SOAPHandler(logging.Handler): - """ - A class which sends records to a SOAP server. - """ - def __init__(self, host, url): - """ - Initialize the instance with the host and the request URL - """ - logging.Handler.__init__(self) - self.host = host - self.url = url - - def emit(self, record): - """ - Send the record to the Web server as a SOAP message - """ - try: - import httplib - h = httplib.HTTP(self.host) - h.putrequest("POST", self.url) - keys = record.__dict__.keys() - keys.sort() - args = "" - for key in keys: - v = record.__dict__[key] - if type(v) == types.StringType: - t = "string" - elif (type(v) == types.IntType) or (type(v) == types.LongType): - t = "integer" - elif type(v) == types.FloatType: - t = "float" - else: - t = "string" - args = args + "%12s%s\n" % ("", - key, t, str(v), key) - data = SOAP_MESSAGE % args[:-1] - h.putheader("Content-type", "text/plain; charset=\"utf-8\"") - h.putheader("Content-length", str(len(data))) - h.endheaders() - #print data - h.send(data) - r = h.getreply() #can't do anything with the result - f = h.getfile() - if f: - #print f.read() - f.close() - except: - self.handleError(record) - -def main(): - sh = SOAPHandler('localhost:%d' % logging.handlers.DEFAULT_SOAP_LOGGING_PORT, '/log') - logger = logging.getLogger("log_test13") - logging.getLogger("").setLevel(logging.DEBUG) - logger.propagate = 0 - logger.addHandler(sh) - logger.info("Jackdaws love my big %s of %s", "sphinx", "quartz") - logger.debug("Pack my %s with five dozen %s", "box", "liquor jugs") - logger.removeHandler(sh) - -if __name__ == "__main__": - main() - diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test14.py b/tools/python/logging/logging-0.4.9.2/test/log_test14.py deleted file mode 100755 index c00121b356..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/log_test14.py +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# -""" -A test harness for the logging module. An example handler - DBHandler - -which writes to an Python DB API 2.0 data source. You'll need to set this -source up before you run the test. - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. -""" -import sys, string, time, logging - -class DBHandler(logging.Handler): - def __init__(self, dsn, uid='', pwd=''): - logging.Handler.__init__(self) - import mx.ODBC.Windows - self.dsn = dsn - self.uid = uid - self.pwd = pwd - self.conn = mx.ODBC.Windows.connect(self.dsn, self.uid, self.pwd) - self.SQL = """INSERT INTO Events ( - Created, - RelativeCreated, - Name, - LogLevel, - LevelText, - Message, - Filename, - Pathname, - Lineno, - Milliseconds, - Exception, - Thread - ) - VALUES ( - %(dbtime)s, - %(relativeCreated)d, - '%(name)s', - %(levelno)d, - '%(levelname)s', - '%(message)s', - '%(filename)s', - '%(pathname)s', - %(lineno)d, - %(msecs)d, - '%(exc_text)s', - '%(thread)s' - ); - """ - self.cursor = self.conn.cursor() - - def formatDBTime(self, record): - record.dbtime = time.strftime("#%m/%d/%Y#", time.localtime(record.created)) - - def emit(self, record): - try: - #use default formatting - self.format(record) - #now set the database time up - self.formatDBTime(record) - if record.exc_info: - record.exc_text = logging._defaultFormatter.formatException(record.exc_info) - else: - record.exc_text = "" - sql = self.SQL % record.__dict__ - self.cursor.execute(sql) - self.conn.commit() - except: - import traceback - ei = sys.exc_info() - traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr) - del ei - - def close(self): - self.cursor.close() - self.conn.close() - logging.Handler.close(self) - -dh = DBHandler('Logging') -logger = logging.getLogger("") -logger.setLevel(logging.DEBUG) -logger.addHandler(dh) -logger.info("Jackdaws love my big %s of %s", "sphinx", "quartz") -logger.debug("Pack my %s with five dozen %s", "box", "liquor jugs") -try: - import math - math.exp(1000) -except: - logger.exception("Problem with %s", "math.exp") -logging.shutdown() diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test15.py b/tools/python/logging/logging-0.4.9.2/test/log_test15.py deleted file mode 100755 index cebb9d8c96..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/log_test15.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# -""" -A test harness for the logging module. Tests Filter. - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. -""" - -import sys, logging - -FILTER = "a.b" - -def message(s): - sys.stderr.write("%s\n" % s) - -def doLog(): - logging.getLogger("a").info("Info 1") - logging.getLogger("a.b").info("Info 2") - logging.getLogger("a.c").info("Info 3") - logging.getLogger("a.b.c").info("Info 4") - logging.getLogger("a.b.c.d").info("Info 5") - logging.getLogger("a.bb.c").info("Info 6") - logging.getLogger("b").info("Info 7") - logging.getLogger("b.a").info("Info 8") - logging.getLogger("c.a.b").info("Info 9") - logging.getLogger("a.bb").info("Info 10") - -def test(fs): - root = logging.getLogger() - root.setLevel(logging.DEBUG) - if __name__ == "__main__": - hand = logging.StreamHandler() - hand.setFormatter(logging.Formatter("%(name)-10s %(message)s")) - root.addHandler(hand) - else: - hand = root.handlers[0] - message("Unfiltered...") - doLog() - message("Filtered with '%s'..." % fs) - filt = logging.Filter(fs) - hand.addFilter(filt) - doLog() - hand.removeFilter(filt) - -if __name__ == "__main__": - import sys - if len(sys.argv) > 1: - fs = sys.argv[1] - else: - fs = FILTER - test(fs) diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test16.py b/tools/python/logging/logging-0.4.9.2/test/log_test16.py deleted file mode 100755 index f98b627698..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/log_test16.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# -""" -A test harness for the logging module. Tests thread safety. - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. -""" - -import logging, logging.handlers, thread, threading, random - -logging.raiseExceptions = 1 - -NUM_THREADS = 10 -LOOP_COUNT = 10000 - -LOG_MESSAGES = [ - (logging.DEBUG, "%3d This is a %s message", "debug"), - (logging.INFO, "%3d This is an %s message", "informational"), - (logging.WARNING, "%3d This is a %s message", "warning"), - (logging.ERROR, "%3d This is an %s message", "error"), - (logging.CRITICAL, "%3d This is a %s message", "critical"), -] - -LOG_NAMES = ["A", "A.B", "A.B.C", "A.B.C.D"] - -def doLog(num): - logger = logging.getLogger('') - logger.info("*** thread %s started (%d)", thread.get_ident(), num) - for i in xrange(LOOP_COUNT): - logger = logging.getLogger(random.choice(LOG_NAMES)) - a = random.choice(LOG_MESSAGES) - args = a[0:2] + (num,) + a[2:] - apply(logger.log, args) - -def test(): - f = logging.Formatter("%(asctime)s %(levelname)-9s %(name)-8s %(thread)5s %(message)s") - root = logging.getLogger('') - root.setLevel(logging.DEBUG) - h = logging.FileHandler('thread.log', 'w') - root.addHandler(h) - h.setFormatter(f) - h = logging.handlers.SocketHandler('localhost', logging.handlers.DEFAULT_TCP_LOGGING_PORT) - #h = logging.handlers.DatagramHandler('localhost', logging.handlers.DEFAULT_UDP_LOGGING_PORT) - root.addHandler(h) - threads = [] - for i in xrange(NUM_THREADS): - threads.append(threading.Thread(target=doLog, args=(len(threads),))) - for t in threads: - t.start() - for t in threads: - t.join() - -if __name__ == "__main__": - test() diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test17.py b/tools/python/logging/logging-0.4.9.2/test/log_test17.py deleted file mode 100755 index 3a72d5ee96..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/log_test17.py +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# -""" -A test harness for the logging module. Tests thread safety. - -To use as a server, run with no arguments in one process. -To use as a client, run with arguments "-client " where -is the name of a file containing a logging configuration. -The example files debug.ini, warn.ini, error.ini and critical.ini are -provided to use in the test. They each have a customized message format -(prefixed with their name) and the loggers have their levels set to the -value implied by their name. - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. -""" - -import sys, logging, logging.config, thread, threading, random, time, struct - -NUM_THREADS = 10 -LOOP_COUNT = 10 - -CONFIG_PORT = 9077 - -logging.raiseExceptions = 1 - -LOG_MESSAGES = [ - (logging.DEBUG, "%3d This is a %s message", "debug"), - (logging.INFO, "%3d This is an %s message", "informational"), - (logging.WARNING, "%3d This is a %s message", "warning"), - (logging.ERROR, "%3d This is an %s message", "error"), - (logging.CRITICAL, "%3d This is a %s message", "critical"), -] - -LOG_NAMES = ["A", "A.B", "A.B.C", "A.B.C.D"] - -def doLog(num): - logger = logging.getLogger('') - logger.setLevel(logging.DEBUG) - logger.info("*** thread %s started (%d)", thread.get_ident(), num) - for i in xrange(LOOP_COUNT): - logger = logging.getLogger(random.choice(LOG_NAMES)) - a = random.choice(LOG_MESSAGES) - args = a[0:2] + (num,) + a[2:] - time.sleep(random.random() * 3) - apply(logger.log, args) - -def runserver(): - f = logging.Formatter("%(asctime)s %(levelname)-9s %(name)-8s %(thread)5s %(message)s") - root = logging.getLogger('') - h = logging.StreamHandler() - root.addHandler(h) - h.setFormatter(f) - threads = [] - for i in xrange(NUM_THREADS): - threads.append(threading.Thread(target=doLog, args=(len(threads),))) - threads.append(logging.config.listen(CONFIG_PORT)) #don't use default port - for t in threads: - t.start() - for t in threads[:-1]: - t.join() - logging.config.stopListening() - threads[-1].join() - -def runclient(fname): - import socket - - print "configuring with '%s'" % fname - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.connect(('localhost', CONFIG_PORT)) - f = open(fname, "r") - s = f.read() - f.close() - slen = struct.pack(">L", len(s)) - s = slen + s - sentsofar = 0 - left = len(s) - while left > 0: - sent = sock.send(s[sentsofar:]) - sentsofar = sentsofar + sent - left = left - sent - sock.close() - -if __name__ == "__main__": - if "-client" not in sys.argv: - runserver() - else: - sys.argv.remove("-client") - if len(sys.argv) > 1: - fname = sys.argv[1] - else: - fname = "warn.ini" - runclient(fname) \ No newline at end of file diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test18.py b/tools/python/logging/logging-0.4.9.2/test/log_test18.py deleted file mode 100755 index 071ff8c28d..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/log_test18.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# -""" -A test harness for the logging module. Tests MatchFilter. - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. -""" - -import logging, types, string - -class MatchFilter(logging.Filter): - def __init__(self, **kwargs): - self.dict = kwargs - - def matchOne(self, key, value, record): - rv = getattr(record, key) - if key != "name": - if key not in ["message", "msg"]: - return rv == value - else: - return string.find(str(rv), value) >= 0 - else: - if rv == value: - return 1 - nlen = len(value) - if string.find(rv, value, 0, nlen) != 0: - return 0 - if rv[nlen] == ".": - return 1 - - def matchValue(self, key, record): - vl = self.dict [key] - if type(vl) != types.ListType: - rv = self.matchOne(key, vl, record) - else: - for v in vl: - rv = self.matchOne(key, v, record) - if rv: - break - return rv - - def filter(self, record): - rv = 1 - for k in self.dict.keys(): - if self.matchValue(k, record): - rv = 0 - break - return rv - -def doLog(logger, n): - logger.debug("Debug %d" % n) - logger.info("Info %d" % n) - logger.warning("Warning %d" % n) - logger.error("Error %d" % n) - logger.critical("Critical %d" % n) - -def test(): - fmt = logging.Formatter("%(name)-10s %(levelname)-9s %(message)s") - hand = logging.StreamHandler() - hand.setFormatter(fmt) - root = logging.getLogger("") - root.setLevel(logging.DEBUG) - root.addHandler(hand) - loggers = ['A', - 'A.B', - 'A.BB', - 'A.C', - 'AA.B', - 'A.B.C', - 'A.B.C.D', - 'A.B.C.D.E', - 'Z.A.B', - ] - filt = MatchFilter(name = ['A.C', 'A.B.C'], #reject these loggers and their children - levelno = [logging.WARNING, logging.CRITICAL], #reject these levels, - msg = 'bug 2' #reject if this in message - ) - hand.addFilter(filt) - for log in loggers: - doLog(logging.getLogger(log), loggers.index(log)) - -if __name__ == "__main__": - test() diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test19.py b/tools/python/logging/logging-0.4.9.2/test/log_test19.py deleted file mode 100755 index cdfa1a077d..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/log_test19.py +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# -"""Test harness for the logging module. A basic test of parents. - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. -""" - -import logging - -def main(): - logging.basicConfig() - root = logging.getLogger("") - ab = logging.getLogger("a.b") - abc = logging.getLogger("a.b.c") - root.setLevel(logging.ERROR) - ab.setLevel(logging.INFO) - abc.info("Info") - abc.warning("Warning") - abc.error("Error") - print "abc = %s" % abc - print "abc.parent = %s" % abc.parent - print "ab = %s" % ab - print "ab.parent = %s" % ab.parent - print "root = %s" % root - -if __name__ == "__main__": - import sys - print sys.argv[0] - args = sys.argv[1:] - if "-profile" in args: - import profile, pstats - args.remove("-profile") - statf = "log_test19.pro" - profile.run("main()", statf) - stats = pstats.Stats(statf) - stats.strip_dirs().sort_stats('time').print_stats() - else: - main() diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test2.py b/tools/python/logging/logging-0.4.9.2/test/log_test2.py deleted file mode 100755 index 2ba0ee11ea..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/log_test2.py +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# -""" -A test harness for the logging module. Tests logger levels and basic Formatter, and logging to -sockets. - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. -""" - -import logging, logging.handlers, socket - -msgcount = 0 - -def nextmessage(): - global msgcount - rv = "Message %d" % msgcount - msgcount = msgcount + 1 - return rv - -def main(): - logging.basicConfig() - logging.getLogger("").setLevel(logging.DEBUG) - hdlr = logging.handlers.SocketHandler('localhost', logging.handlers.DEFAULT_TCP_LOGGING_PORT) - if __name__ == "__main__": - hdlr.setFormatter(logging.Formatter("%(asctime)s %(name)-19s %(levelname)-5s - %(message)s")) - logging.getLogger("").addHandler(hdlr) - ERR = logging.getLogger("ERR") - ERR.setLevel(logging.ERROR) - INF = logging.getLogger("INF") - INF.setLevel(logging.INFO) - INF_ERR = logging.getLogger("INF.ERR") - INF_ERR.setLevel(logging.ERROR) - DEB = logging.getLogger("DEB") - DEB.setLevel(logging.DEBUG) - - INF_UNDEF = logging.getLogger("INF.UNDEF") - INF_ERR_UNDEF = logging.getLogger("INF.ERR.UNDEF") - UNDEF = logging.getLogger("UNDEF") - - GRANDCHILD = logging.getLogger("INF.BADPARENT.UNDEF") - CHILD = logging.getLogger("INF.BADPARENT") - - #These should log - ERR.log(logging.CRITICAL, nextmessage()) - ERR.error(nextmessage()) - - INF.log(logging.CRITICAL, nextmessage()) - INF.error(nextmessage()) - INF.warning(nextmessage()) - INF.info(nextmessage()) - - INF_UNDEF.log(logging.CRITICAL, nextmessage()) - INF_UNDEF.error(nextmessage()) - INF_UNDEF.warning(nextmessage()) - INF_UNDEF.info(nextmessage()) - - INF_ERR.log(logging.CRITICAL, nextmessage()) - INF_ERR.error(nextmessage()) - - INF_ERR_UNDEF.log(logging.CRITICAL, nextmessage()) - INF_ERR_UNDEF.error(nextmessage()) - - DEB.log(logging.CRITICAL, nextmessage()) - DEB.error(nextmessage()) - DEB.warning(nextmessage()) - DEB.info(nextmessage()) - DEB.debug(nextmessage()) - - UNDEF.log(logging.CRITICAL, nextmessage()) - UNDEF.error(nextmessage()) - UNDEF.warning(nextmessage()) - UNDEF.info(nextmessage()) - - GRANDCHILD.log(logging.CRITICAL, nextmessage()) - CHILD.log(logging.CRITICAL, nextmessage()) - - #These should not log - ERR.warning(nextmessage()) - ERR.info(nextmessage()) - ERR.debug(nextmessage()) - - INF.debug(nextmessage()) - INF_UNDEF.debug(nextmessage()) - - INF_ERR.warning(nextmessage()) - INF_ERR.info(nextmessage()) - INF_ERR.debug(nextmessage()) - INF_ERR_UNDEF.warning(nextmessage()) - INF_ERR_UNDEF.info(nextmessage()) - INF_ERR_UNDEF.debug(nextmessage()) - - INF.info("Messages should bear numbers 0 through 24.") - hdlr.close() - logging.getLogger("").removeHandler(hdlr) - -if __name__ == "__main__": - try: - main() - except socket.error: - print "\nA socket error occurred. Ensure that logrecv.py is running to receive logging requests from this script." diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test20.py b/tools/python/logging/logging-0.4.9.2/test/log_test20.py deleted file mode 100755 index d3701f3866..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/log_test20.py +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# -"""Test harness for the logging module. Demonstrates the use of custom class -instances for messages and filtering based on classes. - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. -""" - -import logging - -class MyClass: - def __init__(self, arg1, arg2): - self.arg1 = arg1 - self.arg2 = arg2 - - def __str__(self): - return "%s, %s" % (self.arg1, self.arg2) - -class MyChildClass(MyClass): - pass - -class ClassFilter(logging.Filter): - def __init__(self, klass): - self.klass = klass - - def filter(self, record): - return isinstance(record.msg, self.klass) - -class MyClassFilter(ClassFilter): - def __init__(self, arg): - ClassFilter.__init__(self, MyClass) - self.arg = arg - - def filter(self, record): - return ClassFilter.filter(self, record) and (record.msg.arg2 == self.arg) - -def main(): - handler = logging.StreamHandler() - root = logging.getLogger("") - root.setLevel(logging.DEBUG) - root.addHandler(handler) - root.addFilter(MyClassFilter("world")) - #Not logged, as it's not a MyClass instance - root.info("%s, %s", "Hello", "world") - #Logged, as it's an appropriate instance which matches the filter criteria - root.info(MyClass("Hello", "world")) - #Not logged, as it's an appropriate class but doesn't match the filter criteria - root.info(MyClass("Hello", "world!")) - #Logged, as it's an appropriate instance which matches the filter criteria - root.info(MyClass("Goodbye", "world")) - #Logged, as it's an appropriate class which matches the filter criteria - root.info(MyChildClass("Hello again", "world")) - -if __name__ == "__main__": - import sys - args = sys.argv[1:] - if "-profile" in args: - import profile, pstats - args.remove("-profile") - statf = "log_test20.pro" - profile.run("main()", statf) - stats = pstats.Stats(statf) - stats.strip_dirs().sort_stats('time').print_stats() - else: - main() diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test21.py b/tools/python/logging/logging-0.4.9.2/test/log_test21.py deleted file mode 100755 index 1626beb0f1..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/log_test21.py +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# -"""Test harness for the logging module. Demonstrates the use of a wildcard -name-space filter with and without custom message classes. - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. -""" - -import logging, re, string, types - -class TaggedEvent: - def __init__(self, tag, msg): - self.tag = tag - self.msg = msg - - def __str__(self): - return "%s: %s" % (self.tag, self.msg) - -class WildcardFilter(logging.Filter): - def __init__(self, wildcards): - self.setWildcards(wildcards) - - def setWildcard(self, wildcard): - arr = string.split(wildcard, ".") - for i in xrange(len(arr)): - s = arr[i] - if s == "*": - arr[i] = r'[\w.]*' - elif string.find(s, "*") > 0: - arr[i] = string.replace(s, "*", r'[\w]*') - s = "^%s$" % string.join(arr, r'\.') - self.patterns.append(re.compile(s)) - - def setWildcards(self, wildcards): - if type(wildcards) != types.ListType: - wildcards = [wildcards] - self.patterns = [] - for wildcard in wildcards: - self.setWildcard(wildcard) - - def filter(self, record): - rv = 0 - for pat in self.patterns: - m = pat.match(record.name) - if m is not None: - rv = 1 - break - return rv - -class TagFilter(WildcardFilter): - def filter(self, record): - rv = 0 - if isinstance(record.msg, TaggedEvent): - tag = record.msg.tag - else: - tag = record.name - for pat in self.patterns: - m = pat.match(tag) - if m is not None: - rv = 1 - break - return rv - -def main(): - handler = logging.StreamHandler() - root = logging.getLogger("") - root.setLevel(logging.DEBUG) - ab = logging.getLogger("a.b") - abc = logging.getLogger("a.b.c") - - root.addHandler(handler) - filter = WildcardFilter("*.b") - handler.addFilter(filter) - - ab.info("#1 from a.b") #logged - abc.info("#1 from a.b.c") #not logged - filter.setWildcards("*.b.c") - ab.info("#2 from a.b") #not logged - abc.info("#2 from a.b.c") #logged - filter.setWildcards("*.b*") - ab.info("#3 from a.b") #logged - abc.info("#3 from a.b.c") #not logged - filter.setWildcards("*") - ab.info("#4 from a.b") #logged - abc.info("#4 from a.b.c") #logged - filter.setWildcards("a*") - ab.info("#5 from a.b") #not logged - abc.info("#5 from a.b.c") #not logged - filter.setWildcards("a.*") - ab.info("#6 from a.b") #logged - abc.info("#6 from a.b.c") #logged - filter.setWildcards("*.b.*") - ab.info("#7 from a.b") #not logged - abc.info("#7 from a.b.c") #logged - filter.setWildcards(["*.b", "*.b.*"]) - ab.info("#8 from a.b") #logged - abc.info("#8 from a.b.c") #logged - filter.setWildcards(["a.*.c"]) - ab.info("#9 from a.b") #not logged - abc.info("#9 from a.b.c") #logged - - #Now test filtering with a tagged class - handler.removeFilter(filter) - tagfilter = TagFilter(["*.b", "*.b.*"]) - root.addFilter(tagfilter) - root.info(TaggedEvent("a.b", "#10")) #logged - root.info(TaggedEvent("a.c", "#10")) #not logged - root.info(TaggedEvent("a.b.c", "#10")) #logged - root.info(TaggedEvent("a.b.d", "#10")) #logged - -if __name__ == "__main__": - import sys - args = sys.argv[1:] - if "-profile" in args: - import profile, pstats - args.remove("-profile") - statf = "log_test21.pro" - profile.run("main()", statf) - stats = pstats.Stats(statf) - stats.strip_dirs().sort_stats('time').print_stats() - else: - main() diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test22.py b/tools/python/logging/logging-0.4.9.2/test/log_test22.py deleted file mode 100755 index 427ae40b90..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/log_test22.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# -"""Test harness for the logging module. Demonstrates the use of different -converters for time(secs) -> time(tuple). - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. -""" - -import logging, time - -def main(): - handler = logging.StreamHandler() - f1 = logging.Formatter("%(asctime)s %(message)s", "%m/%d %H:%M:%S") - f2 = logging.Formatter("%(asctime)s %(message)s", "%m/%d %H:%M:%S") - f2.converter = time.gmtime - handler.setFormatter(f1) - root = logging.getLogger("") - root.setLevel(logging.DEBUG) - root.addHandler(handler) - root.info("Something happened! [should be in local time]") - handler.setFormatter(f2) - root.info("Something else happened! [should be in GMT]") - handler.setFormatter(f1) - root.info("Something happened again! [should be in local time]") - logging.Formatter.converter = time.gmtime - root.info("Something else happened again! [should be in GMT]") - logging.Formatter.converter = time.localtime - root.info("Something else happened yet again! [should be in local time]") - -if __name__ == "__main__": - main() diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test3.ini b/tools/python/logging/logging-0.4.9.2/test/log_test3.ini deleted file mode 100644 index 15b751892f..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/log_test3.ini +++ /dev/null @@ -1,95 +0,0 @@ -[loggers] -keys=root,area1,area11,area111,area1111,area11111,area111111 - -[handlers] -keys=console,file,socket,datagram,syslog,NT,SMTP - -[formatters] -keys=short,medium,long - -[logger_root] -handlers=console -level=DEBUG - -[logger_area1] -level=DEBUG -qualname=log02 -handlers=file - -[logger_area11] -level=INFO -qualname=log02.log03 -handlers=socket - -[logger_area111] -level=WARN -propagate=0 -qualname=log02.log03.log04 -handlers=datagram - -[logger_area1111] -level=ERROR -qualname=log02.log03.log04.log05 -handlers=syslog - -[logger_area11111] -level=CRITICAL -qualname=log02.log03.log04.log05.log06 -handlers=NT - -[logger_area111111] -level=WARN -qualname=log02.log03.log04.log05.log06.log07 -handlers=SMTP - -[handler_console] -class=StreamHandler -formatter=medium -stream=sys.stdout -args=(sys.stdout,) - -[handler_file] -class=FileHandler -level=DEBUG -formatter=long -args=('python.log', 'w') - -[handler_socket] -class=handlers.SocketHandler -level=INFO -formatter=medium -args=('localhost', handlers.DEFAULT_TCP_LOGGING_PORT) - -[handler_datagram] -class=handlers.DatagramHandler -level=WARN -formatter=medium -args=('localhost', handlers.DEFAULT_UDP_LOGGING_PORT) - -[handler_syslog] -class=handlers.SysLogHandler -level=ERROR -formatter=short -args=(('localhost', handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER) - -[handler_NT] -class=handlers.NTEventLogHandler -level=CRITICAL -formatter=medium -args=('Python Application', '', 'Application') - -[handler_SMTP] -class=handlers.SMTPHandler -level=WARN -formatter=long -args=('localhost', 'from@abc', ['user1@abc', 'user2@xyz'], 'Logger Subject') - -[formatter_short] -format=%(message)s - -[formatter_long] -format=%(asctime)s %(pathname)s(%(lineno)d): %(levelname)s %(message)s - -[formatter_medium] -format=%(asctime)s %(levelname)s %(message)s -datefmt=%m-%d-%Y diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test3.py b/tools/python/logging/logging-0.4.9.2/test/log_test3.py deleted file mode 100755 index 09ba9ac149..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/log_test3.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# -""" -A test harness for the logging module. Tests new fileConfig (not yet a complete test). - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. -""" -import logging, logging.config - -def doLog(logger): - logger.debug("Debug") - logger.info("Info") - logger.warning("Warning") - logger.error("Error") - logger.critical("Critical") - -def main(): - logging.config.fileConfig("log_test3.ini") - logger = logging.getLogger(None) - print "---------------------------------------------------" - print "-- Logging to root; messages appear on console only" - print "---------------------------------------------------" - doLog(logger) - print "----------------------------------------------------------------------" - print "-- Logging to log02; messages appear on console and in file python.log" - print "----------------------------------------------------------------------" - logger = logging.getLogger("log02") - doLog(logger) - print "--------------------------------------------------------------------------" - print "-- Logging to log02.log03; messages appear on console, in file python.log," - print "-- and at logrecv.py tcp (if running. <= DEBUG messages will not appear)." - print "--------------------------------------------------------------------------" - logger = logging.getLogger("log02.log03") - doLog(logger) - print "-----------------------------------------------------------------------" - print "-- Logging to log02.log03.log04; messages appear only at logrecv.py udp" - print "-- (if running. <= INFO messages will not appear)." - print "-----------------------------------------------------------------------" - logger = logging.getLogger("log02.log03.log04") - doLog(logger) - print "--------------------------------------------------------------------" - print "-- Logging to log02.log03.log04.log05.log06; messages appear at" - print "-- logrecv.py udp (if running. < CRITICAL messages will not appear)." - print "--------------------------------------------------------------------" - logger = logging.getLogger("log02.log03.log04.log05.log06") - doLog(logger) - print "-- All done." - logging.shutdown() - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test4.py b/tools/python/logging/logging-0.4.9.2/test/log_test4.py deleted file mode 100755 index 5b59777e94..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/log_test4.py +++ /dev/null @@ -1,168 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# -""" -A test harness for the logging module. Tests arbitrary logging levels, filtering, and -use of strftime formatting. - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. -""" - -import logging -import locale, sys - -locale.setlocale(locale.LC_ALL, '') - -def message(s): - sys.stderr.write("%s\n" % s) - -# -# First, we define our levels. There can be as many as you want - the only limitations are that -# they should be integers, the lowest should be > 0 and larger values mean less information being -# logged. If you need specific level values which do not fit into these limitations, you can use -# a mapping dictionary to convert between your application levels and the logging system. -# -SILENT = 10 -TACITURN = 9 -TERSE = 8 -EFFUSIVE = 7 -SOCIABLE = 6 -VERBOSE = 5 -TALKATIVE = 4 -GARRULOUS = 3 -CHATTERBOX = 2 -BORING = 1 - -LEVEL_RANGE = range(BORING, SILENT + 1) - -# -# Next, we define names for our levels. You don't need to do this - in which case the system will -# use "Level n" to denote the text for the level. -# -my_logging_levels = { - SILENT : 'Silent', - TACITURN : 'Taciturn', - TERSE : 'Terse', - EFFUSIVE : 'Effusive', - SOCIABLE : 'Sociable', - VERBOSE : 'Verbose', - TALKATIVE : 'Talkative', - GARRULOUS : 'Garrulous', - CHATTERBOX: 'Chatterbox', - BORING : 'Boring', -} - -# -# Now, tell the logging system to associate names with our levels. -# -for lvl in my_logging_levels.keys(): - logging.addLevelName(lvl, my_logging_levels[lvl]) - -# -# Now, define a test function which logs an event at each of our levels. -# -def doLog(log): - for lvl in LEVEL_RANGE: - log.log(lvl, "This should only be seen at the '%s' logging level (or lower)", logging.getLevelName(lvl)) - -# -# Get the root logger and add a console hander to it, when run as a script. -# -log = logging.getLogger("") - -if __name__ == "__main__": - hdlr = logging.StreamHandler() - hdlr.setFormatter(logging.Formatter("%(asctime)s %(message)s", "%X")) #date format is as per the locale - log.addHandler(hdlr) -else: - hdlr = log.handlers[0] -# -# Set the logging level to each different value and call the utility function to log events. -# In the output, you should see that each time round the loop, the logging events actually output -# decreases. -# -for lvl in LEVEL_RANGE: - message("-- setting logging level to '%s' -----" % logging.getLevelName(lvl)) - log.setLevel(lvl) - doLog(log) -# -# Now, we demonstrate level filtering at the handler level. Tell the handler defined above -# to filter at level 'SOCIABLE', and repeat the above loop. Compare the output from the two runs. -# -hdlr.setLevel(SOCIABLE) -message("-- Filtering at handler level to SOCIABLE --") -for lvl in LEVEL_RANGE: - message("-- setting logging level to '%s' -----" % logging.getLevelName(lvl)) - log.setLevel(lvl) - doLog(log) - -hdlr.setLevel(0) #turn off level filtering at the handler - -# -# Now, let's demonstrate filtering. Suppose for some perverse reason we only want to print out -# all except GARRULOUS messages. Let's create a filter for this purpose... -# -class SpecificLevelFilter(logging.Filter): - def __init__(self, lvl): - self.level = lvl - - def filter(self, record): - return self.level != record.levelno - -class GarrulousFilter(SpecificLevelFilter): - def __init__(self): - SpecificLevelFilter.__init__(self, GARRULOUS) - -garr = GarrulousFilter() -hdlr.addFilter(garr) -message("-- Filtering using GARRULOUS filter --") -for lvl in LEVEL_RANGE: - message("-- setting logging level to '%s' -----" % logging.getLevelName(lvl)) - log.setLevel(lvl) - doLog(log) -# -# Now, let's demonstrate filtering at the logger. This time, use a filter which excludes SOCIABLE -# and TACITURN messages. Note that GARRULOUS events are still excluded. -# -class VerySpecificFilter(logging.Filter): - def filter(self, record): - return record.levelno not in [SOCIABLE, TACITURN] - -spec = VerySpecificFilter() -log.addFilter(spec) -message("-- Filtering using specific filter for SOCIABLE, TACITURN --") -for lvl in LEVEL_RANGE: - message("-- setting logging level to '%s' -----" % logging.getLevelName(lvl)) - log.setLevel(lvl) - doLog(log) - -log.removeFilter(spec) -hdlr.removeFilter(garr) -#Undo the one level which clashes...for regression tests -logging.addLevelName(logging.DEBUG, "DEBUG") - -# -# Er...that's it for now -# -if __name__ == "__main__": - print "All done." - logging.shutdown() - diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test5.py b/tools/python/logging/logging-0.4.9.2/test/log_test5.py deleted file mode 100755 index fd8d246787..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/log_test5.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# -""" -A test harness for the logging module. Tests SMTPHandler. - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. -""" -import logging, logging.handlers - -MAILHOST = 'beta' -FROM = 'log_test5@yourdomain.com' -TO = ['arkadi_renko'] -SUBJECT = 'Test Logging email from Python logging module (non-buffering)' - -def main(): - log = logging.getLogger("") - log.setLevel(logging.DEBUG) - hdlr = logging.handlers.SMTPHandler(MAILHOST, FROM, TO, SUBJECT) - hdlr.setFormatter(logging.Formatter("%(asctime)s %(levelname)-5s %(message)s")) - log.addHandler(hdlr) - log.info("Test email contents") - log.removeHandler(hdlr) - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test6.py b/tools/python/logging/logging-0.4.9.2/test/log_test6.py deleted file mode 100755 index 53ad805016..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/log_test6.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# -""" -A test harness for the logging module. Tests NTEventLogHandler. - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. -""" -import logging, logging.handlers - -def main(): - ntl = logging.handlers.NTEventLogHandler("Python Logging Test") - logger = logging.getLogger("") - logger.setLevel(logging.DEBUG) - logger.addHandler(ntl) - logger.debug("This is a '%s' message", "Debug") - logger.info("This is a '%s' message", "Info") - logger.warning("This is a '%s' message", "Warning") - logger.error("This is a '%s' message", "Error") - logger.critical("This is a '%s' message", "Critical") - try: - x = 4 / 0 - except: - logger.info("This is an %s (or should that be %s?)", "informational exception", "exceptional information", exc_info=1) - logger.exception("This is the same stuff, via a %s", "exception() call") - logger.removeHandler(ntl) - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test7.py b/tools/python/logging/logging-0.4.9.2/test/log_test7.py deleted file mode 100755 index 82845ba24b..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/log_test7.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# -""" -A test harness for the logging module. Tests MemoryHandler. - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. -""" -import sys, logging, logging.handlers - -def message(s): - sys.stderr.write("%s\n" % s) - -sh = logging.StreamHandler() -mh = logging.handlers.MemoryHandler(10,logging.WARNING, sh) -logger = logging.getLogger("") -logger.setLevel(logging.DEBUG) -logger.addHandler(mh) -message("-- logging at DEBUG, nothing should be seen yet --") -logger.debug("Debug message") -message("-- logging at INFO, nothing should be seen yet --") -logger.info("Info message") -message("-- logging at WARNING, 3 messages should be seen --") -logger.warning("Warning message") -for i in xrange(102): - message("-- logging %d at level INFO, messages should be seen every 10 events --" % i) - logger.info("Info index = %d", i) -sh.close() -mh.close() -logger.removeHandler(mh) \ No newline at end of file diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test8.py b/tools/python/logging/logging-0.4.9.2/test/log_test8.py deleted file mode 100755 index 774b0dd6d3..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/log_test8.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# -""" -A test harness for the logging module. Tests FileHandler rollover. - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. -""" -import logging, logging.handlers -import locale - -locale.setlocale(locale.LC_ALL, '') - -sequence = 0 - -def doLog(logger): - global sequence - sequence = sequence + 1 - logger.debug("%6d This message should be at level %d - %s", sequence,\ - logging.DEBUG, logging.getLevelName(logging.DEBUG)) - sequence = sequence + 1 - logger.info("%6d This message should be at level %d - %s", sequence, - logging.INFO, logging.getLevelName(logging.INFO)) - sequence = sequence + 1 - logger.warning("%6d This message should be at level %d - %s", sequence,\ - logging.WARNING, logging.getLevelName(logging.WARNING)) - sequence = sequence + 1 - logger.error("%6d This message should be at level %d - %s", sequence,\ - logging.ERROR, logging.getLevelName(logging.ERROR)) - sequence = sequence + 1 - logger.critical("%6d This message should be at level %d - %s", sequence,\ - logging.CRITICAL, logging.getLevelName(logging.CRITICAL)) - -def main(): - logger = logging.getLogger("") #root logger - logger.setLevel(logging.DEBUG) - if __name__ == "__main__": - logname = "rollover.log" - else: - logname = "log_test_rollover.log" - hdlr = logging.handlers.RotatingFileHandler(logname, "a", 5000, 3) - if __name__ == "__main__": - fmt = logging.Formatter("%(asctime)s %(levelname)-5s %(message)s", "%x %X") - hdlr.setFormatter(fmt) - logger.addHandler(hdlr) - for i in xrange(100): - doLog(logger) - logger.removeHandler(hdlr) - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/tools/python/logging/logging-0.4.9.2/test/log_test9.py b/tools/python/logging/logging-0.4.9.2/test/log_test9.py deleted file mode 100755 index 75653af539..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/log_test9.py +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# -""" -A test harness for the logging module. Tests BufferingHandler, BufferingFormatter. - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. -""" -import logging, logging.handlers - -class XMLFormatter(logging.BufferingFormatter): - """ - A formatter which formats a set of records using XML, using an example DTD called "logging.dtd". - """ - def __init__(self): - fmtstr = """ - - %(message)s - """ - logging.BufferingFormatter.__init__(self, logging.Formatter(fmtstr)) - -# def formatHeader(self, records): -# return """ -# -#""" -# -# def formatFooter(self, records): -# return "" - -class XMLHandler(logging.handlers.BufferingHandler): - def __init__(self, capacity): - logging.handlers.BufferingHandler.__init__(self, capacity) - self.setFormatter(XMLFormatter()) - - def flush(self): - if len(self.buffer) > 0: - file = open("events.xml","w") - file.write(self.formatter.format(self.buffer)) - file.close() - self.buffer = [] - -def main(): - logger = logging.getLogger("") - logger.setLevel(logging.DEBUG) - xh = XMLHandler(10) - logger.addHandler(xh) - for i in xrange(100): - logger.info("Info index = %d", i) - xh.close() - logger.removeHandler(xh) - -if __name__ == "__main__": - main() diff --git a/tools/python/logging/logging-0.4.9.2/test/logconf.ini b/tools/python/logging/logging-0.4.9.2/test/logconf.ini deleted file mode 100644 index b74e10c6ad..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/logconf.ini +++ /dev/null @@ -1,180 +0,0 @@ -[loggers] -keys=root,log02,log03,log04,log05,log06,log07 - -[handlers] -keys=hand01,hand02,hand03,hand04,hand05,hand06,hand07,hand08,hand09 - -[formatters] -keys=form01,form02,form03,form04,form05,form06,form07,form08,form09 - -[logger_root] -level=NOTSET -propagate=1 -channel= -parent= -qualname=(root) -handlers=hand01 - -[logger_log02] -level=DEBUG -propagate=1 -channel=log02 -parent=(root) -qualname=log02 -handlers=hand02 - -[logger_log03] -level=INFO -propagate=1 -channel=log03 -parent=log02 -qualname=log02.log03 -handlers=hand03 - -[logger_log04] -level=WARN -propagate=0 -channel=log04 -parent=log03 -qualname=log02.log03.log04 -handlers=hand04 - -[logger_log05] -level=ERROR -propagate=1 -channel=log05 -parent=log04 -qualname=log02.log03.log04.log05 -handlers=hand05 - -[logger_log06] -level=CRITICAL -propagate=1 -channel=log06 -parent=log05 -qualname=log02.log03.log04.log05.log06 -handlers=hand06 - -[logger_log07] -level=WARN -propagate=1 -channel=log07 -parent=log06 -qualname=log02.log03.log04.log05.log06.log07 -handlers=hand07 - -[handler_hand01] -class=StreamHandler -level=NOTSET -formatter=form01 -stream=sys.stdout -args=(sys.stdout,) - -[handler_hand02] -class=FileHandler -level=DEBUG -formatter=form02 -filename=python.log -mode=w -args=('python.log', 'w') - -[handler_hand03] -class=handlers.SocketHandler -level=INFO -formatter=form03 -host=localhost -port=handlers.DEFAULT_TCP_LOGGING_PORT -args=('localhost', handlers.DEFAULT_TCP_LOGGING_PORT) - -[handler_hand04] -class=handlers.DatagramHandler -level=WARN -formatter=form04 -host=localhost -port=handlers.DEFAULT_UDP_LOGGING_PORT -args=('localhost', handlers.DEFAULT_UDP_LOGGING_PORT) - -[handler_hand05] -class=handlers.SysLogHandler -level=ERROR -formatter=form05 -host=localhost -port=handlers.SYSLOG_UDP_PORT -facility=LOG_USER -args=(('localhost', handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER) - -[handler_hand06] -class=handlers.NTEventLogHandler -level=CRITICAL -formatter=form06 -appname=Python Application -dllname= -logtype=Application -args=('Python Application', '', 'Application') - -[handler_hand07] -class=handlers.SMTPHandler -level=WARN -formatter=form07 -host=localhost -port=25 -from=from@abc -to=user1@abc,user2@xyz -subject=Logger Subject -args=('localhost', 'from@abc', ['user1@abc', 'user2@xyz'], 'Logger Subject') - -[handler_hand08] -class=handlers.MemoryHandler -level=NOTSET -formatter=form08 -capacity=10 -flushlevel=ERROR -target= -args=(10, ERROR) - -[handler_hand09] -class=handlers.HTTPHandler -level=NOTSET -formatter=form09 -host=localhost -port=9022 -url=/log -method=GET -args=('localhost:9022', '/log', 'GET') - -[formatter_form01] -format=F1 %(asctime)s %(levelname)s %(message)s -datefmt= - -[formatter_form02] -format=F2 %(asctime)s %(pathname)s(%(lineno)d): %(levelname)s %(message)s -datefmt= - -[formatter_form03] -format=F3 %(asctime)s %(levelname)s %(message)s -datefmt= - -[formatter_form04] -format=%(asctime)s %(levelname)s %(message)s -datefmt= - -[formatter_form05] -format=F5 %(asctime)s %(levelname)s %(message)s -datefmt= - -[formatter_form06] -format=F6 %(asctime)s %(levelname)s %(message)s -datefmt= - -[formatter_form07] -format=F7 %(asctime)s %(levelname)s %(message)s -datefmt= - -[formatter_form08] -format=F8 %(asctime)s %(levelname)s %(message)s -datefmt= - -[formatter_form09] -format=F9 %(asctime)s %(levelname)s %(message)s -datefmt= - diff --git a/tools/python/logging/logging-0.4.9.2/test/logconf.py b/tools/python/logging/logging-0.4.9.2/test/logconf.py deleted file mode 100755 index f54792f4f8..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/logconf.py +++ /dev/null @@ -1,1738 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# This file is part of the Python logging distribution. See -# http://www.red-dove.com/python_logging.html -# - -""" -A simple-minded GUI configurator for the logging module, using Tkinter. - -Should work under Python versions >= 1.5.2. - -Copyright (C) 2002 Vinay Sajip. All Rights Reserved. - -Configuration files are read/written using ConfigParser. -""" -""" - -(C) 2002 Vinay Sajip. All rights reserved. -""" -from Tkinter import * -from tkFileDialog import * -from tkMessageBox import * - -import os, sys, string, types -import ConfigParser - -active = None - -__version__ = "0.4.1" - -DEFAULT_FILENAME = "logconf.ini" - -LOGGING_LEVELS = ( - ("NOTSET", "NOTSET"), - ("DEBUG", "DEBUG"), - ("INFO", "INFO"), - ("WARNING", "WARNING"), - ("ERROR", "ERROR"), - ("CRITICAL", "CRITICAL") -) - -HANDLER_TYPES = ( - ("StreamHandlerProxy", "StreamHandler"), - ("FileHandlerProxy", "FileHandler"), - ("RotatingFileHandlerProxy", "RotatingFileHandler"), - ("SocketHandlerProxy", "SocketHandler"), - ("DatagramHandlerProxy", "DatagramHandler"), - ("SysLogHandlerProxy", "SysLogHandler"), - ("NTEventLogHandlerProxy", "NTEventLogHandler"), - ("SMTPHandlerProxy", "SMTPHandler"), - ("MemoryHandlerProxy", "MemoryHandler"), - ("HTTPHandlerProxy", "HTTPHandler"), -# ("SOAPHandlerProxy", "SOAPHandler"), -) - -OUTPUT_STREAMS = ( - ("sys.stdout", "sys.stdout"), - ("sys.stderr", "sys.stderr") -) - -FILE_MODES = ( - ("a", "a"), - ("w", "w") - ) - -HTTP_METHODS = ( - ("GET", "GET"), - ("POST", "POST") -) - -SYSLOG_FACILITIES = ( - ("LOG_AUTH", "auth"), - ("LOG_AUTHPRIV", "authpriv"), - ("LOG_CRON", "cron"), - ("LOG_DAEMON", "daemon"), - ("LOG_KERN", "kern"), - ("LOG_LPR", "lpr"), - ("LOG_MAIL", "mail"), - ("LOG_NEWS", "news"), - ("LOG_AUTH", "security"), - ("LOG_SYSLOG", "syslog"), - ("LOG_USER", "user"), - ("LOG_UUCP", "uucp"), - ("LOG_LOCAL0", "local0"), - ("LOG_LOCAL1", "local1"), - ("LOG_LOCAL2", "local2"), - ("LOG_LOCAL3", "local3"), - ("LOG_LOCAL4", "local4"), - ("LOG_LOCAL5", "local5"), - ("LOG_LOCAL6", "local6"), - ("LOG_LOCAL7", "local7"), -) - -LOG_TYPES = ( - ("Application", "Application"), - ("System", "System"), - ("Security", "Security") -) - -BOOLEAN_VALUES = ( - ("0", "False"), - ("1", "True") -) - -class Property: - def __init__(self, name, caption, value=None, choices=None): - self.name = name - self.caption = caption - self.value = value - self.choices = choices - - def getChoices(self): - return self.choices - - def isvalid(self, s): - return 0 - - def getCaption(self): - return self.caption - - def getValue(self): - return self.value - - def getChoiceText(self, val): - rv = "" - choices = self.getChoices() - if choices: - for choice in choices: - if choice[0] == val: - rv = choice[1] - break - return rv - - def setValue(self, val): - self.value = val - - def getValueText(self): - if type(self.value) in [types.ListType, types.TupleType]: - v = list(self.value) - else: - v = [self.value] - choices = self.getChoices() - if choices: - v = map(self.getChoiceText, v) - return string.join(v, ',') - -class PropertyHolder: - def __init__(self, dict): - self.dict = dict - self.propnames = [] - self.onPropListChanged = None - - def getPropNames(self): - """ - Return the property names in the order in which they are to - be listed. - """ - return self.propnames - - def getProp(self, name): - return self.dict[name] - - def isReadonly(self, name): - return 0 - - #convenience methods - def getPropValue(self, name): - return self.dict[name].value - - def setPropValue(self, name, value): - self.dict[name].setValue(value) - -LINE_COLOUR = '#999999' - -class ScrollingList(Frame): - def __init__(self, parent, *args, **kwargs): - Frame.__init__(self, parent) - self.parent = parent - self.listener = self.parent - self.sb = Scrollbar(self, orient=VERTICAL) - kwargs["yscrollcommand"] = self.sb.set - self.list = apply(Listbox, (self,) + args, kwargs) - self.sb.config(command=self.list.yview) - self.sb.pack(side=RIGHT, fill=Y) - self.list.pack(side=LEFT, fill=BOTH,expand=1) - self.list.bind('', self.onListChange) - self.choices = None - - def setContents(self, choices, value): - self.choices = choices - self.value = value - self.list.delete(0, END) - if type(value) == types.ListType: - sm = EXTENDED - else: - sm = BROWSE - self.list.configure(selectmode=sm) - i = 0 - for choice in choices: - self.list.insert(END, choice[1]) - if sm == EXTENDED: - if choice[0] in value: - self.list.select_set(i) - else: - if choice[0] == value: - self.list.select_set(i) - i = i + 1 - - def getValue(self): - if type(self.value) == types.ListType: - multi = 1 - rv = [] - else: - multi = 0 - for i in xrange(len(self.choices)): - if self.list.select_includes(i): - if not multi: - rv = self.choices[i][0] - break - else: - rv.append(self.choices[i][0]) - return rv - - def onListChange(self, event): - self.value = self.getValue() - self.listener.onListChange(self.value) - -class PropertyHeader(Canvas): - def __init__(self, parent, *args, **kwargs): - self.namewidth = 120 - if kwargs.has_key("namewidth"): - self.namewidth = kwargs["namewidth"] - del kwargs["namewidth"] - self.rowheight = 16 - if kwargs.has_key("rowheight"): - self.rowheight = kwargs["rowheight"] - del kwargs["rowheight"] - apply(Canvas.__init__, (self, parent)+args, kwargs) - self.bind('', self.onConfigure) - x = 5 - y = 0 - wid = int(self.cget('width')) - self.create_text(x, y, text='Property', anchor='nw') - self.create_text(x + self.namewidth, y, text='Value', anchor='nw') - self.create_line(self.namewidth, 0, self.namewidth, self.rowheight, fill=LINE_COLOUR) - self.tline = self.create_line(0, 0, wid, 0, fill=LINE_COLOUR) - #self.create_line(0, 0, 0, self.rowheight, fill=LINE_COLOUR) - #self.create_line(wid - 1, 0, wid - 1, self.rowheight, fill=LINE_COLOUR) - - def onConfigure(self, event): - self.delete(self.tline) - self.tline = self.create_line(0, 0, event.width, 0, fill=LINE_COLOUR) - -_popup = None - -class PropertyCanvas(Canvas): - def __init__(self, parent, *args, **kwargs): - self.namewidth = 120 - if kwargs.has_key("namewidth"): - self.namewidth = kwargs["namewidth"] - del kwargs["namewidth"] - self.rowheight = 16 - if kwargs.has_key("rowheight"): - self.rowheight = kwargs["rowheight"] - del kwargs["rowheight"] - apply(Canvas.__init__, (self, parent)+args, kwargs) - self.namitems = [] - self.valitems = [] - self.lines = [] - self.pnames = [] - #Event bindings... - self.bind('', self.onEnter) - self.bind('', self.onClick) - self.bind('', self.onConfigure) - self.button = Button(height=self.rowheight, width=self.rowheight, text='...', command=self.onEdit) - self.btnitem = None - self.editor = Entry() - self.edititem = None - self.popup = Toplevel() - self.popup.withdraw() - self.popup.overrideredirect(1) - self.list = ScrollingList(self.popup, background='white', relief=FLAT, borderwidth=0) - self.list.pack(fill=BOTH, expand=1) - self.list.listener = self - self.listvisible = 0 - - def clear(self): - for itm in self.namitems: - self.delete(itm) - self.namitems = [] - for itm in self.valitems: - self.delete(itm) - self.valitems = [] - for lin in self.lines: - self.delete(lin) - self.lines = [] - - def setPropertyHolder(self, ph): - self.ph = ph - self.pnames = ph.getPropNames() - wid = int(self.cget('width')) - hei = int(self.cget('height')) - self.clear() - x = 5 - y = 0 - i = 0 - self.props = [] - for n in self.pnames: - prop = self.ph.getProp(n) - self.props.append(prop) - tn = "n%d" % i - tv = "v%d" % i - self.namitems.append(self.create_text(x, y + 2, text=prop.getCaption(), anchor='nw', tags=tn)) - self.valitems.append(self.create_text(x + self.namewidth, y + 2, text=prop.getValueText(), anchor='nw', tags=tv)) - y = y + self.rowheight - i = i + 1 - self.drawLines(wid, hei) - #self.config(height=y) - - def drawLines(self, wid, hei): - for lin in self.lines: - self.delete(lin) - self.lines = [] - y = 0 - for i in xrange(len(self.pnames)): - self.lines.append(self.create_line(0, y, wid, y, fill=LINE_COLOUR)) - y = y + self.rowheight - self.lines.append(self.create_line(0, y, wid, y, fill=LINE_COLOUR)) - self.create_line(self.namewidth, 0, self.namewidth, hei, fill=LINE_COLOUR) - - def onEnter(self, event): - if not self.edititem and not self.listvisible: - self.focus_set() - - def hideControls(self): - if self.listvisible: - self.popup.withdraw() - global _popup - _popup = None - self.listvisible = 0 - if self.edititem: - self.ph.setPropValue(self.editprop.name, self.editor.get()) - self.itemconfig(self.valitems[self.editrow], text=self.editprop.getValueText()) - self.delete(self.edititem) - self.edititem = None - if self.btnitem: - self.delete(self.btnitem) - self.btnitem = None - - def onClick(self, event): - row = event.y / self.rowheight - self.hideControls() - if row < len(self.pnames): - wid = int(self.cget('width')) - hei = self.rowheight - prop = self.props[row] - if not self.ph.isReadonly(self.pnames[row]): - self.editrow = row - self.editprop = prop - choices = prop.getChoices() - if choices != None: - val = prop.getValue() - self.list.setContents(choices, val) - self.listy = row * hei + self.rowheight - self.btnitem = self.create_window(wid - hei, row * hei, width=hei, height=hei, window=self.button, anchor='nw', tags='button') - else: - self.editor.delete(0, END) - self.editor.insert(0, prop.getValueText()) - self.editor.select_range(0, END) - self.edititem = self.create_window(self.namewidth + 1, row * hei, width=wid - self.namewidth, height = hei + 1, window=self.editor, anchor='nw', tags='editor') - self.editor.focus_set() - - def onConfigure(self, event): - self.hideControls() - self.drawLines(event.width, event.height) - self.configure(width=event.width, height=event.height) - - def onEdit(self): - wid = int(self.cget('width')) - #self.listitem = self.create_window(self.namewidth + 1, self.listy, width=wid - self.namewidth - 1, height = self.rowheight * 3, window=self.list, anchor='nw', tags='list') - w = wid - self.namewidth - 1 - h = self.rowheight * 5 - x = self.winfo_rootx() + self.namewidth + 1 - y = self.winfo_rooty() + self.listy - s = "%dx%d+%d+%d" % (w, h, x, y) - self.popup.deiconify() - self.popup.lift() - self.popup.focus_set() - self.listvisible = 1 - self.list.focus_set() - #For some reason with 1.5.2 (Windows), making the geometry call - #immediately following the assignment to s doesn't work. So we - #do it here - self.popup.geometry(s) - global _popup - _popup = self.popup - - def onListChange(self, val): - self.ph.setPropValue(self.editprop.name, val) - self.itemconfig(self.valitems[self.editrow], text=self.editprop.getValueText()) - if type(val) != types.ListType: - self.hideControls() - -class PropertyEditor(Frame): - def __init__(self, parent, *args, **kwargs): - Frame.__init__(self, parent) - self.parent = parent - nw = kwargs.get("namewidth", 120) - rh = kwargs.get("rowheight", 16) - wid = kwargs.get("width", 300) - hei = kwargs.get("height", 60) - self.header = PropertyHeader(self, namewidth=nw, rowheight=rh, height=14, highlightthickness=0) - self.body = PropertyCanvas(self, namewidth=nw, rowheight=rh, width=wid, height=hei, background='white', highlightthickness=0) - self.header.pack(side=TOP, fill=X) - self.body.pack(side=BOTTOM, fill=BOTH, expand=1) - - def setPropertyHolder(self, ph): - self.body.setPropertyHolder(ph) - -class ADUPanel(Frame): - def __init__(self, parent): - Frame.__init__(self, parent) - self.parent = parent - self.add = Button(self, text="New", command=parent.onAdd) - self.add.pack(side=LEFT) #, fill=X, expand=1) - self.rmv = Button(self, text="Delete", command=parent.onDelete) - self.rmv.pack(side=LEFT) #, fill=X, expand=1) - #self.upd = Button(self, text="Update", command=parent.onUpdate) - #self.upd.pack(side=RIGHT, fill=X, expand=1) - -class ScrollList(Frame): - def __init__(self, parent, *args, **kwargs): - Frame.__init__(self, parent) - self.parent = parent - self.sb = Scrollbar(self, orient=VERTICAL) - kwargs["yscrollcommand"] = self.sb.set - self.list = apply(Listbox, (self,) + args, kwargs) - self.sb.config(command=self.list.yview) - self.sb.pack(side=RIGHT, fill=Y) - self.list.pack(side=LEFT, fill=BOTH,expand=1) - -def sortqn(log1, log2): - qn1 = log1.getQualifiedName() - qn2 = log2.getQualifiedName() - if qn1 == "(root)": - rv = -1 - elif qn2 == "(root)": - rv = 1 - else: - rv = cmp(qn1, qn2) - return rv - -def sortn(obj1, obj2): - return cmp(obj1.getPropValue("name"), obj2.getPropValue("name")) - -class LoggerPanel(Frame): - def __init__(self, parent): - Frame.__init__(self, parent) - self.parent = parent - label = Label(self, text="Loggers:") - label.grid(row=0, column=0, sticky='w') - self.slist = ScrollList(self, height=15, background='white') - self.slist.list.bind('', self.onListChange) - self.slist.grid(row=1, column=0, sticky="nsew") - self.adu = ADUPanel(self) - self.adu.grid(row=2, column=0, sticky="we") - label = Label(self, text="Properties of selected logger:") - label.grid(row=3, column=0, sticky='w') - self.pe = PropertyEditor(self, height=120, borderwidth=1) - self.pe.grid(row=4, column=0, sticky='nsew') - self.columnconfigure(0, weight=1) - self.rowconfigure(1, weight=3) - self.rowconfigure(4, weight=1) - - def setConfig(self, config): - self.config = config - #populate list of loggers - llist = config.getLoggers() - llist.sort(sortqn) - self.slist.list.delete(0, END) - self.pe.body.clear() - self.names = [] - for logger in llist: - self.names.append(logger.getPropValue("name")) - self.slist.list.insert(END, logger.getQualifiedName()) - - def onAdd(self): - items = self.slist.list.curselection() - if not len(items): - showerror("No Parent Selected", "You haven't selected a parent logger.") - else: - idx = int(items[0]) - parent = self.config.getLogger(self.names[idx]) - log = self.config.getLogger(None) - log.onChannelChanged = self.onChannelChanged - log.setPropValue("parent", parent.getPropValue("name")) - self.names.insert(1 + idx, log.getPropValue("name")) - self.slist.list.insert(1 + idx, log.getQualifiedName()) - self.slist.list.select_clear(0, END) - self.slist.list.select_set(1 + idx) - self.pe.setPropertyHolder(log) - - def onDelete(self): - items = self.slist.list.curselection() - if not len(items): - showerror("No Item Selected", "You haven't selected anything to delete.") - else: - idx = int(items[0]) - name = self.slist.list.get(idx) - if name == "(root)": - showerror("Root Item Selected", "You cannot delete the root logger.") - else: - resp = askyesno("Logger Deletion", "Are you sure you want to delete logger '%s'?" % name) - if resp: - #self.config.removeLogger(self.names[idx]) - log = self.config.getLogger(self.names[idx]) - log.deleted = 1 - self.slist.list.delete(idx) - del self.names[idx] - self.pe.body.clear() - - def onChannelChanged(self, nm, chname): - i = self.names.index(nm) - sel = i - while i < len(self.names): - log = self.config.getLogger(self.names[i]) - self.slist.list.delete(i) - self.slist.list.insert(i, log.getQualifiedName()) - i = i + 1 - self.slist.list.select_clear(0, END) - self.slist.list.select_set(sel) - - def onListChange(self, event): - self.pe.body.hideControls() - items = self.slist.list.curselection() - idx = int(items[0]) - name = self.names[idx] - log = self.config.getLogger(name) - self.pe.setPropertyHolder(log) - -class HandlerPanel(Frame): - def __init__(self, parent): - Frame.__init__(self, parent) - self.parent = parent - label = Label(self, text="Handlers:") - label.grid(row=0, column=0, sticky='w') - self.slist = ScrollList(self, height=6, background='white') - self.slist.list.bind('', self.onListChange) - self.slist.grid(row=1, column=0, sticky="nsew") - self.adu = ADUPanel(self) - self.adu.grid(row=2, column=0, sticky="we") - label = Label(self, text="Properties of selected handler:") - label.grid(row=3, column=0, sticky='w') - self.pe = PropertyEditor(self, height=90, borderwidth=1) - self.pe.grid(row=4, column=0, sticky='nsew') - self.columnconfigure(0, weight=1) - self.rowconfigure(1, weight=1) - self.rowconfigure(4, weight=1) - - def setConfig(self, config): - self.config = config - #populate list of handlers - hlist = config.getHandlers() - hlist.sort(sortn) - self.slist.list.delete(0, END) - self.pe.body.clear() - for hand in hlist: - hand.onPropListChanged = self.onPropListChanged - self.slist.list.insert(END, hand.getPropValue("name")) - - def onAdd(self): - self.pe.body.hideControls() - hand = self.config.getHandler(None) - self.slist.list.insert(END, hand.getProp("name").getValueText()) - self.slist.list.select_clear(0, END) - self.slist.list.select_set(END) - hand.onPropListChanged = self.onPropListChanged - self.pe.setPropertyHolder(hand) - - def onDelete(self): - items = self.slist.list.curselection() - if not len(items): - showerror("No Item Selected", "You haven't selected anything to delete") - else: - name = self.slist.list.get(int(items[0])) - log = self.config.handlerIsUsed(name) - if log: - showerror("Handler in use", - "The handler '%s' is being used by logger '%s'"\ - ", so it cannot be deleted." % ( - name, log)) - else: - self.config.removeHandler(name) - self.slist.list.delete(items) - self.pe.body.clear() - - def onUpdate(self): - print "handler update" - - def onListChange(self, event): - self.pe.body.hideControls() - items = self.slist.list.curselection() - name = self.slist.list.get(int(items[0])) - hand = self.config.getHandler(name) - self.pe.setPropertyHolder(hand) - - def onPropListChanged(self, newhand): - newhand.onPropListChanged = self.onPropListChanged - self.pe.setPropertyHolder(newhand) - -class FormatterPanel(Frame): - def __init__(self, parent): - Frame.__init__(self, parent) - self.parent = parent - label = Label(self, text="Formatters:") - label.grid(row=0, column=0, sticky='w') - self.slist = ScrollList(self, height=4, background='white') - self.slist.list.bind('', self.onListChange) - self.slist.grid(row=1, column=0, sticky="nsew") - self.adu = ADUPanel(self) - self.adu.grid(row=2, column=0, sticky="ew") - label = Label(self, text="Properties of selected formatter:") - label.grid(row=3, column=0, sticky='w') - self.pe = PropertyEditor(self, height=60, borderwidth=1) - self.pe.grid(row=4, column=0, sticky='nsew') - self.columnconfigure(0, weight=1) - self.rowconfigure(1, weight=1) - self.rowconfigure(4, weight=1) - - def setConfig(self, config): - self.config = config - #populate list of formatters - flist = config.getFormatters() - flist.sort(sortn) - self.slist.list.delete(0, END) - self.pe.body.clear() - for form in flist: - self.slist.list.insert(END, form.getPropValue("name")) - - def onAdd(self): - self.pe.body.hideControls() - fmt = self.config.getFormatter(None) - self.slist.list.insert(END, fmt.getProp("name").getValueText()) - self.slist.list.select_clear(0, END) - i = self.slist.list.size() - self.slist.list.select_set(i - 1) - self.pe.setPropertyHolder(fmt) - - def onDelete(self): - self.pe.body.hideControls() - items = self.slist.list.curselection() - if not len(items): - showerror("No Item Selected", "You haven't selected anything to delete") - else: - name = self.slist.list.get(int(items[0])) - h = self.config.formatterIsUsed(name) - if h: - showerror("Formatter in use", - "The formatter '%s' is being used by handler '%s'"\ - ", so it cannot be deleted." % ( - name, h)) - else: - self.config.removeFormatter(name) - self.slist.list.delete(items) - self.pe.body.clear() - - def onUpdate(self): - self.pe.body.hideControls() - - def onListChange(self, event): - self.pe.body.hideControls() - items = self.slist.list.curselection() - name = self.slist.list.get(int(items[0])) - fmt = self.config.getFormatter(name) - self.pe.setPropertyHolder(fmt) - -class FilterPanel(Frame): - def __init__(self, parent): - Frame.__init__(self, parent) - self.parent = parent - label = Label(self, text="Filters:") - label.grid(row=0, column=0, sticky='w') - self.slist = ScrollList(self, height=4, background='white') - self.slist.list.bind('', self.onListChange) - self.slist.grid(row=1, column=0, sticky="nsew") - self.adu = ADUPanel(self) - self.adu.grid(row=2, column=0, sticky="ew") - label = Label(self, text="Properties of selected filter:") - label.grid(row=3, column=0, sticky='w') - self.pe = PropertyEditor(self, height=60, borderwidth=1) - self.pe.grid(row=4, column=0, sticky='nsew') - self.columnconfigure(0, weight=1) - self.rowconfigure(1, weight=1) - self.rowconfigure(4, weight=1) - - def setConfig(self, config): - self.config = config - #populate list of filters - flist = config.getFilters() - flist.sort(sortn) - self.slist.list.delete(0, END) - self.pe.body.clear() - for filt in flist: - self.slist.list.insert(END, filt.getPropValue("name")) - - def onAdd(self): - self.pe.body.hideControls() - filt = self.config.getFilter(None) - self.slist.list.insert(END, filt.getProp("name").getValueText()) - self.slist.list.select_clear(0, END) - i = self.slist.list.size() - self.slist.list.select_set(i - 1) - self.pe.setPropertyHolder(filt) - - def onDelete(self): - self.pe.body.hideControls() - items = self.slist.list.curselection() - if not len(items): - showerror("No Item Selected", "You haven't selected anything to delete") - else: - name = self.slist.list.get(int(items[0])) - h = self.config.filterIsUsed(name) - if h: - showerror("Filter in use", - "The filter '%s' is being used by '%s'"\ - ", so it cannot be deleted." % ( - name, h)) - else: - self.config.removeFilter(name) - self.slist.list.delete(items) - self.pe.body.clear() - - def onUpdate(self): - self.pe.body.hideControls() - - def onListChange(self, event): - self.pe.body.hideControls() - items = self.slist.list.curselection() - name = self.slist.list.get(int(items[0])) - filt = self.config.getFilter(name) - self.pe.setPropertyHolder(filt) - -class ConfigPanel(Frame): - def __init__(self, parent): - Frame.__init__(self, parent) - self.parent = parent - self.load = Button(self, text="Load...", command=parent.onLoad) - self.load.pack(side=LEFT) - self.save = Button(self, text="Save", command=parent.onSave) - self.save.pack(side=LEFT) - self.save = Button(self, text="Save as...", command=parent.onSaveAs) - self.save.pack(side=LEFT) - self.reset = Button(self, text="Reset", command=parent.onReset) - self.reset.pack(side=RIGHT) - -class Configurator(Frame): - def __init__(self, parent): - Frame.__init__(self, parent) - self.parent = parent - self.llist = LoggerPanel(self) - self.llist.grid(row=0, column=0, rowspan=2, sticky='nsew') - spacer = Canvas(self, width=2, highlightthickness=0) - spacer.grid(row=0, column=1, rowspan=2, sticky='ns') - self.hlist = HandlerPanel(self) - self.hlist.grid(row=0, column=2, sticky='nsew') - self.flist = FormatterPanel(self) - self.flist.grid(row=1, column=2, sticky='nsew') - self.cfg = ConfigPanel(self) - self.cfg.grid(row=2, column=0, columnspan=2, sticky='w') - self.filename = None - - self.rowconfigure(0, weight=1) - self.columnconfigure(0, weight=1) - self.columnconfigure(2, weight=1) - - label = Label(self, text="Copyright (C) 2002 Vinay Sajip. All rights reserved.", foreground='brown') - label.grid(row=3, column=0, columnspan=2, sticky='w') - - if len(sys.argv) > 1: - fn = sys.argv[1] - try: - self.loadFile(fn) - except Exception, e: - print e - raise - else: - self.onReset(0) - self.setTitle() - self.focus_set() - - def setTitle(self): - if self.filename: - s = os.path.split(self.filename)[1] - else: - s = "untitled" - self.winfo_toplevel().title("%s - Python Logging Configurator V%s" % (s, __version__)) - - def loadFile(self, fn): - self.config = LoggingConfig() - self.config.read(fn) - self.filename = fn - self.llist.setConfig(self.config) - self.hlist.setConfig(self.config) - self.flist.setConfig(self.config) - self.setTitle() - - def onLoad(self): - fn = askopenfilename(title="Choose configuration file", filetypes=[("Logging configurations", "*.ini"), ("All files", "*.*")]) - if fn: - self.loadFile(fn) - - def onSaveAs(self): - if self.filename: - fn = os.path.split(self.filename)[1] - else: - fn = DEFAULT_FILENAME - fn = asksaveasfilename(title="Save configuration as", initialfile=fn, filetypes=[("Logging configurations", "*.ini"), ("All files", "*.*")]) - if fn: - self.config.save(fn) - self.filename = fn - self.setTitle() - - def onSave(self): - if not self.filename: - self.onSaveAs() - else: - self.config.save(self.filename) - - def onReset(self, confirm=1): - if not confirm: - doit = 1 - else: - doit = askyesno("Reset", "Are you sure you want to reset?") - if doit: - self.config = LoggingConfig() - self.llist.setConfig(self.config) - self.hlist.setConfig(self.config) - self.flist.setConfig(self.config) - self.setTitle() - -# -- general properties - -class NameProperty(Property): - def __init__(self, value=None): - Property.__init__(self, "name", "Name", value) - -class LevelProperty(Property): - def __init__(self, value=None): - Property.__init__(self, "level", "Level", value) - - def getChoices(self): - return LOGGING_LEVELS - -# -- formatter properties - -class FormatProperty(Property): - def __init__(self, value=None): - Property.__init__(self, "format", "Format", value) - -class DateFormatProperty(Property): - def __init__(self, value=None): - Property.__init__(self, "datefmt", "Date Format", value) - -class FormatterProxy(PropertyHolder): - def __init__(self, config, dict): - self.config = config - PropertyHolder.__init__(self, dict) - prop = NameProperty(dict.get("name", "")) - self.dict["name"] = prop - prop = FormatProperty(dict.get("format", "%(asctime)s %(levelname)s %(message)s")) - self.dict["format"] = prop - prop = DateFormatProperty(dict.get("datefmt", "")) - self.dict["datefmt"] = prop - self.propnames = ["name", "format", "datefmt"] - - def isReadonly(self, name): - return name == "name" - - def writeConfig(self, file): - file.write("[formatter_%s]\n" % self.getPropValue("name")) - file.write("format=%s\n" % self.getPropValue("format")) - file.write("datefmt=%s\n\n" % self.getPropValue("datefmt")) - -# -- filter properties - -class LoggerNameProperty(Property): - def __init__(self, value=None): - Property.__init__(self, "lname", "Name", value) - -class FilterProxy(PropertyHolder): - def __init__(self, config, dict): - self.config = config - PropertyHolder.__init__(self, dict) - prop = NameProperty(dict.get("name", "")) - self.dict["name"] = prop - prop = LoggerNameProperty(dict.get("lname", "")) - self.dict["lname"] = prop - self.propnames = ["name", "lname"] - - def isReadonly(self, name): - return name == "name" - - def writeConfig(self, file): - file.write("[filter_%s]\n" % self.getPropValue("name")) - file.write("lname=%s\n" % self.getPropValue("lname")) - -# -- handler properties and proxies - -class HandlerTypeProperty(Property): - def __init__(self, value=None): - Property.__init__(self, "class", "Type", value) - - def getChoices(self): - return HANDLER_TYPES - -class FormatterProperty(Property): - def __init__(self, config, value=None): - self.config = config - Property.__init__(self, "formatter", "Formatter", value) - - def getChoices(self): - return self.config.getFormatterChoice() - -class HandlerProxy(PropertyHolder): - def __init__(self, config, dict): - self.config = config - PropertyHolder.__init__(self, dict) - prop = NameProperty(dict.get("name", "")) - self.dict["name"] = prop - prop = HandlerTypeProperty(dict.get("class", "StreamHandlerProxy")) - self.dict["class"] = prop - prop = FormatterProperty(self.config, dict.get("formatter", "")) - self.dict["formatter"] = prop - prop = LevelProperty(dict.get("level", "NOTSET")) - self.dict["level"] = prop - self.propnames = ["name", "class", "level", "formatter"] - - def isReadonly(self, name): - return (name == "name") - - def setPropValue(self, name, value): - PropertyHolder.setPropValue(self, name, value) - if (name == "class"): #morph type of handler - #print "try morph -> %s" % value - try: - klass = eval(value) - except Exception, e: - print e - klass = None - if klass: - n = self.getPropValue("name") - d = { - "name": n, - "class": value, - "formatter": self.getPropValue("formatter"), - "level": self.getPropValue("level"), - } - newhand = klass(self.config, d) - self.config.handlers[n] = newhand #FIXME encapsulation - if self.onPropListChanged: - self.onPropListChanged(newhand) - - def writeConfig(self, file): - file.write("[handler_%s]\n" % self.getPropValue("name")) - s = self.getProp("class").getValueText() - if not s in ["StreamHandler", "FileHandler"]: - s = "handlers." + s - file.write("class=%s\n" % s) - file.write("level=%s\n" % self.getPropValue("level")) - file.write("formatter=%s\n" % self.getPropValue("formatter")) - -class StreamProperty(Property): - def __init__(self, config, value=None): - self.config = config - Property.__init__(self, "stream", "Stream", value) - - def getChoices(self): - return OUTPUT_STREAMS - -class StreamHandlerProxy(HandlerProxy): - def __init__(self, config, dict): - HandlerProxy.__init__(self, config, dict) - prop = StreamProperty(self.config, dict.get("stream", "sys.stderr")) - self.dict["stream"] = prop - self.propnames.append("stream") - - def writeConfig(self, file): - HandlerProxy.writeConfig(self, file) - file.write("stream=%s\n" % self.getPropValue("stream")) - file.write("args=(%s,)\n\n" % self.getPropValue("stream")) - - def readConfig(self, sectname): - prop = StreamProperty(self.config, self.config.get(sectname, "stream")) - self.dict["stream"] = prop - self.propnames.append("stream") - -class FilenameProperty(Property): - def __init__(self, value=None): - Property.__init__(self, "filename", "File name", value) - -class ModeProperty(Property): - def __init__(self, value=None): - Property.__init__(self, "mode", "Mode", value) - - def getChoices(self): - return FILE_MODES - -class MaxSizeProperty(Property): - def __init__(self, value=None): - Property.__init__(self, "maxsize", "Maximum Size (bytes)", value) - -class BackupCountProperty(Property): - def __init__(self, value=None): - Property.__init__(self, "backcount", "Backup Count", value) - -class FileHandlerProxy(HandlerProxy): - def __init__(self, config, dict): - HandlerProxy.__init__(self, config, dict) - prop = FilenameProperty(dict.get("filename", "python.log")) - self.dict["filename"] = prop - prop = ModeProperty(dict.get("mode", "a")) - self.dict["mode"] = prop - self.propnames.extend(["filename", "mode"]) - - def writeConfig(self, file): - HandlerProxy.writeConfig(self, file) - fn = self.getPropValue("filename") - file.write("filename=%s\n" % fn) - mode = self.getPropValue("mode") - file.write("mode=%s\n" % mode) - file.write("args=('%s', '%s')\n\n" % (fn, mode)) - - def readConfig(self, sectname): - prop = FilenameProperty(self.config.get(sectname, "filename")) - self.dict["filename"] = prop - prop = ModeProperty(self.config.get(sectname, "mode")) - self.dict["mode"] = prop - self.propnames.extend(["filename", "mode"]) - -class RotatingFileHandlerProxy(FileHandlerProxy): - def __init__(self, config, dict): - FileHandlerProxy.__init__(self, config, dict) - prop = MaxSizeProperty(dict.get("maxsize", "0")) - self.dict["maxsize"] = prop - prop = BackupCountProperty(dict.get("backcount", "1")) - self.dict["backcount"] = prop - self.propnames.extend(["maxsize", "backcount"]) - - def writeConfig(self, file): - HandlerProxy.writeConfig(self, file) - fn = self.getPropValue("filename") - file.write("filename=%s\n" % fn) - mode = self.getPropValue("mode") - file.write("mode=%s\n" % mode) - ms = self.getPropValue("maxsize") - file.write("maxsize=%s\n" % ms) - bc = self.getPropValue("backcount") - file.write("backcount=%s\n" % bc) - file.write("args=('%s', '%s', %s, %s)\n\n" % (fn, mode, ms, bc)) - - def readConfig(self, sectname): - FileHandlerProxy.readConfig(self, sectname) - prop = MaxSizeProperty(self.config.get(sectname, "maxsize")) - self.dict["maxsize"] = prop - prop = BackupCountProperty(self.config.get(sectname, "backcount")) - self.dict["backcount"] = prop - self.propnames.extend(["maxsize", "backcount"]) - - -class HostProperty(Property): - def __init__(self, value=None): - Property.__init__(self, "host", "Host", value) - -class PortProperty(Property): - def __init__(self, value=None): - Property.__init__(self, "port", "Port", value) - -class SocketHandlerProxy(HandlerProxy): - def __init__(self, config, dict): - HandlerProxy.__init__(self, config, dict) - prop = HostProperty(dict.get("host", "localhost")) - self.dict["host"] = prop - prop = PortProperty(dict.get("port", "handlers.DEFAULT_TCP_LOGGING_PORT")) - self.dict["port"] = prop - self.propnames.extend(["host", "port"]) - - def writeConfig(self, file): - HandlerProxy.writeConfig(self, file) - host = self.getPropValue("host") - file.write("host=%s\n" % host) - port = self.getPropValue("port") - file.write("port=%s\n" % port) - file.write("args=('%s', %s)\n\n" % (host, port)) - - def readConfig(self, sectname): - prop = HostProperty(self.config.get(sectname, "host")) - self.dict["host"] = prop - prop = PortProperty(self.config.get(sectname, "port")) - self.dict["port"] = prop - self.propnames.extend(["host", "port"]) - -class DatagramHandlerProxy(HandlerProxy): - def __init__(self, config, dict): - HandlerProxy.__init__(self, config, dict) - prop = HostProperty(dict.get("host", "localhost")) - self.dict["host"] = prop - prop = PortProperty(dict.get("port", "handlers.DEFAULT_UDP_LOGGING_PORT")) - self.dict["port"] = prop - self.propnames.extend(["host", "port"]) - - def writeConfig(self, file): - HandlerProxy.writeConfig(self, file) - host = self.getPropValue("host") - file.write("host=%s\n" % host) - port = self.getPropValue("port") - file.write("port=%s\n" % port) - file.write("args=('%s', %s)\n\n" % (host, port)) - - def readConfig(self, sectname): - prop = HostProperty(self.config.get(sectname, "host")) - self.dict["host"] = prop - prop = PortProperty(self.config.get(sectname, "port")) - self.dict["port"] = prop - self.propnames.extend(["host", "port"]) - -class URLProperty(Property): - def __init__(self, value=None): - Property.__init__(self, "url", "URL", value) - -class MethodProperty(Property): - def __init__(self, value=None): - Property.__init__(self, "method", "HTTP Method", value) - - def getChoices(self): - return HTTP_METHODS - -class HTTPHandlerProxy(HandlerProxy): - def __init__(self, config, dict): - HandlerProxy.__init__(self, config, dict) - prop = HostProperty(dict.get("host", "localhost")) - self.dict["host"] = prop - prop = PortProperty(dict.get("port", "80")) - self.dict["port"] = prop - prop = URLProperty(dict.get("url", "")) - self.dict["url"] = prop - prop = MethodProperty(dict.get("method", "GET")) - self.dict["method"] = prop - self.propnames.extend(["host", "port", "url", "method"]) - - def writeConfig(self, file): - HandlerProxy.writeConfig(self, file) - host = self.getPropValue("host") - file.write("host=%s\n" % host) - port = self.getPropValue("port") - file.write("port=%s\n" % port) - url = self.getPropValue("url") - file.write("url=%s\n" % url) - meth = self.getPropValue("method") - file.write("method=%s\n" % meth) - file.write("args=('%s:%s', '%s', '%s')\n\n" % (host, port, url, meth)) - - def readConfig(self, sectname): - prop = HostProperty(self.config.get(sectname, "host")) - self.dict["host"] = prop - prop = PortProperty(self.config.get(sectname, "port")) - self.dict["port"] = prop - prop = URLProperty(self.config.get(sectname, "url")) - self.dict["url"] = prop - prop = MethodProperty(self.config.get(sectname, "method")) - self.dict["method"] = prop - self.propnames.extend(["host", "port", "url", "method"]) - -class SOAPHandlerProxy(HandlerProxy): - def __init__(self, config, dict): - HandlerProxy.__init__(self, config, dict) - prop = HostProperty(dict.get("host", "localhost")) - self.dict["host"] = prop - prop = PortProperty(dict.get("port", "80")) - self.dict["port"] = prop - prop = URLProperty(dict.get("url", "")) - self.dict["url"] = prop - self.propnames.extend(["host", "port", "url"]) - - def writeConfig(self, file): - HandlerProxy.writeConfig(self, file) - host = self.getPropValue("host") - file.write("host=%s\n" % host) - port = self.getPropValue("port") - file.write("port=%s\n" % port) - url = self.getPropValue("url") - file.write("url=%s\n" % url) - file.write("args=('%s:%s', '%s')\n\n" % (host, port, url)) - - def readConfig(self, sectname): - prop = HostProperty(self.config.get(sectname, "host")) - self.dict["host"] = prop - prop = PortProperty(self.config.get(sectname, "port")) - self.dict["port"] = prop - prop = URLProperty(self.config.get(sectname, "url")) - self.dict["url"] = prop - self.propnames.extend(["host", "port", "url"]) - -class FacilityProperty(Property): - def __init__(self, value=None): - Property.__init__(self, "facility", "Facility", value) - - def getChoices(self): - return SYSLOG_FACILITIES - -class SysLogHandlerProxy(HandlerProxy): - def __init__(self, config, dict): - HandlerProxy.__init__(self, config, dict) - prop = HostProperty(dict.get("host", "localhost")) - self.dict["host"] = prop - prop = PortProperty(dict.get("port", "handlers.SYSLOG_UDP_PORT")) - self.dict["port"] = prop - prop = FacilityProperty(dict.get("facility", "handlers.SysLogHandler.LOG_USER")) - self.dict["facility"] = prop - self.propnames.extend(["host", "port", "facility"]) - - def writeConfig(self, file): - HandlerProxy.writeConfig(self, file) - host = self.getPropValue("host") - file.write("host=%s\n" % host) - port = self.getPropValue("port") - file.write("port=%s\n" % port) - fac = self.getPropValue("facility") - file.write("facility=%s\n" % fac) - file.write("args=(('%s', %s), handlers.SysLogHandler.%s)\n\n" % (host, port, fac)) - - def readConfig(self, sectname): - prop = HostProperty(self.config.get(sectname, "host")) - self.dict["host"] = prop - prop = PortProperty(self.config.get(sectname, "port")) - self.dict["port"] = prop - prop = FacilityProperty(self.config.get(sectname, "facility")) - self.dict["facility"] = prop - self.propnames.extend(["host", "port", "facility"]) - -class FromProperty(Property): - def __init__(self, value=None): - Property.__init__(self, "from", "From", value) - -class ToProperty(Property): - def __init__(self, value=None): - Property.__init__(self, "to", "To", value) - -class SubjectProperty(Property): - def __init__(self, value=None): - Property.__init__(self, "subject", "Subject", value) - -class SMTPHandlerProxy(HandlerProxy): - def __init__(self, config, dict): - HandlerProxy.__init__(self, config, dict) - prop = HostProperty(dict.get("host", "localhost")) - self.dict["host"] = prop - prop = PortProperty(dict.get("port", "25")) - self.dict["port"] = prop - prop = FromProperty(dict.get("from", "")) - self.dict["from"] = prop - prop = ToProperty(dict.get("to", "")) - self.dict["to"] = prop - prop = SubjectProperty(dict.get("subject", "")) - self.dict["subject"] = prop - self.propnames.extend(["host", "port", "from", "to", "subject"]) - - def writeConfig(self, file): - HandlerProxy.writeConfig(self, file) - host = self.getPropValue("host") - file.write("host=%s\n" % host) - port = self.getPropValue("port") - file.write("port=%s\n" % port) - frm = self.getPropValue("from") - file.write("from=%s\n" % frm) - to = self.getPropValue("to") - file.write("to=%s\n" % to) - subj = self.getPropValue("subject") - file.write("subject=%s\n" % subj) - to = string.split(to, ",") - file.write("args=('%s', '%s', %s, '%s')\n\n" % (host, frm, repr(to), subj)) - - def readConfig(self, sectname): - prop = HostProperty(self.config.get(sectname, "host")) - self.dict["host"] = prop - prop = PortProperty(self.config.get(sectname, "port")) - self.dict["port"] = prop - prop = FromProperty(self.config.get(sectname, "from")) - self.dict["from"] = prop - prop = ToProperty(self.config.get(sectname, "to")) - self.dict["to"] = prop - prop = SubjectProperty(self.config.get(sectname, "subject")) - self.dict["subject"] = prop - self.propnames.extend(["host", "port", "from", "to", "subject"]) - -class CapacityProperty(Property): - def __init__(self, value=None): - Property.__init__(self, "capacity", "Capacity", value) - -class FlushLevelProperty(LevelProperty): - def __init__(self, value=None): - Property.__init__(self, "flushlevel", "Flush Level", value) - -class TargetProperty(Property): - def __init__(self, config, value=None): - self.config = config - Property.__init__(self, "target", "Target", value) - - def getChoices(self): - handlers = self.config.getHandlerChoice() - nm = self.dict["name"].getValueText() - #can't be own target... - return filter(lambda x,nm=nm: x[0] != nm, handlers) - -class MemoryHandlerProxy(HandlerProxy): - def __init__(self, config, dict): - HandlerProxy.__init__(self, config, dict) - prop = CapacityProperty(dict.get("capacity", "10")) - self.dict["capacity"] = prop - prop = FlushLevelProperty(dict.get("flushlevel", "ERROR")) - self.dict["flushlevel"] = prop - prop = TargetProperty(config, dict.get("target", "")) - prop.dict = self.dict - self.dict["target"] = prop - self.propnames.extend(["capacity", "flushlevel", "target"]) - - def writeConfig(self, file): - HandlerProxy.writeConfig(self, file) - cap = self.getPropValue("capacity") - file.write("capacity=%s\n" % cap) - flvl = self.getPropValue("flushlevel") - file.write("flushlevel=%s\n" % flvl) - file.write("target=%s\n" % self.getPropValue("target")) - file.write("args=(%s, %s)\n\n" % (cap, flvl)) - - def readConfig(self, sectname): - prop = CapacityProperty(self.config.get(sectname, "capacity")) - self.dict["capacity"] = prop - prop = FlushLevelProperty(self.config.get(sectname, "flushlevel")) - self.dict["flushlevel"] = prop - prop = TargetProperty(self.config, self.config.get(sectname, "target")) - prop.dict = self.dict - self.dict["target"] = prop - self.propnames.extend(["capacity", "flushlevel", "target"]) - -class AppNameProperty(Property): - def __init__(self, value=None): - Property.__init__(self, "appname", "Application Name", value) - -class DLLNameProperty(Property): - def __init__(self, value=None): - Property.__init__(self, "dllname", "Message DLL name", value) - -class LogTypeProperty(Property): - def __init__(self, value=None): - Property.__init__(self, "logtype", "Log Type", value) - - def getChoices(self): - return LOG_TYPES - -class NTEventLogHandlerProxy(HandlerProxy): - def __init__(self, config, dict): - HandlerProxy.__init__(self, config, dict) - prop = AppNameProperty(dict.get("appname", "Python Application")) - self.dict["appname"] = prop - prop = DLLNameProperty(dict.get("dllname", "")) - self.dict["dllname"] = prop - prop = LogTypeProperty(dict.get("logtype", "Application")) - self.dict["logtype"] = prop - self.propnames.extend(["appname", "dllname", "logtype"]) - - def writeConfig(self, file): - HandlerProxy.writeConfig(self, file) - app = self.getPropValue("appname") - file.write("appname=%s\n" % app) - dll = self.getPropValue("dllname") - file.write("dllname=%s\n" % dll) - ltype = self.getPropValue("logtype") - file.write("logtype=%s\n" % ltype) - file.write("args=('%s', '%s', '%s')\n\n" % (app, dll, ltype)) - - def readConfig(self, sectname): - prop = AppNameProperty(self.config.get(sectname, "appname")) - self.dict["appname"] = prop - prop = DLLNameProperty(self.config.get(sectname, "dllname")) - self.dict["dllname"] = prop - prop = LogTypeProperty(self.config.get(sectname, "logtype")) - self.dict["logtype"] = prop - self.propnames.extend(["appname", "dllname", "logtype"]) - -# -- logger properties and proxies - -class ChannelProperty(Property): - def __init__(self, value=None): - Property.__init__(self, "channel", "Name", value) - -class HandlerProperty(Property): - def __init__(self, config, value=None): - self.config = config - Property.__init__(self, "handler", "Handlers", value) - - def getChoices(self): - return self.config.getHandlerChoice() - -class FilterProperty(Property): - def __init__(self, config, value=None): - self.config = config - Property.__init__(self, "filter", "Filters", value) - - def getChoices(self): - return self.config.getFilterChoice() - -class ParentProperty(Property): - def __init__(self, config, value=None): - self.config = config - Property.__init__(self, "parent", "Parent", value) - - def getChoices(self): - loggers = self.config.getLoggerChoice() - nm = self.dict["name"].getValueText() - #can't be own parent... - return filter(lambda x,nm=nm: x[0] != nm, loggers) - - def getValueText(self): - if self.dict.has_key("root"): - return "" - pn = Property.getValueText(self) - rv = "" - while pn != "(root)": - parent = self.config.getLogger(pn) - rv = parent.getPropValue("channel") + "." + rv - pn = parent.getProp("parent").value - return rv[:-1] - -class PropagateProperty(Property): - def __init__(self, config, value=None): - self.config = config - Property.__init__(self, "propagate", "Propagate", value) - - def getChoices(self): - return BOOLEAN_VALUES - -class LoggerProxy(PropertyHolder): - def __init__(self, config, dict): - self.config = config - PropertyHolder.__init__(self, dict) - prop = ChannelProperty(dict.get("channel", "")) - self.dict["channel"] = prop - prop = NameProperty(dict.get("name", "")) - self.dict["name"] = prop - prop = HandlerProperty(config, dict.get("handler", [])) - self.dict["handler"] = prop - prop = LevelProperty(dict.get("level", "NOTSET")) - self.dict["level"] = prop - prop = PropagateProperty(self.config, dict.get("propagate", "1")) - self.dict["propagate"] = prop - prop = ParentProperty(config, dict.get("parent", "(root)")) - prop.dict = self.dict - self.dict["parent"] = prop - self.propnames = ["parent", "channel", "level", "propagate", "handler"] - self.onChannelChanged = None - self.deleted = 0 - - def isReadonly(self, name): - return (name in ["channel", "parent", "propagate"]) and self.dict.has_key("root") - - def getQualifiedName(self): - pt = self.getProp("parent").getValueText() - nm = self.getPropValue("channel") - if pt: - pn = pt + "." + nm - else: - pn = nm - if pn == "": - pn = "(root)" - return pn - - def setPropValue(self, name, value): - PropertyHolder.setPropValue(self, name, value) - if (name == "channel"): - nm = self.getPropValue("name") - if self.onChannelChanged: - self.onChannelChanged(nm, value) - - def writeConfig(self, file): - if self.dict.has_key("root"): - name = "root" - else: - name = self.getPropValue("name") - file.write("[logger_%s]\n" % name) - file.write("level=%s\n" % self.getPropValue("level")) - file.write("propagate=%s\n" % self.getPropValue("propagate")) - file.write("channel=%s\n" % self.getPropValue("channel")) - file.write("parent=%s\n" % self.getPropValue("parent")) - file.write("qualname=%s\n" % self.getQualifiedName()) - file.write("handlers=%s\n\n" % string.join(self.getPropValue("handler"), ",")) - -# -- logging configuration - -class LoggingConfig(ConfigParser.ConfigParser): - def __init__(self, defaults=None): - ConfigParser.ConfigParser.__init__(self, defaults) - self.formatters = {} - self.handlers = {} - self.loggers = {} -# self.filters = {} - #create root logger - d = { "name": "(root)", "root": 1, "parent": "" } - self.loggers["(root)"] = LoggerProxy(self, d) - - def read(self, fn): - ConfigParser.ConfigParser.read(self, fn) - llist = self.get("loggers", "keys") - llist = string.split(llist, ",") - llist.remove("root") - sectname = "logger_root" - log = self.loggers["(root)"] - log.setPropValue("level", self.get(sectname, "level")) - hlist = self.get(sectname, "handlers") - hlist = string.split(hlist, ",") - log.setPropValue("handler", hlist) - for log in llist: - sectname = "logger_%s" % log - hlist = self.get(sectname, "handlers") - hlist = string.split(hlist, ",") - d = { - "name" : log, - "level" : self.get(sectname, "level"), - "channel" : self.get(sectname, "channel"), - "parent" : self.get(sectname, "parent"), - "propagate" : self.get(sectname, "propagate"), - "handler" : hlist, - } - self.loggers[log] = LoggerProxy(self, d) - hlist = self.get("handlers", "keys") - if len(hlist): - hlist = string.split(hlist, ",") - for hand in hlist: - sectname = "handler_%s" % hand - klass = self.get(sectname, "class") - if klass[:9] == "handlers.": - klass = klass[9:] - d = { - "name" : hand, - "class" : "%sProxy" % klass, - "level" : self.get(sectname, "level"), - "formatter" : self.get(sectname, "formatter"), - } - hobj = HandlerProxy(self, d) - hobj.__class__ = eval("%sProxy" % klass) - hobj.readConfig(sectname) - self.handlers[hand] = hobj - - flist = self.get("formatters", "keys") - if len(flist): - flist = string.split(flist, ",") - for form in flist: - sectname = "formatter_%s" % form - d = { - "name" : form, - "format" : self.get(sectname, "format", 1), - "datefmt" : self.get(sectname, "datefmt", 1), - } - self.formatters[form] = FormatterProxy(self, d) - -# flist = self.get("filters", "keys") -# if len(flist): -# flist = string.split(flist, ",") -# for filt in flist: -# sectname = "filter_%s" % filt -# d = { -# "name" : filt, -# "lname" : self.get(sectname, "lname", 1), -# } -# self.filters[filt] = FilterProxy(self, d) - - def getFormatter(self, name): - if name: - fmt = self.formatters[name] - else: - n = len(self.formatters.keys()) + 1 - name = "form%02d" % n - fmt = FormatterProxy(self, {"name": name}) - self.formatters[name] = fmt - return fmt - - def getHandler(self, name): - if name: - hand = self.handlers[name] - else: - n = len(self.handlers.keys()) + 1 - name = "hand%02d" % n - hand = StreamHandlerProxy(self, {"name": name}) - self.handlers[name] = hand - return hand - - def getLogger(self, name): - if name: - log = self.loggers[name] - else: - n = len(self.loggers.keys()) + 1 - name = "log%02d" % n - log = LoggerProxy(self, {"name": name, "channel": name}) - self.loggers[name] = log - return log - - def getFormatterChoice(self): - values = [] - keys = self.formatters.keys() - keys.sort() - for f in keys: - values.append((f, f)) - return tuple(values) - - def getHandlerChoice(self): - values = [] - keys = self.handlers.keys() - keys.sort() - for f in keys: - values.append((f, f)) - return tuple(values) - - def getFilterChoice(self): - values = [] - keys = self.filters.keys() - keys.sort() - for f in keys: - values.append((f, f)) - return tuple(values) - - def getLoggerChoice(self): - values = [] - keys = self.loggers.keys() - keys.sort() - for f in keys: - values.append((f, f)) - return tuple(values) - - def getLoggers(self): - return self.loggers.values() - - def getHandlers(self): - return self.handlers.values() - - def getFormatters(self): - return self.formatters.values() - - def formatterIsUsed(self, name): - rv = None - for h in self.handlers.keys(): - if self.handlers[h].getPropValue("formatter") == name: - rv = h - break - return rv - - def handlerIsUsed(self, name): - rv = None - for log in self.loggers.keys(): - if name in self.loggers[log].getPropValue("handler"): - rv = log - break - return rv - - def removeFormatter(self, name): - del self.formatters[name] - - def removeHandler(self, name): - del self.handlers[name] - - def removeLogger(self, name): - del self.loggers[name] - - def save(self, fn): - #needed because 1.5.2 ConfigParser should be supported - file = open(fn, "w") - #Write out the keys - loggers = self.loggers.keys() - loggers.remove("(root)") - loggers = filter(lambda x, d=self.loggers: not d[x].deleted, loggers) - loggers.sort() - list = ["root"] - list.extend(loggers) - file.write("[loggers]\nkeys=%s\n\n" % string.join(list, ",")) - handlers = self.handlers.keys() - handlers.sort() - file.write("[handlers]\nkeys=%s\n\n" % string.join(handlers, ",")) - formatters = self.formatters.keys() - formatters.sort() - file.write("[formatters]\nkeys=%s\n\n" % string.join(formatters, ",")) - #write out the root logger properties - log = self.loggers["(root)"] - log.writeConfig(file) - #write out other logger properties - for log in loggers: - log = self.loggers[log] - log.writeConfig(file) - #write out handler properties - for hand in handlers: - hand = self.handlers[hand] - hand.writeConfig(file) - #write out formatter properties - for form in formatters: - form = self.formatters[form] - form.writeConfig(file) - file.close() - -root = None - -def onClose(): - if _popup: - _popup.withdraw() - root.destroy() - -def main(): - global root - root=Tk() - cfg = Configurator(root) - cfg.pack(side=LEFT, fill=BOTH, expand=1) - root.protocol("WM_DELETE_WINDOW", onClose) - root.mainloop() - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/tools/python/logging/logging-0.4.9.2/test/logging.dtd b/tools/python/logging/logging-0.4.9.2/test/logging.dtd deleted file mode 100644 index b2275ab46c..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/logging.dtd +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/tools/python/logging/logging-0.4.9.2/test/logging.xml b/tools/python/logging/logging-0.4.9.2/test/logging.xml deleted file mode 100644 index 6dabaffd51..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/logging.xml +++ /dev/null @@ -1,5 +0,0 @@ - -]> - -&data; - \ No newline at end of file diff --git a/tools/python/logging/logging-0.4.9.2/test/logrecv.ini b/tools/python/logging/logging-0.4.9.2/test/logrecv.ini deleted file mode 100644 index eede0d3e58..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/logrecv.ini +++ /dev/null @@ -1,36 +0,0 @@ -[loggers] -keys=root - -[handlers] -keys=hand01,hand02 - -[formatters] -keys=form01 - -[logger_root] -level=NOTSET -propagate=1 -channel= -parent= -qualname=(root) -handlers=hand01,hand02 - -[handler_hand01] -class=FileHandler -level=NOTSET -formatter=form01 -filename=logrecv.log -mode=w -args=('logrecv.log', 'w') - -[handler_hand02] -class=StreamHandler -level=NOTSET -formatter=form01 -stream=sys.stderr -args=(sys.stderr,) - -[formatter_form01] -format=%(asctime)s %(levelname)-9s %(name)-8s %(thread)5s %(message)s -datefmt= - diff --git a/tools/python/logging/logging-0.4.9.2/test/logrecv.py b/tools/python/logging/logging-0.4.9.2/test/logrecv.py deleted file mode 100755 index 4c8007e433..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/logrecv.py +++ /dev/null @@ -1,443 +0,0 @@ -#! /usr/bin/env python -# -# Copyright 2001-2002 by Vinay Sajip. All Rights Reserved. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose and without fee is hereby granted, -# provided that the above copyright notice appear in all copies and that -# both that copyright notice and this permission notice appear in -# supporting documentation, and that the name of Vinay Sajip -# not be used in advertising or publicity pertaining to distribution -# of the software without specific, written prior permission. -# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -""" -Simple socket-based logging event receiver for use with "logging.py" logging -module. - -Should work under Python versions >= 1.5.2, except that source line information -is not available unless 'inspect' is. - -Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved. -""" - -from select import select -import sys, string, struct, types, cPickle, socket -import logging, logging.handlers, logging.config - -TIMEOUT = 10 -if sys.platform == "win32": - RESET_ERROR = 10054 -else: - RESET_ERROR = 0 #FIXME get correct value for Unix... - -logging.raiseExceptions = 1 - -# -# TCP receiver -# - -from SocketServer import ThreadingTCPServer, StreamRequestHandler - -class LogRecordStreamHandler(StreamRequestHandler): - """ - Handler for a streaming logging request. It basically logs the record - using whatever logging policy is configured locally. - """ - - def handle(self): - """ - Handle multiple requests - each expected to be a 4-byte length, - followed by the LogRecord in pickle format. Logs the record - according to whatever policy is configured locally. - """ - while 1: - try: - chunk = self.connection.recv(4) - if len(chunk) < 4: - break - slen = struct.unpack(">L", chunk)[0] - chunk = self.connection.recv(slen) - while len(chunk) < slen: - chunk = chunk + self.connection.recv(slen - len(chunk)) - obj = self.unPickle(chunk) - record = logging.makeLogRecord(obj) - self.handleLogRecord(record) - except socket.error, e: - if type(e.args) != types.TupleType: - raise - else: - errcode = e.args[0] - if errcode != RESET_ERROR: - raise - break - - def unPickle(self, data): - return cPickle.loads(data) - - def handleLogRecord(self, record): - #if a name is specified, we use the named logger rather than the one - #implied by the record. This is so test harnesses don't get into - #endless loops (particularly log_test.py, which has this code and the - #client code in the same Python instance) - if self.server.logname is not None: - name = self.server.logname - else: - name = record.name - logger = logging.getLogger(name) - logger.handle(record) - -class LogRecordSocketReceiver(ThreadingTCPServer): - """ - A simple-minded TCP socket-based logging receiver suitable for test - purposes. - """ - - allow_reuse_address = 1 - - def __init__(self, host='localhost', port=logging.handlers.DEFAULT_TCP_LOGGING_PORT, - handler=LogRecordStreamHandler): - ThreadingTCPServer.__init__(self, (host, port), handler) - self.abort = 0 - self.timeout = 1 - self.logname = None - - def serve_until_stopped(self): - import select - abort = 0 - while not abort: - rd, wr, ex = select.select([self.socket.fileno()], - [], [], - self.timeout) - if rd: - self.handle_request() - abort = self.abort - -# -# UDP receiver -# - -from SocketServer import ThreadingUDPServer, DatagramRequestHandler - -class LogRecordDatagramHandler(DatagramRequestHandler): - """ - Handler for a datagram logging request. It basically logs the record using - whatever logging policy is configured locally. - """ - def handle(self): - chunk = self.packet - slen = struct.unpack(">L", chunk[:4])[0] - chunk = chunk[4:] - assert len(chunk) == slen - obj = self.unPickle(chunk) - record = logging.LogRecord(None, None, "", 0, "", (), None) - record.__dict__.update(obj) - self.handleLogRecord(record) - - def unPickle(self, data): - return cPickle.loads(data) - - def handleLogRecord(self, record): - #if a name is specified, we use the named logger rather than the one - #implied by the record. This is so test harnesses don't get into - #endless loops (particularly log_test.py, which has this code and the - #client code in the same Python instance) - if self.server.logname is not None: - name = self.server.logname - else: - name = record.name - logger = logging.getLogger(name) - logger.handle(record) - - def finish(self): - pass - -class LogRecordDatagramReceiver(ThreadingUDPServer): - """ - A simple-minded UDP datagram-based logging receiver suitable for test - purposes. - """ - - allow_reuse_address = 1 - - def __init__(self, host='localhost', port=logging.handlers.DEFAULT_UDP_LOGGING_PORT, - handler=LogRecordDatagramHandler): - ThreadingUDPServer.__init__(self, (host, port), handler) - self.abort = 0 - self.timeout = 1 - self.logname = None - - def serve_until_stopped(self): - import select - abort = 0 - while not abort: - rd, wr, ex = select.select([self.socket.fileno()], - [], [], - self.timeout) - if rd: - self.handle_request() - abort = self.abort - -# -# HTTP receiver -# - -from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler - -import cgi - -class LogRecordHTTPHandler(BaseHTTPRequestHandler): - def makeDict(self, fs): - dict = {} - for mfs in fs.list: - dict[mfs.name] = mfs.value - for key in ["args", "exc_info", "exc_text", "lineno", "msecs", "created", - "thread", "levelno", "relativeCreated"]: - if dict.has_key(key): - dict[key] = eval(dict[key]) - return dict - - def do_GET(self): - """Serve a GET request.""" - sts = "OK" - env = { 'REQUEST_METHOD' : 'GET'} - try: - i = string.find(self.path, '?') - if i >= 0: - env['QUERY_STRING'] = self.path[i + 1:] - fs = cgi.FieldStorage(environ=env) - dict = self.makeDict(fs) - record = logging.LogRecord(None, None, "", 0, "", (), None) - record.__dict__.update(dict) - self.handleLogRecord(record) - except Exception, e: - sts = "ERROR" - raise - self.send_head() - self.wfile.write("GET %s" % sts) - - def handleLogRecord(self, record): - #if a name is specified, we use the named logger rather than the one - #implied by the record. This is so test harnesses don't get into - #endless loops (particularly log_test.py, which has this code and the - #client code in the same Python instance) - if self.server.logname is not None: - name = self.server.logname - else: - name = record.name - logger = logging.getLogger(name) - logger.handle(record) - - def do_HEAD(self): - """Serve a HEAD request.""" - self.send_head() - - def do_POST(self): - """Serve a POST request.""" - sts = "OK" - env = { 'REQUEST_METHOD' : 'POST'} - try: - length = self.headers.getheader('content-length') - if length: - env['CONTENT_LENGTH'] = length - #print self.headers - i = string.find(self.path, '?') - if i >= 0: - env['QUERY_STRING'] = self.path[i + 1:] - fs = cgi.FieldStorage(fp=self.rfile, environ=env) - dict = self.makeDict(fs) - record = logging.LogRecord(None, None, "", 0, "", (), None) - record.__dict__.update(dict) - self.handleLogRecord(record) - except Exception, e: - print e - sys.stdout.flush() - sts = "ERROR" - raise - self.send_head() - self.wfile.write("POST %s" % sts) - - def send_head(self): - """Common code for GET and HEAD commands. - - This sends the response code and MIME headers. - - Return value is either a file object (which has to be copied - to the outputfile by the caller unless the command was HEAD, - and must be closed by the caller under all circumstances), or - None, in which case the caller has nothing further to do. - - """ - self.send_response(200) - self.send_header("Content-type", "text/plain") - self.end_headers() - - def log_message(self, *args): - #comment out the following line if you don't want to show requests - #apply(BaseHTTPRequestHandler.log_message, (self,) + args) - pass - -class LogRecordHTTPReceiver(HTTPServer): - def __init__(self, host='localhost', port=logging.handlers.DEFAULT_HTTP_LOGGING_PORT, - handler=LogRecordHTTPHandler): - HTTPServer.__init__(self, (host, port), handler) - self.abort = 0 - self.timeout = 1 - self.logname = None - - def serve_until_stopped(self): - import select - abort = 0 - while not abort: - rd, wr, ex = select.select([self.socket.fileno()], - [], [], - self.timeout) - if rd: - self.handle_request() - abort = self.abort - - -# -# SOAP receiver -# - -try: - from ZSI import dispatch - - logname = None - - def log(args, created, exc_info, exc_text, filename, levelname, levelno, lineno, module, msecs, msg, name, pathname, process, relativeCreated, thread): - record = logging.LogRecord(None, None, "", 0, "", (), None) - record.args = eval(args) - record.exc_info = eval(exc_info) - record.exc_text = eval(exc_text) - record.created = created - record.filename = filename - record.module = module - record.levelname = levelname - record.lineno = lineno - record.levelno = levelno - record.msecs = msecs - record.msg = msg - record.name = name - record.pathname = pathname - record.process = process - record.relativeCreated = relativeCreated - record.thread = thread - #if a name is specified, we use the named logger rather than the one - #implied by the record. This is so test harnesses don't get into - #endless loops (particularly log_test.py, which has this code and the - #client code in the same Python instance) - if logname is not None: - lname = logname - else: - lname = name - logger = logging.getLogger(lname) - logger.handle(record) - - class MySOAPRequestHandler(dispatch.SOAPRequestHandler): - def log_message(self, *args): - #comment out the following line if you don't want to show requests - #apply(BaseHTTPRequestHandler.log_message, (self,) + args) - pass - - class SOAPServer(HTTPServer): - def __init__(self, port=logging.handlers.DEFAULT_SOAP_LOGGING_PORT): - address = ('', port) - HTTPServer.__init__(self, address, MySOAPRequestHandler) - self.abort = 0 - self.timeout = 1 - self.logname = None - self.docstyle = 0 - self.nsdict = {} - self.typesmodule = None - self.rpc = 1 - self.modules = (sys.modules["__main__"],) - - def serve_until_stopped(self): - import select - abort = 0 - while not abort: - rd, wr, ex = select.select([self.socket.fileno()], - [], [], - self.timeout) - if rd: - global logname - logname = self.logname - self.handle_request() - abort = self.abort - -except ImportError: - "Import failed" - SOAPServer = None - -def runTCP(tcpserver=None): - if not tcpserver: - tcpserver = LogRecordSocketReceiver() - print "About to start TCP server..." - tcpserver.serve_until_stopped() - -def runUDP(udpserver=None): - if not udpserver: - udpserver = LogRecordDatagramReceiver() - print "About to start UDP server..." - udpserver.serve_until_stopped() - -def runHTTP(httpserver=None): - if not httpserver: - httpserver = LogRecordHTTPReceiver() - print "About to start HTTP server..." - httpserver.serve_until_stopped() - -def runSOAP(soapserver=None): - if not SOAPServer: - print "Sorry, ZSI is not available. Install PyXML-0.6.6 and ZSI first." - print "See README.txt and python_logging.html for more information." - else: - if not soapserver: - soapserver = SOAPServer() - print "About to start SOAP server..." - soapserver.serve_until_stopped() - -FORMAT_STR = "%(asctime)s %(name)-19s %(levelname)-5s - %(message)s" - -if __name__ == "__main__": - if (len(sys.argv) < 2) or not (string.lower(sys.argv[1]) in \ - ["udp", "tcp", "http", "soap"]): - print "usage: logrecv.py [UDP|TCP|HTTP|SOAP]" - else: - #logging.basicConfig() - logging.config.fileConfig("logrecv.ini") -# both = string.lower(sys.argv[1]) == "both" -# hdlr = logging.FileHandler("test.log") -# hdlr.setFormatter(logging.Formatter(FORMAT_STR)) -# logging.getLogger("").addHandler(hdlr) -# if both: -# import threading -# tcpthread = threading.Thread(target=runTCP) -# udpthread = threading.Thread(target=runUDP) -# tcpthread.start() -# udpthread.start() -# tcpthread.join() -# udpthread.join() -# else: -# tcp = string.lower(sys.argv[1]) == "tcp" -# if tcp: -# runTCP() -# else: -# runUDP() - arg = string.lower(sys.argv[1]) - if arg == "tcp": - runTCP() - elif arg == "udp": - runUDP() - elif arg == "http": - runHTTP() - elif arg == "soap": - runSOAP() diff --git a/tools/python/logging/logging-0.4.9.2/test/myapp.py b/tools/python/logging/logging-0.4.9.2/test/myapp.py deleted file mode 100644 index d1da1c2528..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/myapp.py +++ /dev/null @@ -1,13 +0,0 @@ -import logging, mymodule - -logging.basicConfig() - -log = logging.getLogger("MyApp") -log.setLevel(logging.DEBUG) #set verbosity to show all messages of severity >= DEBUG -log.info("Starting my app") -try: - mymodule.doIt() -except Exception, e: - log.exception("There was a problem.") -log.info("Ending my app") - diff --git a/tools/python/logging/logging-0.4.9.2/test/mymodule.py b/tools/python/logging/logging-0.4.9.2/test/mymodule.py deleted file mode 100644 index ac824df0e6..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/mymodule.py +++ /dev/null @@ -1,8 +0,0 @@ -import logging -log = logging.getLogger("MyModule") - -def doIt(): - log.debug("Doin' stuff...") - #do stuff... - raise TypeError, "Bogus type error for testing" - diff --git a/tools/python/logging/logging-0.4.9.2/test/stderr.exp b/tools/python/logging/logging-0.4.9.2/test/stderr.exp deleted file mode 100644 index 7426e862a2..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/stderr.exp +++ /dev/null @@ -1,566 +0,0 @@ --- log_test0 begin -------------------------------------------------------- -CRITICAL:ERR:Message 0 -ERROR:ERR:Message 1 -CRITICAL:INF:Message 2 -ERROR:INF:Message 3 -WARNING:INF:Message 4 -INFO:INF:Message 5 -CRITICAL:INF.UNDEF:Message 6 -ERROR:INF.UNDEF:Message 7 -WARNING:INF.UNDEF:Message 8 -INFO:INF.UNDEF:Message 9 -CRITICAL:INF.ERR:Message 10 -ERROR:INF.ERR:Message 11 -CRITICAL:INF.ERR.UNDEF:Message 12 -ERROR:INF.ERR.UNDEF:Message 13 -CRITICAL:DEB:Message 14 -ERROR:DEB:Message 15 -WARNING:DEB:Message 16 -INFO:DEB:Message 17 -DEBUG:DEB:Message 18 -CRITICAL:UNDEF:Message 19 -ERROR:UNDEF:Message 20 -WARNING:UNDEF:Message 21 -INFO:UNDEF:Message 22 -CRITICAL:INF.BADPARENT.UNDEF:Message 23 -CRITICAL:INF.BADPARENT:Message 24 -INFO:INF:Messages should bear numbers 0 through 24. --- log_test0 end -------------------------------------------------------- --- log_test2 begin -------------------------------------------------------- -CRITICAL:ERR:Message 0 -ERROR:ERR:Message 1 -CRITICAL:INF:Message 2 -ERROR:INF:Message 3 -WARNING:INF:Message 4 -INFO:INF:Message 5 -CRITICAL:INF.UNDEF:Message 6 -ERROR:INF.UNDEF:Message 7 -WARNING:INF.UNDEF:Message 8 -INFO:INF.UNDEF:Message 9 -CRITICAL:INF.ERR:Message 10 -ERROR:INF.ERR:Message 11 -CRITICAL:INF.ERR.UNDEF:Message 12 -ERROR:INF.ERR.UNDEF:Message 13 -CRITICAL:DEB:Message 14 -ERROR:DEB:Message 15 -WARNING:DEB:Message 16 -INFO:DEB:Message 17 -DEBUG:DEB:Message 18 -CRITICAL:UNDEF:Message 19 -ERROR:UNDEF:Message 20 -WARNING:UNDEF:Message 21 -INFO:UNDEF:Message 22 -CRITICAL:INF.BADPARENT.UNDEF:Message 23 -CRITICAL:INF.BADPARENT:Message 24 -INFO:INF:Messages should bear numbers 0 through 24. --- log_test2 end -------------------------------------------------------- -CRITICAL:ERR:Message 0 -ERROR:ERR:Message 1 -CRITICAL:INF:Message 2 -ERROR:INF:Message 3 -WARNING:INF:Message 4 -INFO:INF:Message 5 -CRITICAL:INF.UNDEF:Message 6 -ERROR:INF.UNDEF:Message 7 -WARNING:INF.UNDEF:Message 8 -INFO:INF.UNDEF:Message 9 -CRITICAL:INF.ERR:Message 10 -ERROR:INF.ERR:Message 11 -CRITICAL:INF.ERR.UNDEF:Message 12 -ERROR:INF.ERR.UNDEF:Message 13 -CRITICAL:DEB:Message 14 -ERROR:DEB:Message 15 -WARNING:DEB:Message 16 -INFO:DEB:Message 17 -DEBUG:DEB:Message 18 -CRITICAL:UNDEF:Message 19 -ERROR:UNDEF:Message 20 -WARNING:UNDEF:Message 21 -INFO:UNDEF:Message 22 -CRITICAL:INF.BADPARENT.UNDEF:Message 23 -CRITICAL:INF.BADPARENT:Message 24 -INFO:INF:Messages should bear numbers 0 through 24. --- log_test4 begin -------------------------------------------------------- --- setting logging level to 'Boring' ----- -Boring:root:This should only be seen at the 'Boring' logging level (or lower) -Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower) -Garrulous:root:This should only be seen at the 'Garrulous' logging level (or lower) -Talkative:root:This should only be seen at the 'Talkative' logging level (or lower) -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Chatterbox' ----- -Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower) -Garrulous:root:This should only be seen at the 'Garrulous' logging level (or lower) -Talkative:root:This should only be seen at the 'Talkative' logging level (or lower) -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Garrulous' ----- -Garrulous:root:This should only be seen at the 'Garrulous' logging level (or lower) -Talkative:root:This should only be seen at the 'Talkative' logging level (or lower) -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Talkative' ----- -Talkative:root:This should only be seen at the 'Talkative' logging level (or lower) -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Verbose' ----- -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Sociable' ----- -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Effusive' ----- -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Terse' ----- -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Taciturn' ----- -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Silent' ----- -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- Filtering at handler level to SOCIABLE -- --- setting logging level to 'Boring' ----- -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Chatterbox' ----- -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Garrulous' ----- -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Talkative' ----- -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Verbose' ----- -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Sociable' ----- -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Effusive' ----- -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Terse' ----- -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Taciturn' ----- -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Silent' ----- -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- Filtering using GARRULOUS filter -- --- setting logging level to 'Boring' ----- -Boring:root:This should only be seen at the 'Boring' logging level (or lower) -Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower) -Talkative:root:This should only be seen at the 'Talkative' logging level (or lower) -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Chatterbox' ----- -Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower) -Talkative:root:This should only be seen at the 'Talkative' logging level (or lower) -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Garrulous' ----- -Talkative:root:This should only be seen at the 'Talkative' logging level (or lower) -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Talkative' ----- -Talkative:root:This should only be seen at the 'Talkative' logging level (or lower) -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Verbose' ----- -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Sociable' ----- -Sociable:root:This should only be seen at the 'Sociable' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Effusive' ----- -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Terse' ----- -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Taciturn' ----- -Taciturn:root:This should only be seen at the 'Taciturn' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Silent' ----- -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- Filtering using specific filter for SOCIABLE, TACITURN -- --- setting logging level to 'Boring' ----- -Boring:root:This should only be seen at the 'Boring' logging level (or lower) -Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower) -Talkative:root:This should only be seen at the 'Talkative' logging level (or lower) -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Chatterbox' ----- -Chatterbox:root:This should only be seen at the 'Chatterbox' logging level (or lower) -Talkative:root:This should only be seen at the 'Talkative' logging level (or lower) -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Garrulous' ----- -Talkative:root:This should only be seen at the 'Talkative' logging level (or lower) -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Talkative' ----- -Talkative:root:This should only be seen at the 'Talkative' logging level (or lower) -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Verbose' ----- -Verbose:root:This should only be seen at the 'Verbose' logging level (or lower) -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Sociable' ----- -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Effusive' ----- -Effusive:root:This should only be seen at the 'Effusive' logging level (or lower) -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Terse' ----- -Terse:root:This should only be seen at the 'Terse' logging level (or lower) -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Taciturn' ----- -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- setting logging level to 'Silent' ----- -Silent:root:This should only be seen at the 'Silent' logging level (or lower) --- log_test4 end -------------------------------------------------------- --- log_test7 begin -------------------------------------------------------- --- logging at DEBUG, nothing should be seen yet -- --- logging at INFO, nothing should be seen yet -- --- logging at WARNING, 3 messages should be seen -- -Debug message -Info message -Warning message --- logging 0 at level INFO, messages should be seen every 10 events -- --- logging 1 at level INFO, messages should be seen every 10 events -- --- logging 2 at level INFO, messages should be seen every 10 events -- --- logging 3 at level INFO, messages should be seen every 10 events -- --- logging 4 at level INFO, messages should be seen every 10 events -- --- logging 5 at level INFO, messages should be seen every 10 events -- --- logging 6 at level INFO, messages should be seen every 10 events -- --- logging 7 at level INFO, messages should be seen every 10 events -- --- logging 8 at level INFO, messages should be seen every 10 events -- --- logging 9 at level INFO, messages should be seen every 10 events -- -Info index = 0 -Info index = 1 -Info index = 2 -Info index = 3 -Info index = 4 -Info index = 5 -Info index = 6 -Info index = 7 -Info index = 8 -Info index = 9 --- logging 10 at level INFO, messages should be seen every 10 events -- --- logging 11 at level INFO, messages should be seen every 10 events -- --- logging 12 at level INFO, messages should be seen every 10 events -- --- logging 13 at level INFO, messages should be seen every 10 events -- --- logging 14 at level INFO, messages should be seen every 10 events -- --- logging 15 at level INFO, messages should be seen every 10 events -- --- logging 16 at level INFO, messages should be seen every 10 events -- --- logging 17 at level INFO, messages should be seen every 10 events -- --- logging 18 at level INFO, messages should be seen every 10 events -- --- logging 19 at level INFO, messages should be seen every 10 events -- -Info index = 10 -Info index = 11 -Info index = 12 -Info index = 13 -Info index = 14 -Info index = 15 -Info index = 16 -Info index = 17 -Info index = 18 -Info index = 19 --- logging 20 at level INFO, messages should be seen every 10 events -- --- logging 21 at level INFO, messages should be seen every 10 events -- --- logging 22 at level INFO, messages should be seen every 10 events -- --- logging 23 at level INFO, messages should be seen every 10 events -- --- logging 24 at level INFO, messages should be seen every 10 events -- --- logging 25 at level INFO, messages should be seen every 10 events -- --- logging 26 at level INFO, messages should be seen every 10 events -- --- logging 27 at level INFO, messages should be seen every 10 events -- --- logging 28 at level INFO, messages should be seen every 10 events -- --- logging 29 at level INFO, messages should be seen every 10 events -- -Info index = 20 -Info index = 21 -Info index = 22 -Info index = 23 -Info index = 24 -Info index = 25 -Info index = 26 -Info index = 27 -Info index = 28 -Info index = 29 --- logging 30 at level INFO, messages should be seen every 10 events -- --- logging 31 at level INFO, messages should be seen every 10 events -- --- logging 32 at level INFO, messages should be seen every 10 events -- --- logging 33 at level INFO, messages should be seen every 10 events -- --- logging 34 at level INFO, messages should be seen every 10 events -- --- logging 35 at level INFO, messages should be seen every 10 events -- --- logging 36 at level INFO, messages should be seen every 10 events -- --- logging 37 at level INFO, messages should be seen every 10 events -- --- logging 38 at level INFO, messages should be seen every 10 events -- --- logging 39 at level INFO, messages should be seen every 10 events -- -Info index = 30 -Info index = 31 -Info index = 32 -Info index = 33 -Info index = 34 -Info index = 35 -Info index = 36 -Info index = 37 -Info index = 38 -Info index = 39 --- logging 40 at level INFO, messages should be seen every 10 events -- --- logging 41 at level INFO, messages should be seen every 10 events -- --- logging 42 at level INFO, messages should be seen every 10 events -- --- logging 43 at level INFO, messages should be seen every 10 events -- --- logging 44 at level INFO, messages should be seen every 10 events -- --- logging 45 at level INFO, messages should be seen every 10 events -- --- logging 46 at level INFO, messages should be seen every 10 events -- --- logging 47 at level INFO, messages should be seen every 10 events -- --- logging 48 at level INFO, messages should be seen every 10 events -- --- logging 49 at level INFO, messages should be seen every 10 events -- -Info index = 40 -Info index = 41 -Info index = 42 -Info index = 43 -Info index = 44 -Info index = 45 -Info index = 46 -Info index = 47 -Info index = 48 -Info index = 49 --- logging 50 at level INFO, messages should be seen every 10 events -- --- logging 51 at level INFO, messages should be seen every 10 events -- --- logging 52 at level INFO, messages should be seen every 10 events -- --- logging 53 at level INFO, messages should be seen every 10 events -- --- logging 54 at level INFO, messages should be seen every 10 events -- --- logging 55 at level INFO, messages should be seen every 10 events -- --- logging 56 at level INFO, messages should be seen every 10 events -- --- logging 57 at level INFO, messages should be seen every 10 events -- --- logging 58 at level INFO, messages should be seen every 10 events -- --- logging 59 at level INFO, messages should be seen every 10 events -- -Info index = 50 -Info index = 51 -Info index = 52 -Info index = 53 -Info index = 54 -Info index = 55 -Info index = 56 -Info index = 57 -Info index = 58 -Info index = 59 --- logging 60 at level INFO, messages should be seen every 10 events -- --- logging 61 at level INFO, messages should be seen every 10 events -- --- logging 62 at level INFO, messages should be seen every 10 events -- --- logging 63 at level INFO, messages should be seen every 10 events -- --- logging 64 at level INFO, messages should be seen every 10 events -- --- logging 65 at level INFO, messages should be seen every 10 events -- --- logging 66 at level INFO, messages should be seen every 10 events -- --- logging 67 at level INFO, messages should be seen every 10 events -- --- logging 68 at level INFO, messages should be seen every 10 events -- --- logging 69 at level INFO, messages should be seen every 10 events -- -Info index = 60 -Info index = 61 -Info index = 62 -Info index = 63 -Info index = 64 -Info index = 65 -Info index = 66 -Info index = 67 -Info index = 68 -Info index = 69 --- logging 70 at level INFO, messages should be seen every 10 events -- --- logging 71 at level INFO, messages should be seen every 10 events -- --- logging 72 at level INFO, messages should be seen every 10 events -- --- logging 73 at level INFO, messages should be seen every 10 events -- --- logging 74 at level INFO, messages should be seen every 10 events -- --- logging 75 at level INFO, messages should be seen every 10 events -- --- logging 76 at level INFO, messages should be seen every 10 events -- --- logging 77 at level INFO, messages should be seen every 10 events -- --- logging 78 at level INFO, messages should be seen every 10 events -- --- logging 79 at level INFO, messages should be seen every 10 events -- -Info index = 70 -Info index = 71 -Info index = 72 -Info index = 73 -Info index = 74 -Info index = 75 -Info index = 76 -Info index = 77 -Info index = 78 -Info index = 79 --- logging 80 at level INFO, messages should be seen every 10 events -- --- logging 81 at level INFO, messages should be seen every 10 events -- --- logging 82 at level INFO, messages should be seen every 10 events -- --- logging 83 at level INFO, messages should be seen every 10 events -- --- logging 84 at level INFO, messages should be seen every 10 events -- --- logging 85 at level INFO, messages should be seen every 10 events -- --- logging 86 at level INFO, messages should be seen every 10 events -- --- logging 87 at level INFO, messages should be seen every 10 events -- --- logging 88 at level INFO, messages should be seen every 10 events -- --- logging 89 at level INFO, messages should be seen every 10 events -- -Info index = 80 -Info index = 81 -Info index = 82 -Info index = 83 -Info index = 84 -Info index = 85 -Info index = 86 -Info index = 87 -Info index = 88 -Info index = 89 --- logging 90 at level INFO, messages should be seen every 10 events -- --- logging 91 at level INFO, messages should be seen every 10 events -- --- logging 92 at level INFO, messages should be seen every 10 events -- --- logging 93 at level INFO, messages should be seen every 10 events -- --- logging 94 at level INFO, messages should be seen every 10 events -- --- logging 95 at level INFO, messages should be seen every 10 events -- --- logging 96 at level INFO, messages should be seen every 10 events -- --- logging 97 at level INFO, messages should be seen every 10 events -- --- logging 98 at level INFO, messages should be seen every 10 events -- --- logging 99 at level INFO, messages should be seen every 10 events -- -Info index = 90 -Info index = 91 -Info index = 92 -Info index = 93 -Info index = 94 -Info index = 95 -Info index = 96 -Info index = 97 -Info index = 98 -Info index = 99 --- logging 100 at level INFO, messages should be seen every 10 events -- --- logging 101 at level INFO, messages should be seen every 10 events -- -Info index = 100 -Info index = 101 --- log_test7 end -------------------------------------------------------- --- log_test8 begin -------------------------------------------------------- --- log_test8 end -------------------------------------------------------- --- log_test9 begin -------------------------------------------------------- --- log_test9 end -------------------------------------------------------- --- log_test10 begin -------------------------------------------------------- -logger not derived from logging.Logger: NotALogger -INFO:mylogger:Starting... -DEBUG:mylogger:Debug message not in exception handler (no traceback) -INFO:mylogger:About to throw exception... -DEBUG:mylogger:Debug message inside exception handler (traceback) -Traceback (most recent call last): - File "C:\Projects\RDC\Python\packages\logging\test\log_test10.py", line 77, in run - print "7" + 4 -TypeError: cannot concatenate 'str' and 'int' objects -INFO:mylogger:Done. --- log_test10 end -------------------------------------------------------- --- log_test12 begin -------------------------------------------------------- -INFO:log_test12:Jackdaws love my big sphinx of quartz -INFO:log_test12:Jackdaws love my big sphinx of quartz -DEBUG:log_test12:Pack my box with twelve dozen liquor jugs -DEBUG:log_test12:Pack my box with twelve dozen liquor jugs --- log_test12 end -------------------------------------------------------- --- log_test13 begin -------------------------------------------------------- -INFO:log_test13:Jackdaws love my big sphinx of quartz -DEBUG:log_test13:Pack my box with five dozen liquor jugs --- log_test13 end -------------------------------------------------------- --- log_test15 begin -------------------------------------------------------- -Unfiltered... -INFO:a:Info 1 -INFO:a.b:Info 2 -INFO:a.c:Info 3 -INFO:a.b.c:Info 4 -INFO:a.b.c.d:Info 5 -INFO:a.bb.c:Info 6 -INFO:b:Info 7 -INFO:b.a:Info 8 -INFO:c.a.b:Info 9 -INFO:a.bb:Info 10 -Filtered with 'a.b'... -INFO:a.b:Info 2 -INFO:a.b.c:Info 4 -INFO:a.b.c.d:Info 5 --- log_test15 end -------------------------------------------------------- diff --git a/tools/python/logging/logging-0.4.9.2/test/stdout.exp b/tools/python/logging/logging-0.4.9.2/test/stdout.exp deleted file mode 100644 index bf3d1504b7..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/stdout.exp +++ /dev/null @@ -1,24 +0,0 @@ -About to start TCP server... -About to start UDP server... -About to start HTTP server... -About to start SOAP server... --- log_test0 begin -------------------------------------------------------- --- log_test0 end -------------------------------------------------------- --- log_test2 begin -------------------------------------------------------- --- log_test2 end -------------------------------------------------------- --- log_test4 begin -------------------------------------------------------- --- log_test4 end -------------------------------------------------------- --- log_test7 begin -------------------------------------------------------- --- log_test7 end -------------------------------------------------------- --- log_test8 begin -------------------------------------------------------- --- log_test8 end -------------------------------------------------------- --- log_test9 begin -------------------------------------------------------- --- log_test9 end -------------------------------------------------------- --- log_test10 begin -------------------------------------------------------- --- log_test10 end -------------------------------------------------------- --- log_test12 begin -------------------------------------------------------- --- log_test12 end -------------------------------------------------------- --- log_test13 begin -------------------------------------------------------- --- log_test13 end -------------------------------------------------------- --- log_test15 begin -------------------------------------------------------- --- log_test15 end -------------------------------------------------------- diff --git a/tools/python/logging/logging-0.4.9.2/test/warn.ini b/tools/python/logging/logging-0.4.9.2/test/warn.ini deleted file mode 100644 index 3a7b374ad5..0000000000 --- a/tools/python/logging/logging-0.4.9.2/test/warn.ini +++ /dev/null @@ -1,60 +0,0 @@ -[loggers] -keys=root,log02,log03,log04,log05 - -[handlers] -keys=hand01 - -[formatters] -keys=form01 - -[logger_root] -level=WARN -propagate=1 -channel= -parent= -qualname=(root) -handlers=hand01 - -[logger_log02] -level=WARN -propagate=1 -channel=A -parent=(root) -qualname=A -handlers= - -[logger_log03] -level=WARN -propagate=1 -channel=B -parent=log02 -qualname=A.B -handlers= - -[logger_log04] -level=WARN -propagate=1 -channel=C -parent=log03 -qualname=A.B.C -handlers= - -[logger_log05] -level=WARN -propagate=1 -channel=D -parent=log04 -qualname=A.B.C.D -handlers= - -[handler_hand01] -class=StreamHandler -level=NOTSET -formatter=form01 -stream=sys.stderr -args=(sys.stderr,) - -[formatter_form01] -format=warn.ini %(name)s %(levelname)s %(message)s -datefmt= - diff --git a/tools/python/logging/setup.py b/tools/python/logging/setup.py deleted file mode 100644 index 724e17e645..0000000000 --- a/tools/python/logging/setup.py +++ /dev/null @@ -1,11 +0,0 @@ -#============================================================================ -# Install the logging package from python 2.3 if not present. -#============================================================================ -import os - -try: - import logging -except ImportError: - print 'logging package not found: installing' - os.chdir('logging-0.4.9.2') - execfile('setup.py') diff --git a/tools/python/ptsname/ptsname.c b/tools/python/ptsname/ptsname.c deleted file mode 100644 index 3849bb8867..0000000000 --- a/tools/python/ptsname/ptsname.c +++ /dev/null @@ -1,44 +0,0 @@ -/****************************************************************************** - * ptsname.c - * - * A python extension to expose the POSIX ptsname() function. - * - * Copyright (C) 2007 XenSource Ltd - */ - -#include -#include - -/* Needed for Python versions earlier than 2.3. */ -#ifndef PyMODINIT_FUNC -#define PyMODINIT_FUNC DL_EXPORT(void) -#endif - -static PyObject *do_ptsname(PyObject *self, PyObject *args) -{ - int fd; - char *path; - - if (!PyArg_ParseTuple(args, "i", &fd)) - return NULL; - - path = ptsname(fd); - - if (!path) - { - PyErr_SetFromErrno(PyExc_IOError); - return NULL; - } - - return PyString_FromString(path); -} - -static PyMethodDef ptsname_methods[] = { - { "ptsname", do_ptsname, METH_VARARGS }, - { NULL } -}; - -PyMODINIT_FUNC initptsname(void) -{ - Py_InitModule("ptsname", ptsname_methods); -} diff --git a/tools/python/setup.py b/tools/python/setup.py index 8127b21fdf..17ebb4a341 100644 --- a/tools/python/setup.py +++ b/tools/python/setup.py @@ -27,58 +27,6 @@ xs = Extension("xs", depends = [ PATH_XENSTORE + "/libxenstore.so" ], sources = [ "xen/lowlevel/xs/xs.c" ]) -scf = Extension("scf", - extra_compile_args = extra_compile_args, - include_dirs = [ "xen/lowlevel/scf" ], - library_dirs = [ ], - libraries = [ ], - depends = [ ], - sources = [ "xen/lowlevel/scf/scf.c" ]) - -process = Extension("process", - extra_compile_args = extra_compile_args, - include_dirs = [ "xen/lowlevel/process" ], - library_dirs = [ ], - libraries = [ "contract" ], - depends = [ ], - sources = [ "xen/lowlevel/process/process.c" ]) - -flask = Extension("flask", - extra_compile_args = extra_compile_args, - include_dirs = [ PATH_XEN, PATH_LIBXC, "xen/lowlevel/flask" ], - library_dirs = [ PATH_LIBXC ], - libraries = [ "xenctrl" ], - depends = [ PATH_LIBXC + "/libxenctrl.so" ], - sources = [ "xen/lowlevel/flask/flask.c" ]) - -ptsname = Extension("ptsname", - extra_compile_args = extra_compile_args, - include_dirs = [ "ptsname" ], - library_dirs = [ ], - libraries = [ ], - depends = [ ], - sources = [ "ptsname/ptsname.c" ]) - -checkpoint = Extension("checkpoint", - extra_compile_args = extra_compile_args, - include_dirs = [ PATH_XEN, PATH_LIBXC, PATH_XENSTORE ], - library_dirs = [ PATH_LIBXC, PATH_XENSTORE ], - libraries = [ "xenctrl", "xenguest", "xenstore", "rt" ], - depends = [ PATH_LIBXC + "/libxenctrl.so", - PATH_LIBXC + "/libxenguest.so", - PATH_XENSTORE + "/libxenstore.so" ], - sources = [ "xen/lowlevel/checkpoint/checkpoint.c", - "xen/lowlevel/checkpoint/libcheckpoint.c"]) - -netlink = Extension("netlink", - extra_compile_args = extra_compile_args, - include_dirs = [ ], - library_dirs = [ ], - libraries = [ ], - depends = [ ], - sources = [ "xen/lowlevel/netlink/netlink.c", - "xen/lowlevel/netlink/libnetlink.c"]) - xl = Extension("xl", extra_compile_args = extra_compile_args, include_dirs = [ PATH_XEN, PATH_LIBXL, PATH_LIBXC, "xen/lowlevel/xl" ], @@ -88,54 +36,15 @@ xl = Extension("xl", sources = [ "xen/lowlevel/xl/xl.c", "xen/lowlevel/xl/_pyxl_types.c" ]) plat = os.uname()[0] -modules = [ xc, xs, ptsname, flask ] +modules = [ xc, xs ] #modules.extend([ xl ]) -if plat == 'SunOS': - modules.extend([ scf, process ]) -if plat == 'Linux': - modules.extend([ checkpoint, netlink ]) - -enable_xend = True -new_argv = [] -for arg in sys.argv: - if arg == "--xend=y": - enable_xend = True - elif arg == "--xend=n": - enable_xend = False - else: - new_argv.append(arg) -sys.argv = new_argv - -if enable_xend: - xend_packages = [ - 'xen.util', - 'xen.util.xsm', - 'xen.util.xsm.dummy', - 'xen.util.xsm.flask', - 'xen.util.xsm.acm', - 'xen.xend', - 'xen.xend.server', - 'xen.xend.xenstore', - 'xen.xm', - 'xen.web', - 'xen.remus', - 'xen.xend.tests', - 'xen.xend.server.tests', - 'xen.xend.xenstore.tests', - 'xen.xm.tests' - ] -else: - xend_packages = [] setup(name = 'xen', version = '3.0', description = 'Xen', packages = ['xen', 'xen.lowlevel', - ] + xend_packages, + ], ext_package = "xen.lowlevel", ext_modules = modules ) - -os.chdir('logging') -execfile('setup.py') diff --git a/tools/python/xen/lowlevel/checkpoint/checkpoint.c b/tools/python/xen/lowlevel/checkpoint/checkpoint.c deleted file mode 100644 index c5cdd83810..0000000000 --- a/tools/python/xen/lowlevel/checkpoint/checkpoint.c +++ /dev/null @@ -1,371 +0,0 @@ -/* python bridge to checkpointing API */ - -#include - -#include -#include - -#include "checkpoint.h" - -#define PKG "xen.lowlevel.checkpoint" - -static PyObject* CheckpointError; - -typedef struct { - PyObject_HEAD - checkpoint_state cps; - - /* milliseconds between checkpoints */ - unsigned int interval; - int armed; - - PyObject* suspend_cb; - PyObject* postcopy_cb; - PyObject* checkpoint_cb; - - PyThreadState* threadstate; -} CheckpointObject; - -static int suspend_trampoline(void* data); -static int postcopy_trampoline(void* data); -static int checkpoint_trampoline(void* data); - -static PyObject* Checkpoint_new(PyTypeObject* type, PyObject* args, - PyObject* kwargs) -{ - CheckpointObject* self = (CheckpointObject*)type->tp_alloc(type, 0); - - if (!self) - return NULL; - - checkpoint_init(&self->cps); - self->suspend_cb = NULL; - self->armed = 0; - - return (PyObject*)self; -} - -static int Checkpoint_init(PyObject* obj, PyObject* args, PyObject* kwargs) -{ - return 0; -} - -static void Checkpoint_dealloc(CheckpointObject* self) -{ - checkpoint_close(&self->cps); - - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject* pycheckpoint_open(PyObject* obj, PyObject* args) -{ - CheckpointObject* self = (CheckpointObject*)obj; - checkpoint_state* cps = &self->cps; - unsigned int domid; - - if (!PyArg_ParseTuple(args, "I", &domid)) - return NULL; - - if (checkpoint_open(cps, domid) < 0) { - PyErr_SetString(CheckpointError, checkpoint_error(cps)); - - return NULL; - } - - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject* pycheckpoint_close(PyObject* obj, PyObject* args) -{ - CheckpointObject* self = (CheckpointObject*)obj; - - if (checkpoint_resume(&self->cps) < 0) - fprintf(stderr, "%s\n", checkpoint_error(&self->cps)); - - checkpoint_close(&self->cps); - - Py_XDECREF(self->suspend_cb); - self->suspend_cb = NULL; - Py_XDECREF(self->postcopy_cb); - self->postcopy_cb = NULL; - Py_XDECREF(self->checkpoint_cb); - self->checkpoint_cb = NULL; - - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject* pycheckpoint_start(PyObject* obj, PyObject* args) { - CheckpointObject* self = (CheckpointObject*)obj; - - PyObject* iofile; - PyObject* suspend_cb = NULL; - PyObject* postcopy_cb = NULL; - PyObject* checkpoint_cb = NULL; - unsigned int interval = 0; - unsigned int flags = 0; - - int fd; - struct save_callbacks callbacks; - int rc; - - if (!PyArg_ParseTuple(args, "O|OOOII", &iofile, &suspend_cb, &postcopy_cb, - &checkpoint_cb, &interval, &flags)) - return NULL; - - self->interval = interval; - - Py_INCREF(iofile); - Py_XINCREF(suspend_cb); - Py_XINCREF(postcopy_cb); - Py_XINCREF(checkpoint_cb); - - fd = PyObject_AsFileDescriptor(iofile); - Py_DECREF(iofile); - if (fd < 0) { - PyErr_SetString(PyExc_TypeError, "invalid file handle"); - return NULL; - } - - if (suspend_cb && suspend_cb != Py_None) { - if (!PyCallable_Check(suspend_cb)) { - PyErr_SetString(PyExc_TypeError, "suspend callback not callable"); - goto err; - } - self->suspend_cb = suspend_cb; - } else - self->suspend_cb = NULL; - - if (postcopy_cb && postcopy_cb != Py_None) { - if (!PyCallable_Check(postcopy_cb)) { - PyErr_SetString(PyExc_TypeError, "postcopy callback not callable"); - return NULL; - } - self->postcopy_cb = postcopy_cb; - } else - self->postcopy_cb = NULL; - - if (checkpoint_cb && checkpoint_cb != Py_None) { - if (!PyCallable_Check(checkpoint_cb)) { - PyErr_SetString(PyExc_TypeError, "checkpoint callback not callable"); - return NULL; - } - self->checkpoint_cb = checkpoint_cb; - } else - self->checkpoint_cb = NULL; - - memset(&callbacks, 0, sizeof(callbacks)); - callbacks.suspend = suspend_trampoline; - callbacks.postcopy = postcopy_trampoline; - callbacks.checkpoint = checkpoint_trampoline; - callbacks.data = self; - - self->threadstate = PyEval_SaveThread(); - rc = checkpoint_start(&self->cps, fd, &callbacks, flags); - PyEval_RestoreThread(self->threadstate); - - if (rc < 0) { - PyErr_SetString(CheckpointError, checkpoint_error(&self->cps)); - goto err; - } - - Py_INCREF(Py_None); - return Py_None; - - err: - self->suspend_cb = NULL; - Py_XDECREF(suspend_cb); - self->postcopy_cb = NULL; - Py_XDECREF(postcopy_cb); - self->checkpoint_cb = NULL; - Py_XDECREF(checkpoint_cb); - - return NULL; -} - -static PyMethodDef Checkpoint_methods[] = { - { "open", pycheckpoint_open, METH_VARARGS, - "open connection to xen" }, - { "close", pycheckpoint_close, METH_NOARGS, - "close connection to xen" }, - { "start", pycheckpoint_start, METH_VARARGS | METH_KEYWORDS, - "begin a checkpoint" }, - { NULL, NULL, 0, NULL } -}; - -static PyTypeObject CheckpointType = { - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ - PKG ".checkpointer", /* tp_name */ - sizeof(CheckpointObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)Checkpoint_dealloc, /* tp_dealloc */ - NULL, /* tp_print */ - NULL, /* tp_getattr */ - NULL, /* tp_setattr */ - NULL, /* tp_compare */ - NULL, /* tp_repr */ - NULL, /* tp_as_number */ - NULL, /* tp_as_sequence */ - NULL, /* tp_as_mapping */ - NULL, /* tp_hash */ - NULL, /* tp_call */ - NULL, /* tp_str */ - NULL, /* tp_getattro */ - NULL, /* tp_setattro */ - NULL, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - "Checkpoint object", /* tp_doc */ - NULL, /* tp_traverse */ - NULL, /* tp_clear */ - NULL, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - NULL, /* tp_iter */ - NULL, /* tp_iternext */ - Checkpoint_methods, /* tp_methods */ - NULL, /* tp_members */ - NULL, /* tp_getset */ - NULL, /* tp_base */ - NULL, /* tp_dict */ - NULL, /* tp_descr_get */ - NULL, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)Checkpoint_init, /* tp_init */ - NULL, /* tp_alloc */ - Checkpoint_new, /* tp_new */ -}; - -static PyMethodDef methods[] = { - { NULL } -}; - -static char doc[] = "checkpoint API"; - -PyMODINIT_FUNC initcheckpoint(void) { - PyObject *m; - - if (PyType_Ready(&CheckpointType) < 0) - return; - - m = Py_InitModule3(PKG, methods, doc); - - if (!m) - return; - - Py_INCREF(&CheckpointType); - PyModule_AddObject(m, "checkpointer", (PyObject*)&CheckpointType); - - CheckpointError = PyErr_NewException(PKG ".error", NULL, NULL); - Py_INCREF(CheckpointError); - PyModule_AddObject(m, "error", CheckpointError); - - block_timer(); -} - -/* private functions */ - -/* bounce C suspend call into python equivalent. - * returns 1 on success or 0 on failure */ -static int suspend_trampoline(void* data) -{ - CheckpointObject* self = (CheckpointObject*)data; - - PyObject* result; - - /* call default suspend function, then python hook if available */ - if (self->armed) { - if (checkpoint_wait(&self->cps) < 0) { - fprintf(stderr, "%s\n", checkpoint_error(&self->cps)); - return 0; - } - } else { - if (self->interval) { - self->armed = 1; - checkpoint_settimer(&self->cps, self->interval); - } - - if (!checkpoint_suspend(&self->cps)) { - fprintf(stderr, "%s\n", checkpoint_error(&self->cps)); - return 0; - } - } - - if (!self->suspend_cb) - return 1; - - PyEval_RestoreThread(self->threadstate); - result = PyObject_CallFunction(self->suspend_cb, NULL); - self->threadstate = PyEval_SaveThread(); - - if (!result) - return 0; - - if (result == Py_None || PyObject_IsTrue(result)) { - Py_DECREF(result); - return 1; - } - - Py_DECREF(result); - - return 0; -} - -static int postcopy_trampoline(void* data) -{ - CheckpointObject* self = (CheckpointObject*)data; - - PyObject* result; - int rc = 0; - - if (!self->postcopy_cb) - goto resume; - - PyEval_RestoreThread(self->threadstate); - result = PyObject_CallFunction(self->postcopy_cb, NULL); - - if (result && (result == Py_None || PyObject_IsTrue(result))) - rc = 1; - - Py_XDECREF(result); - self->threadstate = PyEval_SaveThread(); - - resume: - if (checkpoint_resume(&self->cps) < 0) { - fprintf(stderr, "%s\n", checkpoint_error(&self->cps)); - return 0; - } - - return rc; -} - -static int checkpoint_trampoline(void* data) -{ - CheckpointObject* self = (CheckpointObject*)data; - - PyObject* result; - - if (checkpoint_postflush(&self->cps) < 0) { - fprintf(stderr, "%s\n", checkpoint_error(&self->cps)); - return -1; - } - - if (!self->checkpoint_cb) - return 0; - - PyEval_RestoreThread(self->threadstate); - result = PyObject_CallFunction(self->checkpoint_cb, NULL); - self->threadstate = PyEval_SaveThread(); - - if (!result) - return 0; - - if (result == Py_None || PyObject_IsTrue(result)) { - Py_DECREF(result); - return 1; - } - - Py_DECREF(result); - - return 0; -} diff --git a/tools/python/xen/lowlevel/checkpoint/checkpoint.h b/tools/python/xen/lowlevel/checkpoint/checkpoint.h deleted file mode 100644 index 24149568cb..0000000000 --- a/tools/python/xen/lowlevel/checkpoint/checkpoint.h +++ /dev/null @@ -1,61 +0,0 @@ -/* API for checkpointing */ - -#ifndef _CHECKPOINT_H_ -#define _CHECKPOINT_H_ 1 - -#include -#include -#include - -#include -#include - -typedef enum { - dt_unknown, - dt_pv, - dt_hvm, - dt_pvhvm /* HVM with PV drivers */ -} checkpoint_domtype; - -typedef struct { - xc_interface *xch; - xc_evtchn *xce; /* event channel handle */ - struct xs_handle* xsh; /* xenstore handle */ - int watching_shutdown; /* state of watch on @releaseDomain */ - - unsigned int domid; - checkpoint_domtype domtype; - int fd; - - int suspend_evtchn, suspend_lockfd; - - char* errstr; - - /* suspend deadline thread support */ - volatile int suspended; - volatile int done; - pthread_t suspend_thr; - sem_t suspended_sem; - sem_t resumed_sem; - timer_t timer; -} checkpoint_state; - -#define CHECKPOINT_FLAGS_COMPRESSION 1 -char* checkpoint_error(checkpoint_state* s); - -void checkpoint_init(checkpoint_state* s); -int checkpoint_open(checkpoint_state* s, unsigned int domid); -void checkpoint_close(checkpoint_state* s); -int checkpoint_start(checkpoint_state* s, int fd, - struct save_callbacks* callbacks, - unsigned int remus_flags); -int checkpoint_suspend(checkpoint_state* s); -int checkpoint_resume(checkpoint_state* s); -int checkpoint_postflush(checkpoint_state* s); - -int checkpoint_settimer(checkpoint_state* s, int millis); -int checkpoint_wait(checkpoint_state* s); -void block_timer(void); -void unblock_timer(void); - -#endif diff --git a/tools/python/xen/lowlevel/checkpoint/libcheckpoint.c b/tools/python/xen/lowlevel/checkpoint/libcheckpoint.c deleted file mode 100644 index 74ca062df6..0000000000 --- a/tools/python/xen/lowlevel/checkpoint/libcheckpoint.c +++ /dev/null @@ -1,850 +0,0 @@ -/* API for checkpointing */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "checkpoint.h" - -static char errbuf[256]; - -static int setup_suspend_evtchn(checkpoint_state* s); -static void release_suspend_evtchn(checkpoint_state *s); -static int setup_shutdown_watch(checkpoint_state* s); -static int check_shutdown(checkpoint_state* s); -static void release_shutdown_watch(checkpoint_state* s); - -static int evtchn_suspend(checkpoint_state* s); -static int compat_suspend(checkpoint_state* s); -static int pollfd(checkpoint_state* s, int fd); - -static int switch_qemu_logdirty(checkpoint_state* s, int enable); -static int suspend_hvm(checkpoint_state* s); -static int suspend_qemu(checkpoint_state* s); -static int resume_qemu(checkpoint_state* s); -static int send_qemu(checkpoint_state* s); - -static int create_suspend_timer(checkpoint_state* s); -static int delete_suspend_timer(checkpoint_state* s); -static int create_suspend_thread(checkpoint_state* s); -static void stop_suspend_thread(checkpoint_state* s); - -/* Returns a string describing the most recent error returned by - * a checkpoint function. Static -- do not free. */ -char* checkpoint_error(checkpoint_state* s) -{ - return s->errstr; -} - -void checkpoint_init(checkpoint_state* s) -{ - s->xch = NULL; - s->xce = NULL; - s->xsh = NULL; - s->watching_shutdown = 0; - - s->domid = 0; - s->domtype = dt_unknown; - s->fd = -1; - - s->suspend_evtchn = -1; - s->suspend_lockfd = -1; - - s->errstr = NULL; - - s->suspended = 0; - s->done = 0; - s->suspend_thr = 0; - s->timer = 0; -} - -/* open a checkpoint session to guest domid */ -int checkpoint_open(checkpoint_state* s, unsigned int domid) -{ - xc_dominfo_t dominfo; - unsigned long pvirq; - - s->domid = domid; - - s->xch = xc_interface_open(0,0,0); - if (!s->xch) { - s->errstr = "could not open control interface (are you root?)"; - - return -1; - } - - s->xsh = xs_daemon_open(); - if (!s->xsh) { - checkpoint_close(s); - s->errstr = "could not open xenstore handle"; - - return -1; - } - - s->xce = xc_evtchn_open(NULL, 0); - if (s->xce == NULL) { - checkpoint_close(s); - s->errstr = "could not open event channel handle"; - - return -1; - } - - if (xc_domain_getinfo(s->xch, s->domid, 1, &dominfo) < 0) { - checkpoint_close(s); - s->errstr = "could not get domain info"; - - return -1; - } - if (dominfo.hvm) { - if (xc_get_hvm_param(s->xch, s->domid, HVM_PARAM_CALLBACK_IRQ, &pvirq)) { - checkpoint_close(s); - s->errstr = "could not get HVM callback IRQ"; - - return -1; - } - s->domtype = pvirq ? dt_pvhvm : dt_hvm; - } else - s->domtype = dt_pv; - - if (setup_shutdown_watch(s) < 0) { - checkpoint_close(s); - - return -1; - } - - if (s->domtype == dt_pv) { - if (setup_suspend_evtchn(s) < 0) { - fprintf(stderr, "WARNING: suspend event channel unavailable, " - "falling back to slow xenstore signalling\n"); - } - } else if (s->domtype == dt_pvhvm) { - checkpoint_close(s); - s->errstr = "PV-on-HVM is unsupported"; - - return -1; - } - - return 0; -} - -void checkpoint_close(checkpoint_state* s) -{ - if (s->timer) - delete_suspend_timer(s); - if (s->suspend_thr) - stop_suspend_thread(s); - - release_shutdown_watch(s); - release_suspend_evtchn(s); - - if (s->xch) { - xc_interface_close(s->xch); - s->xch = NULL; - } - if (s->xce != NULL) { - xc_evtchn_close(s->xce); - s->xce = NULL; - } - if (s->xsh) { - xs_daemon_close(s->xsh); - s->xsh = NULL; - } - - s->domid = 0; - s->fd = -1; -} - -/* we toggle logdirty ourselves around the xc_domain_save call -- - * it avoids having to pass around checkpoint_state */ -static int noop_switch_logdirty(int domid, unsigned enable, void *data) -{ - return 0; -} - -int checkpoint_start(checkpoint_state* s, int fd, - struct save_callbacks* callbacks, - unsigned int remus_flags) -{ - int hvm, rc; - int flags = XCFLAGS_LIVE; - unsigned long vm_generationid_addr; - - if (!s->domid) { - s->errstr = "checkpoint state not opened"; - return -1; - } - - s->fd = fd; - - hvm = s->domtype > dt_pv; - if (hvm) { - char path[128]; - char *addr; - - sprintf(path, "/local/domain/%u/hvmloader/generation-id-address", s->domid); - addr = xs_read(s->xsh, XBT_NULL, path, NULL); - - vm_generationid_addr = (addr) ? strtoul(addr, NULL, 0) : 0; - free(addr); - - flags |= XCFLAGS_HVM; - if (switch_qemu_logdirty(s, 1)) - return -1; - } else { - vm_generationid_addr = 0; - } - if (remus_flags & CHECKPOINT_FLAGS_COMPRESSION) - flags |= XCFLAGS_CHECKPOINT_COMPRESS; - - callbacks->switch_qemu_logdirty = noop_switch_logdirty; - - rc = xc_domain_save(s->xch, fd, s->domid, 0, 0, flags, callbacks, hvm, - vm_generationid_addr); - - if (hvm) - switch_qemu_logdirty(s, 0); - - return rc; -} - -/* suspend the domain. Returns 0 on failure, 1 on success */ -int checkpoint_suspend(checkpoint_state* s) -{ - struct timeval tv; - int rc; - - gettimeofday(&tv, NULL); - fprintf(stderr, "PROF: suspending at %lu.%06lu\n", (unsigned long)tv.tv_sec, - (unsigned long)tv.tv_usec); - - if (s->suspend_evtchn >= 0) - rc = evtchn_suspend(s); - else if (s->domtype == dt_hvm) - rc = suspend_hvm(s); - else - rc = compat_suspend(s); - - return rc < 0 ? 0 : 1; -} - -/* wait for a suspend to be triggered by another thread */ -int checkpoint_wait(checkpoint_state* s) -{ - int rc; - - if (!s->suspend_thr) { - s->errstr = "checkpoint timer is not active\n"; - return -1; - } - - do { - rc = sem_wait(&s->suspended_sem); - if (rc < 0 && errno != EINTR) { - snprintf(errbuf, sizeof(errbuf), - "error waiting for suspend semaphore: %d %d\n", rc, errno); - s->errstr = errbuf; - return -1; - } - } while (rc < 0); - - if (!s->suspended) { - snprintf(errbuf, sizeof(errbuf), "domain not suspended?\n"); - s->errstr = errbuf; - return -1; - } - - return 0; -} - -/* let guest execution resume */ -int checkpoint_resume(checkpoint_state* s) -{ - struct timeval tv; - int rc; - - if (xc_domain_resume(s->xch, s->domid, 1)) { - snprintf(errbuf, sizeof(errbuf), "error resuming domain: %d", errno); - s->errstr = errbuf; - - return -1; - } - - gettimeofday(&tv, NULL); - fprintf(stderr, "PROF: resumed at %lu.%06lu\n", (unsigned long)tv.tv_sec, - (unsigned long)tv.tv_usec); - - if (s->domtype > dt_pv && resume_qemu(s) < 0) - return -1; - - /* restore watchability in xenstore */ - if (xs_resume_domain(s->xsh, s->domid) < 0) - fprintf(stderr, "error resuming domain in xenstore\n"); - - s->suspended = 0; - - if (s->suspend_thr) { - if ((rc = sem_post(&s->resumed_sem))) - fprintf(stderr, "error posting resume semaphore\n"); - } - - return 0; -} - -/* called after xc_domain_save has flushed its buffer */ -int checkpoint_postflush(checkpoint_state *s) -{ - if (s->domtype > dt_pv && send_qemu(s) < 0) - return -1; - - return 0; -} - -/* force suspend within millis ms if copy hasn't completed yet */ -int checkpoint_settimer(checkpoint_state* s, int millis) -{ - struct itimerspec t; - int err; - - if (!s->suspend_thr) { - if (create_suspend_timer(s) < 0) - return -1; - - if (create_suspend_thread(s) < 0) { - delete_suspend_timer(s); - return -1; - } - } - - t.it_value.tv_sec = millis / 1000; - t.it_value.tv_nsec = (millis % 1000) * 1000000L; - t.it_interval.tv_sec = t.it_value.tv_sec; - t.it_interval.tv_nsec = t.it_value.tv_nsec; - - if ((err = timer_settime(s->timer, 0, &t, NULL))) { - fprintf(stderr, "Error arming timer: %d\n", err); - return -1; - } - - return 0; -} - -int delete_suspend_timer(checkpoint_state* s) -{ - int rc = 0; - - if (s->timer) { - if ((rc = timer_delete(s->timer))) - fprintf(stderr, "Error deleting timer: %s\n", strerror(errno)); - s->timer = 0; - } - - return rc; -} - -/* Set up event channel used to signal a guest to suspend itself */ -static int setup_suspend_evtchn(checkpoint_state* s) -{ - int port; - - port = xs_suspend_evtchn_port(s->domid); - if (port < 0) { - s->errstr = "failed to read suspend event channel"; - return -1; - } - - s->suspend_evtchn = xc_suspend_evtchn_init_exclusive(s->xch, s->xce, - s->domid, port, &s->suspend_lockfd); - if (s->suspend_evtchn < 0) { - s->errstr = "failed to bind suspend event channel"; - return -1; - } - - fprintf(stderr, "bound to suspend event channel %u:%d as %d\n", s->domid, port, - s->suspend_evtchn); - - return 0; -} - -/* release suspend event channels bound to guest */ -static void release_suspend_evtchn(checkpoint_state *s) -{ - /* TODO: teach xen to clean up if port is unbound */ - if (s->xce != NULL && s->suspend_evtchn >= 0) { - xc_suspend_evtchn_release(s->xch, s->xce, s->domid, - s->suspend_evtchn, &s->suspend_lockfd); - s->suspend_evtchn = -1; - } -} - -static int setup_shutdown_watch(checkpoint_state* s) -{ - char buf[16]; - - /* write domain ID to watch so we can ignore other domain shutdowns */ - snprintf(buf, sizeof(buf), "%u", s->domid); - if ( !xs_watch(s->xsh, "@releaseDomain", buf) ) { - fprintf(stderr, "Could not bind to shutdown watch\n"); - return -1; - } - /* watch fires once on registration */ - s->watching_shutdown = 1; - check_shutdown(s); - - return 0; -} - -/* returns -1 on error or death, 0 if domain is running, 1 if suspended */ -static int check_shutdown(checkpoint_state* s) { - unsigned int count; - int xsfd; - char **vec; - char buf[16]; - xc_dominfo_t info; - - xsfd = xs_fileno(s->xsh); - - /* loop on watch if it fires for another domain */ - while (1) { - if (pollfd(s, xsfd) < 0) - return -1; - - vec = xs_read_watch(s->xsh, &count); - if (s->watching_shutdown == 1) { - s->watching_shutdown = 2; - return 0; - } - if (!vec) { - fprintf(stderr, "empty watch fired\n"); - continue; - } - snprintf(buf, sizeof(buf), "%d", s->domid); - if (!strcmp(vec[XS_WATCH_TOKEN], buf)) - break; - } - - if (xc_domain_getinfo(s->xch, s->domid, 1, &info) != 1 - || info.domid != s->domid) { - snprintf(errbuf, sizeof(errbuf), - "error getting info for domain %u", s->domid); - s->errstr = errbuf; - return -1; - } - if (!info.shutdown) { - snprintf(errbuf, sizeof(errbuf), - "domain %u not shut down", s->domid); - s->errstr = errbuf; - return 0; - } - - if (info.shutdown_reason != SHUTDOWN_suspend) - return -1; - - return 1; -} - -static void release_shutdown_watch(checkpoint_state* s) { - char buf[16]; - - if (!s->xsh) - return; - if (!s->watching_shutdown) - return; - - snprintf(buf, sizeof(buf), "%u", s->domid); - if (!xs_unwatch(s->xsh, "@releaseDomain", buf)) - fprintf(stderr, "Could not release shutdown watch\n"); - - s->watching_shutdown = 0; -} - -static int evtchn_suspend(checkpoint_state* s) -{ - int rc; - - rc = xc_evtchn_notify(s->xce, s->suspend_evtchn); - if (rc < 0) { - snprintf(errbuf, sizeof(errbuf), - "failed to notify suspend event channel: %d", rc); - s->errstr = errbuf; - - return -1; - } - - do - if (!(rc = pollfd(s, xc_evtchn_fd(s->xce)))) - rc = xc_evtchn_pending(s->xce); - while (rc >= 0 && rc != s->suspend_evtchn); - if (rc <= 0) - return -1; - - if (xc_evtchn_unmask(s->xce, s->suspend_evtchn) < 0) { - snprintf(errbuf, sizeof(errbuf), - "failed to unmask suspend notification channel: %d", rc); - s->errstr = errbuf; - - return -1; - } - - return 0; -} - -/* suspend through xenstore if suspend event channel is unavailable */ -static int compat_suspend(checkpoint_state* s) -{ - char path[128]; - - sprintf(path, "/local/domain/%u/control/shutdown", s->domid); - - if (!xs_write(s->xsh, XBT_NULL, path, "suspend", 7)) { - s->errstr = "error signalling qemu logdirty"; - return -1; - } - - if (check_shutdown(s) != 1) - return -1; - - return 0; -} - -/* returns -1 if fd does not become readable within timeout */ -static int pollfd(checkpoint_state* s, int fd) -{ - fd_set rfds; - struct timeval tv; - int rc; - - FD_ZERO(&rfds); - FD_SET(fd, &rfds); - - tv.tv_sec = 0; - tv.tv_usec = 500000; - - rc = select(fd + 1, &rfds, NULL, NULL, &tv); - - if (rc < 0) { - snprintf(errbuf, sizeof(errbuf), - "error polling fd: %s", strerror(errno)); - s->errstr = errbuf; - } else if (!rc) { - snprintf(errbuf, sizeof(errbuf), "timeout polling fd"); - s->errstr = errbuf; - } else if (! FD_ISSET(fd, &rfds)) { - snprintf(errbuf, sizeof(errbuf), "unknown error polling fd"); - s->errstr = errbuf; - } else - return 0; - - return -1; -} - -/* adapted from the eponymous function in xc_save */ -static int switch_qemu_logdirty(checkpoint_state *s, int enable) -{ - char path[128]; - char *tail, *cmd, *response; - char **vec; - unsigned int len; - - sprintf(path, "/local/domain/0/device-model/%u/logdirty/", s->domid); - tail = path + strlen(path); - - strcpy(tail, "ret"); - if (!xs_watch(s->xsh, path, "qemu-logdirty-ret")) { - s->errstr = "error watching qemu logdirty return"; - return 1; - } - /* null fire. XXX unify with shutdown watch! */ - vec = xs_read_watch(s->xsh, &len); - free(vec); - - strcpy(tail, "cmd"); - cmd = enable ? "enable" : "disable"; - if (!xs_write(s->xsh, XBT_NULL, path, cmd, strlen(cmd))) { - s->errstr = "error signalling qemu logdirty"; - return 1; - } - - vec = xs_read_watch(s->xsh, &len); - free(vec); - - strcpy(tail, "ret"); - xs_unwatch(s->xsh, path, "qemu-logdirty-ret"); - - response = xs_read(s->xsh, XBT_NULL, path, &len); - if (!len || strcmp(response, cmd)) { - if (len) - free(response); - s->errstr = "qemu logdirty command failed"; - return 1; - } - free(response); - fprintf(stderr, "qemu logdirty mode: %s\n", cmd); - - return 0; -} - -static int suspend_hvm(checkpoint_state *s) -{ - int rc = -1; - - fprintf(stderr, "issuing HVM suspend hypercall\n"); - rc = xc_domain_shutdown(s->xch, s->domid, SHUTDOWN_suspend); - if (rc < 0) { - s->errstr = "shutdown hypercall failed"; - return -1; - } - fprintf(stderr, "suspend hypercall returned %d\n", rc); - - if (check_shutdown(s) != 1) - return -1; - - rc = suspend_qemu(s); - - return rc; -} - -static int suspend_qemu(checkpoint_state *s) -{ - char path[128]; - - fprintf(stderr, "pausing QEMU\n"); - - sprintf(path, "/local/domain/0/device-model/%d/command", s->domid); - if (!xs_write(s->xsh, XBT_NULL, path, "save", 4)) { - fprintf(stderr, "error signalling QEMU to save\n"); - return -1; - } - - sprintf(path, "/local/domain/0/device-model/%d/state", s->domid); - - do { - char* state; - unsigned int len; - - state = xs_read(s->xsh, XBT_NULL, path, &len); - if (!state) { - s->errstr = "error reading QEMU state"; - return -1; - } - - if (!strcmp(state, "paused")) { - free(state); - return 0; - } - - free(state); - usleep(1000); - } while(1); - - return -1; -} - -static int resume_qemu(checkpoint_state *s) -{ - char path[128]; - fprintf(stderr, "resuming QEMU\n"); - - sprintf(path, "/local/domain/0/device-model/%d/command", s->domid); - if (!xs_write(s->xsh, XBT_NULL, path, "continue", 8)) { - fprintf(stderr, "error signalling QEMU to resume\n"); - return -1; - } - - return 0; -} - -static int send_qemu(checkpoint_state *s) -{ - char buf[8192]; - char path[128]; - struct stat sb; - uint32_t qlen = 0; - int qfd; - int rc; - - if (s->fd < 0) - return -1; - - sprintf(path, "/var/lib/xen/qemu-save.%d", s->domid); - - if (stat(path, &sb) < 0) { - snprintf(errbuf, sizeof(errbuf), - "error getting QEMU state file status: %s", strerror(errno)); - s->errstr = errbuf; - return -1; - } - - qlen = sb.st_size; - qfd = open(path, O_RDONLY); - if (qfd < 0) { - snprintf(errbuf, sizeof(errbuf), "error opening QEMU state file: %s", - strerror(errno)); - s->errstr = errbuf; - return -1; - } - - fprintf(stderr, "Sending %u bytes of QEMU state\n", qlen); - if (write(s->fd, "RemusDeviceModelState", 21) != 21) { - s->errstr = "error writing QEMU header"; - close(qfd); - return -1; - } - if (write(s->fd, &qlen, sizeof(qlen)) != sizeof(qlen)) { - s->errstr = "error writing QEMU size"; - close(qfd); - return -1; - } - - while ((rc = read(qfd, buf, qlen > sizeof(buf) ? sizeof(buf) : qlen)) > 0) { - qlen -= rc; - if (write(s->fd, buf, rc) != rc) { - rc = -1; - break; - } - } - if (rc < 0) { - snprintf(errbuf, sizeof(errbuf), "error writing QEMU state: %s", - strerror(errno)); - s->errstr = errbuf; - } - - close(qfd); - - return rc; -} - -/*thread responsible to suspend the domain early if necessary*/ -static void *suspend_thread(void *arg) -{ - checkpoint_state* s = (checkpoint_state*)arg; - sigset_t tss; - int rc; - int sig; - - fprintf(stderr, "Suspend thread started\n"); - - sigemptyset(&tss); - sigaddset(&tss, SIGRTMIN); - - while (1) { - /* wait for checkpoint thread to signal resume */ - if ((rc = sem_wait(&s->resumed_sem))) - fprintf(stderr, "Error waiting on resume semaphore\n"); - - if ((rc = sigwait(&tss, &sig))) { - fprintf(stderr, "sigwait failed: %d %d\n", rc, errno); - break; - } - if (sig != SIGRTMIN) - fprintf(stderr, "received unexpected signal %d\n", sig); - - if (s->done) - break; - - if (s->suspended) { - fprintf(stderr, "domain already suspended?\n"); - } else { - rc = checkpoint_suspend(s); - if (rc) - s->suspended = 1; - else - fprintf(stderr, "checkpoint_suspend failed\n"); - } - - if ((rc = sem_post(&s->suspended_sem))) - fprintf(stderr, "Error posting suspend semaphore\n"); - } - - fprintf(stderr, "Suspend thread exiting\n"); - - return NULL; -} - -static int create_suspend_timer(checkpoint_state* s) -{ - struct sigevent event; - int err; - - event.sigev_notify = SIGEV_SIGNAL; - event.sigev_signo = SIGRTMIN; - event.sigev_value.sival_int = 0; - - if ((err = timer_create(CLOCK_REALTIME, &event, &s->timer))) { - snprintf(errbuf, sizeof(errbuf), "Error creating timer: %d\n", err); - s->errstr = errbuf; - return -1; - } - - return 0; -} - -void block_timer(void) -{ - sigset_t tss; - - sigemptyset(&tss); - sigaddset(&tss, SIGRTMIN); - - pthread_sigmask(SIG_BLOCK, &tss, NULL); -} - -void unblock_timer(void) -{ - sigset_t tss; - - sigemptyset(&tss); - sigaddset(&tss, SIGRTMIN); - - pthread_sigmask(SIG_UNBLOCK, &tss, NULL); -} - -static int create_suspend_thread(checkpoint_state* s) -{ - int err; - - if ((err = sem_init(&s->suspended_sem, 0, 0))) { - snprintf(errbuf, sizeof(errbuf), - "Error initializing suspend semaphore: %d\n", err); - s->errstr = errbuf; - return -1; - } - - if ((err = sem_init(&s->resumed_sem, 0, 0))) { - snprintf(errbuf, sizeof(errbuf), - "Error initializing resume semaphore: %d\n", err); - s->errstr = errbuf; - return -1; - } - - /* signal mask should be inherited */ - block_timer(); - - if ((err = pthread_create(&s->suspend_thr, NULL, suspend_thread, s))) { - snprintf(errbuf, sizeof(errbuf), "Error creating suspend thread: %d\n", err); - s->errstr = errbuf; - return -1; - } - - return 0; -} - -static void stop_suspend_thread(checkpoint_state* s) -{ - int err; - - s->done = 1; - - err = sem_post(&s->resumed_sem); - - err = pthread_join(s->suspend_thr, NULL); - s->suspend_thr = 0; -} diff --git a/tools/python/xen/lowlevel/flask/flask.c b/tools/python/xen/lowlevel/flask/flask.c deleted file mode 100644 index c3fcf3b853..0000000000 --- a/tools/python/xen/lowlevel/flask/flask.c +++ /dev/null @@ -1,292 +0,0 @@ -/****************************************************************************** - * flask.c - * - * Authors: George Coker, - * Michael LeMay, - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2, - * as published by the Free Software Foundation. - */ - -#include -#include - -#define PKG "xen.lowlevel.flask" -#define CLS "flask" - -#define CTX_LEN 1024 - -static PyObject *xc_error_obj; - -typedef struct { - PyObject_HEAD; - xc_interface *xc_handle; -} XcObject; - -static PyObject *pyflask_context_to_sid(PyObject *self, PyObject *args, - PyObject *kwds) -{ - xc_interface *xc_handle; - char *ctx; - char *buf; - uint32_t len; - uint32_t sid; - int ret; - - static char *kwd_list[] = { "context", NULL }; - - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "s", kwd_list, - &ctx) ) - return NULL; - - len = strlen(ctx); - - buf = malloc(len); - if (!buf) { - errno = -ENOMEM; - PyErr_SetFromErrno(xc_error_obj); - } - - memcpy(buf, ctx, len); - - xc_handle = xc_interface_open(0,0,0); - if (!xc_handle) { - free(buf); - return PyErr_SetFromErrno(xc_error_obj); - } - - ret = xc_flask_context_to_sid(xc_handle, buf, len, &sid); - - xc_interface_close(xc_handle); - - free(buf); - - if ( ret != 0 ) { - errno = -ret; - return PyErr_SetFromErrno(xc_error_obj); - } - - return PyInt_FromLong(sid); -} - -static PyObject *pyflask_sid_to_context(PyObject *self, PyObject *args, - PyObject *kwds) -{ - xc_interface *xc_handle; - uint32_t sid; - char ctx[CTX_LEN]; - uint32_t ctx_len = CTX_LEN; - int ret; - - static char *kwd_list[] = { "sid", NULL }; - - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, - &sid) ) - return NULL; - - xc_handle = xc_interface_open(0,0,0); - if (!xc_handle) { - return PyErr_SetFromErrno(xc_error_obj); - } - - ret = xc_flask_sid_to_context(xc_handle, sid, ctx, ctx_len); - - xc_interface_close(xc_handle); - - if ( ret != 0 ) { - errno = -ret; - return PyErr_SetFromErrno(xc_error_obj); - } - - return Py_BuildValue("s", ctx, ctx_len); -} - -static PyObject *pyflask_load(PyObject *self, PyObject *args, PyObject *kwds) -{ - xc_interface *xc_handle; - char *policy; - uint32_t len; - int ret; - - static char *kwd_list[] = { "policy", NULL }; - - if( !PyArg_ParseTupleAndKeywords(args, kwds, "s#", kwd_list, &policy, &len) ) - return NULL; - - xc_handle = xc_interface_open(0,0,0); - if (!xc_handle) { - return PyErr_SetFromErrno(xc_error_obj); - } - - ret = xc_flask_load(xc_handle, policy, len); - - xc_interface_close(xc_handle); - - if ( ret != 0 ) { - errno = -ret; - return PyErr_SetFromErrno(xc_error_obj); - } - - return Py_BuildValue("i", ret); -} - -static PyObject *pyflask_getenforce(PyObject *self) -{ - xc_interface *xc_handle; - int ret; - - xc_handle = xc_interface_open(0,0,0); - if (!xc_handle) { - return PyErr_SetFromErrno(xc_error_obj); - } - - ret = xc_flask_getenforce(xc_handle); - - xc_interface_close(xc_handle); - - if ( ret < 0 ) { - errno = -ret; - return PyErr_SetFromErrno(xc_error_obj); - } - - return Py_BuildValue("i", ret); -} - -static PyObject *pyflask_setenforce(PyObject *self, PyObject *args, - PyObject *kwds) -{ - xc_interface *xc_handle; - int mode; - int ret; - - static char *kwd_list[] = { "mode", NULL }; - - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, - &mode) ) - return NULL; - - xc_handle = xc_interface_open(0,0,0); - if (!xc_handle) { - return PyErr_SetFromErrno(xc_error_obj); - } - - ret = xc_flask_setenforce(xc_handle, mode); - - xc_interface_close(xc_handle); - - if ( ret != 0 ) { - errno = -ret; - return PyErr_SetFromErrno(xc_error_obj); - } - - return Py_BuildValue("i", ret); -} - -static PyObject *pyflask_access(PyObject *self, PyObject *args, - PyObject *kwds) -{ - xc_interface *xc_handle; - char *tcon, *scon; - uint16_t tclass; - uint32_t req, allowed, decided, auditallow, auditdeny, seqno; - int ret; - - static char *kwd_list[] = { "src_context", "tar_context", - "tar_class", "req_permissions", - "decided", "auditallow","auditdeny", - "seqno", NULL }; - - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ssil|llll", kwd_list, - &scon, &tcon, &tclass, &req, &decided, - &auditallow, &auditdeny, &seqno) ) - return NULL; - - xc_handle = xc_interface_open(0,0,0); - if (!xc_handle) { - return PyErr_SetFromErrno(xc_error_obj); - } - - ret = xc_flask_access(xc_handle, scon, tcon, tclass, req, &allowed, &decided, - &auditallow, &auditdeny, &seqno); - - xc_interface_close(xc_handle); - - if ( ret != 0 ) { - errno = -ret; - return PyErr_SetFromErrno(xc_error_obj); - } - - return Py_BuildValue("i",ret); -} - -static PyMethodDef pyflask_methods[] = { - { "flask_context_to_sid", - (PyCFunction)pyflask_context_to_sid, - METH_KEYWORDS, "\n" - "Convert a context string to a dynamic SID.\n" - " context [str]: String specifying context to be converted\n" - "Returns: [int]: Numeric SID on success; -1 on error.\n" }, - - { "flask_sid_to_context", - (PyCFunction)pyflask_sid_to_context, - METH_KEYWORDS, "\n" - "Convert a dynamic SID to context string.\n" - " context [int]: SID to be converted\n" - "Returns: [str]: Numeric SID on success; -1 on error.\n" }, - - { "flask_load", - (PyCFunction)pyflask_load, - METH_KEYWORDS, "\n" - "Loads a policy into the hypervisor.\n" - " policy [str]: policy to be load\n" - "Returns: [int]: 0 on success; -1 on failure.\n" }, - - { "flask_getenforce", - (PyCFunction)pyflask_getenforce, - METH_NOARGS, "\n" - "Returns the current mode of the Flask XSM module.\n" - "Returns: [int]: 0 for permissive; 1 for enforcing; -1 on failure.\n" }, - - { "flask_setenforce", - (PyCFunction)pyflask_setenforce, - METH_KEYWORDS, "\n" - "Modifies the current mode for the Flask XSM module.\n" - " mode [int]: mode to change to\n" - "Returns: [int]: 0 on success; -1 on failure.\n" }, - - { "flask_access", - (PyCFunction)pyflask_access, - METH_KEYWORDS, "\n" - "Returns whether a source context has access to target context based on \ - class and permissions requested.\n" - " scon [str]: source context\n" - " tcon [str]: target context\n" - " tclass [int]: target security class\n" - " req [int] requested permissions\n" - " allowed [int] permissions allow for the target class between the source \ - and target context\n" - " decided [int] the permissions that were returned in the allowed \ - parameter\n" - " auditallow [int] permissions set to audit on allow\n" - " auditdeny [int] permissions set to audit on deny\n" - " seqno [int] not used\n" - "Returns: [int]: 0 on all permission granted; -1 if any permissions are \ - denied\n" }, - { NULL, NULL, 0, NULL } - -}; - -PyMODINIT_FUNC initflask(void) -{ - Py_InitModule("flask", pyflask_methods); -} - - -/* - * Local variables: - * c-indent-level: 4 - * c-basic-offset: 4 - * End: - */ diff --git a/tools/python/xen/lowlevel/netlink/libnetlink.c b/tools/python/xen/lowlevel/netlink/libnetlink.c deleted file mode 100644 index c5fc0bf46b..0000000000 --- a/tools/python/xen/lowlevel/netlink/libnetlink.c +++ /dev/null @@ -1,585 +0,0 @@ -/* - * libnetlink.c RTnetlink service routines. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Authors: Alexey Kuznetsov, - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libnetlink.h" - -void rtnl_close(struct rtnl_handle *rth) -{ - close(rth->fd); -} - -int rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions, - int protocol) -{ - socklen_t addr_len; - int sndbuf = 32768; - int rcvbuf = 32768; - - memset(rth, 0, sizeof(*rth)); - - rth->fd = socket(AF_NETLINK, SOCK_RAW, protocol); - if (rth->fd < 0) { - perror("Cannot open netlink socket"); - return -1; - } - - if (setsockopt(rth->fd,SOL_SOCKET,SO_SNDBUF,&sndbuf,sizeof(sndbuf)) < 0) { - perror("SO_SNDBUF"); - return -1; - } - - if (setsockopt(rth->fd,SOL_SOCKET,SO_RCVBUF,&rcvbuf,sizeof(rcvbuf)) < 0) { - perror("SO_RCVBUF"); - return -1; - } - - memset(&rth->local, 0, sizeof(rth->local)); - rth->local.nl_family = AF_NETLINK; - rth->local.nl_groups = subscriptions; - - if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) { - perror("Cannot bind netlink socket"); - return -1; - } - addr_len = sizeof(rth->local); - if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) { - perror("Cannot getsockname"); - return -1; - } - if (addr_len != sizeof(rth->local)) { - fprintf(stderr, "Wrong address length %d\n", addr_len); - return -1; - } - if (rth->local.nl_family != AF_NETLINK) { - fprintf(stderr, "Wrong address family %d\n", rth->local.nl_family); - return -1; - } - rth->seq = time(NULL); - return 0; -} - -int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions) -{ - return rtnl_open_byproto(rth, subscriptions, NETLINK_ROUTE); -} - -int rtnl_wilddump_request(struct rtnl_handle *rth, int family, int type) -{ - struct { - struct nlmsghdr nlh; - struct rtgenmsg g; - } req; - struct sockaddr_nl nladdr; - - memset(&nladdr, 0, sizeof(nladdr)); - nladdr.nl_family = AF_NETLINK; - - memset(&req, 0, sizeof(req)); - req.nlh.nlmsg_len = sizeof(req); - req.nlh.nlmsg_type = type; - req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST; - req.nlh.nlmsg_pid = 0; - req.nlh.nlmsg_seq = rth->dump = ++rth->seq; - req.g.rtgen_family = family; - - return sendto(rth->fd, (void*)&req, sizeof(req), 0, - (struct sockaddr*)&nladdr, sizeof(nladdr)); -} - -int rtnl_send(struct rtnl_handle *rth, const char *buf, int len) -{ - struct sockaddr_nl nladdr; - - memset(&nladdr, 0, sizeof(nladdr)); - nladdr.nl_family = AF_NETLINK; - - return sendto(rth->fd, buf, len, 0, (struct sockaddr*)&nladdr, sizeof(nladdr)); -} - -int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len) -{ - struct nlmsghdr nlh; - struct sockaddr_nl nladdr; - struct iovec iov[2] = { - { .iov_base = &nlh, .iov_len = sizeof(nlh) }, - { .iov_base = req, .iov_len = len } - }; - struct msghdr msg = { - .msg_name = &nladdr, - .msg_namelen = sizeof(nladdr), - .msg_iov = iov, - .msg_iovlen = 2, - }; - - memset(&nladdr, 0, sizeof(nladdr)); - nladdr.nl_family = AF_NETLINK; - - nlh.nlmsg_len = NLMSG_LENGTH(len); - nlh.nlmsg_type = type; - nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST; - nlh.nlmsg_pid = 0; - nlh.nlmsg_seq = rth->dump = ++rth->seq; - - return sendmsg(rth->fd, &msg, 0); -} - -int rtnl_dump_filter(struct rtnl_handle *rth, - rtnl_filter_t filter, - void *arg1, - rtnl_filter_t junk, - void *arg2) -{ - struct sockaddr_nl nladdr; - struct iovec iov; - struct msghdr msg = { - .msg_name = &nladdr, - .msg_namelen = sizeof(nladdr), - .msg_iov = &iov, - .msg_iovlen = 1, - }; - char buf[16384]; - - iov.iov_base = buf; - while (1) { - int status; - struct nlmsghdr *h; - - iov.iov_len = sizeof(buf); - status = recvmsg(rth->fd, &msg, 0); - - if (status < 0) { - if (errno == EINTR) - continue; - perror("OVERRUN"); - continue; - } - - if (status == 0) { - fprintf(stderr, "EOF on netlink\n"); - return -1; - } - - h = (struct nlmsghdr*)buf; - while (NLMSG_OK(h, status)) { - int err; - - if (nladdr.nl_pid != 0 || - h->nlmsg_pid != rth->local.nl_pid || - h->nlmsg_seq != rth->dump) { - if (junk) { - err = junk(&nladdr, h, arg2); - if (err < 0) - return err; - } - goto skip_it; - } - - if (h->nlmsg_type == NLMSG_DONE) - return 0; - if (h->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); - if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) { - fprintf(stderr, "ERROR truncated\n"); - } else { - errno = -err->error; - perror("RTNETLINK answers"); - } - return -1; - } - err = filter(&nladdr, h, arg1); - if (err < 0) - return err; - -skip_it: - h = NLMSG_NEXT(h, status); - } - if (msg.msg_flags & MSG_TRUNC) { - fprintf(stderr, "Message truncated\n"); - continue; - } - if (status) { - fprintf(stderr, "!!!Remnant of size %d\n", status); - exit(1); - } - } -} - -int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, - unsigned groups, struct nlmsghdr *answer, - rtnl_filter_t junk, - void *jarg) -{ - int status; - unsigned seq; - struct nlmsghdr *h; - struct sockaddr_nl nladdr; - struct iovec iov = { - .iov_base = (void*) n, - .iov_len = n->nlmsg_len - }; - struct msghdr msg = { - .msg_name = &nladdr, - .msg_namelen = sizeof(nladdr), - .msg_iov = &iov, - .msg_iovlen = 1, - }; - char buf[16384]; - - memset(&nladdr, 0, sizeof(nladdr)); - nladdr.nl_family = AF_NETLINK; - nladdr.nl_pid = peer; - nladdr.nl_groups = groups; - - n->nlmsg_seq = seq = ++rtnl->seq; - - if (answer == NULL) - n->nlmsg_flags |= NLM_F_ACK; - - status = sendmsg(rtnl->fd, &msg, 0); - - if (status < 0) { - perror("Cannot talk to rtnetlink"); - return -1; - } - - memset(buf,0,sizeof(buf)); - - iov.iov_base = buf; - - while (1) { - iov.iov_len = sizeof(buf); - status = recvmsg(rtnl->fd, &msg, 0); - - if (status < 0) { - if (errno == EINTR) - continue; - perror("OVERRUN"); - continue; - } - if (status == 0) { - fprintf(stderr, "EOF on netlink\n"); - return -1; - } - if (msg.msg_namelen != sizeof(nladdr)) { - fprintf(stderr, "sender address length == %d\n", msg.msg_namelen); - exit(1); - } - for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) { - int err; - int len = h->nlmsg_len; - int l = len - sizeof(*h); - - if (l<0 || len>status) { - if (msg.msg_flags & MSG_TRUNC) { - fprintf(stderr, "Truncated message\n"); - return -1; - } - fprintf(stderr, "!!!malformed message: len=%d\n", len); - exit(1); - } - - if (nladdr.nl_pid != peer || - h->nlmsg_pid != rtnl->local.nl_pid || - h->nlmsg_seq != seq) { - if (junk) { - err = junk(&nladdr, h, jarg); - if (err < 0) - return err; - } - continue; - } - - if (h->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); - if (l < sizeof(struct nlmsgerr)) { - fprintf(stderr, "ERROR truncated\n"); - } else { - errno = -err->error; - if (errno == 0) { - if (answer) - memcpy(answer, h, h->nlmsg_len); - return 0; - } - perror("RTNETLINK answers"); - } - return -1; - } - if (answer) { - memcpy(answer, h, h->nlmsg_len); - return 0; - } - - fprintf(stderr, "Unexpected reply!!!\n"); - - status -= NLMSG_ALIGN(len); - h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); - } - if (msg.msg_flags & MSG_TRUNC) { - fprintf(stderr, "Message truncated\n"); - continue; - } - if (status) { - fprintf(stderr, "!!!Remnant of size %d\n", status); - exit(1); - } - } -} - -int rtnl_listen(struct rtnl_handle *rtnl, - rtnl_filter_t handler, - void *jarg) -{ - int status; - struct nlmsghdr *h; - struct sockaddr_nl nladdr; - struct iovec iov; - struct msghdr msg = { - .msg_name = &nladdr, - .msg_namelen = sizeof(nladdr), - .msg_iov = &iov, - .msg_iovlen = 1, - }; - char buf[8192]; - - memset(&nladdr, 0, sizeof(nladdr)); - nladdr.nl_family = AF_NETLINK; - nladdr.nl_pid = 0; - nladdr.nl_groups = 0; - - iov.iov_base = buf; - while (1) { - iov.iov_len = sizeof(buf); - status = recvmsg(rtnl->fd, &msg, 0); - - if (status < 0) { - if (errno == EINTR) - continue; - perror("OVERRUN"); - continue; - } - if (status == 0) { - fprintf(stderr, "EOF on netlink\n"); - return -1; - } - if (msg.msg_namelen != sizeof(nladdr)) { - fprintf(stderr, "Sender address length == %d\n", msg.msg_namelen); - exit(1); - } - for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) { - int err; - int len = h->nlmsg_len; - int l = len - sizeof(*h); - - if (l<0 || len>status) { - if (msg.msg_flags & MSG_TRUNC) { - fprintf(stderr, "Truncated message\n"); - return -1; - } - fprintf(stderr, "!!!malformed message: len=%d\n", len); - exit(1); - } - - err = handler(&nladdr, h, jarg); - if (err < 0) - return err; - - status -= NLMSG_ALIGN(len); - h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); - } - if (msg.msg_flags & MSG_TRUNC) { - fprintf(stderr, "Message truncated\n"); - continue; - } - if (status) { - fprintf(stderr, "!!!Remnant of size %d\n", status); - exit(1); - } - } -} - -int rtnl_from_file(FILE *rtnl, rtnl_filter_t handler, - void *jarg) -{ - int status; - struct sockaddr_nl nladdr; - char buf[8192]; - struct nlmsghdr *h = (void*)buf; - - memset(&nladdr, 0, sizeof(nladdr)); - nladdr.nl_family = AF_NETLINK; - nladdr.nl_pid = 0; - nladdr.nl_groups = 0; - - while (1) { - int err, len, type; - int l; - - status = fread(&buf, 1, sizeof(*h), rtnl); - - if (status < 0) { - if (errno == EINTR) - continue; - perror("rtnl_from_file: fread"); - return -1; - } - if (status == 0) - return 0; - - len = h->nlmsg_len; - type= h->nlmsg_type; - l = len - sizeof(*h); - - if (l<0 || len>sizeof(buf)) { - fprintf(stderr, "!!!malformed message: len=%d @%lu\n", - len, ftell(rtnl)); - return -1; - } - - status = fread(NLMSG_DATA(h), 1, NLMSG_ALIGN(l), rtnl); - - if (status < 0) { - perror("rtnl_from_file: fread"); - return -1; - } - if (status < l) { - fprintf(stderr, "rtnl-from_file: truncated message\n"); - return -1; - } - - err = handler(&nladdr, h, jarg); - if (err < 0) - return err; - } -} - -int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data) -{ - int len = RTA_LENGTH(4); - struct rtattr *rta; - if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) { - fprintf(stderr,"addattr32: Error! max allowed bound %d exceeded\n",maxlen); - return -1; - } - rta = NLMSG_TAIL(n); - rta->rta_type = type; - rta->rta_len = len; - memcpy(RTA_DATA(rta), &data, 4); - n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len; - return 0; -} - -int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, - int alen) -{ - int len = RTA_LENGTH(alen); - struct rtattr *rta; - - if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) { - fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n",maxlen); - return -1; - } - rta = NLMSG_TAIL(n); - rta->rta_type = type; - rta->rta_len = len; - memcpy(RTA_DATA(rta), data, alen); - n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); - return 0; -} - -int addraw_l(struct nlmsghdr *n, int maxlen, const void *data, int len) -{ - if (NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len) > maxlen) { - fprintf(stderr, "addraw_l ERROR: message exceeded bound of %d\n",maxlen); - return -1; - } - - memcpy(NLMSG_TAIL(n), data, len); - memset((void *) NLMSG_TAIL(n) + len, 0, NLMSG_ALIGN(len) - len); - n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len); - return 0; -} - -int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data) -{ - int len = RTA_LENGTH(4); - struct rtattr *subrta; - - if (RTA_ALIGN(rta->rta_len) + len > maxlen) { - fprintf(stderr,"rta_addattr32: Error! max allowed bound %d exceeded\n",maxlen); - return -1; - } - subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len)); - subrta->rta_type = type; - subrta->rta_len = len; - memcpy(RTA_DATA(subrta), &data, 4); - rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len; - return 0; -} - -int rta_addattr_l(struct rtattr *rta, int maxlen, int type, - const void *data, int alen) -{ - struct rtattr *subrta; - int len = RTA_LENGTH(alen); - - if (RTA_ALIGN(rta->rta_len) + RTA_ALIGN(len) > maxlen) { - fprintf(stderr,"rta_addattr_l: Error! max allowed bound %d exceeded\n",maxlen); - return -1; - } - subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len)); - subrta->rta_type = type; - subrta->rta_len = len; - memcpy(RTA_DATA(subrta), data, alen); - rta->rta_len = NLMSG_ALIGN(rta->rta_len) + RTA_ALIGN(len); - return 0; -} - -int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) -{ - memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); - while (RTA_OK(rta, len)) { - if (rta->rta_type <= max) - tb[rta->rta_type] = rta; - rta = RTA_NEXT(rta,len); - } - if (len) - fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len); - return 0; -} - -int parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len) -{ - int i = 0; - - memset(tb, 0, sizeof(struct rtattr *) * max); - while (RTA_OK(rta, len)) { - if (rta->rta_type <= max && i < max) - tb[i++] = rta; - rta = RTA_NEXT(rta,len); - } - if (len) - fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len); - return i; -} diff --git a/tools/python/xen/lowlevel/netlink/libnetlink.h b/tools/python/xen/lowlevel/netlink/libnetlink.h deleted file mode 100644 index 8a4e6c63a6..0000000000 --- a/tools/python/xen/lowlevel/netlink/libnetlink.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef __LIBNETLINK_H__ -#define __LIBNETLINK_H__ 1 - -#include -#include -#include -#include - -struct rtnl_handle -{ - int fd; - struct sockaddr_nl local; - struct sockaddr_nl peer; - __u32 seq; - __u32 dump; -}; - -extern int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions); -extern int rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions, int protocol); -extern void rtnl_close(struct rtnl_handle *rth); -extern int rtnl_wilddump_request(struct rtnl_handle *rth, int fam, int type); -extern int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len); - -typedef int (*rtnl_filter_t)(const struct sockaddr_nl *, - struct nlmsghdr *n, void *); -extern int rtnl_dump_filter(struct rtnl_handle *rth, rtnl_filter_t filter, - void *arg1, - rtnl_filter_t junk, - void *arg2); -extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, - unsigned groups, struct nlmsghdr *answer, - rtnl_filter_t junk, - void *jarg); -extern int rtnl_send(struct rtnl_handle *rth, const char *buf, int); - - -extern int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data); -extern int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, int alen); -extern int addraw_l(struct nlmsghdr *n, int maxlen, const void *data, int len); -extern int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data); -extern int rta_addattr_l(struct rtattr *rta, int maxlen, int type, const void *data, int alen); - -extern int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len); -extern int parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len); - -#define parse_rtattr_nested(tb, max, rta) \ - (parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta))) - -extern int rtnl_listen(struct rtnl_handle *, rtnl_filter_t handler, - void *jarg); -extern int rtnl_from_file(FILE *, rtnl_filter_t handler, - void *jarg); - -#define NLMSG_TAIL(nmsg) \ - ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) - -#endif /* __LIBNETLINK_H__ */ - diff --git a/tools/python/xen/lowlevel/netlink/netlink.c b/tools/python/xen/lowlevel/netlink/netlink.c deleted file mode 100644 index c48b8e4990..0000000000 --- a/tools/python/xen/lowlevel/netlink/netlink.c +++ /dev/null @@ -1,215 +0,0 @@ -/* python binding to libnetlink */ - -#include -#include "libnetlink.h" - -#define PKG "xen.lowlevel.netlink" - -typedef struct { - PyObject_HEAD - int opened; - struct rtnl_handle rth; -} PyRtnlObject; - -/* todo: subscriptions? */ -static PyObject* PyRtnl_new(PyTypeObject* type, PyObject* args, - PyObject* kwargs) -{ - return type->tp_alloc(type, 0); -} - -static int PyRtnl_init(PyObject* obj, PyObject* args, PyObject* kwargs) -{ - PyRtnlObject* self = (PyRtnlObject*)obj; - - if (rtnl_open(&self->rth, 0) < 0) { - PyErr_SetString(PyExc_IOError, "could not open rtnl handle"); - return -1; - } - - return 0; -} - -static void PyRtnl_dealloc(PyRtnlObject* obj) -{ - PyRtnlObject* self = (PyRtnlObject*)obj; - - rtnl_close(&self->rth); -} - -static PyObject* pyrtnl_talk(PyObject* obj, PyObject* args) -{ - PyRtnlObject* self = (PyRtnlObject*)obj; - char* msg; - int len; - int peer = 0; - int groups = 0; - - if (!PyArg_ParseTuple(args, "s#|ii", &msg, &len, &peer, &groups)) - return NULL; - - if (rtnl_talk(&self->rth, (struct nlmsghdr*)msg, peer, groups, NULL, NULL, - NULL) < 0) - { - PyErr_SetString(PyExc_IOError, "error sending message"); - return NULL; - } - - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject* pyrtnl_wilddump_request(PyObject* obj, PyObject* args) -{ - PyRtnlObject* self = (PyRtnlObject*)obj; - int family, type; - - if (!PyArg_ParseTuple(args, "ii", &family, &type)) - return NULL; - - if (rtnl_wilddump_request(&self->rth, family, type) < 0) { - PyErr_SetString(PyExc_IOError, "could not send dump request"); - return NULL; - } - - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject* pyrtnl_dump_request(PyObject* obj, PyObject* args) -{ - PyRtnlObject* self = (PyRtnlObject*)obj; - int type; - char* req; - int len; - - if (!PyArg_ParseTuple(args, "is#", &type, &req, &len)) - return NULL; - - if (rtnl_dump_request(&self->rth, type, req, len) < 0) { - PyErr_SetString(PyExc_IOError, "could not send dump request"); - return NULL; - } - - Py_INCREF(Py_None); - return Py_None; -} - -/* translate args to python and call python callback */ -static int dump_filter_helper(const struct sockaddr_nl *who, - struct nlmsghdr *n, void *arg) -{ - PyObject* filter = arg; - PyObject* args; - PyObject* result; - - args = Py_BuildValue("s#s#", who, sizeof(*who), n, n->nlmsg_len); - result = PyObject_CallObject(filter, args); - Py_DECREF(args); - if (!result) - return -1; - - /* result is ignored as long as an exception isn't raised */ - Py_DECREF(result); - return 0; -} - -static PyObject* pyrtnl_dump_filter(PyObject* obj, PyObject* args) -{ - PyRtnlObject* self = (PyRtnlObject*)obj; - PyObject *filter; - - if (!PyArg_ParseTuple(args, "O:dump_filter", &filter)) - return NULL; - - if (!PyCallable_Check(filter)) { - PyErr_SetString(PyExc_TypeError, "parameter must be callable"); - return NULL; - } - - Py_INCREF(filter); - if (rtnl_dump_filter(&self->rth, dump_filter_helper, filter, NULL, - NULL) < 0) - { - Py_DECREF(filter); - return NULL; - } - Py_DECREF(filter); - - Py_INCREF(Py_None); - return Py_None; -} - -static PyMethodDef PyRtnl_methods[] = { - { "talk", pyrtnl_talk, METH_VARARGS, - "send a message to rtnetlink and receive a response.\n" }, - { "wilddump_request", pyrtnl_wilddump_request, METH_VARARGS, - "dump objects.\n" }, - { "dump_request", pyrtnl_dump_request, METH_VARARGS, - "start a dump of a particular netlink type.\n" }, - { "dump_filter", pyrtnl_dump_filter, METH_VARARGS, - "iterate over an rtnl dump.\n" }, - { NULL } -}; - -static PyTypeObject PyRtnlType = { - PyObject_HEAD_INIT(NULL) - 0, /* ob_size */ - PKG ".rtnl", /* tp_name */ - sizeof(PyRtnlObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)PyRtnl_dealloc, /* tp_dealloc */ - NULL, /* tp_print */ - NULL, /* tp_getattr */ - NULL, /* tp_setattr */ - NULL, /* tp_compare */ - NULL, /* tp_repr */ - NULL, /* tp_as_number */ - NULL, /* tp_as_sequence */ - NULL, /* tp_as_mapping */ - NULL, /* tp_hash */ - NULL, /* tp_call */ - NULL, /* tp_str */ - NULL, /* tp_getattro */ - NULL, /* tp_setattro */ - NULL, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - "rtnetlink handle", /* tp_doc */ - NULL, /* tp_traverse */ - NULL, /* tp_clear */ - NULL, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - NULL, /* tp_iter */ - NULL, /* tp_iternext */ - PyRtnl_methods, /* tp_methods */ - NULL, /* tp_members */ - NULL, /* tp_getset */ - NULL, /* tp_base */ - NULL, /* tp_dict */ - NULL, /* tp_descr_get */ - NULL, /* tp_descr_set */ - 0, /* tp_dictoffset */ - PyRtnl_init, /* tp_init */ - NULL, /* tp_alloc */ - PyRtnl_new, /* tp_new */ -}; - -static PyMethodDef methods[] = { - { NULL } -}; - -static char doc[] = "libnetlink wrapper"; - -PyMODINIT_FUNC initnetlink(void) -{ - PyObject *mod; - - if (PyType_Ready(&PyRtnlType) == -1) - return; - - if (!(mod = Py_InitModule3(PKG, methods, doc))) - return; - - Py_INCREF(&PyRtnlType); - PyModule_AddObject(mod, "rtnl", (PyObject *)&PyRtnlType); -} diff --git a/tools/python/xen/lowlevel/process/process.c b/tools/python/xen/lowlevel/process/process.c deleted file mode 100644 index a1e71bcd4d..0000000000 --- a/tools/python/xen/lowlevel/process/process.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include - -#include -#include -#include -#include - -/* - * On Solaris, xend runs under a contract as an smf(5) service. As a - * result, when spawning long-running children such as a domain's - * qemu-dm instantiation, we have to make sure it's in a separate - * contract. Before we fork, we must activate a separate process - * contract template to place the child processes in a new contract. - */ - -static PyObject * -pyprocess_activate(PyObject *o, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "name", NULL }; - char *name = NULL; - int flags; - int cfd; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", kwlist, &name)) - return (NULL); - - cfd = open64("/system/contract/process/template", O_RDWR); - - if (cfd == -1) - goto err; - - if ((flags = fcntl(cfd, F_GETFD, 0)) == -1) - goto err; - - if (fcntl(cfd, F_SETFD, flags | FD_CLOEXEC) == -1) - goto err; - - if (name != NULL) - ct_pr_tmpl_set_svc_aux(cfd, name); - - if (ct_tmpl_activate(cfd)) - goto err; - - return (PyInt_FromLong((long)cfd)); - -err: - if (cfd != -1) - close(cfd); - PyErr_SetFromErrno(PyExc_OSError); - return (NULL); -} - -static PyObject * -pyprocess_clear(PyObject *o, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "contract", NULL }; - int cfd; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &cfd)) - return (NULL); - - if (ct_tmpl_clear(cfd) != 0) { - PyErr_SetFromErrno(PyExc_OSError); - return (NULL); - } - - close(cfd); - - Py_INCREF(Py_None); - return (Py_None); -} - -static PyObject * -pyprocess_abandon_latest(PyObject *o, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { NULL }; - static char path[PATH_MAX]; - ct_stathdl_t st; - ctid_t latest; - int cfd; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwlist)) - return (NULL); - - cfd = open64("/system/contract/process/latest", O_RDONLY); - if (cfd == -1) - goto err; - - ct_status_read(cfd, CTD_COMMON, &st); - latest = ct_status_get_id(st); - ct_status_free(st); - close(cfd); - - snprintf(path, PATH_MAX, "/system/contract/process/%ld/ctl", - (long)latest); - - if ((cfd = open64(path, O_WRONLY)) < 0) - goto err; - if (ct_ctl_abandon(cfd)) - goto err; - close(cfd); - - Py_INCREF(Py_None); - return (Py_None); -err: - PyErr_SetFromErrno(PyExc_OSError); - return (NULL); -} - -PyDoc_STRVAR(pyprocess_activate__doc__, - "activate(name)\n" - "\n" - "Activate a new process contract template. If name is given,\n" - "it is used as the template's auxiliary value.\n" - "Returns the new contract template.\n"); - -PyDoc_STRVAR(pyprocess_clear__doc__, - "clear(contract)\n" - "\n" - "Clear and close the given contract template.\n"); - -PyDoc_STRVAR(pyprocess_abandon_latest__doc__, - "abandon_latest()\n" - "\n" - "Abandon the latest contract created by this thread.\n"); - -static struct PyMethodDef pyprocess_module_methods[] = { - { "activate", (PyCFunction) pyprocess_activate, - METH_VARARGS|METH_KEYWORDS, pyprocess_activate__doc__ }, - { "clear", (PyCFunction) pyprocess_clear, - METH_VARARGS|METH_KEYWORDS, pyprocess_clear__doc__ }, - { "abandon_latest", (PyCFunction) pyprocess_abandon_latest, - METH_VARARGS|METH_KEYWORDS, pyprocess_abandon_latest__doc__ }, - { NULL, NULL, 0, NULL } -}; - -PyMODINIT_FUNC -initprocess(void) -{ - Py_InitModule("process", pyprocess_module_methods); -} diff --git a/tools/python/xen/lowlevel/scf/scf.c b/tools/python/xen/lowlevel/scf/scf.c deleted file mode 100644 index 22a79606c0..0000000000 --- a/tools/python/xen/lowlevel/scf/scf.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include - -#include -#include - -#define XEND_FMRI "svc:/system/xvm/xend:default" -#define XEND_PG "config" - -static PyObject *scf_exc; - -static void * -scf_exception(const char *err, const char *value) -{ - int scferr = scf_error(); - const char *scfstrerr = scf_strerror(scferr); - PyObject *obj = Py_BuildValue("(isss)", scferr, err, scfstrerr, value); - PyErr_SetObject(scf_exc, obj); - return (NULL); -} - -static PyObject * -pyscf_get_bool(PyObject *o, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "name", NULL }; - scf_simple_prop_t *prop; - uint8_t *val; - char *name; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name)) - return (NULL); - - prop = scf_simple_prop_get(NULL, XEND_FMRI, XEND_PG, name); - - if (prop == NULL) - return (scf_exception("scf_simple_prop_get() failed", name)); - - if ((val = scf_simple_prop_next_boolean(prop)) == NULL) - return (scf_exception("scf_simple_prop_next_boolean() failed", - name)); - - if (*val) { - scf_simple_prop_free(prop); - Py_INCREF(Py_True); - return (Py_True); - } - - scf_simple_prop_free(prop); - Py_INCREF(Py_False); - return (Py_False); -} - -static PyObject * -pyscf_get_int(PyObject *o, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "name", NULL }; - scf_simple_prop_t *prop; - PyObject *obj; - int64_t *val; - char *name; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name)) - return (NULL); - - prop = scf_simple_prop_get(NULL, XEND_FMRI, XEND_PG, name); - - if (prop == NULL) - return (scf_exception("scf_simple_prop_get() failed", name)); - - if ((val = scf_simple_prop_next_integer(prop)) == NULL) - return (scf_exception("scf_simple_prop_next_integer() failed", - name)); - - obj = PyInt_FromLong((long)*val); - scf_simple_prop_free(prop); - return (obj); -} - -static PyObject * -pyscf_get_string(PyObject *o, PyObject *args, PyObject *kwargs) -{ - static char *kwlist[] = { "name", NULL }; - scf_simple_prop_t *prop; - PyObject *obj; - char *name; - char *str; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name)) - return (NULL); - - prop = scf_simple_prop_get(NULL, XEND_FMRI, XEND_PG, name); - - if (prop == NULL) - return (scf_exception("scf_simple_prop_get() failed", name)); - - if ((str = scf_simple_prop_next_astring(prop)) == NULL) { - scf_simple_prop_free(prop); - return (scf_exception("scf_simple_prop_next_astring() failed", - name)); - } - - obj = PyString_FromString(str); - scf_simple_prop_free(prop); - return (obj); -} - -PyDoc_STRVAR(pyscf_get_bool__doc__, - "get_bool(name) - get the value of the named boolean property"); -PyDoc_STRVAR(pyscf_get_int__doc__, - "get_int(name) - get the value of the named integer property"); -PyDoc_STRVAR(pyscf_get_string__doc__, - "get_string(name) - get the value of the named string property"); - -static struct PyMethodDef pyscf_module_methods[] = { - { "get_bool", (PyCFunction) pyscf_get_bool, - METH_VARARGS|METH_KEYWORDS, pyscf_get_bool__doc__ }, - { "get_int", (PyCFunction) pyscf_get_int, - METH_VARARGS|METH_KEYWORDS, pyscf_get_int__doc__ }, - { "get_string", (PyCFunction) pyscf_get_string, - METH_VARARGS|METH_KEYWORDS, pyscf_get_string__doc__ }, - { NULL, NULL, 0, NULL } -}; - -PyMODINIT_FUNC -initscf(void) -{ - PyObject *m; - m = Py_InitModule("scf", pyscf_module_methods); - - scf_exc = PyErr_NewException("scf.error", NULL, NULL); - Py_INCREF(scf_exc); - PyModule_AddObject(m, "error", scf_exc); - PyModule_AddIntConstant(m, "SCF_ERROR_NOT_FOUND", SCF_ERROR_NOT_FOUND); -} diff --git a/tools/python/xen/remus/__init__.py b/tools/python/xen/remus/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tools/python/xen/remus/blkdev.py b/tools/python/xen/remus/blkdev.py deleted file mode 100644 index 6cd1fa2e4b..0000000000 --- a/tools/python/xen/remus/blkdev.py +++ /dev/null @@ -1,31 +0,0 @@ -handlers = [] - -class BlkDevException(Exception): pass - -class BlkDev(object): - "Object representing a VM block device" - def __init__(self, **props): - self.uname = '' - if 'dev' not in props: - raise BlkDevException('no device') - #if 'uname' not in props: - #raise BlkDevException('no uname') - if 'mode' not in props: - raise BlkDevException('no mode') - self.__dict__.update(props) - self.dev = props['dev'].rstrip(':disk') - - def __str__(self): - return '%s,%s,%s' % (self.uname, self.dev, self.mode) - -def register(handler): - "register a block device class with parser" - if handler not in handlers: - handlers.insert(0, handler) - -def parse(props): - "turn a vm device dictionary into a blkdev object" - for handler in handlers: - if handler.handles(**props): - return handler(**props) - return BlkDev(**props) diff --git a/tools/python/xen/remus/device.py b/tools/python/xen/remus/device.py deleted file mode 100644 index 970e1ead5f..0000000000 --- a/tools/python/xen/remus/device.py +++ /dev/null @@ -1,397 +0,0 @@ -# Remus device interface -# -# Coordinates with devices at suspend, resume, and commit hooks - -import os, re, fcntl - -import netlink, qdisc, util - -class ReplicatedDiskException(Exception): pass -class BufferedNICException(Exception): pass - -class CheckpointedDevice(object): - 'Base class for buffered devices' - - def postsuspend(self): - 'called after guest has suspended' - pass - - def preresume(self): - 'called before guest resumes' - pass - - def commit(self): - 'called when backup has acknowledged checkpoint reception' - pass - -class ReplicatedDisk(CheckpointedDevice): - """ - Send a checkpoint message to a replicated disk while the domain - is paused between epochs. - """ - FIFODIR = '/var/run/tap' - SEND_CHECKPOINT = 20 - WAIT_CHECKPOINT_ACK = 30 - - def __init__(self, disk): - # look up disk, make sure it is tap:buffer, and set up socket - # to request commits. - self.ctlfd = None - self.msgfd = None - self.is_drbd = False - self.ackwait = False - - if disk.uname.startswith('tap:remus:') or disk.uname.startswith('tap:tapdisk:remus:'): - fifo = re.match("tap:.*(remus.*)\|", disk.uname).group(1).replace(':', '_') - absfifo = os.path.join(self.FIFODIR, fifo) - absmsgfifo = absfifo + '.msg' - - self.installed = False - self.ctlfd = open(absfifo, 'w+b') - self.msgfd = open(absmsgfifo, 'r+b') - elif disk.uname.startswith('drbd:'): - #get the drbd device associated with this resource - drbdres = re.match("drbd:(.*)", disk.uname).group(1) - drbddev = util.runcmd("drbdadm sh-dev %s" % drbdres).rstrip() - - #check for remus supported drbd installation - rconf = util.runcmd("drbdsetup %s show" % drbddev) - if rconf.find('protocol D;') == -1: - raise ReplicatedDiskException('Remus support for DRBD disks requires the ' - 'resources to operate in protocol D. Please make ' - 'sure that you have installed the remus supported DRBD ' - 'version from git://aramis.nss.cs.ubc.ca/drbd-8.3-remus ' - 'and enabled protocol D in the resource config') - - #check if resource is in connected state - cstate = util.runcmd("drbdadm cstate %s" % drbdres).rstrip() - if cstate != 'Connected': - raise ReplicatedDiskException('DRBD resource %s is not in connected state!' - % drbdres) - - #open a handle to the resource so that we could issue chkpt ioctls - self.ctlfd = open(drbddev, 'r') - self.is_drbd = True - else: - raise ReplicatedDiskException('Disk is not replicated: %s' % - str(disk)) - - def __del__(self): - self.uninstall() - - def uninstall(self): - if self.ctlfd: - self.ctlfd.close() - self.ctlfd = None - - def postsuspend(self): - if not self.is_drbd: - os.write(self.ctlfd.fileno(), 'flush') - elif not self.ackwait: - if (fcntl.ioctl(self.ctlfd.fileno(), self.SEND_CHECKPOINT, 0) > 0): - self.ackwait = False - else: - self.ackwait = True - - def preresume(self): - if self.is_drbd and self.ackwait: - fcntl.ioctl(self.ctlfd.fileno(), self.WAIT_CHECKPOINT_ACK, 0) - self.ackwait = False - - def commit(self): - if not self.is_drbd: - msg = os.read(self.msgfd.fileno(), 4) - if msg != 'done': - print 'Unknown message: %s' % msg - -### Network - -# shared rtnl handle -_rth = None -def getrth(): - global _rth - - if not _rth: - _rth = netlink.rtnl() - return _rth - -class Netbuf(object): - "Proxy for netdev with a queueing discipline" - - @staticmethod - def devclass(): - "returns the name of this device class" - return 'unknown' - - @classmethod - def available(cls): - "returns True if this module can proxy the device" - return cls._hasdev(cls.devclass()) - - def __init__(self, devname): - self.devname = devname - self.vif = None - - # override in subclasses - def install(self, vif): - "set up proxy on device" - raise BufferedNICException('unimplemented') - - def uninstall(self): - "remove proxy on device" - raise BufferedNICException('unimplemented') - - # protected - @staticmethod - def _hasdev(devclass): - """check for existence of device, attempting to load kernel - module if not present""" - devname = '%s0' % devclass - rth = getrth() - - if rth.getlink(devname): - return True - if util.modprobe(devclass) and rth.getlink(devname): - return True - - return False - -class IFBBuffer(Netbuf): - """Capture packets arriving on a VIF using an ingress filter and tc - mirred action to forward them to an IFB device. - """ - - @staticmethod - def devclass(): - return 'ifb' - - def install(self, vif): - self.vif = vif - # voodoo from http://www.linuxfoundation.org/collaborate/workgroups/networking/ifb#Typical_Usage - util.runcmd('ip link set %s up' % self.devname) - try: - util.runcmd('tc qdisc add dev %s ingress' % vif.dev) - except util.PipeException, e: - # check if error indicates that ingress qdisc - # already exists on the vif. If so, ignore it. - ignoreme = 'RTNETLINK answers: File exists' - if ignoreme in str(e): - pass - else: - raise e - util.runcmd('tc filter add dev %s parent ffff: proto ip pref 10 ' - 'u32 match u32 0 0 action mirred egress redirect ' - 'dev %s' % (vif.dev, self.devname)) - - def uninstall(self): - try: - util.runcmd('tc qdisc del dev %s ingress' % self.vif.dev) - except util.PipeException, e: - pass - util.runcmd('ip link set %s down' % self.devname) - -class IMQBuffer(Netbuf): - """Redirect packets coming in on vif to an IMQ device.""" - - imqebt = '/usr/lib/xen/bin/imqebt' - - @staticmethod - def devclass(): - return 'imq' - - def install(self, vif): - # stopgap hack to set up IMQ for an interface. Wrong in many ways. - self.vif = vif - - for mod in ['imq', 'ebt_imq']: - util.runcmd(['modprobe', mod]) - util.runcmd("ip link set %s up" % self.devname) - util.runcmd("%s -F FORWARD" % self.imqebt) - util.runcmd("%s -A FORWARD -i %s -j imq --todev %s" % (self.imqebt, vif.dev, self.devname)) - - def uninstall(self): - util.runcmd("%s -F FORWARD" % self.imqebt) - util.runcmd('ip link set %s down' % self.devname) - -# in order of desirability -netbuftypes = [IFBBuffer, IMQBuffer] - -def selectnetbuf(): - "Find the best available buffer type" - for driver in netbuftypes: - if driver.available(): - return driver - - raise BufferedNICException('no net buffer available') - -class Netbufpool(object): - """Allocates/releases proxy netdevs (IMQ/IFB) - - A file contains a list of entries of the form :\n - To allocate a device, lock the file, then claim a new device if - one is free. If there are no free devices, check each PID for liveness - and take a device if the PID is dead, otherwise return failure. - Add an entry to the file before releasing the lock. - """ - def __init__(self, netbufclass): - "Create a pool of Device" - self.netbufclass = netbufclass - self.path = '/var/run/remus/' + self.netbufclass.devclass() - - self.devices = self.getdevs() - - pooldir = os.path.dirname(self.path) - if not os.path.exists(pooldir): - os.makedirs(pooldir, 0755) - - def get(self): - "allocate a free device" - def getfreedev(table): - for dev in self.devices: - if dev not in table or not util.checkpid(table[dev]): - return dev - - return None - - lock = util.Lock(self.path) - table = self.load() - - dev = getfreedev(table) - if not dev: - lock.unlock() - raise BufferedNICException('no free devices') - dev = self.netbufclass(dev) - - table[dev.devname] = os.getpid() - - self.save(table) - lock.unlock() - - return dev - - def put(self, dev): - "release claim on device" - lock = util.Lock(self.path) - table = self.load() - - del table[dev.devname] - - self.save(table) - lock.unlock() - - # private - def load(self): - """load and parse allocation table""" - table = {} - if not os.path.exists(self.path): - return table - - fd = open(self.path) - for line in fd.readlines(): - iface, pid = line.strip().split() - table[iface] = int(pid) - fd.close() - return table - - def save(self, table): - """write table to disk""" - lines = ['%s %d\n' % (iface, table[iface]) for iface in sorted(table)] - fd = open(self.path, 'w') - fd.writelines(lines) - fd.close() - - def getdevs(self): - """find all available devices of our device type""" - ifaces = [] - for line in util.runcmd('ifconfig -a -s').splitlines(): - iface = line.split()[0] - if iface.startswith(self.netbufclass.devclass()): - ifaces.append(iface) - - return ifaces - -class BufferedNIC(CheckpointedDevice): - """ - Buffer a protected domain's network output between rounds so that - nothing is issued that a failover might not know about. - """ - - def __init__(self, vif): - self.installed = False - self.vif = vif - - self.pool = Netbufpool(selectnetbuf()) - self.rth = getrth() - - self.setup() - - def __del__(self): - self.uninstall() - - def postsuspend(self): - if not self.installed: - self.install() - - self._sendqmsg(qdisc.TC_PLUG_BUFFER) - - def commit(self): - '''Called when checkpoint has been acknowledged by - the backup''' - self._sendqmsg(qdisc.TC_PLUG_RELEASE_ONE) - - # private - def _sendqmsg(self, action): - self.q.action = action - req = qdisc.changerequest(self.bufdevno, self.handle, self.q) - self.rth.talk(req.pack()) - return True - - def setup(self): - """install Remus plug on VIF outbound traffic""" - self.bufdev = self.pool.get() - - devname = self.bufdev.devname - bufdev = self.rth.getlink(devname) - if not bufdev: - raise BufferedNICException('could not find device %s' % devname) - - self.bufdev.install(self.vif) - - self.bufdevno = bufdev['index'] - self.handle = qdisc.TC_H_ROOT - self.q = qdisc.PlugQdisc() - - if not util.modprobe('sch_plug'): - raise BufferedNICException('could not load sch_plug module') - - def install(self): - devname = self.bufdev.devname - q = self.rth.getqdisc(self.bufdevno) - if q: - if q['kind'] == 'plug': - self.installed = True - return - if q['kind'] not in ('ingress', 'pfifo_fast', 'mq'): - raise BufferedNICException('there is already a queueing ' - 'discipline %s on %s' % (q['kind'], devname)) - - print ('installing buffer on %s... ' % devname), - req = qdisc.addrequest(self.bufdevno, self.handle, self.q) - self.rth.talk(req.pack()) - self.installed = True - print 'done.' - - def uninstall(self): - if self.installed: - try: - req = qdisc.delrequest(self.bufdevno, self.handle) - self.rth.talk(req.pack()) - except IOError, e: - pass - self.installed = False - - try: - self.bufdev.uninstall() - except util.PipeException, e: - pass - self.pool.put(self.bufdev) diff --git a/tools/python/xen/remus/image.py b/tools/python/xen/remus/image.py deleted file mode 100644 index b79d1e56b7..0000000000 --- a/tools/python/xen/remus/image.py +++ /dev/null @@ -1,227 +0,0 @@ -# VM image file manipulation - -import logging, struct - -import vm - -SIGNATURE = 'LinuxGuestRecord' -LONGLEN = struct.calcsize('L') -INTLEN = struct.calcsize('i') -PAGE_SIZE = 4096 -# ~0L -P2M_EXT_SIG = 4294967295L -# frames per page -FPP = 1024 -LTAB_MASK = 0xf << 28 -BATCH_SIZE = 1024 -IDXLEN = INTLEN + BATCH_SIZE * LONGLEN - -logging.basicConfig(level=logging.DEBUG) -log = logging.getLogger() - -class VMParseException(Exception): pass - -class VMImage(object): - def __init__(self, img=None): - """img may be a path or a file object. - If compact is True, apply checkpoints to base image instead - of simply concatenating them. - """ - self.img = img - - self.dom = None - self.fd = None - self.header = None - self.nr_pfns = 0 - # p2m extension header (unparsed) - self.p2mext = None - - if self.img: - self.open(self.img) - - def open(self, img): - if isinstance(img, str): - self.fd = file(img, 'rb') - else: - self.fd = img - - self.readheader() - - def readheader(self): - sig = self.fd.read(len(SIGNATURE)) - if sig != SIGNATURE: - raise VMParseException("Bad signature in image") - - hlen = self.fd.read(INTLEN) - hlen, = struct.unpack('!i', hlen) - - self.header = self.fd.read(hlen) - self.dom = parseheader(self.header) - - def readp2mfl(self): - "read the P2M frame list" - pfnlen = self.fd.read(LONGLEN) - self.nr_pfns, = struct.unpack('L', pfnlen) - p2m0 = self.fd.read(LONGLEN) - - p2mhdr = p2m0 - p2m0, = struct.unpack('L', p2m0) - if p2m0 == P2M_EXT_SIG: - elen = self.fd.read(INTLEN) - elen, = struct.unpack('I', elen) - - self.p2mext = self.fd.read(elen) - - p2m0 = self.fd.read(LONGLEN) - p2m0, = struct.unpack('L', p2m0) - p2mfl = [p2m0] - - p2mfle = (self.nr_pfns + FPP - 1)/FPP - 1 - p2ms = self.fd.read(LONGLEN * p2mfle) - p2mfl.extend(struct.unpack('%dL' % p2mfle, p2ms)) - - self.p2mfl = p2mfl - - def flush(self): - self.ofd.write(self.tail) - -class Writer(object): - """compress a stream of checkpoints into a single image of the - last checkpoint""" - def __init__(self, fd, compact=False): - self.fd = fd - self.compact = compact - - self.vm = None - self.tail = None - # offset to first batch of pages - self.imgstart = 0 - # PFN mappings - self.pfns = [] - - def __del__(self): - self.close() - - def writeheader(self): - hlen = struct.pack('!i', len(self.vm.header)) - header = ''.join([SIGNATURE, hlen, self.vm.header]) - self.fd.write(header) - - def writep2mfl(self): - p2m = [struct.pack('L', self.vm.nr_pfns)] - if self.vm.p2mext: - p2m.extend([struct.pack('L', P2M_EXT_SIG), self.vm.p2mext]) - p2m.append(struct.pack('%dL' % len(self.vm.p2mfl), *self.vm.p2mfl)) - self.fd.write(''.join(p2m)) - - def writebatch(self, batch): - def offset(pfn): - isz = (pfn / BATCH_SIZE + 1) * IDXLEN - return self.imgstart + isz + pfn * PAGE_SIZE - - if not self.compact: - return self.fd.write(batch) - - batch = parsebatch(batch) - # sort pages for better disk seek behaviour - batch.sort(lambda x, y: cmp(x[0] & ~LTAB_MASK, y[0] & ~LTAB_MASK)) - - for pfndesc, page in batch: - pfn = pfndesc & ~LTAB_MASK - if pfn > self.vm.nr_pfns: - log.error('INVALID PFN: %d' % pfn) - if len(self.pfns) <= pfn: - self.pfns.extend([0] * (pfn - len(self.pfns) + 1)) - self.pfns[pfn] = pfndesc - self.fd.seek(offset(pfn)) - self.fd.write(page) - - #print "max offset: %d, %d" % (len(self.pfns), offset(self.pfns[-1])) - - def writeindex(self): - "Write batch header in front of each page" - hdrlen = INTLEN + BATCH_SIZE * LONGLEN - batches = (len(self.pfns) + BATCH_SIZE - 1) / BATCH_SIZE - - for i in xrange(batches): - offset = self.imgstart + i * (hdrlen + (PAGE_SIZE * BATCH_SIZE)) - pfnoff = i * BATCH_SIZE - # python auto-clamps overreads - pfns = self.pfns[pfnoff:pfnoff + BATCH_SIZE] - - self.fd.seek(offset) - self.fd.write(struct.pack('i', len(pfns))) - self.fd.write(struct.pack('%dL' % len(pfns), *pfns)) - - def slurp(self, ifd): - """Apply an incremental checkpoint to a loaded image. - accepts a path or a file object.""" - if isinstance(ifd, str): - ifd = file(ifd, 'rb') - - if not self.vm: - self.vm = VMImage(ifd) - self.writeheader() - - self.vm.readp2mfl() - self.writep2mfl() - self.imgstart = self.fd.tell() - - while True: - l, batch = readbatch(ifd) - if l <= 0: - break - self.writebatch(batch) - self.tail = batch + ifd.read() - - def flush(self): - if self.tail: - self.fd.seek(0, 2) - self.fd.write(self.tail) - if self.compact: - self.writeindex() - self.tail = None - - def close(self): - self.flush() - -def parseheader(header): - "parses a header sexpression" - return vm.parsedominfo(vm.strtosxpr(header)) - -def makeheader(dominfo): - "create an image header from a VM dominfo sxpr" - items = [SIGNATURE] - sxpr = vm.sxprtostr(dominfo) - items.append(struct.pack('!i', len(sxpr))) - items.append(sxpr) - return ''.join(items) - -def readbatch(fd): - batch = [] - batchlen = fd.read(INTLEN) - batch.append(batchlen) - batchlen, = struct.unpack('i', batchlen) - log.info("batch length: %d" % batchlen) - if batchlen <= 0: - return (batchlen, batch[0]) - - batchfns = fd.read(LONGLEN * batchlen) - batch.append(batchfns) - pages = fd.read(PAGE_SIZE * batchlen) - if len(pages) != PAGE_SIZE * batchlen: - log.error('SHORT READ: %d' % len(pages)) - batch.append(pages) - - return (batchlen, ''.join(batch)) - -def parsebatch(batch): - "parse a batch string into pages" - batchlen, batch = batch[:INTLEN], batch[INTLEN:] - batchlen, = struct.unpack('i', batchlen) - #print 'batch length: %d' % batchlen - pfnlen = batchlen * LONGLEN - pfns = struct.unpack('%dL' % batchlen, batch[:pfnlen]) - pagebuf = batch[pfnlen:] - pages = [pagebuf[i*PAGE_SIZE:(i+1)*PAGE_SIZE] for i in xrange(batchlen)] - return zip(pfns, pages) diff --git a/tools/python/xen/remus/netlink.py b/tools/python/xen/remus/netlink.py deleted file mode 100644 index 56ea7740af..0000000000 --- a/tools/python/xen/remus/netlink.py +++ /dev/null @@ -1,318 +0,0 @@ -# netlink wrappers - -# See include/linux/netlink.h and rtnetlink.h - -import socket, struct -import xen.lowlevel.netlink - -NETLINK_ROUTE = 0 - -NLM_F_REQUEST = 1 # It is request message. -NLM_F_MULTI = 2 # Multipart message, terminated by NLMSG_DONE -NLM_F_ACK = 4 # Reply with ack, with zero or error code -NLM_F_ECHO = 8 # Echo this request - -# Modifiers to GET request -NLM_F_ROOT = 0x100 # specify tree root -NLM_F_MATCH = 0x200 # return all matching -NLM_F_ATOMIC = 0x400 # atomic GET -NLM_F_DUMP = NLM_F_ROOT|NLM_F_MATCH - -# Modifiers to NEW request -NLM_F_REPLACE = 0x100 # Override existing -NLM_F_EXCL = 0x200 # Do not touch, if it exists -NLM_F_CREATE = 0x400 # Create, if it does not exist -NLM_F_APPEND = 0x800 # Add to end of list - -RTM_NEWLINK = 16 -RTM_GETLINK = 18 -RTM_NEWQDISC = 36 -RTM_DELQDISC = 37 -RTM_GETQDISC = 38 - -IFLA_UNSPEC = 0 -IFLA_ADDRESS = 1 -IFLA_BROADCAST = 2 -IFLA_IFNAME = 3 -IFLA_MTU = 4 -IFLA_LINK = 5 -IFLA_QDISC = 6 -IFLA_STATS = 7 -IFLA_COST = 8 -IFLA_PRIORITY = 9 -IFLA_MASTER = 10 -IFLA_WIRELESS = 11 -IFLA_PROTINFO = 12 -IFLA_TXQLEN = 13 -IFLA_MAP = 14 -IFLA_WEIGHT = 15 - -TCA_UNSPEC = 0 -TCA_KIND = 1 -TCA_OPTIONS = 2 -TCA_STATS = 3 -TCA_XSTATS = 4 -TCA_RATE = 5 -TCA_FCNT = 6 -TCA_STATS2 = 7 - -class RTNLException(Exception): pass - -def align(l, alignto=4): - return (l + alignto - 1) & ~(alignto - 1) - -class rtattr(object): - "rtattribute" - fmt = "HH" - fmtlen = struct.calcsize(fmt) - - def __init__(self, msg=None): - if msg: - self.unpack(msg) - else: - self.rta_len = 0 - self.rta_type = 0 - - self.body = '' - - def __len__(self): - return align(self.rta_len) - - def pack(self): - self.rta_len = self.fmtlen + len(self.body) - s = struct.pack(self.fmt, self.rta_len, self.rta_type) + self.body - pad = align(self.rta_len) - len(s) - if pad: - s += '\0' * pad - return s - - def unpack(self, msg): - args = struct.unpack(self.fmt, msg[:self.fmtlen]) - self.rta_len, self.rta_type = args - - self.body = msg[self.fmtlen:self.rta_len] - -class rtattrlist(object): - def __init__(self, msg): - self.start = msg - - def __iter__(self): - body = self.start - while len(body) > rtattr.fmtlen: - rta = rtattr(body) - yield rta - body = body[len(rta):] - -class nlmsg(object): - "netlink message header" - fmt = "IHHII" - fmtlen = struct.calcsize(fmt) - - def __init__(self, msg=None): - if msg: - self.unpack(msg) - else: - self.nlmsg_len = 0 - self.nlmsg_type = 0 - self.nlmsg_flags = 0 - self.nlmsg_seq = 0 - self.nlmsg_pid = 0 - - self.rta = '' - self.body = '' - - def __len__(self): - return align(self.fmtlen + len(self.body) + len(self.rta)) - - def addattr(self, type, data): - attr = rtattr() - attr.rta_type = type - attr.body = data - self.rta += attr.pack() - self.nlmsg_len = len(self) - - def settype(self, cmd): - self.nlmsg_type = cmd - - def pack(self): - s = struct.pack(self.fmt, len(self), self.nlmsg_type, - self.nlmsg_flags, self.nlmsg_seq, - self.nlmsg_pid) + self.body + self.rta - return s - - def unpack(self, msg): - args = struct.unpack(self.fmt, msg[:self.fmtlen]) - self.nlmsg_len, self.nlmsg_type, self.nlmsg_flags = args[:3] - self.nlmsg_seq, self.nlmsg_pid = args[3:] - - self.body = msg[align(self.fmtlen):] - self.rta = '' - - def __str__(self): - return '' % \ - (self.nlmsg_len, self.nlmsg_type) - -class ifinfomsg(object): - "interface info message" - fmt = "BxHiII" - fmtlen = struct.calcsize(fmt) - - def __init__(self, msg=None): - if msg: - self.unpack(msg) - else: - self.ifi_family = 0 - self.ifi_type = 0 - self.ifi_index = 0 - self.ifi_flags = 0 - self.ifi_change = 0 - - self.body = '' - - def unpack(self, msg): - args = struct.unpack(self.fmt, msg[:self.fmtlen]) - self.ifi_family, self.ifi_type, self.ifi_index= args[:3] - self.ifi_flags, self.ifi_change = args[3:] - - self.body = msg[align(self.fmtlen):] - - def __str__(self): - return '' % \ - (self.ifi_family, self.ifi_type, self.ifi_index) - -class tcmsg(object): - "TC message" - fmt = "BxxxiIII" - fmtlen = struct.calcsize(fmt) - - def __init__(self, msg=None): - if msg: - self.unpack(msg) - else: - self.tcm_family = socket.AF_UNSPEC - self.tcm_ifindex = 0 - self.tcm_handle = 0 - self.tcm_parent = 0 - self.tcm_info = 0 - - self.rta = '' - - def unpack(self, msg): - args = struct.unpack(self.fmt, msg[:self.fmtlen]) - self.tcm_family, self.tcm_ifindex, self.tcm_handle = args[:3] - self.tcm_parent, self.tcm_info = args[3:] - - self.rta = msg[align(self.fmtlen):] - - def pack(self): - return struct.pack(self.fmt, self.tcm_family, self.tcm_ifindex, - self.tcm_handle, self.tcm_parent, self.tcm_info) - - def __str__(self): - return '' % \ - (self.tcm_family, self.tcm_ifindex) - -class newlinkmsg(object): - def __init__(self, nlmsg): - if nlmsg.nlmsg_type != RTM_NEWLINK: - raise RTNLException("wrong message type") - self.nlmsg = nlmsg - self.ifi = ifinfomsg(self.nlmsg.body) - - self.rtattrs = {} - for rta in rtattrlist(self.ifi.body): - self.rtattrs[rta.rta_type] = rta.body - -class newqdiscmsg(object): - def __init__(self, nlmsg): - if nlmsg.nlmsg_type != RTM_NEWQDISC: - raise RTNLException("wrong message type") - self.nlmsg = nlmsg - self.t = tcmsg(self.nlmsg.body) - - self.rtattrs = {} - for rta in rtattrlist(self.t.rta): - self.rtattrs[rta.rta_type] = rta.body - -class rtnl(object): - def __init__(self): - self._rth = xen.lowlevel.netlink.rtnl() - self._linkcache = None - - def getlink(self, key, cached=False): - """returns the interface object corresponding to the key, which - may be an index number or device name.""" - if not cached: - self._linkcache = None - if self._linkcache is None: - self._linkcache = self.getlinks() - - if isinstance(key, int): - return self._linkcache.get(key) - - for k, v in self._linkcache.iteritems(): - if v['name'] == key: - return v - - return None - - def getlinks(self): - """returns a dictionary of interfaces keyed by kernel - interface index""" - links = {} - def dumpfilter(addr, msgstr): - msg = newlinkmsg(nlmsg(msgstr)) - idx = msg.ifi.ifi_index - ifname = msg.rtattrs[IFLA_IFNAME].strip('\0') - address = msg.rtattrs.get(IFLA_ADDRESS) - - link = {'index': idx, - 'type': msg.ifi.ifi_type, - 'name': ifname, - 'address': address} - links[idx] = link - - self._rth.wilddump_request(socket.AF_UNSPEC, RTM_GETLINK) - self._rth.dump_filter(dumpfilter) - - return links - - def getqdisc(self, dev): - """returns the queueing discipline on device dev, which may be - specified by kernel index or device name""" - qdiscs = self.getqdiscs(dev) - if qdiscs: - return qdiscs.values()[0] - return None - - def getqdiscs(self, dev=None): - """returns a dictionary of queueing disciplines keyed by kernel - interface index""" - qdiscs = {} - def dumpfilter(addr, msgstr): - msg = newqdiscmsg(nlmsg(msgstr)) - idx = msg.t.tcm_ifindex - handle = msg.t.tcm_handle - kind = msg.rtattrs[TCA_KIND].strip('\0') - opts = msg.rtattrs.get(TCA_OPTIONS) - - qdisc = {'index': idx, - 'handle': handle, - 'kind': kind, - 'options': opts} - qdiscs[idx] = qdisc - - tcm = tcmsg() - if dev: - link = self.getlink(dev) - if not link: - raise QdiscException('device %s not found' % dev) - tcm.tcm_ifindex = link['index'] - - msg = tcm.pack() - self._rth.dump_request(RTM_GETQDISC, msg) - self._rth.dump_filter(dumpfilter) - return qdiscs - - def talk(self, req): - self._rth.talk(req) diff --git a/tools/python/xen/remus/profile.py b/tools/python/xen/remus/profile.py deleted file mode 100644 index fea8c282d7..0000000000 --- a/tools/python/xen/remus/profile.py +++ /dev/null @@ -1,56 +0,0 @@ -"""Simple profiling module -""" - -import time - -class ProfileBlock(object): - """A section of code to be profiled""" - def __init__(self, name): - self.name = name - - def enter(self): - print "PROF: entered %s at %f" % (self.name, time.time()) - - def exit(self): - print "PROF: exited %s at %f" % (self.name, time.time()) - -class NullProfiler(object): - def enter(self, name): - pass - - def exit(self, name=None): - pass - -class Profiler(object): - def __init__(self): - self.blocks = {} - self.running = [] - - def enter(self, name): - try: - block = self.blocks[name] - except KeyError: - block = ProfileBlock(name) - self.blocks[name] = block - - block.enter() - self.running.append(block) - - def exit(self, name=None): - if name is not None: - block = None - while self.running: - tmp = self.running.pop() - if tmp.name == name: - block = tmp - break - tmp.exit() - if not block: - raise KeyError('block %s not running' % name) - else: - try: - block = self.running.pop() - except IndexError: - raise KeyError('no block running') - - block.exit() diff --git a/tools/python/xen/remus/qdisc.py b/tools/python/xen/remus/qdisc.py deleted file mode 100644 index 4d54e015c3..0000000000 --- a/tools/python/xen/remus/qdisc.py +++ /dev/null @@ -1,189 +0,0 @@ -import socket, struct - -import netlink -import platform - -kernelversion = platform.platform(terse=True).split("-")[1].split(".") - -qdisc_kinds = {} - -TC_H_ROOT = 0xFFFFFFFF - -class QdiscException(Exception): pass - -class request(object): - "qdisc request message" - def __init__(self, cmd, flags=0, dev=None, handle=0): - self.n = netlink.nlmsg() - self.t = netlink.tcmsg() - - self.n.nlmsg_flags = netlink.NLM_F_REQUEST|flags - self.n.nlmsg_type = cmd - self.t.tcm_family = socket.AF_UNSPEC - - if not handle: - handle = TC_H_ROOT - self.t.tcm_parent = handle - - if dev: - self.t.tcm_ifindex = dev - - def pack(self): - t = self.t.pack() - self.n.body = t - return self.n.pack() - -class addrequest(request): - def __init__(self, dev, handle, qdisc): - flags = netlink.NLM_F_EXCL|netlink.NLM_F_CREATE - super(addrequest, self).__init__(netlink.RTM_NEWQDISC, flags=flags, - dev=dev, handle=handle) - self.n.addattr(netlink.TCA_KIND, qdisc.kind + '\0') - opts = qdisc.pack() - if opts: - self.n.addattr(netlink.TCA_OPTIONS, opts) - -class delrequest(request): - def __init__(self, dev, handle): - super(delrequest, self).__init__(netlink.RTM_DELQDISC, dev=dev, - handle=handle) - -class changerequest(request): - def __init__(self, dev, handle, qdisc): - super(changerequest, self).__init__(netlink.RTM_NEWQDISC, - dev=dev, handle=handle) - self.n.addattr(netlink.TCA_KIND, qdisc.kind + '\0') - opts = qdisc.pack() - if opts: - self.n.addattr(netlink.TCA_OPTIONS, opts) - -class Qdisc(object): - def __new__(cls, qdict=None, *args, **opts): - if qdict: - kind = qdict.get('kind') - cls = qdisc_kinds.get(kind, cls) - obj = super(Qdisc, cls).__new__(cls) - return obj - - def __init__(self, qdict): - self._qdict = qdict - self.kind = qdict['kind'] - self.handle = qdict['handle'] >> 16 - - def parse(self, opts): - if opts: - raise QdiscException('cannot parse qdisc parameters') - - def optstr(self): - if self.qdict['options']: - return '[cannot parse qdisc parameters]' - else: - return '' - - def pack(self): - return '' - -TC_PRIO_MAX = 15 -class PrioQdisc(Qdisc): - fmt = 'i%sB' % (TC_PRIO_MAX + 1) - - def __init__(self, qdict): - super(PrioQdisc, self).__init__(qdict) - - if qdict.get('options'): - self.unpack(qdict['options']) - else: - self.bands = 3 - self.priomap = [1, 2, 2, 2, 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1] - - def pack(self): - #return struct.pack(self.fmt, self.bands, *self.priomap) - return '' - - def unpack(self, opts): - args = struct.unpack(self.fmt, opts) - self.bands = args[0] - self.priomap = args[1:] - - def optstr(self): - mapstr = ' '.join([str(p) for p in self.priomap]) - return 'bands %d priomap %s' % (self.bands, mapstr) - -qdisc_kinds['prio'] = PrioQdisc -qdisc_kinds['pfifo_fast'] = PrioQdisc - -class CfifoQdisc(Qdisc): - fmt = 'II' - - def __init__(self, qdict): - super(CfifoQdisc, self).__init__(qdict) - - if qdict.get('options'): - self.unpack(qdict['options']) - else: - self.epoch = 0 - self.vmid = 0 - - def pack(self): - return struct.pack(self.fmt, self.epoch, self.vmid) - - def unpack(self, opts): - self.epoch, self.vmid = struct.unpack(self.fmt, opts) - - def parse(self, opts): - args = list(opts) - try: - while args: - arg = args.pop(0) - if arg == 'epoch': - self.epoch = int(args.pop(0)) - continue - if arg.lower() == 'vmid': - self.vmid = int(args.pop(0)) - continue - except Exception, inst: - raise QdiscException(str(inst)) - - def optstr(self): - return 'epoch %d vmID %d' % (self.epoch, self.vmid) - -qdisc_kinds['cfifo'] = CfifoQdisc - -TC_PLUG_BUFFER = 0 -TC_PLUG_RELEASE_ONE = 1 - -class PlugQdisc(Qdisc): - - def __init__(self, qdict=None): - if int(kernelversion[0]) >= 3 and int(kernelversion[1]) >= 4: - self.fmt = 'iI' - self.limit = 10000 - else: - self.fmt = 'I' - - if not qdict: - qdict = {'kind': 'plug', - 'handle': TC_H_ROOT} - super(PlugQdisc, self).__init__(qdict) - - self.action = 0 - - def pack(self): - if int(kernelversion[0]) >= 3 and int(kernelversion[1]) >= 4: - return struct.pack(self.fmt, self.action, self.limit) - else: - return struct.pack(self.fmt, self.action) - - def parse(self, args): - if not args: - raise QdiscException('no action given') - arg = args[0] - - if arg == 'checkpoint': - self.action = TC_PLUG_BUFFER - elif arg == 'release': - self.action = TC_PLUG_RELEASE_ONE - else: - raise QdiscException('unknown action') - -qdisc_kinds['plug'] = PlugQdisc diff --git a/tools/python/xen/remus/save.py b/tools/python/xen/remus/save.py deleted file mode 100644 index 21930617db..0000000000 --- a/tools/python/xen/remus/save.py +++ /dev/null @@ -1,186 +0,0 @@ -#!/usr/bin/env python - -import os, select, socket, threading, time, signal, xmlrpclib - -from xen.xend.XendClient import server -from xen.xend.xenstore.xswatch import xswatch - -import xen.lowlevel.xc -from xen.xend.xenstore import xsutil -xc = xen.lowlevel.xc.xc() - -import xen.lowlevel.checkpoint - -import vm, image - -XCFLAGS_LIVE = 1 - -xcsave = '/usr/lib/xen/bin/xc_save' - -class _proxy(object): - "proxy simulates an object without inheritance" - def __init__(self, obj): - self._obj = obj - - def __getattr__(self, name): - return getattr(self._obj, name) - - def proxy(self, obj): - self._obj = obj - -class CheckpointError(Exception): pass - -class CheckpointingFile(_proxy): - """Tee writes into separate file objects for each round. - This is necessary because xc_save gets a single file descriptor - for the duration of checkpointing. - """ - def __init__(self, path): - self.path = path - - self.round = 0 - self.rfd, self.wfd = os.pipe() - self.fd = file(path, 'wb') - - # this pipe is used to notify the writer thread of checkpoints - self.cprfd, self.cpwfd = os.pipe() - - super(CheckpointingFile, self).__init__(self.fd) - - wt = threading.Thread(target=self._wrthread, name='disk-write-thread') - wt.setDaemon(True) - wt.start() - self.wt = wt - - def fileno(self): - return self.wfd - - def close(self): - os.close(self.wfd) - # closing wfd should signal writer to stop - self.wt.join() - os.close(self.rfd) - os.close(self.cprfd) - os.close(self.cpwfd) - self.fd.close() - self.wt = None - - def checkpoint(self): - os.write(self.cpwfd, '1') - - def _wrthread(self): - while True: - r, o, e = select.select((self.rfd, self.cprfd), (), ()) - if self.rfd in r: - data = os.read(self.rfd, 256 * 1024) - if not data: - break - self.fd.write(data) - if self.cprfd in r: - junk = os.read(self.cprfd, 1) - self.round += 1 - self.fd = file('%s.%d' % (self.path, self.round), 'wb') - self.proxy(self.fd) - -class MigrationSocket(_proxy): - def __init__(self, address): - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.connect(address) - - sock.send("receive\n") - sock.recv(80) - - fd = os.fdopen(sock.fileno(), 'w+') - - self.sock = sock - super(MigrationSocket, self).__init__(fd) - -class NullSocket(_proxy): - def __init__(self, address): - filedesc = os.open('/dev/null', 0666) - fd = os.fdopen(filedesc, 'w+') - super(NullSocket, self).__init__(fd) - -class Keepalive(object): - "Call a keepalive method at intervals" - def __init__(self, method, interval=0.1): - self.keepalive = method - self.interval = interval - - self.thread = None - self.running = False - - def start(self): - if not self.interval: - return - self.thread = threading.Thread(target=self.run, name='keepalive-thread') - self.thread.setDaemon(True) - self.running = True - self.thread.start() - - def stop(self): - if not self.thread: - return - self.running = False - self.thread.join() - self.thread = None - - def run(self): - while self.running: - self.keepalive() - time.sleep(self.interval) - self.keepalive(stop=True) - -class Saver(object): - def __init__(self, domid, fd, suspendcb=None, resumecb=None, - checkpointcb=None, interval=0, flags=0): - """Create a Saver object for taking guest checkpoints. - domid: name, number or UUID of a running domain - fd: a stream to which checkpoint data will be written. - suspendcb: callback invoked after guest is suspended - resumecb: callback invoked before guest resumes - checkpointcb: callback invoked when a checkpoint is complete. Return - True to take another checkpoint, or False to stop. - flags: Remus flags to be passed to xc_domain_save - """ - self.fd = fd - self.suspendcb = suspendcb - self.resumecb = resumecb - self.checkpointcb = checkpointcb - self.interval = interval - self.flags = flags - - self.vm = vm.VM(domid) - - self.checkpointer = None - - def start(self): - vm.getshadowmem(self.vm) - - hdr = image.makeheader(self.vm.dominfo) - self.fd.write(hdr) - self.fd.flush() - - self.checkpointer = xen.lowlevel.checkpoint.checkpointer() - try: - try: - self.checkpointer.open(self.vm.domid) - self.checkpointer.start(self.fd, self.suspendcb, self.resumecb, - self.checkpointcb, self.interval, - self.flags) - except xen.lowlevel.checkpoint.error, e: - raise CheckpointError(e) - finally: - try: #errors in checkpoint close are not critical atm. - self.checkpointer.close() - except: - pass - - def _resume(self): - """low-overhead version of XendDomainInfo.resumeDomain""" - # TODO: currently assumes SUSPEND_CANCEL is available - if True: - xc.domain_resume(self.vm.domid, 1) - xsutil.ResumeDomain(self.vm.domid) - else: - server.xend.domain.resumeDomain(self.vm.domid) diff --git a/tools/python/xen/remus/tapdisk.py b/tools/python/xen/remus/tapdisk.py deleted file mode 100644 index 49a9bda626..0000000000 --- a/tools/python/xen/remus/tapdisk.py +++ /dev/null @@ -1,4 +0,0 @@ -import blkdev - -class TapDisk(BlkDev): - pass diff --git a/tools/python/xen/remus/util.py b/tools/python/xen/remus/util.py deleted file mode 100644 index b75052c6e1..0000000000 --- a/tools/python/xen/remus/util.py +++ /dev/null @@ -1,82 +0,0 @@ -# utility functions - -import fcntl, os, subprocess - -class PipeException(Exception): - def __init__(self, message, errno): - self.errno = errno - message = '%s: %d, %s' % (message, errno, os.strerror(errno)) - Exception.__init__(self, message) - -class Lock(object): - """advisory lock""" - - def __init__(self, filename): - """lock using filename for synchronization""" - self.filename = filename + '.lock' - - self.fd = None - - self.lock() - - def __del__(self): - self.unlock() - - def lock(self): - if self.fd: - return - - self.fd = open(self.filename, 'w') - fcntl.lockf(self.fd, fcntl.LOCK_EX) - - def unlock(self): - if not self.fd: - return - - fcntl.lockf(self.fd, fcntl.LOCK_UN) - self.fd = None - try: - os.remove(self.filename) - except OSError: - # harmless race - pass - -def canonifymac(mac): - return ':'.join(['%02x' % int(field, 16) for field in mac.split(':')]) - -def checkpid(pid): - """return True if pid is live""" - try: - os.kill(pid, 0) - return True - except OSError: - return False - -def runcmd(args, cwd=None): - # TODO: stdin handling - if type(args) == str: - args = args.split(' ') - try: - proc = subprocess.Popen(args, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, close_fds=True, - cwd=cwd) - stdout = proc.stdout.read() - stderr = proc.stderr.read() - proc.wait() - if proc.returncode: - print ' '.join(args) - errmsg = stderr.strip() - print errmsg - raise PipeException('%s failed (errmsg: %s)' % (args[0], errmsg), - proc.returncode) - return stdout - except (OSError, IOError), inst: - raise PipeException('could not run %s' % args[0], inst.errno) - -def modprobe(modname): - """attempt to load kernel module modname""" - try: - runcmd(['modprobe', '-q', modname]) - return True - except PipeException: - return False diff --git a/tools/python/xen/remus/vbd.py b/tools/python/xen/remus/vbd.py deleted file mode 100644 index 25ed8ea186..0000000000 --- a/tools/python/xen/remus/vbd.py +++ /dev/null @@ -1,9 +0,0 @@ -import blkdev - -class VBD(blkdev.BlkDev): - def handles(self, **props): - uname = props.get('uname', '') - return uname.startswith('phy:') - handles = classmethod(handles) - -blkdev.register(VBD) diff --git a/tools/python/xen/remus/vdi.py b/tools/python/xen/remus/vdi.py deleted file mode 100644 index 56fc3f879c..0000000000 --- a/tools/python/xen/remus/vdi.py +++ /dev/null @@ -1,121 +0,0 @@ -#code to play with vdis and snapshots - -import os - -def run(cmd): - fd = os.popen(cmd) - res = [l for l in fd if l.rstrip()] - return not fd.close(), res - - -_blockstore = '/blockstore.dat' - -def set_blockstore(blockstore): - global _blockstore - __blockstore = blockstore - - -class SnapShot: - def __init__(self, vdi, block, index): - self.__vdi = vdi - self.__block = block - self.__index = index - - #TODO add snapshot date and radix - - def __str__(self): - return '%d %d %d' % (self.__vdi.id(), self.__block, self.__index) - - def vdi(self): - return self.__vdi - - def block(self): - return self.__block - - def index(self): - return self.__index - - def match(self, block, index): - return self.__block == block and self.__index == index - - -class VDIException(Exception): - pass - - -class VDI: - def __init__(self, id, name): - self.__id = id - self.__name = name - - def __str__(self): - return 'vdi: %d %s' % (self.__id, self.__name) - - def id(self): - return self.__id - - def name(self): - return self.__name - - def list_snapshots(self): - res, ls = run('vdi_snap_list %s %d' % (_blockstore, self.__id)) - if res: - return [SnapShot(self, int(l[0]), int(l[1])) for l in [l.split() for l in ls[1:]]] - else: - raise VDIException("Error reading snapshot list") - - def snapshot(self): - res, ls = run('vdi_checkpoint %s %d' % (_blockstore, self.__id)) - if res: - _, block, idx = ls[0].split() - return SnapShot(self, int(block), int(idx)) - else: - raise VDIException("Error taking vdi snapshot") - - -def create(name, snap): - res, _ = run('vdi_create %s %s %d %d' - % (_blockstore, name, snap.block(), snap.index())) - if res: - return lookup_by_name(name) - else: - raise VDIException('Unable to create vdi from snapshot') - - -def fill(name, img_file): - res, _ = run('vdi_create %s %s' % (_blockstore, name)) - - if res: - vdi = lookup_by_name(name) - res, _ = run('vdi_fill %d %s' % (vdi.id(), img_file)) - if res: - return vdi - raise VDIException('Unable to create vdi from disk img file') - - -def list_vdis(): - vdis = [] - res, lines = run('vdi_list %s' % _blockstore) - if res: - for l in lines: - r = l.split() - vdis.append(VDI(int(r[0]), r[1])) - return vdis - else: - raise VDIException("Error doing vdi list") - - -def lookup_by_id(id): - vdis = list_vdis() - for v in vdis: - if v.id() == id: - return v - raise VDIException("No match from vdi id") - - -def lookup_by_name(name): - vdis = list_vdis() - for v in vdis: - if v.name() == name: - return v - raise VDIException("No match for vdi name") diff --git a/tools/python/xen/remus/vif.py b/tools/python/xen/remus/vif.py deleted file mode 100644 index d14d54b14f..0000000000 --- a/tools/python/xen/remus/vif.py +++ /dev/null @@ -1,18 +0,0 @@ -from xen.remus.util import canonifymac - -class VIF(object): - def __init__(self, **props): - self.dev = 'unknown' - self.__dict__.update(props) - if 'mac' in props: - self.mac = canonifymac(props['mac']) - - def __str__(self): - return self.mac - -def parse(props, domid, index): - "turn a vm device dictionary into a vif object" - vif = VIF(**props) - vif.dev = 'vif%d.%d' % (domid, index) - - return vif diff --git a/tools/python/xen/remus/vm.py b/tools/python/xen/remus/vm.py deleted file mode 100644 index 90002e3f21..0000000000 --- a/tools/python/xen/remus/vm.py +++ /dev/null @@ -1,168 +0,0 @@ -#!/usr/bin/env python - -import xmlrpclib - -from xen.xend.XendClient import server -from xen.xend import sxp, osdep -from xen.lowlevel.xc import xc - -import vif -import blkdev -# need a nicer way to load disk drivers -import vbd - -class VMException(Exception): pass - -class VM(object): - "Representation of a virtual machine" - def __init__(self, domid=None, dominfo=None): - self.dominfo = dominfo - - self.domid = -1 - self.name = 'unknown' - self.dom = {} - self.disks = [] - self.vifs = [] - - if domid: - try: - self.dominfo = server.xend.domain(domid, 'all') - except xmlrpclib.Fault: - raise VMException('error looking up domain %s' % str(domid)) - - if self.dominfo: - self.loaddominfo() - - def loaddominfo(self): - self.dom = parsedominfo(self.dominfo) - self.domid = self.dom['domid'] - self.name = self.dom['name'] - - self.disks = getdisks(self.dom) - self.vifs = getvifs(self.dom) - - def __str__(self): - return 'VM %d (%s), vifs: [%s], disks: [%s]' % \ - (self.domid, self.name, - ', '.join([str(v) for v in self.vifs]), - ', '.join([str(d) for d in self.disks])) - -def parsedominfo(dominfo): - "parses a dominfo sexpression in the form of python lists of lists" - def s2d(s): - r = {} - for elem in s: - if len(elem) == 0: - continue - name = elem[0] - if len(elem) == 1: - val = None - else: - val = elem[1] - if isinstance(val, list): - val = s2d(elem[1:]) - if isinstance(name, list): - # hack for ['cpus', [[1]]] - return s2d(elem) - if name in r: - for k, v in val.iteritems(): - if k in r[name]: - if not isinstance(r[name][k], list): - r[name][k] = [r[name][k]] - r[name][k].append(v) - else: - r[name][k] = v - else: - r[name] = val - return r - - return s2d(dominfo[1:]) - -def domtosxpr(dom): - "convert a dominfo into a python sxpr" - def d2s(d): - r = [] - for k, v in d.iteritems(): - elem = [k] - if isinstance(v, dict): - elem.extend(d2s(v)) - else: - if v is None: - v = '' - elem.append(v) - r.append(elem) - return r - - sxpr = ['domain'] - sxpr.extend(d2s(dom)) - return sxpr - -def strtosxpr(s): - "convert a string to a python sxpr" - p = sxp.Parser() - p.input(s) - return p.get_val() - -def sxprtostr(sxpr): - "convert an sxpr to string" - return sxp.to_string(sxpr) - -def getvifs(dom): - "return vif objects for devices in dom" - vifs = dom['device'].get('vif', []) - if type(vifs) != list: - vifs = [vifs] - - vifno = 0 - parsed = [] - for v in vifs: - parsed.append(vif.parse(v, dom['domid'], vifno)) - vifno += 1 - - return parsed - -def getdisks(dom): - "return block device objects for devices in dom" - disks = dom['device'].get('vbd', []) - if type(disks) != list: - disks = [disks] - - # tapdisk1 devices - tap1s = dom['device'].get('tap', []) - if type(tap1s) != list: - disks.append(tap1s) - else: - disks.extend(tap1s) - - # tapdisk2 devices - tap2s = dom['device'].get('tap2', []) - if type(tap2s) != list: - disks.append(tap2s) - else: - disks.extend(tap2s) - - return [blkdev.parse(disk) for disk in disks] - -def fromxend(domid): - "create a VM object from xend information" - return VM(domid) - -def getshadowmem(vm): - "Balloon down domain0 to create free memory for shadow paging." - maxmem = int(vm.dom['maxmem']) - shadow = int(vm.dom['shadow_memory']) - vcpus = int(vm.dom['vcpus']) - - # from XendDomainInfo.checkLiveMigrateMemory: - # 1MB per vcpu plus 4Kib/Mib of RAM. This is higher than - # the minimum that Xen would allocate if no value were given. - shadowneeded = vcpus * 1024 + maxmem * 4 - shadow * 1024 - physinfo = xc().physinfo() - freemem = int(physinfo['free_memory']) - needed = shadowneeded - freemem - if needed > 0: - print "Freeing %d kB for shadow mode" % needed - dom0cur = osdep.lookup_balloon_stat('current') - # target is in MB, not KB - target = (dom0cur - needed) / 1024 - server.xend.domain.setMemoryTarget(0, target) diff --git a/tools/python/xen/util/Brctl.py b/tools/python/xen/util/Brctl.py deleted file mode 100644 index 5dc9a7fb9f..0000000000 --- a/tools/python/xen/util/Brctl.py +++ /dev/null @@ -1,186 +0,0 @@ -"""Bridge control utilities. -""" -import os -import os.path -import re -import sys - -CMD_IFCONFIG = 'ifconfig' -CMD_ROUTE = 'route' -CMD_BRCTL = 'brctl' -CMD_IPTABLES = "iptables" - -opts = None - -class Opts: - - def __init__(self, defaults): - for (k, v) in defaults.items(): - setattr(self, k, v) - pass - -def cmd(p, s): - """Print and execute command 'p' with args 's'. - """ - global opts - c = p + ' ' + s - if opts.verbose: print c - if not opts.dryrun: - os.system(c) - -bridgeRE = re.compile(r'([^\t]*)\t*[^\t]*\t*[^\t]*\t*([^\t]*)') -def get_state(): - fin = os.popen(CMD_BRCTL + ' show', 'r') - try: - bridges = {} - brlist = None - brname = None - first = True - for line in fin: - if first: - first = False - elif line[0] == '\t': - brlist.append(line.strip()) - else: - if brname: - bridges[brname] = brlist - m = bridgeRE.match(line) - brname = m.group(1) - brlist = [m.group(2).strip()] - if brname: - bridges[brname] = brlist - return bridges - finally: - fin.close() - -def vif_bridge_add(params): - """Add the network interface for vif on dom to a bridge. - """ - cmd(CMD_BRCTL, 'addif %(bridge)s %(vif)s' % params) - -def vif_bridge_rem(params): - """Remove the network interface for vif on dom from a bridge. - """ - cmd(CMD_BRCTL, 'delif %(bridge)s %(vif)s' % params) - -def vif_restrict_addr(vif, addr, delete=0): - d = { 'vif': vif, 'addr': addr} - if delete: - d['flag'] = '-D' - else: - d['flag'] = '-A' - cmd(CMD_IPTABLES, '-P FORWARD DROP') - cmd(CMD_IPTABLES, '%(flag)s FORWARD -m physdev --physdev-in %(vif)s -s %(addr)s -j ACCEPT' % d) - cmd(CMD_IPTABLES, '%(flag)s FORWARD -m physdev --physdev-out %(vif)s -d %(addr)s -j ACCEPT' % d) - -def bridge_create(bridge, **kwd): - """Create a bridge. - Defaults hello time to 0, forward delay to 0 and stp off. - """ - cmd(CMD_BRCTL, 'addbr %s' % bridge) - if kwd.get('hello', None) is None: - kwd['hello'] = 0 - if kwd.get('fd', None) is None: - kwd['fd'] = 0 - if kwd.get('stp', None) is None: - kwd['stp'] = 'off' - bridge_set(bridge, **kwd) - cmd(CMD_IFCONFIG, "%s up" % bridge) - -def bridge_set(bridge, hello=None, fd=None, stp=None): - """Set bridge parameters. - """ - if hello is not None: - cmd(CMD_BRCTL, 'sethello %s %d' % (bridge, hello)) - if fd is not None: - cmd(CMD_BRCTL, 'setfd %s %d' % (bridge, fd)) - if stp is not None: - cmd(CMD_BRCTL, 'stp %s %s' % (bridge, stp)) - -def bridge_del(bridge): - """Delete a bridge. - """ - cmd(CMD_IFCONFIG, '%s down' % bridge) - cmd(CMD_BRCTL, 'delbr %s' % bridge) - -def routes(): - """Return a list of the routes. - """ - fin = os.popen(CMD_ROUTE + ' -n', 'r') - routes = [] - for x in fin: - if x.startswith('Kernel'): continue - if x.startswith('Destination'): continue - x = x.strip() - y = x.split() - z = { 'destination': y[0], - 'gateway' : y[1], - 'mask' : y[2], - 'flags' : y[3], - 'metric' : y[4], - 'ref' : y[5], - 'use' : y[6], - 'interface' : y[7] } - routes.append(z) - return routes - -def ifconfig(interface): - """Return the ip config for an interface, - """ - fin = os.popen(CMD_IFCONFIG + ' %s' % interface, 'r') - inetre = re.compile('\s*inet\s*addr:(?P
\S*)\s*Bcast:(?P\S*)\s*Mask:(?P\S*)') - info = None - for x in fin: - m = inetre.match(x) - if not m: continue - info = m.groupdict() - info['interface'] = interface - break - return info - -def reconfigure(interface, bridge): - """Reconfigure an interface to be attached to a bridge, and give the bridge - the IP address etc. from interface. Move the default route to the interface - to the bridge. - - """ - global opts - intf_info = ifconfig(interface) - if not intf_info: - print >>sys.stderr, 'Interface not found:', interface - return - #bridge_info = ifconfig(bridge) - #if not bridge_info: - # print >>sys.stderr, 'Bridge not found:', bridge - # return - route_info = routes() - intf_info['bridge'] = bridge - intf_info['gateway'] = None - for r in route_info: - if (r['destination'] == '0.0.0.0' and - 'G' in r['flags'] and - r['interface'] == interface): - intf_info['gateway'] = r['gateway'] - if not intf_info['gateway']: - print >>sys.stderr, 'Gateway not found: ', interface - return - cmd(CMD_IFCONFIG, - '%(bridge)s %(address)s netmask %(mask)s broadcast %(broadcast)s up' - % intf_info) - cmd(CMD_ROUTE, - 'add default gateway %(gateway)s dev %(bridge)s' - % intf_info) - cmd(CMD_BRCTL, 'addif %(bridge)s %(interface)s' % intf_info) - cmd(CMD_IFCONFIG, '%(interface)s 0.0.0.0' % intf_info) - -defaults = { - 'verbose' : 1, - 'dryrun' : 0, - } - -opts = Opts(defaults) - -def set_opts(val): - global opts - opts = val - return opts diff --git a/tools/python/xen/util/SSHTransport.py b/tools/python/xen/util/SSHTransport.py deleted file mode 100644 index fa975f3712..0000000000 --- a/tools/python/xen/util/SSHTransport.py +++ /dev/null @@ -1,102 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2006 Anthony Liguori -# Copyright (C) 2006 XenSource Inc. -#============================================================================ - -""" -XML-RPC SSH transport. -""" - -from xmlrpclib import getparser, Fault -from subprocess import Popen, PIPE -from getpass import getuser -from fcntl import ioctl -import errno -import os -import termios - - -def getHTTPURI(uri): - (protocol, rest) = uri.split(':', 1) - if not rest.startswith('//'): - raise ValueError("Invalid ssh URL '%s'" % uri) - rest = rest[2:] - user = getuser() - path = 'RPC2' - if rest.find('@') != -1: - (user, rest) = rest.split('@', 1) - if rest.find('/') != -1: - (host, rest) = rest.split('/', 1) - if len(rest) > 0: - path = rest - else: - host = rest - transport = SSHTransport(host, user) - uri = 'http://%s/%s' % (host, path) - return transport, uri - - -class SSHTransport(object): - def __init__(self, host, user, askpass=None): - self.host = host - self.user = user - self.askpass = askpass - self.ssh = None - - def getssh(self): - if self.ssh == None: - if self.askpass: - f = open('/dev/tty', 'w') - try: - os.environ['SSH_ASKPASS'] = self.askpass - ioctl(f.fileno(), termios.TIOCNOTTY) - finally: - f.close() - - cmd = ['ssh', '%s@%s' % (self.user, self.host), 'xm serve'] - try: - self.ssh = Popen(cmd, bufsize=0, stdin=PIPE, stdout=PIPE) - except OSError, (err, msg): - if err == errno.ENOENT: - raise Fault(0, "ssh executable not found!") - raise - return self.ssh - - def request(self, host, handler, request_body, verbose=0): - p, u = getparser() - ssh = self.getssh() - ssh.stdin.write("""POST /%s HTTP/1.1 -User-Agent: Xen -Host: %s -Content-Type: text/xml -Content-Length: %d - -%s""" % (handler, host, len(request_body), request_body)) - ssh.stdin.flush() - - content_length = 0 - line = ssh.stdout.readline() - if line.split()[1] != '200': - raise Fault(0, 'Server returned %s' % (' '.join(line[1:]))) - - while line not in ['', '\r\n', '\n']: - if line.lower().startswith('content-length:'): - content_length = int(line[15:].strip()) - line = ssh.stdout.readline() - content = ssh.stdout.read(content_length) - p.feed(content) - p.close() - return u.close() diff --git a/tools/python/xen/util/__init__.py b/tools/python/xen/util/__init__.py deleted file mode 100644 index 8d1c8b69c3..0000000000 --- a/tools/python/xen/util/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tools/python/xen/util/acmpolicy.py b/tools/python/xen/util/acmpolicy.py deleted file mode 100644 index 6752169c7b..0000000000 --- a/tools/python/xen/util/acmpolicy.py +++ /dev/null @@ -1,1622 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2006,2007 International Business Machines Corp. -# Author: Stefan Berger -#============================================================================ - -import os -import stat -import array -import struct -import shutil -import commands - -# sha is deprecated as of python 2.6 -try: - from hashlib import sha1 -except ImportError: - # but hashlib was only added in python 2.5 - from sha import new as sha1 - -from xml.dom import minidom, Node -from xen.xend.XendLogging import log -from xen.util import xsconstants, bootloader, mkdir -from xen.util.xspolicy import XSPolicy -from xen.xend.XendError import SecurityError -import xen.util.xsm.acm.acm as security -from xen.util.xsm.xsm import XSMError -from xen.xend import XendOptions - -ACM_POLICIES_DIR = security.policy_dir_prefix + "/" - -# Constants needed for generating a binary policy from its XML -# representation -ACM_POLICY_VERSION = 4 # Latest one -ACM_CHWALL_VERSION = 1 - -ACM_STE_VERSION = 1 - -ACM_MAGIC = 0x001debc; - -ACM_NULL_POLICY = 0 -ACM_CHINESE_WALL_POLICY = 1 -ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY = 2 -ACM_POLICY_UNDEFINED = 15 - - -ACM_LABEL_UNLABELED = "__UNLABELED__" -ACM_LABEL_UNLABELED_DISPLAY = "unlabeled" - -""" - Error codes reported in when trying to test for a new policy - These error codes are reported in an array of tuples where - each error code is followed by a parameter describing the error - more closely, such as a domain id. -""" -ACM_EVTCHN_SHARING_VIOLATION = 0x100 -ACM_GNTTAB_SHARING_VIOLATION = 0x101 -ACM_DOMAIN_LOOKUP = 0x102 -ACM_CHWALL_CONFLICT = 0x103 -ACM_SSIDREF_IN_USE = 0x104 - - -DEFAULT_policy = \ -"\n" +\ -"\n" +\ -" \n" +\ -" DEFAULT\n" +\ -" 1.0\n" +\ -" \n" +\ -" \n" +\ -" \n" +\ -" SystemManagement\n" +\ -" __UNLABELED__\n" +\ -" \n" +\ -" \n" +\ -" \n" +\ -" \n" +\ -" SystemManagement\n" +\ -" \n" +\ -" \n" +\ -" \n" +\ -" \n" +\ -" \n" +\ -" SystemManagement\n" +\ -" \n" +\ -" SystemManagement\n" +\ -" __UNLABELED__\n" +\ -" \n" +\ -" \n" +\ -" \n" +\ -" \n" +\ -" \n" +\ -" \n" +\ -" __UNLABELED__\n" +\ -" \n" +\ -" __UNLABELED__\n" +\ -" \n" +\ -" \n" +\ -" \n" +\ -" \n" +\ -" \n" +\ -" \n" +\ -" \n" +\ -" \n" +\ -" __UNLABELED__\n" +\ -" \n" +\ -" __UNLABELED__\n" +\ -" \n" +\ -" \n" +\ -" \n" +\ -" \n" +\ -"\n" - -ACM_SCHEMA=""" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -""" - - -def get_DEFAULT_policy(dom0label=""): - fromnode = "" - if dom0label != "": - fromnode = " from=\"%s\"" % dom0label - return DEFAULT_policy % fromnode - -def initialize(): - xoptions = XendOptions.instance() - basedir = xoptions.get_xend_security_path() - policiesdir = basedir + "/policies" - mkdir.parents(policiesdir, stat.S_IRWXU) - - instdir = security.install_policy_dir_prefix - DEF_policy_file = "DEFAULT-security_policy.xml" - - #Install default policy. - f = open(policiesdir + "/" + DEF_policy_file, 'w') - if f: - f.write(get_DEFAULT_policy()) - f.close() - else: - log.error("Could not write the default policy's file.") - defpol = ACMPolicy(xml=get_DEFAULT_policy()) - defpol.compile() - - -class ACMPolicy(XSPolicy): - """ - ACMPolicy class. Implements methods for getting information from - the XML representation of the policy as well as compilation and - loading of a policy into the HV. - """ - - def __init__(self, name=None, dom=None, ref=None, xml=None): - if name: - self.name = name - try: - self.dom = minidom.parse(self.path_from_policy_name(name)) - except Exception, e: - raise SecurityError(-xsconstants.XSERR_XML_PROCESSING, - str(e)) - elif dom: - self.dom = dom - self.name = self.get_name() - elif xml: - try: - self.dom = minidom.parseString(xml) - except Exception, e: - raise SecurityError(-xsconstants.XSERR_XML_PROCESSING, - str(e)) - self.name = self.get_name() - rc = self.validate() - if rc != xsconstants.XSERR_SUCCESS: - raise SecurityError(rc) - if ref: - from xen.xend.XendXSPolicy import XendACMPolicy - self.xendacmpolicy = XendACMPolicy(self, {}, ref) - else: - self.xendacmpolicy = None - XSPolicy.__init__(self, name=self.name, ref=ref) - - def get_dom(self): - return self.dom - - def get_name(self): - return self.policy_dom_get_hdr_item("PolicyName") - - def get_type(self): - return xsconstants.XS_POLICY_ACM - - def get_type_name(self): - return xsconstants.ACM_POLICY_ID - - def __str__(self): - return self.get_name() - - - def validate(self): - """ - validate against the policy's schema Does not fail if the - libxml2 python lib is not installed - """ - rc = xsconstants.XSERR_SUCCESS - try: - import libxml2 - except Exception, e: - log.warn("Libxml2 python-wrapper is not installed on the system.") - return xsconstants.XSERR_SUCCESS - try: - parserctxt = libxml2.schemaNewMemParserCtxt(ACM_SCHEMA, - len(ACM_SCHEMA)) - schemaparser = parserctxt.schemaParse() - valid = schemaparser.schemaNewValidCtxt() - doc = libxml2.parseDoc(self.toxml()) - if doc.schemaValidateDoc(valid) != 0: - rc = -xsconstants.XSERR_BAD_XML - except Exception, e: - log.warn("Problem with the schema: %s" % str(e)) - rc = -xsconstants.XSERR_GENERAL_FAILURE - if rc != xsconstants.XSERR_SUCCESS: - log.warn("XML did not validate against schema") - if rc == xsconstants.XSERR_SUCCESS: - rc = self.__validate_name_and_labels() - return rc - - def __validate_name_and_labels(self): - """ no ':' allowed in the policy name and the labels """ - if ':' in self.get_name(): - return -xsconstants.XSERR_BAD_POLICY_NAME - for s in self.policy_get_resourcelabel_names(): - if ':' in s: - return -xsconstants.XSERR_BAD_LABEL - for s in self.policy_get_virtualmachinelabel_names(): - if ':' in s: - return -xsconstants.XSERR_BAD_LABEL - return xsconstants.XSERR_SUCCESS - - - def is_default_policy(self): - """ - Determine whether this is the default policy - """ - default = ['SystemManagement', ACM_LABEL_UNLABELED ] - if self.policy_get_virtualmachinelabel_names() == default and \ - self.policy_get_bootstrap_vmlabel() == default[0] and \ - self.policy_get_stetypes_types() == default and \ - self.policy_get_stes_of_vmlabel(default[0]) == default and \ - self.policy_get_stes_of_vmlabel(default[1]) == [default[1]] and \ - self.policy_get_resourcelabel_names() == [default[1]] and \ - self.policy_get_chwall_types() == [ default[0] ] and \ - self.get_name() == "DEFAULT": - return True - return False - - def update(self, xml_new): - """ - Update the policy with the new XML. The hypervisor decides - whether the new policy can be applied. - """ - rc = -xsconstants.XSERR_XML_PROCESSING - errors = "" - acmpol_old = self - try: - acmpol_new = ACMPolicy(xml=xml_new) - except Exception: - return -xsconstants.XSERR_XML_PROCESSING, errors - - vmlabel_map = acmpol_new.policy_get_vmlabel_translation_map() - - # An update requires version information in the current - # and new policy. The version number of the current policy - # must be the same as what is in the FromPolicy/Version node - # in the new one and the current policy's name must be the - # same as in FromPolicy/PolicyName - # The default policy when it is set skips this step. - if not acmpol_new.is_default_policy() and \ - not acmpol_old.is_default_policy(): - irc = self.__do_update_version_check(acmpol_new) - if irc != xsconstants.XSERR_SUCCESS: - return irc, errors - - if self.isloaded(): - newvmnames = \ - acmpol_new.policy_get_virtualmachinelabel_names_sorted() - oldvmnames = \ - acmpol_old.policy_get_virtualmachinelabel_names_sorted() - del_array = "" - chg_array = "" - - for o in oldvmnames: - if o not in newvmnames: - old_idx = oldvmnames.index(o) - if vmlabel_map.has_key(o): - #not a deletion, but a renaming - new = vmlabel_map[o] - new_idx = newvmnames.index(new) - chg_array += struct.pack("ii", old_idx, new_idx) - else: - del_array += struct.pack("i", old_idx) - for v in newvmnames: - if v in oldvmnames: - old_idx = oldvmnames.index(v) - new_idx = newvmnames.index(v) - if old_idx != new_idx: - chg_array += struct.pack("ii", old_idx, new_idx) - - # VM labels indicated in the 'from' attribute of a VM or - # resource node but that did not exist in the old policy - # are considered bad labels. - bad_renamings = set(vmlabel_map.keys()) - set(oldvmnames) - if len(bad_renamings) > 0: - log.error("Bad VM label renamings: %s" % - list(bad_renamings)) - return -xsconstants.XSERR_BAD_LABEL, errors - - reslabel_map = acmpol_new.policy_get_reslabel_translation_map() - oldresnames = acmpol_old.policy_get_resourcelabel_names() - bad_renamings = set(reslabel_map.keys()) - set(oldresnames) - if len(bad_renamings) > 0: - log.error("Bad resource label renamings: %s" % - list(bad_renamings)) - return -xsconstants.XSERR_BAD_LABEL, errors - - #Get binary and map from the new policy - rc, pol_map, bin_pol = acmpol_new.policy_create_map_and_bin() - if rc != xsconstants.XSERR_SUCCESS: - log.error("Could not build the map and binary policy.") - return rc, errors - - #Need to do / check the following: - # - relabel all resources where there is a 'from' field in - # the policy and mark those as unlabeled where the label - # does not appear in the new policy anymore - # - relabel all VMs where there is a 'from' field in the - # policy and mark those as unlabeled where the label - # does not appear in the new policy anymore; no running - # or paused VM may be unlabeled through this - # - check that under the new labeling conditions the VMs - # still have access to their resources as before. Unlabeled - # resources are inaccessible. If this check fails, the - # update failed. - # - Attempt changes in the hypervisor; if this step fails, - # roll back the relabeling of resources and VMs - # - Commit the relabeling of resources - - - rc, errors = security.change_acm_policy(bin_pol, - del_array, chg_array, - vmlabel_map, reslabel_map, - self, acmpol_new, - acmpol_new.is_default_policy()) - - if rc == 0: - # Replace the old DOM with the new one and save it - self.dom = acmpol_new.dom - self.compile() - log.info("ACM policy update was successful") - else: - #Not loaded in HV - self.dom = acmpol_new.dom - rc = self.compile() - return rc, errors - - def force_default_policy(klass, policy_ref): - """ - Force the installation of the DEFAULT policy if for - example no XML of the current policy is available and - the update path with comparisons of old and new policy - cannot be taken. - This only succeeds if only Domain-0 is running or - all guest have the same ssidref as Domain-0. - """ - errors = "" - - acmpol_new = ACMPolicy(xml = get_DEFAULT_policy(), ref=policy_ref) - - from xen.lowlevel import acm - dom0_ssidref = acm.getssid(0) - del_array = "" - chg_array = struct.pack("ii", - dom0_ssidref['ssidref'] & 0xffff, - 0x1) - - rc, pol_map, bin_pol = acmpol_new.policy_create_map_and_bin() - if rc != xsconstants.XSERR_SUCCESS: - return rc, errors, acmpol_new - rc, errors = security.hv_chg_policy(bin_pol, del_array, chg_array) - return rc, errors, acmpol_new - - force_default_policy = classmethod(force_default_policy) - - def get_reset_policy_xml(klass): - dom0_label = security.get_ssid(0)[1] - return get_DEFAULT_policy(dom0_label) - - get_reset_policy_xml = classmethod(get_reset_policy_xml) - - def __do_update_version_check(self, acmpol_new): - acmpol_old = self - - now_vers = acmpol_old.policy_dom_get_hdr_item("Version") - now_name = acmpol_old.policy_dom_get_hdr_item("PolicyName") - req_oldvers = acmpol_new.policy_dom_get_frompol_item("Version") - req_oldname = acmpol_new.policy_dom_get_frompol_item("PolicyName") - - if now_vers == "" or \ - now_vers != req_oldvers or \ - now_name != req_oldname: - log.info("Policy rejected: %s != %s or %s != %s" % \ - (now_vers,req_oldvers,now_name,req_oldname)) - return -xsconstants.XSERR_VERSION_PREVENTS_UPDATE - - if not self.isVersionUpdate(acmpol_new): - log.info("Policy rejected since new version is not an update.") - return -xsconstants.XSERR_VERSION_PREVENTS_UPDATE - - return xsconstants.XSERR_SUCCESS - - - def compareVersions(self, v1, v2): - """ - Compare two policy versions given their tuples of major and - minor. - Return '0' if versions are equal, '>0' if v1 > v2 and - '<' if v1 < v2 - """ - rc = v1[0] - v2[0] - if rc == 0: - rc = v1[1] - v2[1] - return rc - - def getVersionTuple(self, item="Version"): - v_str = self.policy_dom_get_hdr_item(item) - return self.__convVersionToTuple(v_str) - - def get_version(self): - return self.policy_dom_get_hdr_item("Version") - - def isVersionUpdate(self, polnew): - if self.compareVersions(polnew.getVersionTuple(), - self.getVersionTuple()) > 0: - return True - return False - - def __convVersionToTuple(self, v_str): - """ Convert a version string, formatted according to the scheme - "%d.%d" into a tuple of (major, minor). Return (0,0) if the - string is empty. - """ - major = 0 - minor = 0 - if v_str != "": - tmp = v_str.split(".") - major = int(tmp[0]) - if len(tmp) > 1: - minor = int(tmp[1]) - return (major, minor) - - def get_policies_path(self): - xoptions = XendOptions.instance() - basedir = xoptions.get_xend_security_path() - return basedir + "/policies/" - - def policy_path(self, name): - prefix = self.get_policies_path() - path = prefix + name.replace('.','/') - _path = path.split("/") - del _path[-1] - mkdir.parents("/".join(_path), stat.S_IRWXU) - return path - - def path_from_policy_name(self, name): - return self.policy_path(name) + "-security_policy.xml" - - # - # Functions interacting with the bootloader - # - def vmlabel_to_ssidref(self, vm_label): - """ Convert a VMlabel into an ssidref given the current - policy - Return xsconstants.INVALID_SSIDREF if conversion failed. - """ - ssidref = xsconstants.INVALID_SSIDREF - names = self.policy_get_virtualmachinelabel_names_sorted() - try: - vmidx = names.index(vm_label) - ssidref = (vmidx << 16) | vmidx - except: - pass - return ssidref - - def set_vm_bootlabel(self, vm_label, remove=False): - parms="<>" - if vm_label != "": - ssidref = self.vmlabel_to_ssidref(vm_label) - if ssidref == xsconstants.INVALID_SSIDREF: - return -xsconstants.XSERR_BAD_LABEL - parms = "0x%08x:%s:%s:%s" % \ - (ssidref, xsconstants.ACM_POLICY_ID, \ - self.get_name(),vm_label) - else: - ssidref = 0 #Identifier for removal - - if remove == True: - parms = "<>" - - try: - def_title = bootloader.get_default_title() - bootloader.set_kernel_attval(def_title, "ssidref", parms) - except: - return -xsconstants.XSERR_GENERAL_FAILURE - return ssidref - - # - # Utility functions related to the policy's files - # - def get_filename(self, postfix, prefix=None, dotted=False): - """ - Create the filename for the policy. The prefix is prepended - to the path. If dotted is True, then a policy name like - 'a.b.c' will remain as is, otherwise it will become 'a/b/c' - """ - if prefix == None: - prefix = self.get_policies_path() - name = self.get_name() - if name: - p = name.split(".") - path = "" - if dotted: - sep = "." - else: - sep = "/" - if len(p) > 1: - path = sep.join(p[0:len(p)-1]) - if prefix != "" or path != "": - allpath = prefix + path + sep + p[-1] + postfix - else: - allpath = p[-1] + postfix - return allpath - return None - - def __readfile(self, name): - cont = "" - filename = self.get_filename(name) - f = open(filename, "r") - if f: - cont = f.read() - f.close() - return cont - - def get_map(self): - return self.__readfile(".map") - - def get_bin(self): - return self.__readfile(".bin") - - def copy_policy_file(self, suffix, destdir): - spolfile = self.get_filename(suffix) - dpolfile = destdir + "/" + self.get_filename(suffix,"",dotted=True) - try: - shutil.copyfile(spolfile, dpolfile) - except Exception, e: - log.error("Could not copy policy file %s to %s: %s" % - (spolfile, dpolfile, str(e))) - return -xsconstants.XSERR_FILE_ERROR - return xsconstants.XSERR_SUCCESS - - # - # DOM-related functions - # - - def policy_dom_get(self, parent, key, createit=False): - for node in parent.childNodes: - if node.nodeType == Node.ELEMENT_NODE: - if node.nodeName == key: - return node - if createit: - self.dom_create_node(parent, key) - return self.policy_dom_get(parent, key) - - def dom_create_node(self, parent, newname, value=" "): - xml = "<"+newname+">"+ value +"" - frag = minidom.parseString(xml) - frag.childNodes[0].nodeType = Node.DOCUMENT_FRAGMENT_NODE - parent.appendChild(frag.childNodes[0]) - return frag.childNodes[0] - - def dom_get_node(self, path, createit=False): - node = None - parts = path.split("/") - doc = self.get_dom() - if len(parts) > 0: - node = self.policy_dom_get(doc.documentElement, parts[0]) - if node: - i = 1 - while i < len(parts): - _node = self.policy_dom_get(node, parts[i], createit) - if not _node: - if not createit: - break - else: - self.dom_create_node(node, parts[i]) - _node = self.policy_dom_get(node, parts[i]) - node = _node - i += 1 - return node - - # - # Header-related functions - # - def policy_dom_get_header_subnode(self, nodename): - node = self.dom_get_node("PolicyHeader/%s" % nodename) - return node - - def policy_dom_get_hdr_item(self, name, default=""): - node = self.policy_dom_get_header_subnode(name) - if node and len(node.childNodes) > 0: - return node.childNodes[0].nodeValue - return default - - def policy_dom_get_frompol_item(self, name, default="", createit=False): - node = self.dom_get_node("PolicyHeader/FromPolicy",createit) - if node: - node = self.policy_dom_get(node, name, createit) - if node and len(node.childNodes) > 0: - return node.childNodes[0].nodeValue - return default - - def get_header_fields_map(self): - header = { - 'policyname' : self.policy_dom_get_hdr_item("PolicyName"), - 'policyurl' : self.policy_dom_get_hdr_item("PolicyUrl"), - 'reference' : self.policy_dom_get_hdr_item("Reference"), - 'date' : self.policy_dom_get_hdr_item("Date"), - 'namespaceurl' : self.policy_dom_get_hdr_item("NameSpaceUrl"), - 'version' : self.policy_dom_get_hdr_item("Version") - } - return header - - def set_frompolicy_name(self, name): - """ For tools to adapt the header of the policy """ - node = self.dom_get_node("PolicyHeader/FromPolicy/PolicyName", - createit=True) - node.childNodes[0].nodeValue = name - - def set_frompolicy_version(self, version): - """ For tools to adapt the header of the policy """ - node = self.dom_get_node("PolicyHeader/FromPolicy/Version", - createit=True) - node.childNodes[0].nodeValue = version - - def set_policy_name(self, name): - """ For tools to adapt the header of the policy """ - node = self.dom_get_node("PolicyHeader/PolicyName") - node.childNodes[0].nodeValue = name - - def set_policy_version(self, version): - """ For tools to adapt the header of the policy """ - node = self.dom_get_node("PolicyHeader/Version") - node.childNodes[0].nodeValue = version - - def update_frompolicy(self, curpol): - self.set_frompolicy_name(curpol.policy_dom_get_hdr_item("PolicyName")) - version = curpol.policy_dom_get_hdr_item("Version") - self.set_frompolicy_version(version) - (maj, minor) = self.__convVersionToTuple(version) - self.set_policy_version("%s.%s" % (maj, minor+1)) - - # - # Get all types that are part of a node - # - - def policy_get_types(self, node): - strings = [] - i = 0 - while i < len(node.childNodes): - if node.childNodes[i].nodeName == "Type" and \ - len(node.childNodes[i].childNodes) > 0: - strings.append(node.childNodes[i].childNodes[0].nodeValue) - i += 1 - return strings - - # - # Simple Type Enforcement-related functions - # - - def policy_get_stetypes_node(self): - node = self.dom_get_node("SimpleTypeEnforcement/SimpleTypeEnforcementTypes") - return node - - def policy_get_stetypes_types(self): - strings = [] - node = self.policy_get_stetypes_node() - if node: - strings = self.policy_get_types(node) - return strings - - # - # Chinese Wall Type-related functions - # - - def policy_get_chwall_types(self): - strings = [] - node = self.dom_get_node("ChineseWall/ChineseWallTypes") - if node: - strings = self.policy_get_types(node) - return strings - - def policy_get_chwall_cfses(self): - cfs = [] - node = self.dom_get_node("ChineseWall/ConflictSets") - if node: - i = 0 - while i < len(node.childNodes): - _cfs = {} - if node.childNodes[i].nodeName == "Conflict": - _cfs['name'] = node.childNodes[i].getAttribute('name') - _cfs['chws'] = self.policy_get_types(node.childNodes[i]) - cfs.append(_cfs) - i += 1 - return cfs - - def policy_get_chwall_cfses_names_sorted(self): - """ - Return the list of all conflict set names in alphabetical - order. - """ - cfs_names = [] - node = self.dom_get_node("ChineseWall/ConflictSets") - if node: - i = 0 - while i < len(node.childNodes): - if node.childNodes[i].nodeName == "Conflict": - n = node.childNodes[i].getAttribute('name') - #it better have a name! - if n: - cfs_names.append(n) - i += 1 - cfs_names.sort() - return cfs_names - - # - # Subject Label-related functions - # - - def policy_get_bootstrap_vmlabel(self): - node = self.dom_get_node("SecurityLabelTemplate/SubjectLabels") - if node: - vmlabel = node.getAttribute("bootstrap") - return vmlabel - - # Get the names of all virtual machine labels; returns an array - def policy_get_virtualmachinelabel_names(self): - strings = [] - node = self.dom_get_node("SecurityLabelTemplate/SubjectLabels") - if node: - i = 0 - while i < len(node.childNodes): - if node.childNodes[i].nodeName == "VirtualMachineLabel": - name = self.policy_dom_get(node.childNodes[i], "Name") - if len(name.childNodes) > 0: - strings.append(name.childNodes[0].nodeValue) - i += 1 - return strings - - def policy_sort_virtualmachinelabel_names(self, vmnames): - bootstrap = self.policy_get_bootstrap_vmlabel() - if bootstrap not in vmnames: - raise SecurityError(-xsconstants.XSERR_POLICY_INCONSISTENT) - vmnames.remove(bootstrap) - vmnames.sort() - vmnames.insert(0, bootstrap) - if ACM_LABEL_UNLABELED in vmnames: - vmnames.remove(ACM_LABEL_UNLABELED) - vmnames.insert(0, ACM_LABEL_UNLABELED) - return vmnames - - def policy_get_virtualmachinelabel_names_sorted(self): - """ Get a sorted list of VMlabel names. The bootstrap VM's - label will be the first one in that list, followed - by an alphabetically sorted list of VM label names """ - vmnames = self.policy_get_virtualmachinelabel_names() - res = self.policy_sort_virtualmachinelabel_names(vmnames) - if res[0] != ACM_LABEL_UNLABELED: - res.insert(0, ACM_LABEL_UNLABELED) - return res - - def policy_get_virtualmachinelabels(self): - """ Get a list of all virtual machine labels in this policy """ - res = [] - node = self.dom_get_node("SecurityLabelTemplate/SubjectLabels") - if node: - i = 0 - while i < len(node.childNodes): - if node.childNodes[i].nodeName == "VirtualMachineLabel": - name = self.policy_dom_get(node.childNodes[i], "Name") - if len(name.childNodes) > 0: - _res = {} - _res['type'] = xsconstants.ACM_LABEL_VM - _res['name'] = name.childNodes[0].nodeValue - stes = self.policy_dom_get(node.childNodes[i], - "SimpleTypeEnforcementTypes") - if stes: - _res['stes'] = self.policy_get_types(stes) - else: - _res['stes'] = [] - chws = self.policy_dom_get(node.childNodes[i], - "ChineseWallTypes") - if chws: - _res['chws'] = self.policy_get_types(chws) - else: - _res['chws'] = [] - res.append(_res) - i += 1 - return res - - def policy_get_stes_of_vmlabel(self, vmlabel): - """ Get a list of all STEs of a given VMlabel """ - return self.__policy_get_stes_of_labeltype(vmlabel, - "/SubjectLabels", "VirtualMachineLabel") - - def policy_get_stes_of_resource(self, reslabel): - """ Get a list of all resources of a given VMlabel """ - return self.__policy_get_stes_of_labeltype(reslabel, - "/ObjectLabels", "ResourceLabel") - - def __policy_get_stes_of_labeltype(self, label, path, labeltype): - node = self.dom_get_node("SecurityLabelTemplate" + path) - if node: - i = 0 - while i < len(node.childNodes): - if node.childNodes[i].nodeName == labeltype: - name = self.policy_dom_get(node.childNodes[i], "Name") - if len(name.childNodes) > 0 and \ - name.childNodes[0].nodeValue == label: - stes = self.policy_dom_get(node.childNodes[i], - "SimpleTypeEnforcementTypes") - if not stes: - return [] - return self.policy_get_types(stes) - i += 1 - return [] - - def policy_check_vmlabel_against_reslabels(self, vmlabel, resources): - """ - Check whether the given vmlabel is compatible with the given - resource labels. Do this by getting all the STEs of the - vmlabel and the STEs of the resources. Any STE type of the - VM label must match an STE type of the resource. - """ - vm_stes = self.policy_get_stes_of_vmlabel(vmlabel) - if len(vm_stes) == 0: - return False - for res in resources: - res_stes = self.policy_get_stes_of_resource(res) - if len(res_stes) == 0 or \ - len( set(res_stes).intersection( set(vm_stes) ) ) == 0: - return False - return True - - def __policy_get_label_translation_map(self, path, labeltype): - res = {} - node = self.dom_get_node("SecurityLabelTemplate/" + path) - if node: - i = 0 - while i < len(node.childNodes): - if node.childNodes[i].nodeName == labeltype: - name = self.policy_dom_get(node.childNodes[i], "Name") - from_name = name.getAttribute("from") - if from_name and len(name.childNodes) > 0: - res.update({from_name : name.childNodes[0].nodeValue}) - i += 1 - return res - - def policy_get_vmlabel_translation_map(self): - """ - Get a dictionary of virtual machine mappings from their - old VMlabel name to the new VMlabel name. - """ - return self.__policy_get_label_translation_map("SubjectLabels", - "VirtualMachineLabel") - - def policy_get_reslabel_translation_map(self): - """ - Get a dictionary of resource mappings from their - old resource label name to the new resource label name. - """ - return self.__policy_get_label_translation_map("ObjectLabels", - "ResourceLabel") - - # - # Object Label-related functions - # - def policy_get_resourcelabel_names(self): - """ - Get the names of all resource labels in an array but - only those that actually have types - """ - strings = [] - node = self.dom_get_node("SecurityLabelTemplate/ObjectLabels") - if node: - i = 0 - while i < len(node.childNodes): - if node.childNodes[i].nodeName == "ResourceLabel": - name = self.policy_dom_get(node.childNodes[i], "Name") - stes = self.policy_dom_get(node.childNodes[i], - "SimpleTypeEnforcementTypes") - if stes and len(name.childNodes) > 0: - strings.append(name.childNodes[0].nodeValue) - i += 1 - return strings - - def policy_get_resourcelabels(self): - """ - Get all information about all resource labels of this policy. - """ - res = [] - node = self.dom_get_node("SecurityLabelTemplate/ObjectLabels") - if node: - i = 0 - while i < len(node.childNodes): - if node.childNodes[i].nodeName == "ResourceLabel": - name = self.policy_dom_get(node.childNodes[i], "Name") - if len(name.childNodes) > 0: - _res = {} - _res['type'] = xsconstants.ACM_LABEL_RES - _res['name'] = name.childNodes[0].nodeValue - stes = self.policy_dom_get(node.childNodes[i], - "SimpleTypeEnforcementTypes") - if stes: - _res['stes'] = self.policy_get_types(stes) - else: - _res['stes'] = [] - _res['chws'] = [] - res.append(_res) - i += 1 - return res - - - def policy_find_reslabels_with_stetype(self, stetype): - """ - Find those resource labels that hold a given STE type. - """ - res = [] - reslabels = self.policy_get_resourcelabels() - for resl in reslabels: - if stetype in resl['stes']: - res.append(resl['name']) - return res - - - def toxml(self): - dom = self.get_dom() - if dom: - return dom.toxml() - return None - - def hash(self): - """ Calculate a SHA1 hash of the XML policy """ - return sha1(self.toxml()) - - def save(self): - ### Save the XML policy into a file ### - rc = -xsconstants.XSERR_FILE_ERROR - name = self.get_name() - if name: - path = self.path_from_policy_name(name) - if path: - f = open(path, 'w') - if f: - try: - try: - f.write(self.toxml()) - rc = 0 - except: - pass - finally: - f.close() - return rc - - def __write_to_file(self, suffix, data): - #write the data into a file with the given suffix - f = open(self.get_filename(suffix),"w") - if f: - try: - try: - f.write(data) - except Exception, e: - log.error("Error writing file: %s" % str(e)) - return -xsconstants.XSERR_FILE_ERROR - finally: - f.close() - else: - return -xsconstants.XSERR_FILE_ERROR - return xsconstants.XSERR_SUCCESS - - - def compile(self): - rc = self.save() - if rc == 0: - rc, mapfile, bin_pol = self.policy_create_map_and_bin() - - if rc == 0: - try: - security.mapfile_lock() - - rc = self.__write_to_file(".map", mapfile) - if rc != 0: - log.error("Error writing map file") - - finally: - security.mapfile_unlock() - - if rc == 0: - rc = self.__write_to_file(".bin", bin_pol) - if rc != 0: - log.error("Error writing binary policy file") - return rc - - def loadintohv(self): - """ - load this policy into the hypervisor - if successful,the policy's flags will indicate that the - policy is the one loaded into the hypervisor - """ - if not self.isloaded(): - (ret, output) = commands.getstatusoutput( - security.xensec_tool + - " loadpolicy " + - self.get_filename(".bin")) - if ret != 0: - return -xsconstants.XSERR_POLICY_LOAD_FAILED - return xsconstants.XSERR_SUCCESS - - def isloaded(self): - """ - Determine whether this policy is the active one. - """ - if self.get_name() == security.get_active_policy_name(): - return True - return False - - def destroy(self): - """ - Destroy the policy including its binary, mapping and - XML files. - This only works if the policy is not the one that's loaded - """ - if self.isloaded(): - return -xsconstants.XSERR_POLICY_LOADED - files = [ self.get_filename(".map",""), - self.get_filename(".bin","") ] - for f in files: - try: - os.unlink(f) - except: - pass - if self.xendacmpolicy: - self.xendacmpolicy.destroy() - XSPolicy.destroy(self) - return xsconstants.XSERR_SUCCESS - - def policy_get_domain_label(self, domid): - """ - Given a domain's ID, retrieve the label it has using - its ssidref for reverse calculation. - """ - try: - mgmt_dom = security.get_ssid(domid) - except: - return "" - return self.policy_get_domain_label_by_ssidref(int(mgmt_dom[3])) - - def policy_get_domain_label_by_ssidref(self, ssidref): - """ Given an ssidref, find the corresponding VM label """ - chwall_ref = ssidref & 0xffff - try: - allvmtypes = self.policy_get_virtualmachinelabel_names_sorted() - except: - return None - return allvmtypes[chwall_ref] - - def policy_get_domain_label_formatted(self, domid): - label = self.policy_get_domain_label(domid) - if label == "": - label = ACM_LABEL_UNLABELED - return "%s:%s:%s" % (xsconstants.ACM_POLICY_ID, self.get_name(), label) - - def policy_get_domain_label_by_ssidref_formatted(self, ssidref): - label = self.policy_get_domain_label_by_ssidref(ssidref) - if label == "": - return "" - return "%s:%s:%s" % (xsconstants.ACM_POLICY_ID, self.get_name(), label) - - def policy_create_map_and_bin(self): - """ - Create the policy's map and binary files -- compile the policy. - """ - def roundup8(len): - return ((len + 7) & ~7) - - rc = xsconstants.XSERR_SUCCESS - mapfile = "" - primpolcode = ACM_POLICY_UNDEFINED - secpolcode = ACM_POLICY_UNDEFINED - unknown_ste = set() - unknown_chw = set() - unlabeled_ste = "__NULL_LABEL__" - unlabeled_chw = "__NULL_LABEL__" - - rc = self.validate() - if rc: - return rc, "", "" - - stes = self.policy_get_stetypes_types() - if stes: - stes.sort() - - chws = self.policy_get_chwall_types() - if chws: - chws.sort() - - vms = self.policy_get_virtualmachinelabels() - bootstrap = self.policy_get_bootstrap_vmlabel() - - vmlabels = self.policy_get_virtualmachinelabel_names_sorted() - if bootstrap not in vmlabels: - log.error("Bootstrap label '%s' not found among VM labels '%s'." \ - % (bootstrap, vmlabels)) - return -xsconstants.XSERR_POLICY_INCONSISTENT, "", "" - - vms_with_chws = [] - chws_by_vm = { ACM_LABEL_UNLABELED : [] } - for v in vms: - if v.has_key("chws"): - vms_with_chws.append(v["name"]) - chws_by_vm[v["name"]] = v["chws"] - - - if bootstrap in vms_with_chws: - vms_with_chws.remove(bootstrap) - vms_with_chws.sort() - vms_with_chws.insert(0, bootstrap) - else: - vms_with_chws.sort() - - if ACM_LABEL_UNLABELED in vms_with_chws: - unlabeled_chw = ACM_LABEL_UNLABELED - vms_with_chws.remove(ACM_LABEL_UNLABELED) ; # @1 - - vms_with_stes = [] - stes_by_vm = { ACM_LABEL_UNLABELED : [] } - for v in vms: - if v.has_key("stes"): - vms_with_stes.append(v["name"]) - stes_by_vm[v["name"]] = v["stes"] - - if bootstrap in vms_with_stes: - vms_with_stes.remove(bootstrap) - vms_with_stes.sort() - vms_with_stes.insert(0, bootstrap) - else: - vms_with_stes.sort() - - if ACM_LABEL_UNLABELED in vms_with_stes: - unlabeled_ste = ACM_LABEL_UNLABELED - vms_with_stes.remove(ACM_LABEL_UNLABELED) ; # @2 - - resnames = self.policy_get_resourcelabel_names() - resnames.sort() - stes_by_res = {} - res = self.policy_get_resourcelabels() - for r in res: - if r.has_key("stes"): - stes_by_res[r["name"]] = r["stes"] - - if ACM_LABEL_UNLABELED in resnames: - resnames.remove(ACM_LABEL_UNLABELED) - - # check for duplicate labels - if len(vmlabels) != len(set(vmlabels)) or \ - len(resnames) != len(set(resnames)) or \ - len(stes) != len(set(stes)) or \ - len(chws) != len(set(chws)): - return -xsconstants.XSERR_POLICY_HAS_DUPLICATES, "", "" - - max_chw_ssids = 1 + len(vms_with_chws) - max_chw_types = 1 + len(vms_with_chws) - max_ste_ssids = 1 + len(vms_with_stes) + len(resnames) - max_ste_types = 1 + len(vms_with_stes) + len(resnames) - - mapfile = "POLICYREFERENCENAME %s\n" % self.get_name() - mapfile += "MAGIC %08x\n" % ACM_MAGIC - mapfile += "POLICFILE %s\n" % \ - self.path_from_policy_name(self.get_name()) - mapfile += "BINARYFILE %s\n" % self.get_filename(".bin") - mapfile += "MAX-CHWALL-TYPES %08x\n" % len(chws) - mapfile += "MAX-CHWALL-SSIDS %08x\n" % max_chw_ssids - mapfile += "MAX-CHWALL-LABELS %08x\n" % max_chw_ssids - mapfile += "MAX-STE-TYPES %08x\n" % len(stes) - mapfile += "MAX-STE-SSIDS %08x\n" % max_ste_ssids - mapfile += "MAX-STE-LABELS %08x\n" % max_ste_ssids - mapfile += "\n" - - if chws: - mapfile += \ - "PRIMARY CHWALL\n" - primpolcode = ACM_CHINESE_WALL_POLICY - if stes: - mapfile += \ - "SECONDARY STE\n" - else: - mapfile += \ - "SECONDARY NULL\n" - secpolcode = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY - else: - if stes: - mapfile += \ - "PRIMARY STE\n" - primpolcode = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY - mapfile += \ - "SECONDARY NULL\n" - - mapfile += "\n" - - if len(vms_with_chws) > 0: - mapfile += \ - "LABEL->SSID ANY CHWALL %-20s %x\n" % \ - (unlabeled_chw, 0) - i = 0 - for v in vms_with_chws: - mapfile += \ - "LABEL->SSID VM CHWALL %-20s %x\n" % \ - (v, i+1) - i += 1 - mapfile += "\n" - - if len(vms_with_stes) > 0 or len(resnames) > 0: - mapfile += \ - "LABEL->SSID ANY STE %-20s %08x\n" % \ - (unlabeled_ste, 0) - i = 0 - for v in vms_with_stes: - mapfile += \ - "LABEL->SSID VM STE %-20s %x\n" % (v, i+1) - i += 1 - j = 0 - for r in resnames: - mapfile += \ - "LABEL->SSID RES STE %-20s %x\n" % (r, j+i+1) - j += 1 - mapfile += "\n" - - if vms_with_chws: - mapfile += \ - "SSID->TYPE CHWALL %08x\n" % 0 - i = 1 - for v in vms_with_chws: - mapfile += \ - "SSID->TYPE CHWALL %08x" % i - for c in chws_by_vm[v]: - mapfile += " %s" % c - mapfile += "\n" - i += 1 - mapfile += "\n" - - if len(vms_with_stes) > 0 or len(resnames) > 0: - mapfile += \ - "SSID->TYPE STE %08x\n" % 0 - i = 1 - for v in vms_with_stes: - mapfile += \ - "SSID->TYPE STE %08x" % i - for s in stes_by_vm[v]: - mapfile += " %s" % s - mapfile += "\n" - i += 1 - - for r in resnames: - mapfile += \ - "SSID->TYPE STE %08x" % i - for s in stes_by_res[r]: - mapfile += " %s" % s - mapfile += "\n" - i += 1 - mapfile += "\n" - - if chws: - i = 0 - while i < len(chws): - mapfile += \ - "TYPE CHWALL %-20s %d\n" % (chws[i], i) - i += 1 - mapfile += "\n" - if stes: - i = 0 - while i < len(stes): - mapfile += \ - "TYPE STE %-20s %d\n" % (stes[i], i) - i += 1 - mapfile += "\n" - - mapfile += "\n" - - # Build header with policy name - length = roundup8(4 + len(self.get_name()) + 1) - polname = self.get_name(); - pr_bin = struct.pack("!i", len(polname)+1) - pr_bin += polname; - while len(pr_bin) < length: - pr_bin += "\x00" - - # Build chinese wall part - vms_with_chws.insert(0, ACM_LABEL_UNLABELED) - - cfses_names = self.policy_get_chwall_cfses_names_sorted() - cfses = self.policy_get_chwall_cfses() - - chwformat = "!iiiiiiiii" - max_chw_cfs = len(cfses) - chw_ssid_offset = struct.calcsize(chwformat) - chw_confset_offset = chw_ssid_offset + \ - 2 * len(chws) * max_chw_types - chw_running_types_offset = 0 - chw_conf_agg_offset = 0 - - chw_bin = struct.pack(chwformat, - ACM_CHWALL_VERSION, - ACM_CHINESE_WALL_POLICY, - len(chws), - max_chw_ssids, - max_chw_cfs, - chw_ssid_offset, - chw_confset_offset, - chw_running_types_offset, - chw_conf_agg_offset) - chw_bin_body = "" - - # VMs that are listed and their chinese walls - for v in vms_with_chws: - for c in chws: - unknown_chw |= (set(chws_by_vm[v]) - set(chws)) - if c in chws_by_vm[v]: - chw_bin_body += struct.pack("!h",1) - else: - chw_bin_body += struct.pack("!h",0) - - # Conflict sets -- they need to be processed in alphabetical order - for cn in cfses_names: - if cn == "" or cn is None: - return -xsconstants.XSERR_BAD_CONFLICTSET, "", "" - i = 0 - while i < len(cfses): - if cfses[i]['name'] == cn: - conf = cfses[i]['chws'] - break - i += 1 - for c in chws: - if c in conf: - chw_bin_body += struct.pack("!h",1) - else: - chw_bin_body += struct.pack("!h",0) - del cfses[i] - - if len(cfses) != 0: - return -xsconstants.XSERR_BAD_CONFLICTSET, "", "" - - chw_bin += chw_bin_body - - while len(chw_bin) < roundup8(len(chw_bin)): - chw_bin += "\x00" - - # Build STE part - vms_with_stes.insert(0, ACM_LABEL_UNLABELED) # Took out in @2 - - steformat="!iiiii" - ste_bin = struct.pack(steformat, - ACM_STE_VERSION, - ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, - len(stes), - max_ste_types, - struct.calcsize(steformat)) - ste_bin_body = "" - if stes: - # VMs that are listed and their STE types - for v in vms_with_stes: - unknown_ste |= (set(stes_by_vm[v]) - set(stes)) - for s in stes: - if s in stes_by_vm[v]: - ste_bin_body += struct.pack("!h",1) - else: - ste_bin_body += struct.pack("!h",0) - for r in resnames: - unknown_ste |= (set(stes_by_res[r]) - set(stes)) - for s in stes: - if s in stes_by_res[r]: - ste_bin_body += struct.pack("!h",1) - else: - ste_bin_body += struct.pack("!h",0) - - ste_bin += ste_bin_body; - - while len(ste_bin) < roundup8(len(ste_bin)): - ste_bin += "\x00" - - #Write binary header: - headerformat="!iiiiiiiiii20s" - totallen_bin = struct.calcsize(headerformat) + \ - len(pr_bin) + len(chw_bin) + len(ste_bin) - polref_offset = struct.calcsize(headerformat) - primpoloffset = polref_offset + len(pr_bin) - if primpolcode == ACM_CHINESE_WALL_POLICY: - secpoloffset = primpoloffset + len(chw_bin) - elif primpolcode == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY: - secpoloffset = primpoloffset + len(ste_bin) - else: - secpoloffset = primpoloffset - - (major, minor) = self.getVersionTuple() - hdr_bin = struct.pack(headerformat, - ACM_MAGIC, - ACM_POLICY_VERSION, - totallen_bin, - polref_offset, - primpolcode, - primpoloffset, - secpolcode, - secpoloffset, - major, minor, - self.hash().digest()) - - all_bin = array.array('B') - for s in [ hdr_bin, pr_bin, chw_bin, ste_bin ]: - for c in s: - all_bin.append(ord(c)) - - log.info("Compiled policy: rc = %s" % hex(rc)) - if len(unknown_ste) > 0: - log.info("The following STEs in VM/res labels were unknown:" \ - " %s" % list(unknown_ste)) - rc = -xsconstants.XSERR_BAD_LABEL - if len(unknown_chw) > 0: - log.info("The following Ch. Wall types in labels were unknown:" \ - " %s" % list(unknown_chw)) - rc = -xsconstants.XSERR_BAD_LABEL - return rc, mapfile, all_bin.tostring() - - def validate_enforced_policy_hash(self): - """ verify that the policy hash embedded in the binary policy - that is currently enforce matches the one of the XML policy. - """ - if self.hash().digest() != self.get_enforced_policy_hash(): - raise Exception('Policy hashes do not match') - - def get_enforced_policy_hash(self): - binpol = self.get_enforced_binary() - headerformat="!iiiiiiiiii20s" - res = struct.unpack(headerformat, binpol[:60]) - if len(res) >= 11: - return res[10] - return None - - def get_enforced_binary(self): - rc, binpol = security.hv_get_policy() - if rc != 0: - raise SecurityError(-xsconstants.XSERR_HV_OP_FAILED) - return binpol - - get_enforced_binary = classmethod(get_enforced_binary) diff --git a/tools/python/xen/util/asserts.py b/tools/python/xen/util/asserts.py deleted file mode 100644 index dd3cb7f852..0000000000 --- a/tools/python/xen/util/asserts.py +++ /dev/null @@ -1,27 +0,0 @@ -#=========================================================================== -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2005 XenSource Ltd -#============================================================================ - - -def isCharConvertible(c): - """Assert that the given value is convertible to a character using the %c - conversion. This implies that c is either an integer, or a character - (i.e. a string of length 1). - """ - - assert (isinstance(c, int) or - (isinstance(c, str) and - len(c) == 1)), "%s is not convertible to a character" % c diff --git a/tools/python/xen/util/auxbin.py b/tools/python/xen/util/auxbin.py deleted file mode 100644 index a690ad94d1..0000000000 --- a/tools/python/xen/util/auxbin.py +++ /dev/null @@ -1,47 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2005-2006 XenSource Inc. -#============================================================================ - - -import os -import os.path -import sys -from xen.util.path import * - -def execute(exe, args = None): - exepath = pathTo(exe) - a = [ exepath ] - if args: - a.extend(args) - try: - os.execv(exepath, a) - except (OSError, TypeError), exn: - print exepath, ": ", exn - sys.exit(1) - -SEARCHDIRS = [ BINDIR, SBINDIR, LIBEXEC, PRIVATE_BINDIR, XENFIRMWAREDIR ] -def pathTo(exebin): - for dir in SEARCHDIRS: - exe = os.path.join(dir, exebin) - if os.path.exists(exe): - return exe - return None - -def xen_configdir(): - return XEN_CONFIG_DIR - -def scripts_dir(): - return XEN_SCRIPT_DIR diff --git a/tools/python/xen/util/blkif.py b/tools/python/xen/util/blkif.py deleted file mode 100644 index 4bbae308af..0000000000 --- a/tools/python/xen/util/blkif.py +++ /dev/null @@ -1,107 +0,0 @@ -import os -import re -import string - -def expand_dev_name(name): - if not name: - return name - if re.match( '^/', name ): - return name - else: - return '/dev/' + name - -def blkdev_name_to_number(name): - """Take the given textual block-device name (e.g., '/dev/sda1', - 'hda') and return the device number used by the OS. """ - - n = expand_dev_name(name) - - devname = 'virtual-device' - devnum = None - - scsi_major = [ 8, 65, 66, 67, 68, 69, 70, 71, 128, 129, 130, 131, 132, 133, 134, 135 ] - if re.match( '/dev/sd[a-z]([1-9]|1[0-5])?$', n): - major = scsi_major[(ord(n[7:8]) - ord('a')) / 16] - minor = ((ord(n[7:8]) - ord('a')) % 16) * 16 + int(n[8:] or 0) - devnum = major * 256 + minor - elif re.match( '/dev/sd[a-i][a-z]([1-9]|1[0-5])?$', n): - major = scsi_major[((ord(n[7:8]) - ord('a') + 1) * 26 + (ord(n[8:9]) - ord('a'))) / 16 ] - minor = (((ord(n[7:8]) - ord('a') + 1 ) * 26 + (ord(n[8:9]) - ord('a'))) % 16) * 16 + int(n[9:] or 0) - devnum = major * 256 + minor - elif re.match( '/dev/hd[a-t]([1-9]|[1-5][0-9]|6[0-3])?$', n): - ide_majors = [ 3, 22, 33, 34, 56, 57, 88, 89, 90, 91 ] - major = ide_majors[(ord(n[7:8]) - ord('a')) / 2] - minor = ((ord(n[7:8]) - ord('a')) % 2) * 64 + int(n[8:] or 0) - devnum = major * 256 + minor - elif re.match( '/dev/xvd[a-p]([1-9]|1[0-5])?$', n): - devnum = (202 << 8) + ((ord(n[8:9]) - ord('a')) << 4) + int(n[9:] or 0) - elif re.match('/dev/xvd[q-z]([1-9]|1[0-5])?$', n): - devname = 'virtual-device-ext' - devnum = (1 << 28) + ((ord(n[8:9]) - ord('a')) << 8) + int(n[9:] or 0) - elif re.match('/dev/xvd[a-i][a-z]([1-9]|1[0-5])?$', n): - devname = 'virtual-device-ext' - devnum = (1 << 28) + (((ord(n[8:9]) - ord('a') + 1) * 26 + (ord(n[9:10]) - ord('a'))) << 8) + int(n[10:] or 0) - elif re.match( '^(0x)[0-9a-fA-F]+$', name ): - devnum = string.atoi(name, 16) - elif re.match('^[0-9]+$', name): - devnum = string.atoi(name, 10) - - return (devname, devnum) - -def blkdev_segment(name): - """Take the given block-device name (e.g. '/dev/sda1', 'hda') - and return a dictionary { device, start_sector, - nr_sectors, type } - device: Device number of the given partition - start_sector: Index of first sector of the partition - nr_sectors: Number of sectors comprising this partition - type: 'Disk' or identifying name for partition type - """ - val = None - (name, n) = blkdev_name_to_number(name) - if not n is None: - val = { 'device' : n, - 'start_sector' : long(0), - 'nr_sectors' : long(1L<<63), - 'type' : 'Disk' } - return val - -def parse_uname(uname): - fn = typ = taptype = None - if uname.find(":") != -1: - (typ, fn) = uname.split(":", 1) - - if typ in ("phy") and not fn.startswith("/"): - fn = "/dev/%s" %(fn,) - - if typ in ("tap", "tap2"): - (taptype, fn) = fn.split(":", 1) - if taptype in ("tapdisk", "ioemu"): - (taptype, fn) = fn.split(":", 1) - return (fn, (typ,taptype)) - - -def blkdev_uname_to_file(uname): - """Take a blkdev uname and return the corresponding filename.""" - return parse_uname(uname)[0] - -def blkdev_uname_to_taptype(uname): - """Take a blkdev uname and return the blktap type.""" - return parse_uname(uname)[1] - -def mount_mode(name): - mode = None - name = expand_dev_name(name) - lines = os.popen('mount 2>/dev/null').readlines() - exp = re.compile('^' + name + ' .*[\(,]r(?P[ow])[,\)]') - for line in lines: - pm = exp.match(line) - if not pm: continue - mode = pm.group('mode') - break - if mode == 'w': - return mode - if mode == 'o': - mode = 'r' - return mode - diff --git a/tools/python/xen/util/bootloader.py b/tools/python/xen/util/bootloader.py deleted file mode 100644 index d3b2de7fcc..0000000000 --- a/tools/python/xen/util/bootloader.py +++ /dev/null @@ -1,626 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2006,2007 International Business Machines Corp. -# Author: Stefan Berger -#============================================================================ - -import re -import os, stat -import tempfile -import shutil -import threading - -from xen.xend.XendLogging import log -from xen.util import mkdir -import xen.util.xsm.xsm as security - -# -# Functions for modifying entries in the bootloader, i.e. adding -# a module to boot the system with a policy. -# - -def get_default_title(): - """ See description in Bootloader class below """ - return __bootloader.get_default_title() - - -def get_boot_policies(): - """ See description in Bootloader class below """ - return __bootloader.get_boot_policies() - - -def add_boot_policy(index, binpolname): - """ See description in Bootloader class below """ - return __bootloader.add_boot_policy(index, binpolname) - - -def rm_policy_from_boottitle(index, unamelist): - """ See description in Bootloader class below """ - return __bootloader.rm_policy_from_boottitle(index, unamelist) - - -def set_kernel_attval(index, att, val): - """ See description in Bootloader class below """ - return __bootloader.set_kernel_attval(index, att, val) - - -def get_kernel_val(index, att): - """ See description in Bootloader class below """ - return __bootloader.get_kernel_val(index, att) - - -def set_boot_policy(title_idx, filename): - boottitles = get_boot_policies() - for key in boottitles.iterkeys(): - boottitles[key] += ".bin" - if boottitles.has_key(title_idx): - rm_policy_from_boottitle(title_idx, [ boottitles[title_idx] ]) - rc = add_boot_policy(title_idx, filename) - return rc - - -def loads_default_policy(filename): - """ Determine whether the given policy is loaded by the default boot title """ - policy = get_default_policy() - if policy: - polfile = policy + ".bin" - if polfile == filename or \ - "/"+polfile == filename: - return True - return False - - -def get_default_policy(): - """ Get the name of the policy loaded by the default boot title """ - title = get_default_title() - policies = get_boot_policies() - return policies.get(title) - - -def set_default_boot_policy(filename): - """ Set the boot policy in the default title to the given name. """ - title = get_default_title() - return set_boot_policy(title, filename) - - -def __is_bootdir_mounted(): - """ - Determine whether the boot partition /boot is mounted or not - """ - rc = False - file = open("/proc/mounts") - for line in file: - tmp = line.split(" ") - if tmp[1] == "/boot": - rc = True - break - return rc - -def get_prefix(): - if __is_bootdir_mounted(): - return "/" - else: - return "/boot/" - - - -class Bootloader: - """ Bootloader class that real bootloader implementations must overwrite """ - def __init__(self): - pass - - def probe(self): - """ Test whether this implementation of a bootloader is supported on the - local system """ - return True - - def get_default_title(self): - """ Get the index (starting with 0) of the default boot title - This number is read from the grub configuration file. - In case of an error '-1' is returned - @rtype: int - @return: the index of the default boot title - """ - return None - - def get_boot_policies(self): - """ Get a dictionary of policies that the system is booting with. - @rtype: dict - @return: dictionary of boot titles where the keys are the - indices of the boot titles - """ - return {} - - def add_boot_policy(self, index, binpolname): - """ Add the binary policy for automatic loading when - booting the system. Add it to the boot title at index - 'index'. - """ - return False - - def rm_policy_from_boottitle(self, index, unamelist): - """ Remove a policy from the given title. A list of possible policies - must be given to detect what module to remove - """ - return False - - def set_kernel_attval(self, index, att, val): - """ - Append an attribut/value pair to the kernel line. - @param index : The index of the title to modify - @param att : The attribute to add - @param val : The value to add. If no value or the special value - '<>' is given, then the attribute will be removed. - If an empty value is given, then only the attribute - is added in the format "att", otherwise "att=val" - is added. - """ - return False - - def get_kernel_val(self, index, att): - """ - Get an attribute's value from the kernel line. - @param index : The index of the title to get the attribute/value from - @param att : The attribute to read the value of - """ - return None - - -class Grub(Bootloader): - """ Implementation for manipulating bootloader entries in grub according - to the 'Bootloader' class interface """ - - def __init__(self): - self.__bootfile_lock = threading.RLock() - self.title_re = re.compile("\s*title\s", re.IGNORECASE) - self.module_re = re.compile("\s+module\s", re.IGNORECASE) - self.policy_re = re.compile(".*\.bin", re.IGNORECASE) - self.kernel_re = re.compile("\s*kernel\s", re.IGNORECASE) - Bootloader.__init__(self) - - def probe(self): - try: - boot_file = self.__get_bootfile() - except: - return False - return True - - - def __get_bootfile(self): - """ Get the name of the bootfile """ - boot_file = "/boot/grub/grub.conf" - alt_boot_file = "/boot/grub/menu.lst" - - if not os.path.isfile(boot_file): - #take alternate boot file instead - boot_file = alt_boot_file - - #follow symlink since menue.lst might be linked to grub.conf - if not os.path.exists(boot_file): - raise IOError("Boot file \'%s\' not found." % boot_file) - - if stat.S_ISLNK(os.lstat(boot_file)[stat.ST_MODE]): - new_name = os.readlink(boot_file) - if new_name[0] == "/": - boot_file = new_name - else: - path = boot_file.split('/') - path[len(path)-1] = new_name - boot_file = '/'.join(path) - if not os.path.exists(boot_file): - raise IOError("Boot file \'%s\' not found." % boot_file) - return boot_file - - - def get_default_title(self): - """ Get the index (starting with 0) of the default boot title - This number is read from the grub configuration file. - In case of an error '-1' is returned - @rtype: int - @return: the index of the default boot title - """ - def_re = re.compile("default", re.IGNORECASE) - default = None - try: - boot_file = self.__get_bootfile() - except: - return default - try: - self.__bootfile_lock.acquire() - grub_fd = open(boot_file) - for line in grub_fd: - line = line.rstrip() - if def_re.match(line): - #remove 'default=' - line = line.lstrip()[8:] - default = int(line) - break - finally: - self.__bootfile_lock.release() - return default - - - def get_boot_policies(self): - """ Get a dictionary of policies that the system is booting with. - @rtype: dict - @return: dictionary of boot titles where the keys are the - indices of the boot titles - """ - policies = {} - within_title = 0 - idx = -1 - try: - boot_file = self.__get_bootfile() - except: - return policies - try: - self.__bootfile_lock.acquire() - - grub_fd = open(boot_file) - for line in grub_fd: - if self.title_re.match(line): - within_title = 1 - idx = idx + 1 - if within_title and self.module_re.match(line): - if self.policy_re.match(line): - start = line.find("module") - pol = line[start+6:] - pol = pol.strip() - if pol[0] == '/': - pol = pol[1:] - if pol[0:5] == "boot/": - pol = pol[5:] - if pol.endswith(".bin"): - pol = pol[:-4] - policies[idx] = pol - finally: - self.__bootfile_lock.release() - return policies - - - def add_boot_policy(self, index, binpolname): - """ Add the binary policy for automatic loading when - booting the system. Add it to the boot title at index - 'index'. - """ - ctr = 0 - module_line = "" - within_title = 0 - found = False - try: - boot_file = self.__get_bootfile() - except: - return False - try: - self.__bootfile_lock.acquire() - grub_fd = open(boot_file) - (tmp_fd, tmp_grub) = tempfile.mkstemp() - for line in grub_fd: - if self.title_re.match(line): - if module_line != "" and not found: - os.write(tmp_fd, module_line) - found = True - - if ctr == index: - within_title = 1 - else: - within_title = 0 - ctr = ctr + 1 - elif within_title and self.module_re.match(line): - start = line.find("module") - l = line[start+6:len(line)] - l = l.lstrip() - if l[0] == '/': - prefix = "/" - else: - prefix = "" - prefix = get_prefix() - module_line = "\tmodule %s%s\n" % (prefix,binpolname) - else: - if module_line != "" and not found: - os.write(tmp_fd, module_line) - found = True - - os.write(tmp_fd, line) - - if module_line != "" and not found: - if ord(line[-1]) not in [ 10 ]: - os.write(tmp_fd, '\n') - os.write(tmp_fd, module_line) - found = True - - shutil.move(boot_file, boot_file+"_save") - shutil.copyfile(tmp_grub, boot_file) - os.close(tmp_fd) - try: - os.remove(tmp_grub) - except: - pass - finally: - self.__bootfile_lock.release() - return found - - - def rm_policy_from_boottitle(self, index, unamelist): - """ Remove a policy from the given title. A list of possible policies - must be given to detect what module to remove - """ - found = False - ctr = 0 - within_title = 0 - - prefix = get_prefix() - namelist = [prefix+name for name in unamelist] - - try: - boot_file = self.__get_bootfile() - except: - return False - try: - self.__bootfile_lock.acquire() - - grub_fd = open(boot_file) - (tmp_fd, tmp_grub) = tempfile.mkstemp() - for line in grub_fd: - omit_line = False - if self.title_re.match(line): - if ctr == index: - within_title = 1 - else: - within_title = 0 - ctr = ctr + 1 - if within_title and self.module_re.match(line): - if self.policy_re.match(line): - start = line.find("module") - pol = line[start+6:len(line)] - pol = pol.strip() - if pol in namelist: - omit_line = True - found = True - if not omit_line: - os.write(tmp_fd, line) - if found: - shutil.move(boot_file, boot_file+"_save") - shutil.copyfile(tmp_grub, boot_file) - os.close(tmp_fd) - try: - os.remove(tmp_grub) - except: - pass - finally: - self.__bootfile_lock.release() - return found - - - def set_kernel_attval(self, index, att, val): - """ - Append an attribut/value pair to the kernel line. - @param index : The index of the title to modify - @param att : The attribute to add - @param val : The value to add. If no value or the special value - '<>' is given, then the attribute will be removed. - If an empty value is given, then only the attribute - is added in the format "att", otherwise "att=val" - is added. - """ - found = False - ctr = 0 - within_title = 0 - try: - boot_file = self.__get_bootfile() - except: - False - try: - self.__bootfile_lock.acquire() - - grub_fd = open(boot_file) - (tmp_fd, tmp_grub) = tempfile.mkstemp() - for line in grub_fd: - if self.title_re.match(line): - if ctr == index: - within_title = 1 - else: - within_title = 0 - ctr = ctr + 1 - if within_title and self.kernel_re.match(line): - nitems = [] - items = line.split(" ") - i = 0 - while i < len(items): - el = items[i].split("=",1) - if el[0] != att: - nitems.append(items[i].rstrip("\n")) - i += 1 - if val == "": - nitems.append("%s" % (att)) - elif val != None and val != "<>": - nitems.append("%s=%s" % (att,val)) - line = " ".join(nitems) + "\n" - os.write(tmp_fd, line) - shutil.move(boot_file, boot_file+"_save") - shutil.copyfile(tmp_grub, boot_file) - os.close(tmp_fd) - try: - os.remove(tmp_grub) - except: - pass - finally: - self.__bootfile_lock.release() - return found - - - def get_kernel_val(self, index, att): - """ - Get an attribute's value from the kernel line. - @param index : The index of the title to get the attribute/value from - @param att : The attribute to read the value of - """ - ctr = 0 - within_title = 0 - try: - boot_file = self.__get_bootfile() - except: - return None - try: - self.__bootfile_lock.acquire() - - grub_fd = open(boot_file) - for line in grub_fd: - if self.title_re.match(line): - if ctr == index: - within_title = 1 - else: - within_title = 0 - ctr = ctr + 1 - if within_title and self.kernel_re.match(line): - line = line.strip() - items = line.split(" ") - i = 0 - while i < len(items): - el = items[i].split("=",1) - if el[0] == att: - if len(el) == 1: - return "<>" - return el[1] - i += 1 - finally: - self.__bootfile_lock.release() - return None # Not found - -class LatePolicyLoader(Bootloader): - """ A fake bootloader file that holds the policy to load automatically - once xend has started up and the Domain-0 label to set. """ - def __init__(self): - self.__bootfile_lock = threading.RLock() - self.PATH = security.security_dir_prefix - self.FILENAME = self.PATH + "/xen_boot_policy" - self.DEFAULT_TITLE = "ANY" - self.POLICY_ATTR = "POLICY" - Bootloader.__init__(self) - - def probe(self): - try: - _dir=os.path.dirname(self.FILENAME) - mkdir.parents(_dir, stat.S_IRWXU) - except: - return False - return True - - def get_default_title(self): - return self.DEFAULT_TITLE - - def get_boot_policies(self): - policies = {} - try: - self.__bootfile_lock.acquire() - - res = self.__loadcontent() - - pol = res.get( self.POLICY_ATTR ) - if pol: - policies.update({ self.DEFAULT_TITLE : pol }) - - finally: - self.__bootfile_lock.release() - - return policies - - def add_boot_policy(self, index, binpolname): - try: - self.__bootfile_lock.acquire() - - res = self.__loadcontent() - if binpolname.endswith(".bin"): - binpolname = binpolname[0:-4] - res[ self.POLICY_ATTR ] = binpolname - self.__writecontent(res) - finally: - self.__bootfile_lock.release() - - return True - - def rm_policy_from_boottitle(self, index, unamelist): - try: - self.__bootfile_lock.acquire() - - res = self.__loadcontent() - if self.POLICY_ATTR in res: - del(res[self.POLICY_ATTR]) - self.__writecontent(res) - finally: - self.__bootfile_lock.release() - - return True - - def set_kernel_attval(self, index, att, val): - try: - self.__bootfile_lock.acquire() - - res = self.__loadcontent() - res[att] = val - self.__writecontent(res) - finally: - self.__bootfile_lock.release() - - return True - - def get_kernel_val(self, index, att): - try: - self.__bootfile_lock.acquire() - - res = self.__loadcontent() - return res.get(att) - finally: - self.__bootfile_lock.release() - - def __loadcontent(self): - res={} - try: - file = open(self.FILENAME) - for line in file: - tmp = line.split("=",1) - if len(tmp) == 2: - res[tmp[0]] = tmp[1].strip() - file.close() - except: - pass - - return res - - def __writecontent(self, items): - rc = True - try: - file = open(self.FILENAME,"w") - if file: - for key, value in items.items(): - file.write("%s=%s\n" % (str(key),str(value))) - file.close() - except: - rc = False - - return rc - - -__bootloader = Bootloader() - -def init(): - global __bootloader - grub = Grub() - if grub.probe() == True: - __bootloader = grub - else: - late = LatePolicyLoader() - if late.probe() == True: - __bootloader = late diff --git a/tools/python/xen/util/bugtool.py b/tools/python/xen/util/bugtool.py deleted file mode 100644 index 2abcc86a43..0000000000 --- a/tools/python/xen/util/bugtool.py +++ /dev/null @@ -1,234 +0,0 @@ -#!/usr/bin/env python - -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# Copyright (c) 2005, XenSource Ltd. - - -import errno -import getpass -import httplib -import re -import os -import os.path -import StringIO -import sys -import tarfile -import tempfile -import time -import urllib - -import xen.lowlevel.xc - -from xen.xend import encode - - -SERVER = 'bugzilla.xen.org' -SHOW_BUG_PATTERN = 'http://%s/bugzilla/show_bug.cgi?id=%%d' % SERVER -ATTACH_PATTERN = \ - 'http://%s/bugzilla/attachment.cgi?bugid=%%d&action=enter' % SERVER - -TITLE_RE = re.compile(r'(.*)') - -FILES_TO_SEND = [ '/var/log/' + x for x in - [ 'syslog', 'messages', 'debug', - 'xen/xend-debug.log', 'xen/xenstored-trace.log', - 'xen/xen-hotplug.log', 'xen/xend.log' ] + - [ 'xen/xend.log.%d' % z for z in range(1,6) ] ] -#FILES_TO_SEND = [ ] - - -def main(argv = None): - if argv is None: - argv = sys.argv - - print ''' -This application will collate the Xen dmesg output, details of the hardware -configuration of your machine, information about the build of Xen that you are -using, plus, if you allow it, various logs. - -The information collated can either be posted to a Xen Bugzilla bug (this bug -must already exist in the system, and you must be a registered user there), or -it can be saved as a .tar.bz2 for sending or archiving. - -The collated logs may contain private information, and if you are at all -worried about that, you should exit now, or you should explicitly exclude -those logs from the archive. - -''' - - bugball = [] - - xc = xen.lowlevel.xc.xc() - - def do(n, f): - try: - s = f() - except Exception, exn: - s = str(exn) - bugball.append(string_iterator(n, s)) - - do('xen-dmesg', lambda: xc.readconsolering()) - do('physinfo', lambda: prettyDict(xc.physinfo())) - do('xeninfo', lambda: prettyDict(xc.xeninfo())) - - for filename in FILES_TO_SEND: - if not os.path.exists(filename): - continue - - if yes('Include %s? [Y/n] ' % filename): - bugball.append(file(filename)) - - maybeAttach(bugball) - - if (yes(''' -Do you wish to save these details as a tarball (.tar.bz2)? [Y/n] ''')): - tar(bugball) - - return 0 - - -def maybeAttach(bugball): - if not yes(''' -Do you wish to attach these details to a Bugzilla bug? [Y/n] '''): - return - - bug = int(raw_input('Bug number? ')) - - bug_title = getBugTitle(bug) - - if bug_title == 'Search by bug number' or bug_title == 'Invalid Bug ID': - print >>sys.stderr, 'Bug %d does not exist!' % bug - maybeAttach(bugball) - elif yes('Are you sure that you want to attach to %s? [Y/n] ' % - bug_title): - attach(bug, bugball) - else: - maybeAttach(bugball) - - -def attach(bug, bugball): - username = raw_input('Bugzilla username: ') - password = getpass.getpass('Bugzilla password: ') - - conn = httplib.HTTPConnection(SERVER) - try: - for f in bugball: - send(bug, conn, f, f.name, username, password) - finally: - conn.close() - - -def getBugTitle(bug): - f = urllib.urlopen(SHOW_BUG_PATTERN % bug) - - try: - for line in f: - m = TITLE_RE.search(line) - if m: - return m.group(1) - finally: - f.close() - - raise ValueError("Could not find title of bug %d!" % bug) - - -def send(bug, conn, fd, filename, username, password): - - print "Attaching %s to bug %d." % (filename, bug) - - headers, data = encode.encode_data( - { 'bugid' : str(bug), - 'action' : 'insert', - 'data' : fd, - 'description' : '%s from %s' % (filename, username), - 'contenttypeselection' : 'text/plain', - 'contenttypemethod' : 'list', - 'ispatch' : '0', - 'GoAheadAndLogIn' : '1', - 'Bugzilla_login' : username, - 'Bugzilla_password' : password, - }) - - conn.request('POST',ATTACH_PATTERN % bug, data, headers) - response = conn.getresponse() - try: - body = response.read() - m = TITLE_RE.search(body) - - if response.status != 200: - print >>sys.stderr, ( - 'Attach failed: %s %s.' % (response.status, response.reason)) - elif not m or m.group(1) != 'Changes Submitted': - print >>sys.stderr, ( - 'Attach failed: got a page titled %s.' % m.group(1)) - else: - print "Attaching %s to bug %d succeeded." % (filename, bug) - finally: - response.close() - - -def tar(bugball): - filename = raw_input('Tarball destination filename? ') - - now = time.time() - - tf = tarfile.open(filename, 'w:bz2') - - try: - for f in bugball: - ti = tarfile.TarInfo(f.name.split('/')[-1]) - if hasattr(f, 'size'): - ti.size = f.size() - else: - ti.size = os.stat(f.name).st_size - - ti.mtime = now - ti.type = tarfile.REGTYPE - ti.uid = 0 - ti.gid = 0 - ti.uname = 'root' - ti.gname = 'root' - - f.seek(0) # If we've added this file to a bug, it will have been - # read once already, so reset it. - tf.addfile(ti, f) - finally: - tf.close() - - print 'Writing tarball %s successful.' % filename - - -def prettyDict(d): - format = '%%-%ds: %%s' % max(map(len, [k for k, _ in d.items()])) - return '\n'.join([format % i for i in d.items()]) + '\n' - - -class string_iterator(StringIO.StringIO): - def __init__(self, name, val): - StringIO.StringIO.__init__(self, val) - self.name = name - - def size(self): - return len(self.getvalue()) - - -def yes(prompt): - yn = raw_input(prompt) - - return len(yn) == 0 or yn.lower()[0] == 'y' - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/tools/python/xen/util/diagnose.py b/tools/python/xen/util/diagnose.py deleted file mode 100644 index e31f396e73..0000000000 --- a/tools/python/xen/util/diagnose.py +++ /dev/null @@ -1,185 +0,0 @@ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# Copyright (c) 2005-2006 XenSource Inc - - -import re -import socket -import sys - -from xen.xend import sxp - -from xen.xend.XendClient import server -from xen.xend.XendError import XendError -from xen.xend.xenstore.xstransact import xstransact -from xen.xend.server import DevConstants - -import xen.xend.XendProtocol - - -domain = None -domid = None -deviceClass = None -device = None -frontendPath = None -backendPath = None - - -def diagnose(dom): - global domain - global domid - global dompath - - try: - domain = server.xend.domain(dom) - state = sxp.child_value(domain, 'state') - domid = int(sxp.child_value(domain, 'domid')) - name = sxp.child_value(domain, 'name') - - print "Domain ID is %d." % domid - print "Domain name is %s." % name - - if not state: - raise XendError("Cannot find state") - - if state.find('c') != -1: - print "Domain has crashed." - except socket.error, exn: - print "Cannot contact Xend." - - try: - domid = int(dom) - name = dom - except ValueError: - print \ -"Without Xend, you will have to specify the domain ID, not the domain name." - sys.exit(1) - except xen.xend.XendProtocol.XendError, exn: - print exn - sys.exit(1) - - dompath = '/local/domain/%d' % domid - diagnose_console() - diagnose_devices() - - -def diagnose_console(): - port = xstransact.Read(dompath + '/console/port') - ringref = xstransact.Read(dompath + '/console/ring-ref') - tty = xstransact.Read(dompath + '/console/tty') - - if not port: - print "Console port is missing; Xend has failed." - if not ringref: - print "Console ring-ref is missing; Xend has failed." - if not tty: - print "Console tty is missing; Xenconsoled has failed." - - -def diagnose_devices(): - global deviceClass - global device - global frontendPath - global backendPath - - device_path = dompath + '/device' - - device_classes = xstransact.List(device_path) - - print "Found %d device classes in use." % len(device_classes) - - for dc in device_classes: - deviceClass = dc - device_class_path = device_path + '/' + deviceClass - - devices = xstransact.List(device_class_path) - - print "Found %d %s devices." % (len(devices), deviceClass) - - for d in devices: - device = d - - print "Found device %s, %s." % (deviceClass, device) - - frontendPath = device_class_path + '/' + device - backendPath = xstransact.Read(frontendPath, 'backend') - - if not backendPath: - print ("Cannot find backend path for device %s, %s." % - (deviceClass, device)) - else: - frontend_state = xstransact.Read(frontendPath, 'state') - backend_state = xstransact.Read(backendPath, 'state') - - print "Backend is in state %s." % stateString(backend_state) - print "Frontend is in state %s." % stateString(frontend_state) - - check_for_error(True) - check_for_error(False) - - diagnose_hotplugging() - - -def check_for_error(backend): - if backend: - path = backendPath.replace('backend/', 'error/backend/') - else: - path = frontendPath.replace('device/', 'error/device/') - - err = xstransact.Read(path, 'error') - - if err: - print ("%s for device %s, %s shows error %s." % - (backend and 'Backend' or 'Frontend', deviceClass, device, - err)) - - -def diagnose_hotplugging(): - if deviceClass == 'vbd': - phy = xstransact.Read(backendPath, 'physical-device') - - if phy: - print ('Device %s, %s hotplugging has completed successfully, ' - 'and is connected to physical device %s.' % - (deviceClass, device, phy)) - else: - print ('Device %s, %s hotplugging failed.' % - (deviceClass, device)) - elif deviceClass == 'vif': - handle = xstransact.Read(backendPath, 'handle') - - if handle: - print ('Device %s, %s hotplugging has completed successfully, ' - 'and is using handle %s.' % - (deviceClass, device, handle)) - else: - print ('Device %s, %s hotplugging failed.' % - (deviceClass, device)) - - -def stateString(state): - return state and DevConstants.xenbusState[int(state)] or '' - - -def main(argv = None): - if argv is None: - argv = sys.argv - - diagnose(argv[1]) - - return 0 - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/tools/python/xen/util/dictio.py b/tools/python/xen/util/dictio.py deleted file mode 100644 index 4fcebdb88a..0000000000 --- a/tools/python/xen/util/dictio.py +++ /dev/null @@ -1,50 +0,0 @@ -#=========================================================================== -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2006 International Business Machines Corp. -# Author: Bryan D. Payne -#============================================================================ - - -def dict_read(dictname, filename): - """Loads and returns the dictionary named from - the file. - """ - dict = {} - - # read in the config file - globs = {} - locs = {} - execfile(filename, globs, locs) - - for (k, v) in locs.items(): - if k == dictname: - dict = v - break - - return dict - -def dict_write(dict, dictname, filename): - """Writes to using the name . If the file - contains any other data, it will be overwritten. - """ - prefix = dictname + " = {\n" - suffix = "}\n" - fd = open(filename, "wb") - fd.write(prefix) - for key in dict: - line = " '" + str(key) + "': " + str(dict[key]) + ",\n" - fd.write(line) - fd.write(suffix) - fd.close() diff --git a/tools/python/xen/util/fileuri.py b/tools/python/xen/util/fileuri.py deleted file mode 100644 index b4a79234fe..0000000000 --- a/tools/python/xen/util/fileuri.py +++ /dev/null @@ -1,156 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2009 flonatel GmbH & Co. KG -#============================================================================ - -import logging -import os -import base64 -import tempfile -import stat -from xen.xend.XendLogging import log -from xen.util import mkdir - -# -# This functions and classes can be used where a filename is expected - -# especially in the xenapi.VM.create() for PV_kernel and PV_ramdisk. -# -# The functions have a backward compatibility mode, i.e. when there is -# no appropriate scheme detected, the data is seens as a path to a -# (local) file. -# - -class scheme_error(Exception): - def __init__(self, value): - self.value = value - def __str__(self): - return repr(self.value) - -# Data scheme (as defined in RFC 2397): -# data:application/octet-stream;base64, -# It looks that there is currently no general purpose implementation -# available (in python) for this URL scheme - so the very basic is -# done here. -# -# Limitations -# o Only base64 is currently supported -class scheme_data: - - def encode(data, mediatype = 'application/octet-stream', - encoding = 'base64'): - # XXX Limit this to base64 for current implementation - if encoding!='base64': - raise scheme_error("invalid encoding") - return 'data:' + mediatype + ";" + encoding \ - + "," + base64.b64encode(data) - encode = staticmethod(encode) - - # Private method: parse encoded data - def parse(encoded_data): - if not isinstance(encoded_data, str): - raise scheme_error("encoded data has wrong type") - if not encoded_data.startswith('data:'): - raise scheme_error("'data:' scheme declaration missing") - comma = encoded_data.find(',', 5) - if comma == -1: - raise scheme_error("data separator (comma) is missing") - # Cut off the media type and encoding - mtenc = encoded_data[5:comma] - if len(mtenc)==0: - raise scheme_error("encoding is empty") - # XXX Limit to base64 encoding - if not mtenc.endswith(';base64'): - raise scheme_error("encoding is not base64") - mediatype = mtenc[:-7] - return (mediatype, 'base64', comma+1) - parse = staticmethod(parse) - - # Stores the data in a local file and returns the filename - # and a flag if this file in temporary only and must be deleted - # after starting the VM. - def decode(encoded_data): - mkdir.parents("/var/run/xend/boot/", stat.S_IRWXU) - mediatype, encoding, data_start = scheme_data.parse(encoded_data) - fd, filename = tempfile.mkstemp( - prefix="data_uri_file.", dir="/var/run/xend/boot") - # Because of python 2.3 support, there is a need to nest these - # (see http://www.python.org/doc/2.3/ref/try.html) - try: - try: - os.write(fd, base64.b64decode(encoded_data[data_start:])) - except TypeError, se: - raise scheme_error("failed to decode as base64") - finally: - os.close(fd) - return filename, True - decode = staticmethod(decode) - - # Utility function which reads in the given (local) file and - # creates a data scheme from this. - def create_from_file(filename): - try: - f = open(filename, "r") - d = f.read() - f.close() - return scheme_data.encode(d) - except IOError: - raise scheme_error("file does not exists") - create_from_file = staticmethod(create_from_file) - - -# File Scheme -# This class supports absolut paths only. -class scheme_file: - - def encode(filename): - if len(filename) == 0: - raise scheme_error("filename is empty") - if filename[0] != '/': - raise scheme_error("filename is not absolut") - return 'file://' + filename - encode = staticmethod(encode) - - def decode(encoded_data): - if not encoded_data.startswith("file://"): - raise scheme_error("no file:// scheme found") - path = encoded_data[7:] - if len(path)==0: - raise scheme_error("path is empty") - if path[0]!='/': - raise scheme_error("path is not absolute") - return path, False - decode = staticmethod(decode) - - -class scheme_set: - - def __init__(self): - self.schemes = [scheme_data, scheme_file] - - # log_decode_exception flags whether a specific uri schema - # decoding exception should be logged or not (default: False - do - # not log). - def decode(self, uri, log_decode_exception=False): - for scheme in self.schemes: - try: - # If this passes, it is the correct scheme - return scheme.decode(uri) - except scheme_error, se: - if log_decode_exception: - log.debug("Decode throws an error: '%s'" % se) - return uri, False - -schemes = scheme_set() - diff --git a/tools/python/xen/util/ip.py b/tools/python/xen/util/ip.py deleted file mode 100644 index 9133e886f2..0000000000 --- a/tools/python/xen/util/ip.py +++ /dev/null @@ -1,121 +0,0 @@ -import os -import re -import socket -import struct -import errno - -##### Networking-related functions - -def get_defaultroute(): - fd = os.popen('/sbin/ip route list 2>/dev/null') - for line in fd.readlines(): - m = re.search('^default via ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+) dev ([^ ]*)', - line) - if m: - return [m.group(1), m.group(2)] - return [None, None] - -def get_current_ipaddr(dev='defaultroute'): - """Get the primary IP address for the given network interface. - - dev network interface (default: default route device) - - returns interface address as a string - """ - if dev == 'defaultroute': - dev = get_defaultroute()[1] - if not dev: - return - fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' ) - for line in fd.readlines(): - m = re.search( '^\s+inet addr:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*', - line ) - if m: - return m.group(1) - return None - -def get_current_ipmask(dev='defaultroute'): - """Get the primary IP netmask for a network interface. - - dev network interface (default: default route device) - - returns interface netmask as a string - """ - if dev == 'defaultroute': - dev = get_defaultroute()[1] - if not dev: - return - fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' ) - for line in fd.readlines(): - m = re.search( '^.+Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*', - line ) - if m: - return m.group(1) - return None - -def get_current_ipgw(dev='defaultroute'): - """Get the IP gateway for a network interface. - - dev network interface (default: default route device) - - returns gateway address as a string - """ - if dev == 'defaultroute': - return get_defaultroute()[0] - if not dev: - return - fd = os.popen( '/sbin/route -n' ) - for line in fd.readlines(): - m = re.search( '^\S+\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)' + - '\s+\S+\s+\S*G.*' + dev + '.*', line ) - if m: - return m.group(1) - return None - -def inet_aton(addr): - """Convert an IP addr in IPv4 dot notation into an int. - - addr IP address as a string - - returns integer - """ - b = socket.inet_aton(addr) - return struct.unpack('!I', b)[0] - -def inet_ntoa(n): - """Convert an int into an IP addr in IPv4 dot notation. - - n IP address - - returns string - """ - b = struct.pack('!I', n) - return socket.inet_ntoa(b) - -def add_offset_to_ip(addr, offset): - """Add a numerical offset to an IP addr in IPv4 dot notation. - - addr IP address - offset offset to add - - returns new address - """ - n = inet_aton(addr) - n += offset - return inet_ntoa(n) - -def check_subnet( ip, network, netmask ): - """Check if an IP address is in the subnet defined by - a network address and mask'. - - ip IP adress - network network address - netmask network mask - - returns 1 if it is in the subnet, 0 if not - """ - n_ip = inet_aton(ip) - n_net = inet_aton(network) - n_mask = inet_aton(netmask) - return (n_ip & n_mask) == (n_net & n_mask) - diff --git a/tools/python/xen/util/mac.py b/tools/python/xen/util/mac.py deleted file mode 100644 index 47dffd80d5..0000000000 --- a/tools/python/xen/util/mac.py +++ /dev/null @@ -1,11 +0,0 @@ - -from string import join, split - -def macToString(mac): - return ':'.join(map(lambda x: "%02x" % x, mac)) - -def macFromString(str): - mac = [ int(x, 16) for x in str.split(':') ] - if len(mac) != 6: - raise ValueError("invalid mac: %s" % str) - return mac diff --git a/tools/python/xen/util/mkdir.py b/tools/python/xen/util/mkdir.py deleted file mode 100644 index 121e498a23..0000000000 --- a/tools/python/xen/util/mkdir.py +++ /dev/null @@ -1,44 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (c) 2006 XenSource Inc. -#============================================================================ - -import errno -import os -import os.path -import stat - - -def parents(dir, perms, enforcePermissions = False): - """ - Ensure that the given directory exists, creating it if necessary, but not - complaining if it's already there. - - @param dir The directory name. - @param perms One of the stat.S_ constants. - @param enforcePermissions Enforce our ownership and the given permissions, - even if the directory pre-existed with different ones. - """ - # Catch the exception here, rather than checking for the directory's - # existence first, to avoid races. - try: - os.makedirs(dir, perms) - except OSError, exn: - if exn.args[0] != errno.EEXIST or not os.path.isdir(dir): - raise - if enforcePermissions: - os.chown(dir, os.geteuid(), os.getegid()) - os.chmod(dir, stat.S_IRWXU) diff --git a/tools/python/xen/util/oshelp.py b/tools/python/xen/util/oshelp.py deleted file mode 100644 index c2c02824ce..0000000000 --- a/tools/python/xen/util/oshelp.py +++ /dev/null @@ -1,33 +0,0 @@ -import fcntl -import os - -def close_fds(pass_fds=()): - try: - MAXFD = os.sysconf('SC_OPEN_MAX') - except: - MAXFD = 256 - for i in range(3, MAXFD): - if i in pass_fds: - continue - try: - os.close(i) - except OSError: - pass - -def fcntl_setfd_cloexec(file, bool): - f = fcntl.fcntl(file, fcntl.F_GETFD) - if bool: f |= fcntl.FD_CLOEXEC - else: f &= ~fcntl.FD_CLOEXEC - fcntl.fcntl(file, fcntl.F_SETFD, f) - -def waitstatus_description(st): - if os.WIFEXITED(st): - es = os.WEXITSTATUS(st) - if es: return "exited with nonzero status %i" % es - else: return "exited" - elif os.WIFSIGNALED(st): - s = "died due to signal %i" % os.WTERMSIG(st) - if os.WCOREDUMP(st): s += " (core dumped)" - return s - else: - return "failed with unexpected wait status %i" % st diff --git a/tools/python/xen/util/pci.py b/tools/python/xen/util/pci.py deleted file mode 100644 index adeca4bbf9..0000000000 --- a/tools/python/xen/util/pci.py +++ /dev/null @@ -1,1416 +0,0 @@ -#!/usr/bin/env python -# -# PCI Device Information Class -# - Helps obtain information about which I/O resources a PCI device needs -# -# Author: Ryan Wilson - -import sys -import os, os.path -import errno -import resource -import re -import types -import struct -import time -import threading -from xen.util import utils -from xen.xend import uuid -from xen.xend import sxp -from xen.xend.XendConstants import AUTO_PHP_SLOT -from xen.xend.XendSXPDev import dev_dict_to_sxp -from xen.xend.XendLogging import log - -# for 2.3 compatibility -try: - set() -except NameError: - from sets import Set as set - -PROC_PCI_PATH = '/proc/bus/pci/devices' -PROC_PCI_NUM_RESOURCES = 7 - -SYSFS_PCI_DEVS_PATH = '/bus/pci/devices' -SYSFS_PCI_DEV_RESOURCE_PATH = '/resource' -SYSFS_PCI_DEV_CONFIG_PATH = '/config' -SYSFS_PCI_DEV_IRQ_PATH = '/irq' -SYSFS_PCI_DEV_DRIVER_DIR_PATH = '/driver' -SYSFS_PCI_DEV_VENDOR_PATH = '/vendor' -SYSFS_PCI_DEV_DEVICE_PATH = '/device' -SYSFS_PCI_DEV_SUBVENDOR_PATH = '/subsystem_vendor' -SYSFS_PCI_DEV_SUBDEVICE_PATH = '/subsystem_device' -SYSFS_PCI_DEV_CLASS_PATH = '/class' -SYSFS_PCIBACK_PATH = '/bus/pci/drivers/pciback/' -SYSFS_PCISTUB_PATH = '/bus/pci/drivers/pci-stub/' - -LSPCI_CMD = 'lspci' - -PCI_DEV_REG_EXPRESS_STR = r"[0-9a-fA-F]{4}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}."+ \ - r"[0-9a-fA-F]{1}" - -DEV_TYPE_PCIe_ENDPOINT = 0 -DEV_TYPE_PCIe_BRIDGE = 1 -DEV_TYPE_PCI_BRIDGE = 2 -DEV_TYPE_PCI = 3 - -PCI_VENDOR_ID = 0x0 -PCI_STATUS = 0x6 -PCI_CLASS_DEVICE = 0x0a -PCI_CLASS_BRIDGE_PCI = 0x0604 - -PCI_HEADER_TYPE = 0x0e -PCI_HEADER_TYPE_MASK = 0x7f -PCI_HEADER_TYPE_NORMAL = 0 -PCI_HEADER_TYPE_BRIDGE = 1 -PCI_HEADER_TYPE_CARDBUS = 2 - -PCI_CAPABILITY_LIST = 0x34 -PCI_CB_BRIDGE_CONTROL = 0x3e -PCI_BRIDGE_CTL_BUS_RESET= 0x40 - -PCI_CAP_ID_EXP = 0x10 -PCI_EXP_FLAGS = 0x2 -PCI_EXP_FLAGS_TYPE = 0x00f0 -PCI_EXP_TYPE_DOWNSTREAM = 0x6 -PCI_EXP_TYPE_PCI_BRIDGE = 0x7 -PCI_EXP_DEVCAP = 0x4 -PCI_EXP_DEVCAP_FLR = (0x1 << 28) -PCI_EXP_DEVCTL = 0x8 -PCI_EXP_DEVCTL_FLR = (0x1 << 15) - -PCI_EXT_CAP_ID_ACS = 0x000d -PCI_EXT_CAP_ACS_ENABLED = 0x1d # The bits V, R, C, U. -PCI_EXT_ACS_CTRL = 0x06 - - -PCI_CAP_ID_PM = 0x01 -PCI_PM_CTRL = 4 -PCI_PM_CTRL_NO_SOFT_RESET = 0x0008 -PCI_PM_CTRL_STATE_MASK = 0x0003 -PCI_D3hot = 3 -PCI_D0hot = 0 - -VENDOR_INTEL = 0x8086 -PCI_CAP_ID_VENDOR_SPECIFIC_CAP = 0x09 -PCI_CLASS_ID_USB = 0x0c03 -PCI_USB_FLRCTRL = 0x4 - -PCI_DEVICE_ID = 0x02 -PCI_COMMAND = 0x04 -PCI_CLASS_ID_VGA = 0x0300 - -PCI_DEVICE_ID_IGFX_GM45 = 0x2a42 -PCI_DEVICE_ID_IGFX_EAGLELAKE = 0x2e02 -PCI_DEVICE_ID_IGFX_Q45 = 0x2e12 -PCI_DEVICE_ID_IGFX_G45 = 0x2e22 -PCI_DEVICE_ID_IGFX_G41 = 0x2e32 - -PCI_CAP_IGFX_CAP09_OFFSET = 0xa4 -PCI_CAP_IGFX_CAP13_OFFSET = 0xa4 -PCI_CAP_IGFX_GDRST = 0X0d -PCI_CAP_IGFX_GDRST_OFFSET = 0xc0 - -# The VF of Intel 82599 10GbE Controller -# See http://download.intel.com/design/network/datashts/82599_datasheet.pdf -# For 'VF PCIe Configuration Space', see its Table 9.7. -DEVICE_ID_82599 = 0x10ed - -PCI_CAP_ID_AF = 0x13 -PCI_AF_CAPs = 0x3 -PCI_AF_CAPs_TP_FLR = 0x3 -PCI_AF_CTL = 0x4 -PCI_AF_CTL_FLR = 0x1 - -PCI_BAR_0 = 0x10 -PCI_BAR_5 = 0x24 -PCI_BAR_SPACE = 0x01 -PCI_BAR_IO = 0x01 -PCI_BAR_IO_MASK = ~0x03 -PCI_BAR_MEM = 0x00 -PCI_BAR_MEM_MASK = ~0x0f -PCI_STATUS_CAP_MASK = 0x10 -PCI_STATUS_OFFSET = 0x6 -PCI_CAP_OFFSET = 0x34 -MSIX_BIR_MASK = 0x7 -MSIX_SIZE_MASK = 0x7ff - -# Global variable to store information from lspci -lspci_info = None -lspci_info_lock = threading.RLock() - -#Calculate PAGE_SHIFT: number of bits to shift an address to get the page number -PAGE_SIZE = resource.getpagesize() -PAGE_SHIFT = 0 -t = PAGE_SIZE -while not (t&1): - t>>=1 - PAGE_SHIFT+=1 - -PAGE_MASK=~(PAGE_SIZE - 1) -# Definitions from Linux: include/linux/pci.h -def PCI_DEVFN(slot, func): - return ((((slot) & 0x1f) << 3) | ((func) & 0x07)) -def PCI_SLOT(devfn): - return (devfn >> 3) & 0x1f -def PCI_FUNC(devfn): - return devfn & 0x7 - -def PCI_BDF(domain, bus, slot, func): - return (((domain & 0xffff) << 16) | ((bus & 0xff) << 8) | - PCI_DEVFN(slot, func)) - -def check_pci_opts(opts): - def f((k, v)): - if k not in ['msitranslate', 'power_mgmt'] or \ - not v.lower() in ['0', '1', 'yes', 'no']: - raise PciDeviceParseError('Invalid pci option %s=%s: ' % (k, v)) - - map(f, opts) - -def serialise_pci_opts(opts): - return ','.join(map(lambda x: '='.join(x), opts)) - -def split_pci_opts(opts): - return map(lambda x: x.split('='), - filter(lambda x: x != '', opts.split(','))) - -def append_default_pci_opts(opts, defopts): - optsdict = dict(opts) - return opts + filter(lambda (k, v): not optsdict.has_key(k), defopts) - -def pci_opts_list_to_sxp(list): - return dev_dict_to_sxp({'opts': list}) - -def pci_opts_list_from_sxp(dev): - return map(lambda x: sxp.children(x)[0], sxp.children(dev, 'opts')) - -def pci_convert_dict_to_sxp(dev, state, sub_state = None): - pci_sxp = ['pci', dev_dict_to_sxp(dev), ['state', state]] - if sub_state != None: - pci_sxp.append(['sub_state', sub_state]) - return pci_sxp - -def pci_convert_sxp_to_dict(dev_sxp): - """Convert pci device sxp to dict - @param dev_sxp: device configuration - @type dev_sxp: SXP object (parsed config) - @return: dev_config - @rtype: dictionary - """ - # Parsing the device SXP's. In most cases, the SXP looks - # like this: - # - # [device, [vif, [mac, xx:xx:xx:xx:xx:xx], [ip 1.3.4.5]]] - # - # However, for PCI devices it looks like this: - # - # [device, [pci, [dev, [domain, 0], [bus, 0], [slot, 1], [func, 2]]] - # - # It seems the reasoning for this difference is because - # pciif.py needs all the PCI device configurations at - # the same time when creating the devices. - # - # To further complicate matters, Xen 2.0 configuration format - # uses the following for pci device configuration: - # - # [device, [pci, [domain, 0], [bus, 0], [dev, 1], [func, 2]]] - - # For PCI device hotplug support, the SXP of PCI devices is - # extendend like this: - # - # [device, [pci, [dev, [domain, 0], [bus, 0], [slot, 1], [func, 2], - # [vdevfn, 0]], - # [state, 'Initialising']]] - # - # 'vdevfn' shows the virtual hotplug slot number which the PCI device - # is inserted in. This is only effective for HVM domains. - # - # state 'Initialising' indicates that the device is being attached, - # while state 'Closing' indicates that the device is being detached. - # - # The Dict looks like this: - # - # { devs: [{domain: 0, bus: 0, slot: 1, func: 2, vdevfn: 0}], - # states: ['Initialising'] } - - dev_config = {} - - pci_devs = [] - for pci_dev in sxp.children(dev_sxp, 'dev'): - pci_dev_info = dict(pci_dev[1:]) - if 'opts' in pci_dev_info: - pci_dev_info['opts'] = pci_opts_list_from_sxp(pci_dev) - # If necessary, initialize uuid, key, and vdevfn for each pci device - if not pci_dev_info.has_key('uuid'): - pci_dev_info['uuid'] = uuid.createString() - if not pci_dev_info.has_key('key'): - pci_dev_info['key'] = "%02x:%02x.%x" % \ - (int(pci_dev_info['bus'], 16), - int(pci_dev_info['slot'], 16), - int(pci_dev_info['func'], 16)) - if not pci_dev_info.has_key('vdevfn'): - pci_dev_info['vdevfn'] = "0x%02x" % AUTO_PHP_SLOT - pci_devs.append(pci_dev_info) - dev_config['devs'] = pci_devs - - pci_states = [] - for pci_state in sxp.children(dev_sxp, 'state'): - try: - pci_states.append(pci_state[1]) - except IndexError: - raise XendError("Error reading state while parsing pci sxp") - dev_config['states'] = pci_states - - return dev_config - -def parse_hex(val): - try: - if isinstance(val, types.StringTypes): - return int(val, 16) - else: - return val - except ValueError: - return None - -AUTO_PHP_FUNC = 1 -MANUAL_PHP_FUNC = 2 - -def parse_pci_pfunc_vfunc(func_str): - list = func_str.split('=') - l = len(list) - if l == 0 or l > 2: - raise PciDeviceParseError('Invalid function: ' + func_str) - p = int(list[0], 16) - if p < 0 or p > 7: - raise PciDeviceParseError('Invalid physical function in: ' + func_str) - if l == 1: - # This defaults to linear mapping of physical to virtual functions - return (p, p, AUTO_PHP_FUNC) - else: - v = int(list[1], 16) - if v < 0 or v > 7: - raise PciDeviceParseError('Invalid virtual function in: ' + - func_str) - return (p, v, MANUAL_PHP_FUNC) - -def pci_func_range(start, end): - if end < start: - x = pci_func_range(end, start) - x.reverse() - return x - return range(start, end + 1) - -def pci_pfunc_vfunc_range(orig, a, b): - phys = pci_func_range(a[0], b[0]) - virt = pci_func_range(a[1], b[1]) - if len(phys) != len(virt): - raise PciDeviceParseError('Invalid range in: ' + orig) - return map(lambda x: x + (MANUAL_PHP_FUNC,), zip(phys, virt)) - -def pci_func_list_map_fn(key, func_str): - if func_str == "*": - return map(lambda x: parse_pci_pfunc_vfunc(x['func']), - filter(lambda x: - pci_dict_cmp(x, key, ['domain', 'bus', 'slot']), - get_all_pci_dict())) - l = map(parse_pci_pfunc_vfunc, func_str.split("-")) - if len(l) == 1: - return l - if len(l) == 2: - return pci_pfunc_vfunc_range(func_str, l[0], l[1]) - return [] - -def pci_func_list_process(pci_dev_str, template, func_str): - l = reduce(lambda x, y: x + y, - (map(lambda x: pci_func_list_map_fn(template, x), - func_str.split(",")))) - - phys = map(lambda x: x[0], l) - virt = map(lambda x: x[1], l) - if len(phys) != len(set(phys)) or len(virt) != len(set(virt)): - raise PciDeviceParseError("Duplicate functions: %s" % pci_dev_str) - - return l - -def parse_pci_name_extended(pci_dev_str): - pci_match = re.match(r"((?P[0-9a-fA-F]{1,4})[:,])?" + - r"(?P[0-9a-fA-F]{1,2})[:,]" + - r"(?P[0-9a-fA-F]{1,2})[.,]" + - r"(?P(\*|[0-7]([,-=][0-7])*))" + - r"(@(?P[01]?[0-9a-fA-F]))?" + - r"(,(?P.*))?$", pci_dev_str) - - if pci_match == None: - raise PciDeviceParseError("Failed to parse pci device: %s" % - pci_dev_str) - - pci_dev_info = pci_match.groupdict('') - - template = {} - if pci_dev_info['domain'] != '': - domain = int(pci_dev_info['domain'], 16) - else: - domain = 0 - template['domain'] = "0x%04x" % domain - template['bus'] = "0x%02x" % int(pci_dev_info['bus'], 16) - template['slot'] = "0x%02x" % int(pci_dev_info['slot'], 16) - template['key'] = pci_dev_str.split(',')[0] - if pci_dev_info['opts'] != '': - template['opts'] = split_pci_opts(pci_dev_info['opts']) - check_pci_opts(template['opts']) - - # This is where virtual function assignment takes place - func_list = pci_func_list_process(pci_dev_str, template, - pci_dev_info['func']) - if len(func_list) == 0: - return [] - - # Set the virtual function of the numerically lowest physical function - # to zero if it has not been manually set - if not filter(lambda x: x[1] == 0, func_list): - auto = filter(lambda x: x[2] == AUTO_PHP_FUNC, func_list) - manual = filter(lambda x: x[2] == MANUAL_PHP_FUNC, func_list) - if not auto: - raise PciDeviceParseError('Virtual device does not include ' - 'virtual function 0: ' + pci_dev_str) - auto.sort(lambda x,y: cmp(x[1], y[1])) - auto[0] = (auto[0][0], 0, AUTO_PHP_FUNC) - func_list = auto + manual - - # For pci attachment and detachment is it important that virtual - # function 0 is done last. This is because is virtual function 0 that - # is used to singnal changes to the guest using ACPI - func_list.sort(lambda x,y: cmp(PCI_FUNC(y[1]), PCI_FUNC(x[1]))) - - # Virtual slot assignment takes place here if specified in the bdf, - # else it is done inside qemu-xen, as it knows which slots are free - pci = [] - for (pfunc, vfunc, auto) in func_list: - pci_dev = template.copy() - pci_dev['func'] = "0x%x" % pfunc - - if pci_dev_info['vdevfn'] == '': - vdevfn = AUTO_PHP_SLOT | vfunc - else: - vdevfn = PCI_DEVFN(int(pci_dev_info['vdevfn'], 16), vfunc) - pci_dev['vdevfn'] = "0x%02x" % vdevfn - - pci.append(pci_dev) - - return pci - -def parse_pci_name(pci_name_string): - dev = parse_pci_name_extended(pci_name_string) - - if len(dev) != 1: - raise PciDeviceParseError(("Failed to parse pci device: %s: " - "multiple functions specified prohibited") % - pci_name_string) - - pci = dev[0] - if not int(pci['vdevfn'], 16) & AUTO_PHP_SLOT: - raise PciDeviceParseError(("Failed to parse pci device: %s: " + - "vdevfn provided where prohibited: 0x%02x") % - (pci_name_string, - PCI_SLOT(int(pci['vdevfn'], 16)))) - if 'opts' in pci: - raise PciDeviceParseError(("Failed to parse pci device: %s: " + - "options provided where prohibited: %s") % - (pci_name_string, pci['opts'])) - - return pci - -def __pci_dict_to_fmt_str(fmt, dev): - return fmt % (int(dev['domain'], 16), int(dev['bus'], 16), - int(dev['slot'], 16), int(dev['func'], 16)) - -def pci_dict_to_bdf_str(dev): - return __pci_dict_to_fmt_str('%04x:%02x:%02x.%01x', dev) - -def pci_dict_to_xc_str(dev): - return __pci_dict_to_fmt_str('0x%x, 0x%x, 0x%x, 0x%x', dev) - -def pci_dict_cmp(a, b, keys=['domain', 'bus', 'slot', 'func']): - return reduce(lambda x, y: x and y, - map(lambda k: int(a[k], 16) == int(b[k], 16), keys)) - -def extract_the_exact_pci_names(pci_names): - result = [] - - if isinstance(pci_names, types.StringTypes): - pci_names = pci_names.split() - elif isinstance(pci_names, types.ListType): - pci_names = re.findall(PCI_DEV_REG_EXPRESS_STR, '%s' % pci_names) - else: - raise PciDeviceParseError('Invalid argument: %s' % pci_names) - - for pci in pci_names: - # The length of DDDD:bb:dd.f is 12. - if len(pci) != 12: - continue - if re.match(PCI_DEV_REG_EXPRESS_STR, pci) is None: - continue - result = result + [pci] - return result - -def find_sysfs_mnt(): - try: - return utils.find_sysfs_mount() - except IOError, (errno, strerr): - raise PciDeviceParseError(('Failed to locate sysfs mount: %s: %s (%d)'% - (PROC_PCI_PATH, strerr, errno))) - return None - -def get_all_pci_names(): - if not sys.platform.startswith('linux'): return [] - sysfs_mnt = find_sysfs_mnt() - if sysfs_mnt is None: - return None - pci_names = os.popen('ls ' + sysfs_mnt + SYSFS_PCI_DEVS_PATH).read().split() - return pci_names - -def get_all_pci_dict(): - return map(parse_pci_name, get_all_pci_names()) - -def get_all_pci_devices(): - return map(PciDevice, get_all_pci_dict()) - -def _create_lspci_info(): - """Execute 'lspci' command and parse the result. - If the command does not exist, lspci_info will be kept blank ({}). - - Expects to be protected by lspci_info_lock. - """ - global lspci_info - - lspci_info = {} - - for paragraph in os.popen(LSPCI_CMD + ' -vmm').read().split('\n\n'): - device_name = None - device_info = {} - # FIXME: workaround for pciutils without the -mm option. - # see: git://git.kernel.org/pub/scm/utils/pciutils/pciutils.git - # commit: 3fd6b4d2e2fda814047664ffc67448ac782a8089 - first_device = True - for line in paragraph.split('\n'): - try: - (opt, value) = line.split(':\t') - if opt == 'Slot' or (opt == 'Device' and first_device): - device_name = pci_dict_to_bdf_str(parse_pci_name(value)) - first_device = False - else: - device_info[opt] = value - except: - pass - if device_name is not None: - lspci_info[device_name] = device_info - -def create_lspci_info(): - global lspci_info_lock - lspci_info_lock.acquire() - try: - _create_lspci_info() - finally: - lspci_info_lock.release() - -def save_pci_conf_space(devs_string): - pci_list = [] - cfg_list = [] - sysfs_mnt = find_sysfs_mnt() - for pci_str in devs_string: - pci_path = sysfs_mnt + SYSFS_PCI_DEVS_PATH + '/' + pci_str + \ - SYSFS_PCI_DEV_CONFIG_PATH - fd = os.open(pci_path, os.O_RDONLY) - size = os.fstat(fd).st_size - configs = [] - for i in range(0, size, 4): - configs = configs + [os.read(fd,4)] - os.close(fd) - pci_list = pci_list + [pci_path] - cfg_list = cfg_list + [configs] - return (pci_list, cfg_list) - -def restore_pci_conf_space(pci_cfg_list): - time.sleep(1.0) - pci_list = pci_cfg_list[0] - cfg_list = pci_cfg_list[1] - for i in range(0, len(pci_list)): - pci_path = pci_list[i] - configs = cfg_list[i] - fd = os.open(pci_path, os.O_WRONLY) - for dw in configs: - os.write(fd, dw) - os.close(fd) - -def find_all_assignable_devices(): - ''' devices owned by pcibak or pci-stub can be directly assigned to - guest with IOMMU (VT-d or AMD IOMMU), find all these devices. - ''' - sysfs_mnt = find_sysfs_mnt() - pciback_path = sysfs_mnt + SYSFS_PCIBACK_PATH - pcistub_path = sysfs_mnt + SYSFS_PCISTUB_PATH - pci_names1 = os.popen('ls %s 2>/dev/null' % pciback_path).read() - pci_names2 = os.popen('ls %s 2>/dev/null' % pcistub_path).read() - if len(pci_names1) + len(pci_names2) == 0 : - return None - pci_list = extract_the_exact_pci_names(pci_names1) - pci_list = pci_list + extract_the_exact_pci_names(pci_names2) - dev_list = [] - for pci in pci_list: - dev = PciDevice(parse_pci_name(pci)) - dev_list = dev_list + [dev] - return dev_list - -def transform_list(target, src): - ''' src: its element is pci string (Format: xxxx:xx:xx.x). - target: its element is pci string, or a list of pci string. - - If all the elements in src are in target, we remove them from target - and add src into target; otherwise, we remove from target all the - elements that also appear in src. - ''' - result = [] - target_contains_src = True - for e in src: - if not e in target: - target_contains_src = False - break - - if target_contains_src: - result = result + [src] - for e in target: - if not e in src: - result = result + [e] - return result - -def check_FLR_capability(dev_list): - if len(dev_list) == 0: - return [] - - pci_list = [] - pci_dev_dict = {} - for dev in dev_list: - pci_list = pci_list + [dev.name] - pci_dev_dict[dev.name] = dev - - while True: - need_transform = False - for pci in pci_list: - if isinstance(pci, types.StringTypes): - dev = pci_dev_dict[pci] - if dev.bus == 0: - continue - if dev.dev_type == DEV_TYPE_PCIe_ENDPOINT and not dev.pcie_flr: - coassigned_pci_list = dev.find_all_the_multi_functions() - need_transform = True - elif dev.dev_type == DEV_TYPE_PCI and not dev.pci_af_flr: - coassigned_pci_list = dev.find_coassigned_pci_devices(True) - del coassigned_pci_list[0] - need_transform = True - - if need_transform: - pci_list = transform_list(pci_list, coassigned_pci_list) - if not need_transform: - break - - if len(pci_list) == 0: - return [] - - for i in range(0, len(pci_list)): - if isinstance(pci_list[i], types.StringTypes): - pci_list[i] = [pci_list[i]] - - # Now every element in pci_list is a list of pci string. - - result = [] - for pci_names in pci_list: - devs = [] - for pci in pci_names: - devs = devs + [pci_dev_dict[pci]] - result = result + [devs] - return result - -def check_mmio_bar(devs_list): - result = [] - - for dev_list in devs_list: - non_aligned_bar_found = False - for dev in dev_list: - if dev.has_non_page_aligned_bar: - non_aligned_bar_found = True - break - if not non_aligned_bar_found: - result = result + [dev_list] - - return result - -class PciDeviceParseError(Exception): - def __init__(self,msg): - self.message = msg - def __str__(self): - return self.message - -class PciDeviceAssignmentError(Exception): - def __init__(self,msg): - self.message = msg - def __str__(self): - return 'pci: improper device assignment specified: ' + \ - self.message - -class PciDeviceVslotMissing(Exception): - def __init__(self,msg): - self.message = msg - def __str__(self): - return 'pci: no vslot: ' + self.message - -class PciDevice: - def __init__(self, dev): - self.domain = int(dev['domain'], 16) - self.bus = int(dev['bus'], 16) - self.slot = int(dev['slot'], 16) - self.func = int(dev['func'], 16) - self.name = pci_dict_to_bdf_str(dev) - self.cfg_space_path = find_sysfs_mnt()+SYSFS_PCI_DEVS_PATH+'/'+ \ - self.name + SYSFS_PCI_DEV_CONFIG_PATH - self.irq = 0 - self.iomem = [] - self.ioports = [] - self.driver = None - self.vendor = None - self.device = None - self.subvendor = None - self.subdevice = None - self.msix = 0 - self.msix_iomem = [] - self.revision = 0 - self.classcode = None - self.vendorname = "" - self.devicename = "" - self.classname = "" - self.subvendorname = "" - self.subdevicename = "" - self.dev_type = None - self.is_downstream_port = False - self.acs_enabled = False - self.has_non_page_aligned_bar = False - self.pcie_flr = False - self.pci_af_flr = False - self.detect_dev_info() - if (self.dev_type == DEV_TYPE_PCI_BRIDGE) or \ - (self.dev_type == DEV_TYPE_PCIe_BRIDGE): - return - self.get_info_from_sysfs() - self.get_info_from_lspci() - - def find_parent(self): - # i.e., /sys/bus/pci/devices/0000:00:19.0 or - # /sys/bus/pci/devices/0000:03:04.0 - path = find_sysfs_mnt()+SYSFS_PCI_DEVS_PATH+'/'+ self.name - # i.e., ../../../devices/pci0000:00/0000:00:19.0 - # ../../../devices/pci0000:00/0000:00:02.0/0000:01:00.2/0000:03:04.0 - try: - target = os.readlink(path) - lst = target.split('/') - parent = lst[len(lst)-2] - if parent[0:3] == 'pci': - # We have reached the upmost one. - return None - return parse_pci_name(parent) - except OSError, (errno, strerr): - raise PciDeviceParseError('Can not locate the parent of %s', - self.name) - - def find_the_uppermost_pci_bridge(self): - # Find the uppermost PCI/PCI-X bridge - dev = self.find_parent() - if dev is None: - return None - dev = dev_parent = PciDevice(dev) - while dev_parent.dev_type != DEV_TYPE_PCIe_BRIDGE: - parent = dev_parent.find_parent() - if parent is None: - break - dev = dev_parent - dev_parent = PciDevice(parent) - return dev - - def find_all_devices_behind_the_bridge(self, ignore_bridge): - sysfs_mnt = find_sysfs_mnt() - self_path = sysfs_mnt + SYSFS_PCI_DEVS_PATH + '/' + self.name - pci_names = os.popen('ls ' + self_path).read() - dev_list = extract_the_exact_pci_names(pci_names) - - list = [self.name] - for pci_str in dev_list: - dev = PciDevice(parse_pci_name(pci_str)) - if dev.dev_type == DEV_TYPE_PCI_BRIDGE or \ - dev.dev_type == DEV_TYPE_PCIe_BRIDGE: - sub_list_including_self = \ - dev.find_all_devices_behind_the_bridge(ignore_bridge) - if ignore_bridge: - del sub_list_including_self[0] - list = list + [sub_list_including_self] - else: - list = list + [dev.name] - return list - - def find_coassigned_pci_devices(self, ignore_bridge = True): - ''' Here'self' is a PCI device, we need find the uppermost PCI/PCI-X - bridge, and all devices behind it must be co-assigned to the same - guest. - - Parameter: - [ignore_bridge]: if set, the returned result doesn't include - any bridge behind the uppermost PCI/PCI-X bridge. - - Note: The first element of the return value is the uppermost - PCI/PCI-X bridge. If the caller doesn't need the first - element, the caller itself can remove it explicitly. - ''' - dev = self.find_the_uppermost_pci_bridge() - - # The 'self' device is on bus0. - if dev is None: - return [self.name] - - dev_list = dev.find_all_devices_behind_the_bridge(ignore_bridge) - dev_list = extract_the_exact_pci_names(dev_list) - return dev_list - - def do_secondary_bus_reset(self, target_bus, devs): - # Save the config spaces of all the devices behind the bus. - (pci_list, cfg_list) = save_pci_conf_space(devs) - - #Do the Secondary Bus Reset - sysfs_mnt = find_sysfs_mnt() - parent_path = sysfs_mnt + SYSFS_PCI_DEVS_PATH + '/' + \ - target_bus + SYSFS_PCI_DEV_CONFIG_PATH - fd = os.open(parent_path, os.O_RDWR) - os.lseek(fd, PCI_CB_BRIDGE_CONTROL, 0) - br_cntl = (struct.unpack('H', os.read(fd, 2)))[0] - # Assert Secondary Bus Reset - os.lseek(fd, PCI_CB_BRIDGE_CONTROL, 0) - br_cntl |= PCI_BRIDGE_CTL_BUS_RESET - os.write(fd, struct.pack('H', br_cntl)) - time.sleep(0.100) - # De-assert Secondary Bus Reset - os.lseek(fd, PCI_CB_BRIDGE_CONTROL, 0) - br_cntl &= ~PCI_BRIDGE_CTL_BUS_RESET - os.write(fd, struct.pack('H', br_cntl)) - time.sleep(0.100) - os.close(fd) - - # Restore the config spaces - restore_pci_conf_space((pci_list, cfg_list)) - - def do_Dstate_transition(self): - pos = self.find_cap_offset(PCI_CAP_ID_PM) - if pos == 0: - return False - - # No_Soft_Reset - When set 1, this bit indicates that - # devices transitioning from D3hot to D0 because of - # PowerState commands do not perform an internal reset. - pm_ctl = self.pci_conf_read32(pos + PCI_PM_CTRL) - if (pm_ctl & PCI_PM_CTRL_NO_SOFT_RESET) == PCI_PM_CTRL_NO_SOFT_RESET: - return False - - (pci_list, cfg_list) = save_pci_conf_space([self.name]) - - # Enter D3hot - pm_ctl &= ~PCI_PM_CTRL_STATE_MASK - pm_ctl |= PCI_D3hot - self.pci_conf_write32(pos + PCI_PM_CTRL, pm_ctl) - time.sleep(0.010) - - # From D3hot to D0 - pm_ctl &= ~PCI_PM_CTRL_STATE_MASK - pm_ctl |= PCI_D0hot - self.pci_conf_write32(pos + PCI_PM_CTRL, pm_ctl) - time.sleep(0.010) - - restore_pci_conf_space((pci_list, cfg_list)) - return True - - def do_vendor_specific_FLR_method(self): - pos = self.find_cap_offset(PCI_CAP_ID_VENDOR_SPECIFIC_CAP) - if pos == 0: - return - - vendor_id = self.pci_conf_read16(PCI_VENDOR_ID) - if vendor_id != VENDOR_INTEL: - return - - class_id = self.pci_conf_read16(PCI_CLASS_DEVICE) - if class_id != PCI_CLASS_ID_USB: - return - - (pci_list, cfg_list) = save_pci_conf_space([self.name]) - - self.pci_conf_write8(pos + PCI_USB_FLRCTRL, 1) - time.sleep(0.100) - - restore_pci_conf_space((pci_list, cfg_list)) - - def do_FLR_for_integrated_device(self): - if not self.do_Dstate_transition(): - self.do_vendor_specific_FLR_method() - - def do_AF_FLR(self, af_pos): - ''' use PCI Advanced Capability to do FLR - ''' - (pci_list, cfg_list) = save_pci_conf_space([self.name]) - self.pci_conf_write8(af_pos + PCI_AF_CTL, PCI_AF_CTL_FLR) - time.sleep(0.100) - restore_pci_conf_space((pci_list, cfg_list)) - - def do_FLR_for_intel_4Series_iGFX(self): - af_pos = PCI_CAP_IGFX_CAP13_OFFSET - self.do_AF_FLR(af_pos) - log.debug("Intel 4 Series iGFX FLR done") - - def do_FLR_for_GM45_iGFX(self): - reg32 = self.pci_conf_read32(PCI_CAP_IGFX_CAP09_OFFSET) - if ((reg32 >> 16) & 0x000000FF) != 0x06 or \ - ((reg32 >> 24) & 0x000000F0) != 0x20: - return - - self.pci_conf_write8(PCI_CAP_IGFX_GDRST_OFFSET, PCI_CAP_IGFX_GDRST) - for i in range(0, 10): - time.sleep(0.100) - reg8 = self.pci_conf_read8(PCI_CAP_IGFX_GDRST_OFFSET) - if (reg8 & 0x01) == 0: - break - if i == 10: - log.debug("Intel iGFX FLR fail on GM45") - return - - # This specific reset will hang if the command register does not have - # memory space access enabled - cmd = self.pci_conf_read16(PCI_COMMAND) - self.pci_conf_write16(PCI_COMMAND, (cmd | 0x02)) - af_pos = PCI_CAP_IGFX_CAP09_OFFSET - self.do_AF_FLR(af_pos) - self.pci_conf_write16(PCI_COMMAND, cmd) - - log.debug("Intel iGFX FLR on GM45 done") - - def find_all_the_multi_functions(self): - sysfs_mnt = find_sysfs_mnt() - parentdict = self.find_parent() - if parentdict is None : - return [ self.name ] - parent = pci_dict_to_bdf_str(parentdict) - pci_names = os.popen('ls ' + sysfs_mnt + SYSFS_PCI_DEVS_PATH + '/' + \ - parent + '/').read() - funcs = extract_the_exact_pci_names(pci_names) - return funcs - - def find_coassigned_devices(self): - if self.dev_type == DEV_TYPE_PCIe_ENDPOINT and not self.pcie_flr: - return self.find_all_the_multi_functions() - elif self.dev_type == DEV_TYPE_PCI and not self.pci_af_flr: - coassigned_pci_list = self.find_coassigned_pci_devices(True) - if len(coassigned_pci_list) > 1: - del coassigned_pci_list[0] - return coassigned_pci_list - else: - return [self.name] - - def find_cap_offset(self, cap): - path = find_sysfs_mnt()+SYSFS_PCI_DEVS_PATH+'/'+ \ - self.name+SYSFS_PCI_DEV_CONFIG_PATH - - pos = PCI_CAPABILITY_LIST - - try: - fd = None - fd = os.open(path, os.O_RDONLY) - os.lseek(fd, PCI_STATUS, 0) - status = struct.unpack('H', os.read(fd, 2))[0] - if (status & 0x10) == 0: - os.close(fd) - # The device doesn't support PCI_STATUS_CAP_LIST - return 0 - - max_cap = 48 - while max_cap > 0: - os.lseek(fd, pos, 0) - pos = ord(os.read(fd, 1)) - if pos < 0x40: - pos = 0 - break; - os.lseek(fd, pos + 0, 0) - id = ord(os.read(fd, 1)) - if id == 0xff: - pos = 0 - break; - - # Found the capability - if id == cap: - break; - - # Test the next one - pos = pos + 1 - max_cap = max_cap - 1; - - os.close(fd) - except OSError, (errno, strerr): - if fd is not None: - os.close(fd) - raise PciDeviceParseError(('Error when accessing sysfs: %s (%d)' % - (strerr, errno))) - return pos - - def find_ext_cap(self, cap): - path = find_sysfs_mnt()+SYSFS_PCI_DEVS_PATH+'/'+ \ - self.name+SYSFS_PCI_DEV_CONFIG_PATH - - ttl = 480; # 3840 bytes, minimum 8 bytes per capability - pos = 0x100 - - fd = None - try: - fd = os.open(path, os.O_RDONLY) - os.lseek(fd, pos, 0) - h = os.read(fd, 4) - if len(h) == 0: # MMCONF is not enabled? - os.close(fd) - return 0 - header = struct.unpack('I', h)[0] - if header == 0 or header == -1: - os.close(fd) - return 0 - - while ttl > 0: - if (header & 0x0000ffff) == cap: - os.close(fd) - return pos - pos = (header >> 20) & 0xffc - if pos < 0x100: - break - os.lseek(fd, pos, 0) - header = struct.unpack('I', os.read(fd, 4))[0] - ttl = ttl - 1 - os.close(fd) - except OSError, (errno, strerr): - if fd is not None: - os.close(fd) - raise PciDeviceParseError(('Error when accessing sysfs: %s (%d)' % - (strerr, errno))) - return 0 - - def is_behind_switch_lacking_acs(self): - # If there is intermediate PCIe switch, which doesn't support ACS or - # doesn't enable ACS, between Root Complex and the function, we return - # True, meaning the function is not allowed to be assigned to guest due - # to potential security issue. - parent = self.find_parent() - while parent is not None: - dev_parent = PciDevice(parent) - if dev_parent.is_downstream_port and not dev_parent.acs_enabled: - return True - parent = dev_parent.find_parent() - return False - - def pci_conf_read8(self, pos): - fd = os.open(self.cfg_space_path, os.O_RDONLY) - os.lseek(fd, pos, 0) - str = os.read(fd, 1) - os.close(fd) - val = struct.unpack('B', str)[0] - return val - - def pci_conf_read16(self, pos): - fd = os.open(self.cfg_space_path, os.O_RDONLY) - os.lseek(fd, pos, 0) - str = os.read(fd, 2) - os.close(fd) - val = struct.unpack('H', str)[0] - return val - - def pci_conf_read32(self, pos): - fd = os.open(self.cfg_space_path, os.O_RDONLY) - os.lseek(fd, pos, 0) - str = os.read(fd, 4) - os.close(fd) - val = struct.unpack('I', str)[0] - return val - - def pci_conf_write8(self, pos, val): - str = struct.pack('B', val) - fd = os.open(self.cfg_space_path, os.O_WRONLY) - os.lseek(fd, pos, 0) - os.write(fd, str) - os.close(fd) - - def pci_conf_write16(self, pos, val): - str = struct.pack('H', val) - fd = os.open(self.cfg_space_path, os.O_WRONLY) - os.lseek(fd, pos, 0) - os.write(fd, str) - os.close(fd) - - def pci_conf_write32(self, pos, val): - str = struct.pack('I', val) - fd = os.open(self.cfg_space_path, os.O_WRONLY) - os.lseek(fd, pos, 0) - os.write(fd, str) - os.close(fd) - - def detect_dev_info(self): - try: - class_dev = self.pci_conf_read16(PCI_CLASS_DEVICE) - except OSError, (err, strerr): - if err == errno.ENOENT: - strerr = "the device doesn't exist?" - raise PciDeviceParseError('%s: %s' %\ - (self.name, strerr)) - pos = self.find_cap_offset(PCI_CAP_ID_EXP) - if class_dev == PCI_CLASS_BRIDGE_PCI: - if pos == 0: - self.dev_type = DEV_TYPE_PCI_BRIDGE - else: - creg = self.pci_conf_read16(pos + PCI_EXP_FLAGS) - type = (creg & PCI_EXP_FLAGS_TYPE) >> 4 - if type == PCI_EXP_TYPE_PCI_BRIDGE: - self.dev_type = DEV_TYPE_PCI_BRIDGE - else: - self.dev_type = DEV_TYPE_PCIe_BRIDGE - if type == PCI_EXP_TYPE_DOWNSTREAM: - self.is_downstream_port = True - pos = self.find_ext_cap(PCI_EXT_CAP_ID_ACS) - if pos != 0: - ctrl = self.pci_conf_read16(pos + PCI_EXT_ACS_CTRL) - if (ctrl & PCI_EXT_CAP_ACS_ENABLED) == \ - (PCI_EXT_CAP_ACS_ENABLED): - self.acs_enabled = True - else: - if pos != 0: - self.dev_type = DEV_TYPE_PCIe_ENDPOINT - else: - self.dev_type = DEV_TYPE_PCI - - # Force 0000:00:00.0 to be DEV_TYPE_PCIe_BRIDGE - if self.name == '0000:00:00.0': - self.dev_type = DEV_TYPE_PCIe_BRIDGE - - if (self.dev_type == DEV_TYPE_PCI_BRIDGE) or \ - (self.dev_type == DEV_TYPE_PCIe_BRIDGE): - return - - # Try to findthe PCIe FLR capability - if self.dev_type == DEV_TYPE_PCIe_ENDPOINT: - dev_cap = self.pci_conf_read32(pos + PCI_EXP_DEVCAP) - if dev_cap & PCI_EXP_DEVCAP_FLR: - self.pcie_flr = True - else: - # Quirk for the VF of Intel 82599 10GbE Controller. - # We know it does have PCIe FLR capability even if it doesn't - # report that (dev_cap.PCI_EXP_DEVCAP_FLR is 0). - # See the 82599 datasheet. - dev_path = find_sysfs_mnt()+SYSFS_PCI_DEVS_PATH+'/'+self.name - vendor_id = parse_hex(os.popen('cat %s/vendor' % dev_path).read()) - device_id = parse_hex(os.popen('cat %s/device' % dev_path).read()) - if (vendor_id == VENDOR_INTEL) and \ - (device_id == DEVICE_ID_82599): - self.pcie_flr = True - elif self.dev_type == DEV_TYPE_PCI: - # Try to find the "PCI Advanced Capabilities" - pos = self.find_cap_offset(PCI_CAP_ID_AF) - if pos != 0: - af_cap = self.pci_conf_read8(pos + PCI_AF_CAPs) - if (af_cap & PCI_AF_CAPs_TP_FLR) == PCI_AF_CAPs_TP_FLR: - self.pci_af_flr = True - - bar_addr = PCI_BAR_0 - while bar_addr <= PCI_BAR_5: - bar = self.pci_conf_read32(bar_addr) - if (bar & PCI_BAR_SPACE) == PCI_BAR_MEM: - bar = bar & PCI_BAR_MEM_MASK - bar = bar & ~PAGE_MASK - if bar != 0: - self.has_non_page_aligned_bar = True - break - bar_addr = bar_addr + 4 - - def devs_check_driver(self, devs): - if len(devs) == 0: - return - for pci_dev in devs: - dev = PciDevice(parse_pci_name(pci_dev)) - if dev.driver == 'pciback' or dev.driver == 'pci-stub': - continue - err_msg = 'pci: %s must be co-assigned to the same guest with %s' + \ - ', but it is not owned by pciback or pci-stub.' - raise PciDeviceAssignmentError(err_msg % (pci_dev, self.name)) - - def do_FLR(self, is_hvm, strict_check): - """ Perform FLR (Functional Level Reset) for the device. - """ - if self.dev_type == DEV_TYPE_PCIe_ENDPOINT: - # If PCIe device supports FLR, we use it. - if self.pcie_flr: - (pci_list, cfg_list) = save_pci_conf_space([self.name]) - pos = self.find_cap_offset(PCI_CAP_ID_EXP) - self.pci_conf_write32(pos + PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_FLR) - # We must sleep at least 100ms for the completion of FLR - time.sleep(0.100) - restore_pci_conf_space((pci_list, cfg_list)) - else: - if self.bus == 0: - self.do_FLR_for_integrated_device() - else: - funcs = self.find_all_the_multi_functions() - - if not is_hvm and (len(funcs) > 1): - return - if is_hvm and not strict_check: - return - - self.devs_check_driver(funcs) - - parent = pci_dict_to_bdf_str(self.find_parent()) - - # Do Secondary Bus Reset. - self.do_secondary_bus_reset(parent, funcs) - # PCI devices - else: - # For PCI device on host bus, we test "PCI Advanced Capabilities". - if self.bus == 0 and self.pci_af_flr: - af_pos = self.find_cap_offset(PCI_CAP_ID_AF) - self.do_AF_FLR(af_pos) - else: - if self.bus == 0: - if self.slot == 0x02 and self.func == 0x0: - vendor_id = self.pci_conf_read16(PCI_VENDOR_ID) - if vendor_id != VENDOR_INTEL: - return - class_id = self.pci_conf_read16(PCI_CLASS_DEVICE) - if class_id != PCI_CLASS_ID_VGA: - return - device_id = self.pci_conf_read16(PCI_DEVICE_ID) - if device_id == PCI_DEVICE_ID_IGFX_GM45: - self.do_FLR_for_GM45_iGFX() - elif device_id == PCI_DEVICE_ID_IGFX_EAGLELAKE or \ - device_id == PCI_DEVICE_ID_IGFX_Q45 or \ - device_id == PCI_DEVICE_ID_IGFX_G45 or \ - device_id == PCI_DEVICE_ID_IGFX_G41: - self.do_FLR_for_intel_4Series_iGFX() - else: - log.debug("Unknown iGFX device_id:%x", device_id) - else: - self.do_FLR_for_integrated_device() - else: - devs = self.find_coassigned_pci_devices(False) - # Remove the element 0 which is a bridge - target_bus = devs[0] - del devs[0] - - if not is_hvm and (len(devs) > 1): - return - if is_hvm and not strict_check: - return - - self.devs_check_driver(devs) - - # Do Secondary Bus Reset. - self.do_secondary_bus_reset(target_bus, devs) - - def find_capability(self, type): - sysfs_mnt = find_sysfs_mnt() - if sysfs_mnt == None: - return False - path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \ - self.name+SYSFS_PCI_DEV_CONFIG_PATH - try: - conf_file = open(path, 'rb') - conf_file.seek(PCI_HEADER_TYPE) - header_type = ord(conf_file.read(1)) & PCI_HEADER_TYPE_MASK - if header_type == PCI_HEADER_TYPE_CARDBUS: - return - conf_file.seek(PCI_STATUS_OFFSET) - status = ord(conf_file.read(1)) - if status&PCI_STATUS_CAP_MASK: - conf_file.seek(PCI_CAP_OFFSET) - capa_pointer = ord(conf_file.read(1)) - capa_count = 0 - while capa_pointer: - if capa_pointer < 0x40: - raise PciDeviceParseError( - ('Broken capability chain: %s' % self.name)) - capa_count += 1 - if capa_count > 96: - raise PciDeviceParseError( - ('Looped capability chain: %s' % self.name)) - conf_file.seek(capa_pointer) - capa_id = ord(conf_file.read(1)) - capa_pointer = ord(conf_file.read(1)) - if capa_id == type: - # get the type - message_cont_lo = ord(conf_file.read(1)) - message_cont_hi = ord(conf_file.read(1)) - self.msix=1 - self.msix_entries = (message_cont_lo + \ - (message_cont_hi << 8)) \ - & MSIX_SIZE_MASK - t_off=conf_file.read(4) - p_off=conf_file.read(4) - self.table_offset=ord(t_off[0]) | (ord(t_off[1])<<8) | \ - (ord(t_off[2])<<16)| \ - (ord(t_off[3])<<24) - self.pba_offset=ord(p_off[0]) | (ord(p_off[1]) << 8)| \ - (ord(p_off[2])<<16) | \ - (ord(p_off[3])<<24) - self.table_index = self.table_offset & MSIX_BIR_MASK - self.table_offset = self.table_offset & ~MSIX_BIR_MASK - self.pba_index = self.pba_offset & MSIX_BIR_MASK - self.pba_offset = self.pba_offset & ~MSIX_BIR_MASK - break - except IOError, (errno, strerr): - raise PciDeviceParseError(('Failed to locate sysfs mount: %s: %s (%d)' % - (PROC_PCI_PATH, strerr, errno))) - except TypeError, err: - log.debug("Caught TypeError '%s'" % err) - pass - - def get_info_from_sysfs(self): - self.find_capability(0x11) - sysfs_mnt = find_sysfs_mnt() - if sysfs_mnt == None: - return False - - path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \ - self.name+SYSFS_PCI_DEV_RESOURCE_PATH - try: - resource_file = open(path,'r') - - for i in range(PROC_PCI_NUM_RESOURCES): - line = resource_file.readline() - sline = line.split() - if len(sline)<3: - continue - - start = int(sline[0],16) - end = int(sline[1],16) - flags = int(sline[2],16) - size = end-start+1 - - if start!=0: - if flags&PCI_BAR_IO: - self.ioports.append( (start,size) ) - else: - self.iomem.append( (start,size) ) - - except IOError, (errno, strerr): - raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' % - (path, strerr, errno))) - - path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \ - self.name+SYSFS_PCI_DEV_IRQ_PATH - try: - self.irq = int(open(path,'r').readline()) - except IOError, (errno, strerr): - raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' % - (path, strerr, errno))) - - path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \ - self.name+SYSFS_PCI_DEV_DRIVER_DIR_PATH - try: - self.driver = os.path.basename(os.readlink(path)) - except OSError, (errno, strerr): - self.driver = "" - - path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \ - self.name+SYSFS_PCI_DEV_VENDOR_PATH - try: - self.vendor = int(open(path,'r').readline(), 16) - except IOError, (errno, strerr): - raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' % - (path, strerr, errno))) - - path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \ - self.name+SYSFS_PCI_DEV_DEVICE_PATH - try: - self.device = int(open(path,'r').readline(), 16) - except IOError, (errno, strerr): - raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' % - (path, strerr, errno))) - - path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \ - self.name+SYSFS_PCI_DEV_SUBVENDOR_PATH - try: - self.subvendor = int(open(path,'r').readline(), 16) - except IOError, (errno, strerr): - raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' % - (path, strerr, errno))) - - path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \ - self.name+SYSFS_PCI_DEV_SUBDEVICE_PATH - try: - self.subdevice = int(open(path,'r').readline(), 16) - except IOError, (errno, strerr): - raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' % - (path, strerr, errno))) - - path = sysfs_mnt+SYSFS_PCI_DEVS_PATH+'/'+ \ - self.name+SYSFS_PCI_DEV_CLASS_PATH - try: - self.classcode = int(open(path,'r').readline(), 16) - except IOError, (errno, strerr): - raise PciDeviceParseError(('Failed to open & read %s: %s (%d)' % - (path, strerr, errno))) - - return True - - def get_info_from_lspci(self): - """ Get information such as vendor name, device name, class name, etc. - Since we cannot obtain these data from sysfs, use 'lspci' command. - """ - global lspci_info - global lspci_info_lock - - lspci_info_lock.acquire() - try: - if lspci_info is None: - _create_lspci_info() - - device_info = lspci_info.get(self.name) - if device_info: - try: - self.revision = int(device_info.get('Rev', '0'), 16) - except ValueError: - pass - self.vendorname = device_info.get('Vendor', '') - self.devicename = device_info.get('Device', '') - self.classname = device_info.get('Class', '') - self.subvendorname = device_info.get('SVendor', '') - self.subdevicename = device_info.get('SDevice', '') - return True - finally: - lspci_info_lock.release() - - def __str__(self): - str = "PCI Device %s\n" % (self.name) - for (start,size) in self.ioports: - str = str + "IO Port 0x%02x [size=%d]\n"%(start,size) - for (start,size) in self.iomem: - str = str + "IO Mem 0x%02x [size=%d]\n"%(start,size) - str = str + "IRQ %d\n"%(self.irq) - str = str + "Vendor ID 0x%04x\n"%(self.vendor) - str = str + "Device ID 0x%04x\n"%(self.device) - str = str + "Sybsystem Vendor ID 0x%04x\n"%(self.subvendor) - str = str + "Subsystem Device ID 0x%04x"%(self.subdevice) - return str - -def main(): - if len(sys.argv)<5: - print "Usage: %s \n" % sys.argv[0] - sys.exit(2) - - dev = PciDevice(int(sys.argv[1],16), int(sys.argv[2],16), - int(sys.argv[3],16), int(sys.argv[4],16)) - print str(dev) - -if __name__=='__main__': - main() diff --git a/tools/python/xen/util/rwlock.py b/tools/python/xen/util/rwlock.py deleted file mode 100644 index e79a82f8e8..0000000000 --- a/tools/python/xen/util/rwlock.py +++ /dev/null @@ -1,137 +0,0 @@ -""" Reader-writer lock implementation based on a condition variable """ - -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2008 International Business Machines Corp. -# Author: Stefan Berger -#============================================================================ - -from threading import Condition - -class RWLock: - - RWLOCK_STATE_WRITER = -1 - RWLOCK_STATE_UNUSED = 0 - - def __init__(self): - self.__condition = Condition() - self.__state = RWLock.RWLOCK_STATE_UNUSED - self.__blocked_writers = 0 - - def acquire_reader(self): - self.__condition.acquire() - while True: - if self.__state == RWLock.RWLOCK_STATE_WRITER: - self.__condition.wait() - else: - break - self.__state += 1 - self.__condition.release() - - def acquire_writer(self): - self.__condition.acquire() - self.__acquire_writer(RWLock.RWLOCK_STATE_UNUSED) - self.__condition.release() - - def __acquire_writer(self, wait_for_state): - while True: - if self.__state == wait_for_state: - self.__state = RWLock.RWLOCK_STATE_WRITER - break - else: - self.__blocked_writers += 1 - self.__condition.wait() - self.__blocked_writers -= 1 - - def release(self): - self.__condition.acquire() - if self.__state == RWLock.RWLOCK_STATE_WRITER: - self.__state = RWLock.RWLOCK_STATE_UNUSED - elif self.__state == RWLock.RWLOCK_STATE_UNUSED: - assert False, 'Lock not in use.' - else: - self.__state -= 1 - self.__condition.notifyAll() - self.__condition.release() - - -if __name__ == '__main__': - from threading import Thread - from time import sleep - - rwlock = RWLock() - - class Base(Thread): - def __init__(self, name, timeout): - self.name = name - self.timeout = timeout - Thread.__init__(self) - - class Reader(Base): - def __init__(self, name = 'Reader', timeout = 10): - Base.__init__(self, name, timeout) - - def run(self): - print '%s begin' % self.name - rwlock.acquire_reader() - print '%s acquired' % self.name - sleep(self.timeout) - rwlock.release() - print '%s end' % self.name - - class ReaderTwice(Base): - def __init__(self, name = 'Reader', timeout = 10): - Base.__init__(self, name, timeout) - - def run(self): - print '%s begin' % self.name - rwlock.acquire_reader() - print '%s acquired once' % self.name - sleep(self.timeout) - rwlock.acquire_reader() - print '%s acquired twice' % self.name - sleep(self.timeout) - rwlock.release() - rwlock.release() - print '%s end' % self.name - - class Writer(Base): - def __init__(self, name = 'Writer', timeout = 10): - Base.__init__(self, name, timeout) - - def run(self): - print '%s begin' % self.name - rwlock.acquire_writer() - print '%s acquired' % self.name - sleep(self.timeout) - rwlock.release() - print '%s end' % self.name - - def run_test(threadlist, msg): - print msg - for t in threadlist: - t.start() - sleep(1) - for t in threads: - t.join() - print 'Done\n\n' - - threads = [] - threads.append( Reader('R1', 4) ) - threads.append( Reader('R2', 4) ) - threads.append( Writer('W1', 4) ) - threads.append( Reader('R3', 4) ) - run_test(threads, - 'Test: readers may bypass blocked writers') diff --git a/tools/python/xen/util/sxputils.py b/tools/python/xen/util/sxputils.py deleted file mode 100644 index ff5678b530..0000000000 --- a/tools/python/xen/util/sxputils.py +++ /dev/null @@ -1,64 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (c) 2009 Fujitsu Technology Solutions -#============================================================================ - -""" convert sxp to map / map to sxp. -""" - -import types -from xen.xend import sxp - -def map2sxp(map_val): - """ conversion of all key-value pairs of a map (recursively) to sxp. - @param map_val: map; if a value contains a list or dict it is also - converted to sxp - @type map_val: dict - @return sxp expr - @rtype: list - """ - sxp_vals = [] - for (k, v) in map_val.items(): - if isinstance(v, types.DictionaryType): - sxp_vals += [[k] + map2sxp(v)] - elif isinstance(v, types.ListType): - sxp_vals += [[k] + v] - else: - sxp_vals += [[k, v]] - return sxp_vals - -def sxp2map( s ): - """ conversion of sxp to map. - @param s: sxp expr - @type s: list - @return: map - @rtype: dict - """ - sxphash = {} - - for child in sxp.children( s ): - if isinstance( child, types.ListType ) and len( child ) > 1: - if isinstance( child[1], types.ListType ) and len( child[1] ) > 1: - sxphash[ child[0] ] = sxp2map( child ) - else: - childs = sxp.children(child) - if len(childs) > 1: - sxphash[ child[0] ] = childs - else: - sxphash[ child[0] ] = childs[0] - - return sxphash - - diff --git a/tools/python/xen/util/utils.py b/tools/python/xen/util/utils.py deleted file mode 100644 index 6be3e8e202..0000000000 --- a/tools/python/xen/util/utils.py +++ /dev/null @@ -1,78 +0,0 @@ -import traceback -import sys -import os - -def exception_string(e): - (ty,v,tb) = sys.exc_info() - return traceback.format_exception_only(ty,v) - -def daemonize(prog, args, stdin_tmpfile=None): - """Runs a program as a daemon with the list of arguments. Returns the PID - of the daemonized program, or returns 0 on error. - """ - r, w = os.pipe() - pid = os.fork() - - if pid == 0: - os.close(r) - w = os.fdopen(w, 'w') - os.setsid() - try: - pid2 = os.fork() - except: - pid2 = None - if pid2 == 0: - os.chdir("/") - null_fd = os.open("/dev/null", os.O_RDWR) - if stdin_tmpfile is not None: - os.dup2(stdin_tmpfile.fileno(), 0) - else: - os.dup2(null_fd, 0) - os.dup2(null_fd, 1) - os.dup2(null_fd, 2) - for fd in range(3, 256): - try: - os.close(fd) - except: - pass - os.execvp(prog, args) - os._exit(1) - else: - w.write(str(pid2 or 0)) - w.close() - os._exit(0) - os.close(w) - r = os.fdopen(r) - daemon_pid = int(r.read()) - r.close() - os.waitpid(pid, 0) - return daemon_pid - -# Global variable to store the sysfs mount point -sysfs_mount_point = None - -PROC_MOUNTS_PATH = '/proc/mounts' - -def find_sysfs_mount(): - global sysfs_mount_point - - if not sysfs_mount_point is None: - return sysfs_mount_point - - try: - mounts_file = open(PROC_MOUNTS_PATH, 'r') - - for line in mounts_file: - sline = line.split() - if len(sline) < 3: - continue - if sline[2] == 'sysfs': - sysfs_mount_point= sline[1] - break - mounts_file.close() - return sysfs_mount_point - except IOError, (errno, strerr): - raise - - return None - diff --git a/tools/python/xen/util/vscsi_util.py b/tools/python/xen/util/vscsi_util.py deleted file mode 100644 index a4f5ad3ce8..0000000000 --- a/tools/python/xen/util/vscsi_util.py +++ /dev/null @@ -1,307 +0,0 @@ -#!/usr/bin/env python -# -*- mode: python; -*- - -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2008 FUJITSU Limited -# Based on the blkif.py -#============================================================================ - - -"""Support for VSCSI Devices. -""" -import os -import os.path -import sys -import re -import string -from xen.util import utils - -SYSFS_SCSI_PATH = "/bus/scsi/devices" -SYSFS_SCSI_DEV_VENDOR_PATH = '/vendor' -SYSFS_SCSI_DEV_MODEL_PATH = '/model' -SYSFS_SCSI_DEV_TYPEID_PATH = '/type' -SYSFS_SCSI_DEV_REVISION_PATH = '/rev' -SYSFS_SCSI_DEV_SCSILEVEL_PATH = '/scsi_level' - -SCSI_ID_COMMANDS = [ - "/lib/udev/scsi_id -gu --sg-version 3 -d /dev/%s 2>/dev/null", - "/sbin/scsi_id -gu -s /class/scsi_generic/%s 2>/dev/null" -] - -def _vscsi_get_devname_by(name, scsi_devices): - """A device name is gotten by the HCTL. - (e.g., '0:0:0:0' to '/dev/sda') - """ - - try: - search = re.compile(r'' + name + '$', re.DOTALL) - except Exception, e: - raise VmError("vscsi: invalid expression. " + str(e)) - - for hctl, devname, sg, scsi_id in scsi_devices: - if search.match(hctl): - return (hctl, devname) - - return (None, None) - - -def _vscsi_get_hctl_by(phyname, scsi_devices): - """An HCTL is gotten by the device name or the scsi_id. - (e.g., '/dev/sda' to '0:0:0:0') - """ - - if re.match('/dev/sd[a-z]+([1-9]|1[0-5])?$', phyname): - # sd driver - name = re.sub('(^/dev/)|([1-9]|1[0-5])?$', '', phyname) - elif re.match('/dev/sr[0-9]+$', phyname): - # sr driver - name = re.sub('^/dev/', '', phyname) - elif re.match('/dev/sg[0-9]+$', phyname): - # sg driver - name = re.sub('^/dev/', '', phyname) - elif re.match('/dev/st[0-9]+$', phyname): - # st driver - name = re.sub('^/dev/', '', phyname) - else: - # scsi_id -gu - name = phyname - - for hctl, devname, sg, scsi_id in scsi_devices: - if name in [devname, sg, scsi_id]: - return (hctl, devname) - - return (None, None) - - -def _vscsi_get_scsiid(sg): - for scsi_id_command in SCSI_ID_COMMANDS: - scsi_id = os.popen(scsi_id_command % sg).read().split() - if len(scsi_id): - return scsi_id[0] - return None - - -def _vscsi_get_scsidevices_by_lsscsi(option = ""): - """ get all scsi devices information by lsscsi """ - - devices = [] - - for scsiinfo in os.popen('{ lsscsi -g %s; } 2>/dev/null' % option).readlines(): - s = scsiinfo.replace(']', '] ').split() - hctl = s[0][1:-1] - try: - devname = s[-2].split('/dev/')[1] - except IndexError: - devname = None - try: - sg = s[-1].split('/dev/')[1] - if devname is None: - devname = sg - scsi_id = _vscsi_get_scsiid(sg) - except IndexError: - sg = None - scsi_id = None - devices.append([hctl, devname, sg, scsi_id]) - - return devices - - -def _vscsi_get_scsidevices_by_sysfs(): - """ get all scsi devices information by sysfs """ - - devices = [] - try: - sysfs_mnt = utils.find_sysfs_mount() - except: - return devices - - if sysfs_mnt is None: - return devices - - for dirpath, dirnames, files in os.walk(sysfs_mnt + SYSFS_SCSI_PATH): - for hctl in dirnames: - if len(hctl.split(':')) != 4: - continue - paths = os.path.join(dirpath, hctl) - devname = None - sg = None - scsi_id = None - for f in os.listdir(paths): - realpath = os.path.realpath(os.path.join(paths, f)) - if re.match('^block:', f) or \ - re.match('^tape:', f) or \ - re.match('^scsi_changer:', f) or \ - re.match('^onstream_tape:', f): - devname = os.path.basename(realpath) - elif f == "block" or \ - f == "tape" or \ - f == "scsi_changer" or \ - f == "onstream_tape": - for dir in os.listdir(os.path.join(paths, f)): - if os.path.exists(os.path.join(paths, f, dir, "dev")): - devname = os.path.basename(dir) - - if re.match('^scsi_generic:', f): - sg = os.path.basename(realpath) - elif f == "scsi_generic": - for dir in os.listdir(os.path.join(paths, f)): - if os.path.exists(os.path.join(paths, f, dir, "dev")): - sg = os.path.basename(dir) - if sg: - if devname is None: - devname = sg - scsi_id = _vscsi_get_scsiid(sg) - devices.append([hctl, devname, sg, scsi_id]) - - return devices - - -def vscsi_get_scsidevices(mask="*"): - """ get all scsi devices information """ - - devices = _vscsi_get_scsidevices_by_lsscsi("[%s]" % mask) - if devices or (len(mask) and mask[0] != "*"): - # devices found or partial device scan - return devices - return _vscsi_get_scsidevices_by_sysfs() - - -def vscsi_get_hctl_and_devname_by(target, scsi_devices = None): - if target.startswith('/dev/'): - target = os.path.realpath(target) - if scsi_devices is None: - if len(target.split(':')) == 4: - scsi_devices = _vscsi_get_scsidevices_by_lsscsi(target) - elif target.startswith('/dev/'): - scsi_devices = _vscsi_get_scsidevices_by_lsscsi("| grep %s" % target) - else: - scsi_devices = _vscsi_get_scsidevices_by_lsscsi("") - if not scsi_devices: - scsi_devices = _vscsi_get_scsidevices_by_sysfs() - - if len(target.split(':')) == 4: - return _vscsi_get_devname_by(target, scsi_devices) - else: - return _vscsi_get_hctl_by(target, scsi_devices) - - -def get_scsi_vendor(pHCTL): - try: - sysfs_mnt = utils.find_sysfs_mount() - sysfs_scsi_dev_path = \ - os.path.join(sysfs_mnt + SYSFS_SCSI_PATH, pHCTL) - scsi_vendor = \ - os.popen('cat ' + sysfs_scsi_dev_path + \ - SYSFS_SCSI_DEV_VENDOR_PATH).read() - return scsi_vendor.splitlines()[0] - except: - return None - -def get_scsi_model(pHCTL): - try: - sysfs_mnt = utils.find_sysfs_mount() - sysfs_scsi_dev_path = \ - os.path.join(sysfs_mnt + SYSFS_SCSI_PATH, pHCTL) - scsi_model = \ - os.popen('cat ' + sysfs_scsi_dev_path + \ - SYSFS_SCSI_DEV_MODEL_PATH).read() - return scsi_model.splitlines()[0] - except: - return None - -def get_scsi_typeid(pHCTL): - try: - sysfs_mnt = utils.find_sysfs_mount() - sysfs_scsi_dev_path = \ - os.path.join(sysfs_mnt + SYSFS_SCSI_PATH, pHCTL) - scsi_typeid = \ - os.popen('cat ' + sysfs_scsi_dev_path + \ - SYSFS_SCSI_DEV_TYPEID_PATH).read() - return int(scsi_typeid.splitlines()[0]) - except: - return None - -def get_scsi_revision(pHCTL): - try: - sysfs_mnt = utils.find_sysfs_mount() - sysfs_scsi_dev_path = \ - os.path.join(sysfs_mnt + SYSFS_SCSI_PATH, pHCTL) - scsi_revision = \ - os.popen('cat ' + sysfs_scsi_dev_path + \ - SYSFS_SCSI_DEV_REVISION_PATH).read() - return scsi_revision.splitlines()[0] - except: - return None - -def get_scsi_scsilevel(pHCTL): - try: - sysfs_mnt = utils.find_sysfs_mount() - sysfs_scsi_dev_path = \ - os.path.join(sysfs_mnt + SYSFS_SCSI_PATH, pHCTL) - scsi_scsilevel = \ - os.popen('cat ' + sysfs_scsi_dev_path + \ - SYSFS_SCSI_DEV_SCSILEVEL_PATH).read() - return int(scsi_scsilevel.splitlines()[0]) - except: - return None - -def _make_scsi_record(scsi_info): - scsi_rec = { - 'physical_HCTL': scsi_info[0], - 'dev_name': None, - 'sg_name': scsi_info[2], - 'scsi_id': None - } - if scsi_info[1] is not None: - scsi_rec['dev_name'] = scsi_info[1] - if scsi_info[3] is not None: - scsi_rec['scsi_id'] = scsi_info[3] - - scsi_rec['vendor_name'] = \ - get_scsi_vendor(scsi_rec['physical_HCTL']) - scsi_rec['model'] = \ - get_scsi_model(scsi_rec['physical_HCTL']) - scsi_rec['type_id'] = \ - get_scsi_typeid(scsi_rec['physical_HCTL']) - scsi_rec['revision'] = \ - get_scsi_revision(scsi_rec['physical_HCTL']) - scsi_rec['scsi_level'] = \ - get_scsi_scsilevel(scsi_rec['physical_HCTL']) - - try: - lsscsi_info = os.popen('lsscsi %s 2>/dev/null' % scsi_rec['physical_HCTL']).read().split() - scsi_rec['type'] = lsscsi_info[1] - except: - scsi_rec['type'] = None - - return scsi_rec - -def get_scsi_device(pHCTL): - scsis_info = _vscsi_get_scsidevices_by_lsscsi(pHCTL) - if not scsis_info: - scsis_info = _vscsi_get_scsidevices_by_sysfs() - for scsi_info in scsis_info: - if scsi_info[0] == pHCTL: - return _make_scsi_record(scsi_info) - return None - -def get_all_scsi_devices(mask="*"): - scsi_records = [] - for scsi_info in vscsi_get_scsidevices(mask): - scsi_record = _make_scsi_record(scsi_info) - scsi_records.append(scsi_record) - return scsi_records - diff --git a/tools/python/xen/util/vusb_util.py b/tools/python/xen/util/vusb_util.py deleted file mode 100644 index 9ca498cb46..0000000000 --- a/tools/python/xen/util/vusb_util.py +++ /dev/null @@ -1,338 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2009, FUJITSU LABORATORIES LTD. -# Author: Noboru Iwamatsu -#============================================================================ - - -"""Support for VUSB Devices. -""" -import os -import os.path -import sys -import re -import string -from xen.util import utils - -SYSFS_USB_DEVS_PATH = '/bus/usb/devices' -SYSFS_USB_DEV_BDEVICECLASS_PATH = '/bDeviceClass' -SYSFS_USB_DEV_BDEVICESUBCLASS_PATH = '/bDeviceSubClass' -SYSFS_USB_DEV_DEVNUM_PATH = '/devnum' -SYSFS_USB_DEV_IDVENDOR_PATH = '/idVendor' -SYSFS_USB_DEV_IDPRODUCT_PATH = '/idProduct' -SYSFS_USB_DEV_MANUFACTURER_PATH = '/manufacturer' -SYSFS_USB_DEV_PRODUCT_PATH = '/product' -SYSFS_USB_DEV_SERIAL_PATH = '/serial' -SYSFS_USB_DEV_DRIVER_PATH = '/driver' -SYSFS_USB_DRIVER_BIND_PATH = '/bind' -SYSFS_USB_DRIVER_UNBIND_PATH = '/unbind' -SYSFS_USBBACK_PATH = '/bus/usb/drivers/usbback' -SYSFS_PORTIDS_PATH = '/port_ids' -USBHUB_CLASS_CODE = '09' - -def get_usb_bDeviceClass(dev): - try: - sysfs_mnt = utils.find_sysfs_mount() - sysfs_usb_dev_path = \ - os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev) - if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_BDEVICECLASS_PATH): - usb_deviceclass = \ - os.popen('cat ' + sysfs_usb_dev_path + \ - SYSFS_USB_DEV_BDEVICECLASS_PATH).readline() - return usb_deviceclass.splitlines()[0] - else: - return "" - except: - return None - -def get_usb_bDeviceSubClass(dev): - try: - sysfs_mnt = utils.find_sysfs_mount() - sysfs_usb_dev_path = \ - os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev) - if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_BDEVICESUBCLASS_PATH): - usb_devicesubclass = \ - os.popen('cat ' + sysfs_usb_dev_path + \ - SYSFS_USB_DEV_BDEVICESUBCLASS_PATH).readline() - return usb_devicesubclass.splitlines()[0] - else: - return "" - except: - return None - -def get_usb_devnum(dev): - try: - sysfs_mnt = utils.find_sysfs_mount() - sysfs_usb_dev_path = \ - os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev) - if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_DEVNUM_PATH): - usb_devicesubclass = \ - os.popen('cat ' + sysfs_usb_dev_path + \ - SYSFS_USB_DEV_DEVNUM_PATH).readline() - return usb_devicesubclass.splitlines()[0] - else: - return "" - except: - return None - -def get_usb_idvendor(dev): - try: - sysfs_mnt = utils.find_sysfs_mount() - sysfs_usb_dev_path = \ - os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev) - if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_IDVENDOR_PATH): - usb_idvendor = \ - os.popen('cat ' + sysfs_usb_dev_path + \ - SYSFS_USB_DEV_IDVENDOR_PATH).readline() - return usb_idvendor.splitlines()[0] - else: - return "" - except: - return None - -def get_usb_idproduct(dev): - try: - sysfs_mnt = utils.find_sysfs_mount() - sysfs_usb_dev_path = \ - os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev) - if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_IDPRODUCT_PATH): - usb_idproduct = \ - os.popen('cat ' + sysfs_usb_dev_path + \ - SYSFS_USB_DEV_IDPRODUCT_PATH).readline() - return usb_idproduct.splitlines()[0] - else: - return "" - except: - return None - -def get_usb_manufacturer(dev): - try: - sysfs_mnt = utils.find_sysfs_mount() - sysfs_usb_dev_path = \ - os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev) - - if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_MANUFACTURER_PATH): - usb_manufacturer = \ - os.popen('cat ' + sysfs_usb_dev_path + \ - SYSFS_USB_DEV_MANUFACTURER_PATH).readline() - return usb_manufacturer.splitlines()[0] - else: - return "" - except: - return None - -def get_usb_product(dev): - try: - sysfs_mnt = utils.find_sysfs_mount() - sysfs_usb_dev_path = \ - os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev) - if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_PRODUCT_PATH): - usb_product = \ - os.popen('cat ' + sysfs_usb_dev_path + \ - SYSFS_USB_DEV_PRODUCT_PATH).readline() - return usb_product.splitlines()[0] - else: - return "" - except: - return None - -def get_usb_serial(dev): - try: - sysfs_mnt = utils.find_sysfs_mount() - sysfs_usb_dev_path = \ - os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev) - if os.path.exists(sysfs_usb_dev_path + SYSFS_USB_DEV_SERIAL_PATH): - usb_serial = \ - os.popen('cat ' + sysfs_usb_dev_path + \ - SYSFS_USB_DEV_SERIAL_PATH).readline() - return usb_serial.splitlines()[0] - else: - return "" - except: - return None - -def get_usbdevice_info_by_lsusb(dev): - try: - vend = get_usb_idvendor(dev) - prod = get_usb_idproduct(dev) - output = os.popen('lsusb -d ' + vend + ':' + prod).readline().split() - text = "" - if len(output) > 6: - for str in output[6:]: - if text != "": - text= text + ' ' - text = text + str - return text - else: - return "" - except: - return None - -def get_usbdevice_info(dev): - try: - manuf = get_usb_manufacturer(dev) - prod = get_usb_product(dev) - if manuf == "" or prod == "": - return get_usbdevice_info_by_lsusb(dev) - else: - return manuf + ' ' + prod - except: - return None - -def usb_device_is_hub(dev): - usb_classcode = get_usb_bDeviceClass(dev) - if (usb_classcode == USBHUB_CLASS_CODE): - return True - else: - return False - -def get_all_usb_names(): - usb_names = [] - try: - sysfs_mnt = utils.find_sysfs_mount() - usb_names = os.popen('ls ' + sysfs_mnt + SYSFS_USB_DEVS_PATH).read().split() - except: - pass - return usb_names - -def get_usb_devices(): - devs = [] - for name in get_all_usb_names(): - dev_match = re.match(r"(^(?P[0-9]{1,2})[-,])" + \ - r"(?P[0-9]{1,2})" + \ - r"(?P([\.,]{1}[0-9]{1,2}){0,5})$", name) - if dev_match is not None: - dev = dev_match.group('bus') + '-' \ - + dev_match.group('root_port') \ - + dev_match.group('port') - if (usb_device_is_hub(dev)): - continue - else: - devs.append(dev) - return devs - -def get_usb_intfs(dev): - intfs = [] - try: - search = re.compile(r'^' + dev + ':') - except: - raise UsbDeviceParseError("Invalid expression.") - for name in get_all_usb_names(): - if search.match(name): - intfs.append(name) - return intfs - -def get_assigned_buses(): - buses = [] - try: - sysfs_mnt = utils.find_sysfs_mount() - if os.path.exists(sysfs_mnt + SYSFS_USBBACK_PATH + SYSFS_PORTIDS_PATH): - portids = \ - os.popen('cat ' + sysfs_mnt + SYSFS_USBBACK_PATH + SYSFS_PORTIDS_PATH).read().splitlines() - for portid in portids: - buses.append(portid.split(':')[0]) - except: - raise UsbDeviceParseError("Can't get assigned buses from port_ids.") - return buses - -def get_assigned_bus(domid, dev, port): - bus = "" - try: - sysfs_mnt = utils.find_sysfs_mount() - if os.path.exists(sysfs_mnt + SYSFS_USBBACK_PATH + SYSFS_PORTIDS_PATH): - portids = \ - os.popen('cat ' + sysfs_mnt + SYSFS_USBBACK_PATH + SYSFS_PORTIDS_PATH).read().splitlines() - for portid in portids: - if portid.split(':')[1] == str(domid) and portid.split(':')[2] == str(dev) and portid.split(':')[3] == str(port): - bus = portid.split(':')[0] - except: - raise UsbDeviceParseError("Can't get assigned bus (%d:%d:%d)." % (domid, dev, port)) - return bus - -def bus_is_assigned(bus): - assigned = False - try: - sysfs_mnt = utils.find_sysfs_mount() - if os.path.exists(sysfs_mnt + SYSFS_USBBACK_PATH + SYSFS_PORTIDS_PATH): - portids = \ - os.popen('cat ' + sysfs_mnt + SYSFS_USBBACK_PATH + SYSFS_PORTIDS_PATH).read().splitlines() - for portid in portids: - if portid.split(':')[0] == bus: - assigned = True - except: - raise UsbDeviceParseError("Can't get assignment status: (%s)." % bus) - return assigned - -def usb_intf_is_binded(intf): - if os.path.exists(SYSFS_USBBACK_PATH + '/' + intf): - return True - else: - return False - -def usb_device_is_connected(dev): - try: - sysfs_mnt = utils.find_sysfs_mount() - sysfs_dev_path = \ - os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, dev) - if os.path.exists(sysfs_dev_path): - return True - else: - return False - except: - raise UsbDeviceParseError("Can't get connection status (%s)." % dev) - -def unbind_usb_device(dev): - try: - sysfs_mnt = utils.find_sysfs_mount() - for intf in get_usb_intfs(dev): - sysfs_usb_intf_path = \ - os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, intf) - if os.path.exists(sysfs_usb_intf_path + SYSFS_USB_DEV_DRIVER_PATH): - fd = os.open(sysfs_usb_intf_path + \ - SYSFS_USB_DEV_DRIVER_PATH + \ - SYSFS_USB_DRIVER_UNBIND_PATH, os.O_WRONLY) - os.write(fd, intf) - os.close(fd) - except: - raise UsbDeviceBindingError("can't unbind intf (%s). " % intf) - -def bind_usb_device(dev): - try: - sysfs_mnt = utils.find_sysfs_mount() - for intf in get_usb_intfs(dev): - sysfs_usb_intf_path = \ - os.path.join(sysfs_mnt + SYSFS_USB_DEVS_PATH, intf) - if os.path.exists(sysfs_usb_intf_path + SYSFS_USB_DEV_DRIVER_PATH): - unbind_usb_device(dev) - - fd = os.open(sysfs_mnt + SYSFS_USBBACK_PATH + \ - SYSFS_USB_DRIVER_BIND_PATH, os.O_WRONLY) - os.write(fd, intf) - os.close(fd) - except: - raise UsbDeviceBindingError("can't bind intf (%s). " % intf) - -class UsbDeviceParseError(Exception): - def __init__(self,msg): - self.message = msg - def __str__(self): - return 'vusb: Error parsing USB device info: '+self.message - -class UsbDeviceBindingError(Exception): - def __init__(self,msg): - self.message = msg - def __str__(self): - return 'vusb: Failed to bind/unbind USB device: ' + \ - self.message diff --git a/tools/python/xen/util/xmlrpcclient.py b/tools/python/xen/util/xmlrpcclient.py deleted file mode 100644 index d4191b7489..0000000000 --- a/tools/python/xen/util/xmlrpcclient.py +++ /dev/null @@ -1,129 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2006 Anthony Liguori -# Copyright (C) 2007 XenSource Inc. -#============================================================================ - - -from httplib import FakeSocket, HTTPConnection, HTTP -import socket -import string -import xmlrpclib -from types import StringTypes -from sys import hexversion - - -try: - import SSHTransport - ssh_enabled = True -except ImportError: - # SSHTransport is disabled on Python <2.4, because it uses the subprocess - # package. - ssh_enabled = False - - -# A new ServerProxy that also supports httpu urls. An http URL comes in the -# form: -# -# httpu:///absolute/path/to/socket.sock -# -# It assumes that the RPC handler is /RPC2. This probably needs to be improved - -class HTTPUnixConnection(HTTPConnection): - def connect(self): - self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - self.sock.connect(self.host) - -class HTTPUnix(HTTP): - _connection_class = HTTPUnixConnection - -class UnixTransport(xmlrpclib.Transport): - def request(self, host, handler, request_body, verbose=0): - self.__handler = handler - return xmlrpclib.Transport.request(self, host, '/RPC2', - request_body, verbose) - def make_connection(self, host): - if hexversion < 0x02070000: - # python 2.6 or earlier - return HTTPUnix(self.__handler) - else: - # xmlrpclib.Transport changed in python 2.7 - return HTTPUnixConnection(self.__handler) - - -# We need our own transport for HTTPS, because xmlrpclib.SafeTransport is -# broken -- it does not handle ERROR_ZERO_RETURN properly. -class HTTPSTransport(xmlrpclib.SafeTransport): - def _parse_response(self, file, sock): - p, u = self.getparser() - while 1: - try: - if sock: - response = sock.recv(1024) - else: - response = file.read(1024) - except socket.sslerror, exn: - if exn[0] == socket.SSL_ERROR_ZERO_RETURN: - break - raise - - if not response: - break - if self.verbose: - print 'body:', repr(response) - p.feed(response) - - file.close() - p.close() - return u.close() - - -# See xmlrpclib2.TCPXMLRPCServer._marshalled_dispatch. -def conv_string(x): - if isinstance(x, StringTypes): - s = string.replace(x, "'", r"\047") - exec "s = '" + s + "'" - return s - else: - return x - - -class ServerProxy(xmlrpclib.ServerProxy): - def __init__(self, uri, transport=None, encoding=None, verbose=0, - allow_none=1): - if transport == None: - (protocol, rest) = uri.split(':', 1) - if protocol == 'httpu': - uri = 'http:' + rest - transport = UnixTransport() - elif protocol == 'https': - transport = HTTPSTransport() - elif protocol == 'ssh': - global ssh_enabled - if ssh_enabled: - (transport, uri) = SSHTransport.getHTTPURI(uri) - else: - raise ValueError( - "SSH transport not supported on Python <2.4.") - xmlrpclib.ServerProxy.__init__(self, uri, transport, encoding, - verbose, allow_none) - - def __request(self, methodname, params): - response = xmlrpclib.ServerProxy.__request(self, methodname, params) - - if isinstance(response, tuple): - return tuple([conv_string(x) for x in response]) - else: - return conv_string(response) diff --git a/tools/python/xen/util/xmlrpclib2.py b/tools/python/xen/util/xmlrpclib2.py deleted file mode 100644 index 065a0a3e96..0000000000 --- a/tools/python/xen/util/xmlrpclib2.py +++ /dev/null @@ -1,220 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2006 Anthony Liguori -# Copyright (C) 2006 XenSource Inc. -#============================================================================ - -""" -An enhanced XML-RPC client/server interface for Python. -""" - -import re -import fcntl -from types import * - - -from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler -import SocketServer -import xmlrpclib, socket, os, stat - -import mkdir - -from xen.web import connection -from xen.xend.XendLogging import log - -# -# Convert all integers to strings as described in the Xen API -# - - -def stringify(value): - if isinstance(value, long) or \ - (isinstance(value, int) and not isinstance(value, bool)): - return str(value) - elif isinstance(value, dict): - new_value = {} - for k, v in value.items(): - new_value[stringify(k)] = stringify(v) - return new_value - elif isinstance(value, (tuple, list)): - return [stringify(v) for v in value] - else: - return value - - -# We're forced to subclass the RequestHandler class so that we can work around -# some bugs in Keep-Alive handling and also enabled it by default -class XMLRPCRequestHandler(SimpleXMLRPCRequestHandler): - protocol_version = "HTTP/1.1" - # xend crashes in python 2.7 unless disable_nagle_algorithm = False - # it isn't used in earlier versions so it is harmless to set it generally - disable_nagle_algorithm = False - - def __init__(self, hosts_allowed, request, client_address, server): - self.hosts_allowed = hosts_allowed - SimpleXMLRPCRequestHandler.__init__(self, request, client_address, - server) - - # this is inspired by SimpleXMLRPCRequestHandler's do_POST but differs - # in a few non-trivial ways - # 1) we never generate internal server errors. We let the exception - # propagate so that it shows up in the Xend debug logs - # 2) we don't bother checking for a _dispatch function since we don't - # use one - def do_POST(self): - addrport = self.client_address - if not connection.hostAllowed(addrport, self.hosts_allowed): - self.connection.shutdown(1) - return - - data = self.rfile.read(int(self.headers["content-length"])) - rsp = self.server._marshaled_dispatch(data) - - self.send_response(200) - self.send_header("Content-Type", "text/xml") - self.send_header("Content-Length", str(len(rsp))) - self.end_headers() - - self.wfile.write(rsp) - self.wfile.flush() - if self.close_connection == 1: - self.connection.shutdown(1) - -# This is a base XML-RPC server for TCP. It sets allow_reuse_address to -# true, and has an improved marshaller that logs and serializes exceptions. - -class TCPXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer): - allow_reuse_address = True - - def __init__(self, addr, allowed, xenapi, requestHandler=None, - logRequests = 1): - self.xenapi = xenapi - - if requestHandler is None: - requestHandler = XMLRPCRequestHandler - SimpleXMLRPCServer.__init__(self, addr, - (lambda x, y, z: - requestHandler(allowed, x, y, z)), - logRequests) - - flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD) - flags |= fcntl.FD_CLOEXEC - fcntl.fcntl(self.fileno(), fcntl.F_SETFD, flags) - - def get_request(self): - (client, addr) = SimpleXMLRPCServer.get_request(self) - flags = fcntl.fcntl(client.fileno(), fcntl.F_GETFD) - flags |= fcntl.FD_CLOEXEC - fcntl.fcntl(client.fileno(), fcntl.F_SETFD, flags) - return (client, addr) - - def _marshaled_dispatch(self, data, dispatch_method = None): - params, method = xmlrpclib.loads(data) - if False: - # Enable this block of code to exit immediately without sending - # a response. This allows you to test client-side crash handling. - import sys - sys.exit(1) - try: - if dispatch_method is not None: - response = dispatch_method(method, params) - else: - response = self._dispatch(method, params) - - if self.xenapi and \ - (response is None or - not isinstance(response, dict) or - 'Status' not in response): - log.exception('Internal error handling %s: Invalid result %s', - method, response) - response = { "Status": "Failure", - "ErrorDescription": - ['INTERNAL_ERROR', - 'Invalid result %s handling %s' % - (response, method)]} - - # With either Unicode or normal strings, we can only transmit - # \t, \n, \r, \u0020-\ud7ff, \ue000-\ufffd, and \u10000-\u10ffff - # in an XML document. xmlrpclib does not escape these values - # properly, and then breaks when it comes to parse the document. - # To hack around this problem, we use repr here and exec above - # to transmit the string using Python encoding. - # Thanks to David Mertz for the trick (buried - # in xml_pickle.py). - if isinstance(response, StringTypes): - response = repr(response)[1:-1] - - response = (response,) - response = xmlrpclib.dumps(response, - methodresponse=1, - allow_none=1) - except Exception, exn: - try: - if self.xenapi: - if _is_not_supported(exn): - errdesc = ['MESSAGE_METHOD_UNKNOWN', method] - else: - log.exception('Internal error handling %s', method) - errdesc = ['INTERNAL_ERROR', str(exn)] - - response = xmlrpclib.dumps( - ({ "Status": "Failure", - "ErrorDescription": errdesc },), - methodresponse = 1) - else: - import xen.xend.XendClient - if isinstance(exn, xmlrpclib.Fault): - response = xmlrpclib.dumps(exn) - else: - log.exception('Internal error handling %s', method) - response = xmlrpclib.dumps( - xmlrpclib.Fault(xen.xend.XendClient.ERROR_INTERNAL, str(exn))) - except: - log.exception('Internal error handling error') - - return response - - -notSupportedRE = re.compile(r'method "(.*)" is not supported') -def _is_not_supported(exn): - try: - m = notSupportedRE.search(exn[0]) - return m is not None - except: - return False - - -# This is a XML-RPC server that sits on a Unix domain socket. -# It implements proper support for allow_reuse_address by -# unlink()'ing an existing socket. - -class UnixXMLRPCRequestHandler(XMLRPCRequestHandler): - def address_string(self): - try: - return XMLRPCRequestHandler.address_string(self) - except ValueError, e: - return self.client_address[:2] - -class UnixXMLRPCServer(TCPXMLRPCServer): - address_family = socket.AF_UNIX - allow_address_reuse = True - - def __init__(self, addr, allowed, xenapi, logRequests = 1): - mkdir.parents(os.path.dirname(addr), stat.S_IRWXU, True) - if self.allow_reuse_address and os.path.exists(addr): - os.unlink(addr) - - TCPXMLRPCServer.__init__(self, addr, allowed, xenapi, - UnixXMLRPCRequestHandler, logRequests) diff --git a/tools/python/xen/util/xpopen.py b/tools/python/xen/util/xpopen.py deleted file mode 100644 index 75aa08e678..0000000000 --- a/tools/python/xen/util/xpopen.py +++ /dev/null @@ -1,182 +0,0 @@ -# -# Copyright (c) 2001, 2002, 2003, 2004 Python Software Foundation; All Rights Reserved -# -# PSF LICENSE AGREEMENT FOR PYTHON 2.3 -# ------------------------------------ -# -# 1. This LICENSE AGREEMENT is between the Python Software Foundation -# ("PSF"), and the Individual or Organization ("Licensee") accessing and -# otherwise using Python 2.3 software in source or binary form and its -# associated documentation. -# -# 2. Subject to the terms and conditions of this License Agreement, PSF -# hereby grants Licensee a nonexclusive, royalty-free, world-wide -# license to reproduce, analyze, test, perform and/or display publicly, -# prepare derivative works, distribute, and otherwise use Python 2.3 -# alone or in any derivative version, provided, however, that PSF's -# License Agreement and PSF's notice of copyright, i.e., "Copyright (c) -# 2001, 2002, 2003, 2004 Python Software Foundation; All Rights Reserved" are -# retained in Python 2.3 alone or in any derivative version prepared by -# Licensee. -# -# 3. In the event Licensee prepares a derivative work that is based on -# or incorporates Python 2.3 or any part thereof, and wants to make -# the derivative work available to others as provided herein, then -# Licensee hereby agrees to include in any such work a brief summary of -# the changes made to Python 2.3. -# -# 4. PSF is making Python 2.3 available to Licensee on an "AS IS" -# basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR -# IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND -# DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS -# FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 2.3 WILL NOT -# INFRINGE ANY THIRD PARTY RIGHTS. -# -# 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON -# 2.3 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS -# A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.3, -# OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. -# -# 6. This License Agreement will automatically terminate upon a material -# breach of its terms and conditions. -# -# 7. Nothing in this License Agreement shall be deemed to create any -# relationship of agency, partnership, or joint venture between PSF and -# Licensee. This License Agreement does not grant permission to use PSF -# trademarks or trade name in a trademark sense to endorse or promote -# products or services of Licensee, or any third party. -# -# 8. By copying, installing or otherwise using Python 2.3, Licensee -# agrees to be bound by the terms and conditions of this License -# Agreement. -# -# Modifications: Copyright (c) 2005 Christian Limpach -# - add support for excluding a list of file descriptors from being -# closed, allowing access to those file descriptors from the command. -# - -"""Spawn a command with pipes to its stdin, stdout, and optionally stderr. - -The normal os.popen(cmd, mode) call spawns a shell command and provides a -file interface to just the input or output of the process depending on -whether mode is 'r' or 'w'. This module provides the functions xpopen2(cmd) -and xpopen3(cmd) which return two or three pipes to the spawned command. -Optionally exclude a list of file descriptors from being closed, allowing -access to those file descriptors from the command. -""" - -import os -import sys - -try: - MAXFD = os.sysconf('SC_OPEN_MAX') -except (AttributeError, ValueError): - MAXFD = 256 - -_active = [] - -def _cleanup(): - for inst in _active[:]: - inst.poll() - -class xPopen3: - """Class representing a child process. Normally instances are created - by the factory functions popen2() and popen3().""" - - sts = -1 # Child not completed yet - - def __init__(self, cmd, capturestderr=False, bufsize=-1, passfd=(), env=None): - """The parameter 'cmd' is the shell command to execute in a - sub-process. The 'capturestderr' flag, if true, specifies that - the object should capture standard error output of the child process. - The default is false. If the 'bufsize' parameter is specified, it - specifies the size of the I/O buffers to/from the child process.""" - _cleanup() - self.passfd = passfd - p2cread, p2cwrite = os.pipe() - c2pread, c2pwrite = os.pipe() - if capturestderr: - errout, errin = os.pipe() - self.pid = os.fork() - if self.pid == 0: - # Child - os.dup2(p2cread, 0) - os.dup2(c2pwrite, 1) - if capturestderr: - os.dup2(errin, 2) - self._run_child(cmd, env) - os.close(p2cread) - self.tochild = os.fdopen(p2cwrite, 'w', bufsize) - os.close(c2pwrite) - self.fromchild = os.fdopen(c2pread, 'r', bufsize) - if capturestderr: - os.close(errin) - self.childerr = os.fdopen(errout, 'r', bufsize) - else: - self.childerr = None - _active.append(self) - - def _run_child(self, cmd, env): - if isinstance(cmd, basestring): - cmd = ['/bin/sh', '-c', cmd] - for i in range(3, MAXFD): - if i in self.passfd: - continue - try: - os.close(i) - except OSError: - pass - try: - if env is None: - os.execvp(cmd[0], cmd) - else: - os.execvpe(cmd[0], cmd, env) - finally: - os._exit(127) - - def poll(self): - """Return the exit status of the child process if it has finished, - or -1 if it hasn't finished yet.""" - if self.sts < 0: - try: - pid, sts = os.waitpid(self.pid, os.WNOHANG) - if pid == self.pid: - self.sts = sts - _active.remove(self) - except os.error: - pass - return self.sts - - def wait(self): - """Wait for and return the exit status of the child process.""" - if self.sts < 0: - pid, sts = os.waitpid(self.pid, 0) - if pid == self.pid: - self.sts = sts - _active.remove(self) - return self.sts - - -def xpopen2(cmd, bufsize=-1, mode='t', passfd=[], env=None): - """Execute the shell command 'cmd' in a sub-process. If 'bufsize' is - specified, it sets the buffer size for the I/O pipes. The file objects - (child_stdout, child_stdin) are returned.""" - inst = xPopen3(cmd, False, bufsize, passfd, env) - return inst.fromchild, inst.tochild - -def xpopen3(cmd, bufsize=-1, mode='t', passfd=[], env=None): - """Execute the shell command 'cmd' in a sub-process. If 'bufsize' is - specified, it sets the buffer size for the I/O pipes. The file objects - (child_stdout, child_stdin, child_stderr) are returned.""" - inst = xPopen3(cmd, True, bufsize, passfd, env) - return inst.fromchild, inst.tochild, inst.childerr - -def call(*popenargs, **kwargs): - """Run command with arguments. Wait for command to complete, then - return the status. - - The arguments are the same as for the xPopen3 constructor. Example: - - status = call("ls -l") - """ - return xPopen3(*popenargs, **kwargs).wait() diff --git a/tools/python/xen/util/xsconstants.py b/tools/python/xen/util/xsconstants.py deleted file mode 100644 index 8d2e9ecaa0..0000000000 --- a/tools/python/xen/util/xsconstants.py +++ /dev/null @@ -1,115 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2007 International Business Machines Corp. -# Author: Stefan Berger -#============================================================================ - -XS_INST_NONE = 0 -XS_INST_BOOT = (1 << 0) -XS_INST_LOAD = (1 << 1) - -XS_POLICY_ACM = (1 << 0) -XS_POLICY_FLASK = (1 << 1) -XS_POLICY_DUMMY = (1 << 2) -XS_POLICY_USE = 0 - -# Some internal variables used by the Xen-API -ACM_LABEL_VM = (1 << 0) -ACM_LABEL_RES = (1 << 1) - -# Base for XS error codes for collision avoidance with other error codes -XSERR_BASE = 0x1000 - -# XS error codes as used by the Xen-API -XSERR_SUCCESS = 0 -XSERR_GENERAL_FAILURE = 1 + XSERR_BASE -XSERR_BAD_XML = 2 + XSERR_BASE # XML is wrong (not according to schema) -XSERR_XML_PROCESSING = 3 + XSERR_BASE -XSERR_POLICY_INCONSISTENT = 4 + XSERR_BASE # i.e., bootstrap name not a VM label -XSERR_FILE_ERROR = 5 + XSERR_BASE -XSERR_BAD_RESOURCE_FORMAT = 6 + XSERR_BASE # badly formatted resource -XSERR_BAD_LABEL_FORMAT = 7 + XSERR_BASE -XSERR_RESOURCE_NOT_LABELED = 8 + XSERR_BASE -XSERR_RESOURCE_ALREADY_LABELED = 9 + XSERR_BASE -XSERR_WRONG_POLICY_TYPE = 10 + XSERR_BASE -XSERR_BOOTPOLICY_INSTALLED = 11 + XSERR_BASE -XSERR_NO_DEFAULT_BOOT_TITLE = 12 + XSERR_BASE -XSERR_POLICY_LOAD_FAILED = 13 + XSERR_BASE -XSERR_POLICY_LOADED = 14 + XSERR_BASE -XSERR_POLICY_TYPE_UNSUPPORTED = 15 + XSERR_BASE -XSERR_BAD_CONFLICTSET = 16 + XSERR_BASE -XSERR_RESOURCE_IN_USE = 17 + XSERR_BASE -XSERR_BAD_POLICY_NAME = 18 + XSERR_BASE -XSERR_VERSION_PREVENTS_UPDATE = 19 + XSERR_BASE -XSERR_BAD_LABEL = 20 + XSERR_BASE -XSERR_VM_WRONG_STATE = 21 + XSERR_BASE -XSERR_POLICY_NOT_LOADED = 22 + XSERR_BASE -XSERR_RESOURCE_ACCESS = 23 + XSERR_BASE -XSERR_HV_OP_FAILED = 24 + XSERR_BASE -XSERR_BOOTPOLICY_INSTALL_ERROR = 25 + XSERR_BASE -XSERR_VM_NOT_AUTHORIZED = 26 + XSERR_BASE -XSERR_VM_IN_CONFLICT = 27 + XSERR_BASE -XSERR_POLICY_HAS_DUPLICATES = 28 + XSERR_BASE -XSERR_LAST = 28 + XSERR_BASE ## KEEP LAST - -XSERR_MESSAGES = [ - '', - 'General Failure', - 'XML is malformed', - 'Error while processing XML', - 'Policy has inconsistencies', - 'A file access error occurred', - 'The resource format is not valid', - 'The label format is not valid', - 'The resource is not labeld', - 'The resource is already labeld', - 'The policy type is wrong', - 'The system boot policy is installed', - 'Could not find the default boot title', - 'Loading of the policy failed', - 'The policy is loaded', - 'The policy type is unsupported', - 'There is a bad conflict set', - 'The resource is in use', - 'The policy has an invalid name', - 'The version of the policy prevents an update', - 'The label is bad', - 'Operation not premittend - the VM is in the wrong state', - 'The policy is not loaded', - 'Error accessing resource', - 'Operation failed in hypervisor', - 'Boot policy installation error', - 'VM is not authorized to run', - 'VM label conflicts with another VM', - 'Duplicate labels or types in policy' -] - -def xserr2string(err): - if err == XSERR_SUCCESS: - return "Success" - if err >= XSERR_GENERAL_FAILURE and \ - err <= XSERR_LAST: - return XSERR_MESSAGES[err - XSERR_BASE] - return "Unknown XSERR code '%s'." % (hex(err)) - -# Policy identifiers used in labels -ACM_POLICY_ID = 'ACM' -FLASK_POLICY_ID = 'FLASK' - -INVALID_POLICY_PREFIX = 'INV_' - -INVALID_SSIDREF = 0xFFFFFFFFL - -XS_INACCESSIBLE_LABEL = '__INACCESSIBLE__' diff --git a/tools/python/xen/util/xsm/__init__.py b/tools/python/xen/util/xsm/__init__.py deleted file mode 100644 index 139597f9cb..0000000000 --- a/tools/python/xen/util/xsm/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/tools/python/xen/util/xsm/acm/__init__.py b/tools/python/xen/util/xsm/acm/__init__.py deleted file mode 100644 index 8d1c8b69c3..0000000000 --- a/tools/python/xen/util/xsm/acm/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tools/python/xen/util/xsm/acm/acm.py b/tools/python/xen/util/xsm/acm/acm.py deleted file mode 100644 index 20ff88f67d..0000000000 --- a/tools/python/xen/util/xsm/acm/acm.py +++ /dev/null @@ -1,1627 +0,0 @@ -#=========================================================================== -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2006 International Business Machines Corp. -# Author: Reiner Sailer -# Author: Bryan D. Payne -# Author: Stefan Berger -#============================================================================ - -import commands -import logging -import os, string, re -import threading -import struct -import stat -import base64 -from xen.xend import sxp -from xen.xend import XendConstants -from xen.xend import XendOptions -from xen.xend.XendLogging import log -from xen.xend.XendError import VmError -from xen.util import dictio, xsconstants, auxbin, xpopen -from xen.xend.XendConstants import * - -#global directories and tools for security management -install_policy_dir_prefix = auxbin.xen_configdir() + "/acm-security/policies" -security_dir_prefix = XendOptions.instance().get_xend_security_path() -policy_dir_prefix = security_dir_prefix + "/policies" -res_label_filename = policy_dir_prefix + "/resource_labels" -boot_filename = "/boot/grub/menu.lst" -altboot_filename = "/boot/grub/grub.conf" -xensec_tool = "/usr/sbin/xensec_tool" - -#global patterns for map file -#police_reference_tagname = "POLICYREFERENCENAME" -primary_entry_re = re.compile("\s*PRIMARY\s+.*", re.IGNORECASE) -secondary_entry_re = re.compile("\s*SECONDARY\s+.*", re.IGNORECASE) -label_template_re = re.compile(".*security_label_template.xml", re.IGNORECASE) -mapping_filename_re = re.compile(".*\.map", re.IGNORECASE) -policy_reference_entry_re = re.compile("\s*POLICYREFERENCENAME\s+.*", re.IGNORECASE) -vm_label_re = re.compile("\s*LABEL->SSID\s.+[VM|ANY]\s+.*", re.IGNORECASE) -res_label_re = re.compile("\s*LABEL->SSID\s+RES\s+.*", re.IGNORECASE) -all_label_re = re.compile("\s*LABEL->SSID\s+.*", re.IGNORECASE) -access_control_re = re.compile("\s*access_control\s*=", re.IGNORECASE) - -#global patterns for boot configuration file -xen_title_re = re.compile("\s*title\s+XEN", re.IGNORECASE) -any_title_re = re.compile("\s*title\s", re.IGNORECASE) -xen_kernel_re = re.compile("\s*kernel.*xen.*\.gz", re.IGNORECASE) -kernel_ver_re = re.compile("\s*module.*vmlinuz", re.IGNORECASE) -any_module_re = re.compile("\s*module\s", re.IGNORECASE) -empty_line_re = re.compile("^\s*$") -binary_name_re = re.compile(".*[chwall|ste|chwall_ste].*\.bin", re.IGNORECASE) -policy_name_re = re.compile(".*[chwall|ste|chwall_ste].*", re.IGNORECASE) - -#decision hooks known to the hypervisor -ACMHOOK_sharing = 1 -ACMHOOK_authorization = 2 -ACMHOOK_conflictset = 3 - -#other global variables -NULL_SSIDREF = 0 - -#general Rlock for map files; only one lock for all mapfiles -__mapfile_lock = threading.RLock() -__resfile_lock = threading.RLock() - -log = logging.getLogger("xend.util.security") - - -#Functions exported through XML-RPC -xmlrpc_exports = [ - 'on', - 'set_resource_label', - 'get_resource_label', - 'list_labels', - 'get_labeled_resources', - 'set_policy', - 'reset_policy', - 'get_policy', - 'activate_policy', - 'rm_bootpolicy', - 'get_xstype', - 'get_domain_label', - 'set_domain_label' -] - -# Our own exception definition. It is masked (pass) if raised and -# whoever raises this exception must provide error information. -class XSMError(Exception): - def __init__(self,value): - self.value = value - def __str__(self): - return repr(self.value) - - - -def err(msg): - """Raise ACM exception. - """ - raise XSMError(msg) - - - -active_policy = None - - -def mapfile_lock(): - __mapfile_lock.acquire() - -def mapfile_unlock(): - __mapfile_lock.release() - - -def resfile_lock(): - __resfile_lock.acquire() - -def resfile_unlock(): - __resfile_lock.release() - - -def refresh_security_policy(): - """ - retrieves security policy - """ - global active_policy - - active_policy = 'INACCESSIBLE' - - if os.access("/proc/xen/privcmd", os.R_OK|os.W_OK): - active_policy = "INACTIVE" - -def get_active_policy_name(): - refresh_security_policy() - return active_policy - -# now set active_policy -refresh_security_policy() - -def on(): - """ - returns none if security policy is off (not compiled), - any string otherwise, use it: if not security.on() ... - """ - if get_active_policy_name() not in ['INACTIVE', 'NULL', '']: - return xsconstants.XS_POLICY_ACM - return 0 - - -def calc_dom_ssidref_from_info(info): - """ - Calculate a domain's ssidref from the security_label in its - info. - This function is called before the domain is started and - makes sure that: - - the type of the policy is the same as indicated in the label - - the name of the policy is the same as indicated in the label - - calculates an up-to-date ssidref for the domain - The latter is necessary since the domain's ssidref could have - changed due to changes to the policy. - """ - import xen.xend.XendConfig - if isinstance(info, xen.xend.XendConfig.XendConfig): - if info.has_key('security_label'): - seclab = info['security_label'] - tmp = seclab.split(":") - if len(tmp) != 3: - raise VmError("VM label '%s' in wrong format." % seclab) - typ, policyname, vmlabel = seclab.split(":") - if typ != xsconstants.ACM_POLICY_ID: - raise VmError("Policy type '%s' must be changed." % typ) - if get_active_policy_name() != policyname: - raise VmError("Active policy '%s' different than " - "what in VM's label ('%s')." % - (get_active_policy_name(), policyname)) - ssidref = label2ssidref(vmlabel, policyname, "dom") - return ssidref - else: - return 0x0 - raise VmError("security.calc_dom_ssidref_from_info: info of type '%s'" - "not supported." % type(info)) - - -def getmapfile(policyname): - """ - in: if policyname is None then the currently - active hypervisor policy is used - out: 1. primary policy, 2. secondary policy, - 3. open file descriptor for mapping file, and - 4. True if policy file is available, False otherwise - """ - if not policyname: - policyname = get_active_policy_name() - map_file_ok = False - primary = None - secondary = None - #strip last part of policy as file name part - policy_dir_list = string.split(policyname, ".") - policy_file = policy_dir_list.pop() - if len(policy_dir_list) > 0: - policy_dir = string.join(policy_dir_list, "/") + "/" - else: - policy_dir = "" - - map_filename = policy_dir_prefix + "/" + policy_dir + policy_file + ".map" - # check if it is there, if not check if policy file is there - if not os.path.isfile(map_filename): - policy_filename = policy_dir_prefix + "/" + policy_dir + policy_file + "-security_policy.xml" - if not os.path.isfile(policy_filename): - err("Policy file \'" + policy_filename + "\' not found.") - else: - err("Mapping file \'" + map_filename + "\' not found.") - - f = open(map_filename) - for line in f: - if policy_reference_entry_re.match(line): - l = line.split() - if (len(l) == 2) and (l[1] == policyname): - map_file_ok = True - elif primary_entry_re.match(line): - l = line.split() - if len(l) == 2: - primary = l[1] - elif secondary_entry_re.match(line): - l = line.split() - if len(l) == 2: - secondary = l[1] - f.close() - f = open(map_filename) - if map_file_ok and primary and secondary: - return (primary, secondary, f, True) - else: - err("Mapping file inconsistencies found.") - - - -def ssidref2label(ssidref_var): - """ - returns labelname corresponding to ssidref; - maps current policy to default directory - to find mapping file - """ - #1. translated permitted input formats - if isinstance(ssidref_var, str): - ssidref_var.strip() - if ssidref_var[0:2] == "0x": - ssidref = int(ssidref_var[2:], 16) - else: - ssidref = int(ssidref_var) - elif isinstance(ssidref_var, int): - ssidref = ssidref_var - else: - err("Instance type of ssidref not supported (must be of type 'str' or 'int')") - - if ssidref == 0: - from xen.util.acmpolicy import ACM_LABEL_UNLABELED - return ACM_LABEL_UNLABELED - - try: - mapfile_lock() - - (primary, secondary, f, pol_exists) = getmapfile(None) - if not f: - if (pol_exists): - err("Mapping file for policy not found.") - else: - err("Policy file for \'" + get_active_policy_name() + - "\' not found.") - - #2. get labelnames for both ssidref parts - pri_ssid = ssidref & 0xffff - sec_ssid = ssidref >> 16 - pri_null_ssid = NULL_SSIDREF & 0xffff - sec_null_ssid = NULL_SSIDREF >> 16 - pri_labels = [] - sec_labels = [] - labels = [] - - for line in f: - l = line.split() - if (len(l) < 5) or (l[0] != "LABEL->SSID"): - continue - if primary and (l[2] == primary) and (int(l[4], 16) == pri_ssid): - pri_labels.append(l[3]) - if secondary and (l[2] == secondary) and (int(l[4], 16) == sec_ssid): - sec_labels.append(l[3]) - f.close() - finally: - mapfile_unlock() - - #3. get the label that is in both lists (combination must be a single label) - if (primary == "CHWALL") and (pri_ssid == pri_null_ssid) and (sec_ssid != sec_null_ssid): - labels = sec_labels - elif (secondary == "CHWALL") and (pri_ssid != pri_null_ssid) and (sec_ssid == sec_null_ssid): - labels = pri_labels - elif secondary == "NULL": - labels = pri_labels - else: - for i in pri_labels: - for j in sec_labels: - if (i==j): - labels.append(i) - if len(labels) != 1: - err("Label for ssidref \'" + str(ssidref) + - "\' unknown or not unique in policy \'" + active_policy + "\'") - - return labels[0] - - - -def label2ssidref(labelname, policyname, typ): - """ - returns ssidref corresponding to labelname; - maps current policy to default directory - to find mapping file """ - - if policyname in ['NULL', 'INACTIVE', 'INACCESSIBLE' ]: - err("Cannot translate labels for \'" + policyname + "\' policy.") - - allowed_types = ['ANY'] - if typ == 'dom': - allowed_types.append('VM') - elif typ == 'res': - allowed_types.append('RES') - else: - err("Invalid type. Must specify 'dom' or 'res'.") - - try: - mapfile_lock() - (primary, secondary, f, pol_exists) = getmapfile(policyname) - - #2. get labelnames for ssidref parts and find a common label - pri_ssid = [] - sec_ssid = [] - for line in f: - l = line.split() - if (len(l) < 5) or (l[0] != "LABEL->SSID"): - continue - if primary and (l[1] in allowed_types) and \ - (l[2] == primary) and \ - (l[3] == labelname): - pri_ssid.append(int(l[4], 16)) - if secondary and (l[1] in allowed_types) and \ - (l[2] == secondary) and \ - (l[3] == labelname): - sec_ssid.append(int(l[4], 16)) - f.close() - if (typ == 'res') and (primary == "CHWALL") and (len(pri_ssid) == 0): - pri_ssid.append(NULL_SSIDREF) - elif (typ == 'res') and (secondary == "CHWALL") and \ - (len(sec_ssid) == 0): - sec_ssid.append(NULL_SSIDREF) - - #3. sanity check and composition of ssidref - if (len(pri_ssid) == 0) or ((len(sec_ssid) == 0) and \ - (secondary != "NULL")): - err("Label \'" + labelname + "\' not found.") - elif (len(pri_ssid) > 1) or (len(sec_ssid) > 1): - err("Label \'" + labelname + "\' not unique in policy (policy error)") - if secondary == "NULL": - return pri_ssid[0] - else: - return (sec_ssid[0] << 16) | pri_ssid[0] - finally: - mapfile_unlock() - - -def refresh_ssidref(config): - """ - looks up ssidref from security field - and refreshes the value if label exists - """ - #called by dom0, policy could have changed after xen.utils.security was initialized - refresh_security_policy() - - security = None - if isinstance(config, dict): - security = config['security'] - elif isinstance(config, list): - security = sxp.child_value(config, 'security') - else: - err("Instance type of config parameter not supported.") - if not security: - #nothing to do (no security label attached) - return config - - policyname = None - labelname = None - # compose new security field - for idx in range(0, len(security)): - if security[idx][0] == 'ssidref': - security.pop(idx) - break - elif security[idx][0] == 'access_control': - for jdx in [1, 2]: - if security[idx][jdx][0] == 'label': - labelname = security[idx][jdx][1] - elif security[idx][jdx][0] == 'policy': - policyname = security[idx][jdx][1] - else: - err("Illegal field in access_control") - #verify policy is correct - if active_policy != policyname: - err("Policy \'" + str(policyname) + - "\' in label does not match active policy \'" - + str(active_policy) +"\'!") - - new_ssidref = label2ssidref(labelname, policyname, 'dom') - if not new_ssidref: - err("SSIDREF refresh failed!") - - security.append([ 'ssidref',str(new_ssidref)]) - security = ['security', security ] - - for idx in range(0,len(config)): - if config[idx][0] == 'security': - config.pop(idx) - break - config.append(security) - - - -def get_ssid(domain): - """ - enables domains to retrieve the label / ssidref of a running domain - """ - err("No policy active.") - - - -def get_decision(arg1, arg2): - """ - enables domains to retrieve access control decisions from - the hypervisor Access Control Module. - IN: args format = ['domid', id] or ['ssidref', ssidref] - or ['access_control', ['policy', policy], ['label', label], ['type', type]] - """ - err("No policy active.") - - -def has_authorization(ssidref): - """ Check if the domain with the given ssidref has authorization to - run on this system. To have authoriztion dom0's STE types must - be a superset of that of the domain's given through its ssidref. - """ - return True - - -def hv_chg_policy(bin_pol, del_array, chg_array): - """ - Change the binary policy in the hypervisor - The 'del_array' and 'chg_array' give hints about deleted ssidrefs - and changed ssidrefs which can be due to deleted VM labels - or reordered VM labels - """ - err("No policy active.") - -def hv_get_policy(): - """ - Gte the binary policy enforced in the hypervisor - """ - err("No policy active.") - - -def is_in_conflict(ssidref): - """ Check whether the given ssidref is in conflict with any running - domain. - """ - return False - - -def set_policy(xs_type, xml, flags, overwrite): - """ - Xend exports this function via XML-RPC - """ - from xen.xend import XendXSPolicyAdmin - xspoladmin = XendXSPolicyAdmin.XSPolicyAdminInstance() - try: - acmpol, rc, errors = \ - xspoladmin.add_acmpolicy_to_system(xml, - int(flags), - True) - return rc, base64.b64encode(errors) - except Exception, e: - err(str(e)) - - -def reset_policy(): - """ - Xend exports this function via XML-RPC - """ - from xen.xend import XendXSPolicyAdmin - xspoladmin = XendXSPolicyAdmin.XSPolicyAdminInstance() - try: - acmpol, rc, errors = \ - xspoladmin.reset_acmpolicy() - return rc, base64.b64encode(errors) - except Exception, e: - err(str(e)) - - -def get_policy(): - """ - Xend exports this function via XML-RPC - """ - from xen.xend import XendXSPolicyAdmin - poladmin = XendXSPolicyAdmin.XSPolicyAdminInstance() - try: - policy = poladmin.get_loaded_policy() - if policy != None: - return policy.toxml(), poladmin.get_policy_flags(policy) - except Exception, e: - err(str(e)) - return "", 0 - -def activate_policy(flags): - """ - Xend exports this function via XML-RPC - """ - from xen.xend import XendXSPolicyAdmin - poladmin = XendXSPolicyAdmin.XSPolicyAdminInstance() - try: - policies = poladmin.get_policies() - if len(policies) > 0: - flags = int(flags) - irc = poladmin.activate_xspolicy(policies[0], flags) - return irc - except Exception, e: - err("Error while activating the policy: " % str(e)) - return 0 - - -def rm_bootpolicy(): - """ - Xend exports this function via XML-RPC - """ - from xen.xend import XendXSPolicyAdmin - rc = XendXSPolicyAdmin.XSPolicyAdminInstance().rm_bootpolicy() - if rc != xsconstants.XSERR_SUCCESS: - err("Error while removing boot policy: %s" % \ - str(xsconstants.xserr2string(-rc))) - return rc - - -def get_xstype(): - """ - Xend exports this function via XML-RPC - """ - from xen.xend import XendXSPolicyAdmin - return XendXSPolicyAdmin.XSPolicyAdminInstance().isXSEnabled() - - -def get_domain_label(domain): - """ - Xend exports this function via XML-RPC - """ - from xen.xend import XendDomain - dom = XendDomain.instance().domain_lookup_nr(domain) - if dom: - seclab = dom.get_security_label() - return seclab - else: - err("Domain not found.") - - -def set_domain_label(domain, seclab, old_seclab): - """ - Xend exports this function via XML-RPC - """ - from xen.xend import XendDomain - dom = XendDomain.instance().domain_lookup_nr(domain) - if dom: - results = dom.set_security_label(seclab, old_seclab) - rc, errors, old_label, new_ssidref = results - return rc, new_ssidref - else: - err("Domain not found.") - - -def dump_policy(): - if active_policy in ['NULL', 'INACTIVE', 'INACCESSIBLE' ]: - err("\'" + active_policy + "\' policy. Nothing to dump.") - - (ret, output) = commands.getstatusoutput(xensec_tool + " getpolicy") - if ret: - err("Dumping hypervisor policy failed:\n" + output) - - print output - - -def dump_policy_file(filename, ssidref=None): - ssid = "" - if ssidref: - ssid = " " + str(ssidref) - (ret, output) = commands.getstatusoutput(xensec_tool + " dumppolicy " + - filename + ssid) - if ret: - err("Dumping policy failed:\n" + output) - - print output - - -def list_labels(policy_name, ltype): - """ - Xend exports this function via XML-RPC - - List the VM,resource or any kind of labels contained in the - given policy. If no policy name is given, the currently - active policy's label will be returned if they exist. - """ - if not policy_name: - if active_policy in [ 'NULL', 'INACTIVE', "" ]: - err("Current policy \'" + active_policy + "\' " - "has no labels defined.\n") - - if not ltype or ltype == 'dom': - condition = vm_label_re - elif ltype == 'res': - condition = res_label_re - elif ltype == 'any': - condition = all_label_re - else: - err("Unknown label type \'" + ltype + "\'") - - try: - mapfile_lock() - - (primary, secondary, f, pol_exists) = getmapfile(policy_name) - if not f: - if pol_exists: - err("Cannot find mapfile for policy \'" + policy_name + "\'.\n") - else: - err("Unknown policy \'" + policy_name + "\'") - - labels = [] - for line in f: - if condition.match(line): - label = line.split()[3] - if label not in labels: - labels.append(label) - finally: - mapfile_unlock() - - if '__NULL_LABEL__' in labels: - labels.remove('__NULL_LABEL__') - - return labels - - -def get_res_label(resource): - """Returns resource label information (policytype, label, policy) if - it exists. Otherwise returns null label and policy. - """ - def default_res_label(): - ssidref = NULL_SSIDREF - if on(): - label = ssidref2label(ssidref) - else: - label = None - return (xsconstants.ACM_POLICY_ID, 'NULL', label) - - - tmp = get_resource_label(resource) - if len(tmp) == 2: - policytype = xsconstants.ACM_POLICY_ID - policy, label = tmp - elif len(tmp) == 3: - policytype, policy, label = tmp - else: - policytype, policy, label = default_res_label() - - return (policytype, label, policy) - - -def get_res_security_details(resource): - """Returns the (label, ssidref, policy) associated with a given - resource from the global resource label file. - """ - def default_security_details(): - ssidref = NULL_SSIDREF - if on(): - label = ssidref2label(ssidref) - else: - label = None - policy = active_policy - return (label, ssidref, policy) - - # find the entry associated with this resource - (policytype, label, policy) = get_res_label(resource) - if policy == 'NULL': - log.info("Resource label for "+resource+" not in file, using DEFAULT.") - return default_security_details() - - if policytype != xsconstants.ACM_POLICY_ID: - raise VmError("Unknown policy type '%s in label for resource '%s'" % - (policytype, resource)) - - # is this resource label for the running policy? - if policy == active_policy: - ssidref = label2ssidref(label, policy, 'res') - elif label == xsconstants.XS_INACCESSIBLE_LABEL: - ssidref = NULL_SSIDREF - else: - log.info("Resource label not for active policy, using DEFAULT.") - return default_security_details() - - return (label, ssidref, policy) - -def security_label_to_details(seclab): - """ Convert a Xen-API type of security label into details """ - def default_security_details(): - ssidref = NULL_SSIDREF - if on(): - label = ssidref2label(ssidref) - else: - label = None - policy = active_policy - return (label, ssidref, policy) - - (policytype, policy, label) = seclab.split(":") - - # is this resource label for the running policy? - if policy == active_policy: - ssidref = label2ssidref(label, policy, 'res') - else: - log.info("Resource label not for active policy, using DEFAULT.") - return default_security_details() - - return (label, ssidref, policy) - -def unify_resname(resource, mustexist=True): - """Makes all resource locations absolute. In case of physical - resources, '/dev/' is added to local file names""" - - if not resource: - return resource - - # sanity check on resource name - try: - (typ, resfile) = resource.split(":", 1) - except: - err("Resource spec '%s' contains no ':' delimiter" % resource) - - if typ == "tap": - try: - (subtype, resfile) = resfile.split(":") - except: - err("Resource spec '%s' contains no tap subtype" % resource) - - if typ in ["phy"]: - if not resfile.startswith("/"): - resfile = "/dev/" + resfile - if mustexist: - resfile = os.path.realpath(resfile) - try: - stats = os.lstat(resfile) - if not (stat.S_ISBLK(stats[stat.ST_MODE])): - err("Invalid resource") - except: - err("Invalid resource") - - if typ in [ "file", "tap" ]: - resfile = os.path.realpath(resfile) - if mustexist and not os.path.isfile(resfile): - err("Invalid resource") - - if typ == "vlan": - try: - vlan = int(resfile) - if vlan < 1 or vlan > 4095: - err("VLAN ID %d out of range." % vlan) - except Exception, e: - err("Invalid VLAN : %s" % resfile) - - - #file: resources must be specified with absolute path - #vlan resources don't start with '/' - if typ != "vlan": - if (not resfile.startswith("/")) or \ - (mustexist and not os.path.exists(resfile)): - err("Invalid resource.") - - # from here on absolute file names with resources - if typ == "tap": - typ = typ + ":" + subtype - resource = typ + ":" + resfile - return resource - - -def res_security_check(resource, domain_label): - """Checks if the given resource can be used by the given domain - label. Returns 1 if the resource can be used, otherwise 0. - """ - rtnval = 1 - - # if security is on, ask the hypervisor for a decision - if on(): - #build canonical resource name - resource = unify_resname(resource) - - (label, ssidref, policy) = get_res_security_details(resource) - domac = ['access_control'] - domac.append(['policy', active_policy]) - domac.append(['label', domain_label]) - domac.append(['type', 'dom']) - decision = get_decision(domac, ['ssidref', str(ssidref)]) - - # provide descriptive error messages - if decision == 'DENIED': - if label == ssidref2label(NULL_SSIDREF): - raise XSMError("Resource '"+resource+"' is not labeled") - rtnval = 0 - else: - raise XSMError("Permission denied for resource '"+resource+"' because label '"+label+"' is not allowed") - rtnval = 0 - - # security is off, make sure resource isn't labeled - else: - # Note, we can't canonicalise the resource here, because people using - # xm without ACM are free to use relative paths. - (policytype, label, policy) = get_res_label(resource) - if policy != 'NULL': - raise XSMError("Security is off, but '"+resource+"' is labeled") - rtnval = 0 - - return rtnval - -def res_security_check_xapi(rlabel, rssidref, rpolicy, xapi_dom_label): - """Checks if the given resource can be used by the given domain - label. Returns 1 if the resource can be used, otherwise 0. - """ - rtnval = 1 - # if security is on, ask the hypervisor for a decision - if on(): - if rlabel == xsconstants.XS_INACCESSIBLE_LABEL: - return 0 - typ, dpolicy, domain_label = xapi_dom_label.split(":") - if not dpolicy or not domain_label: - raise VmError("VM security label in wrong format.") - if active_policy != rpolicy: - raise VmError("Resource's policy '%s' != active policy '%s'" % - (rpolicy, active_policy)) - domac = ['access_control'] - domac.append(['policy', active_policy]) - domac.append(['label', domain_label]) - domac.append(['type', 'dom']) - decision = get_decision(domac, ['ssidref', str(rssidref)]) - - log.info("Access Control Decision : %s" % decision) - # provide descriptive error messages - if decision == 'DENIED': - if rlabel == ssidref2label(NULL_SSIDREF): - #raise XSMError("Resource is not labeled") - rtnval = 0 - else: - #raise XSMError("Permission denied for resource because label '"+rlabel+"' is not allowed") - rtnval = 0 - - # security is off, make sure resource isn't labeled - else: - # Note, we can't canonicalise the resource here, because people using - # xm without ACM are free to use relative paths. - if rpolicy != 'NULL': - #raise XSMError("Security is off, but resource is labeled") - rtnval = 0 - - return rtnval - - -def validate_label_xapi(xapi_label, dom_or_res): - """ - Make sure that this label is part of the currently enforced policy - and that it references the current policy. - dom_or_res defines whether this is a VM ('res') or resource label - ('res') - """ - tmp = xapi_label.split(":") - if len(tmp) != 3: - return -xsconstants.XSERR_BAD_LABEL_FORMAT - policytyp, policyref, label = tmp - return validate_label(policytyp, policyref, label, dom_or_res) - - -def validate_label(policytype, policyref, label, dom_or_res): - """ - Make sure that this label is part of the currently enforced policy - and that it reference the current policy. - """ - if policytype != xsconstants.ACM_POLICY_ID: - return -xsconstants.XSERR_WRONG_POLICY_TYPE - if not policytype or not label: - return -xsconstants.XSERR_BAD_LABEL_FORMAT - rc = xsconstants.XSERR_SUCCESS - if label == xsconstants.XS_INACCESSIBLE_LABEL: - return rc - from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance - curpol = XSPolicyAdminInstance().get_loaded_policy() - if not curpol or curpol.get_name() != policyref: - rc = -xsconstants.XSERR_BAD_LABEL - else: - try: - label2ssidref(label, curpol.get_name() , dom_or_res) - except: - rc = -xsconstants.XSERR_BAD_LABEL - return rc - - -def set_resource_label_xapi(resource, reslabel_xapi, oldlabel_xapi): - """Assign a resource label to a resource - @param resource: The name of a resource, i.e., "phy:/dev/hda", or - "tap:qcow:/path/to/file.qcow" - - @param reslabel_xapi: A resource label foramtted as in all other parts of - the Xen-API, i.e., ACM:xm-test:blue" - @rtype: int - @return Success (0) or failure value (< 0) - """ - olabel = "" - if reslabel_xapi == "": - return rm_resource_label(resource, oldlabel_xapi) - - rc = validate_label_xapi(reslabel_xapi, 'res') - if rc != xsconstants.XSERR_SUCCESS: - return rc - - if oldlabel_xapi not in [ "" ]: - tmp = oldlabel_xapi.split(":") - if len(tmp) != 3: - return -xsconstants.XSERR_BAD_LABEL_FORMAT - otyp, opolicyref, olabel = tmp - # Only ACM is supported - if otyp != xsconstants.ACM_POLICY_ID and \ - otyp != xsconstants.INVALID_POLICY_PREFIX + \ - xsconstants.ACM_POLICY_ID: - return -xsconstants.XSERR_WRONG_POLICY_TYPE - typ, policyref, label = reslabel_xapi.split(":") - return set_resource_label(resource, typ, policyref, label, olabel) - - -def is_resource_in_use(resource): - """ - Domain-0 'owns' resources of type 'VLAN', the rest are owned by - the guests. - """ - from xen.xend import XendDomain - lst = [] - if resource.startswith('vlan'): - from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance - curpol = XSPolicyAdminInstance().get_loaded_policy() - policytype, label, policy = get_res_label(resource) - if curpol and \ - policytype == xsconstants.ACM_POLICY_ID and \ - policy == curpol.get_name() and \ - label in curpol.policy_get_resourcelabel_names(): - # VLAN is in use. - lst.append(XendDomain.instance(). - get_vm_by_uuid(XendDomain.DOM0_UUID)) - else: - dominfos = XendDomain.instance().list('all') - for dominfo in dominfos: - if is_resource_in_use_by_dom(dominfo, resource): - lst.append(dominfo) - return lst - -def devices_equal(res1, res2, mustexist=True): - """ Determine whether two devices are equal """ - return (unify_resname(res1, mustexist) == - unify_resname(res2, mustexist)) - -def is_resource_in_use_by_dom(dominfo, resource): - """ Determine whether a resources is in use by a given domain - @return True or False - """ - if not dominfo.domid: - return False - if dominfo._stateGet() not in [ DOM_STATE_RUNNING ]: - return False - devs = dominfo.info['devices'] - uuids = devs.keys() - for uuid in uuids: - dev = devs[uuid] - if len(dev) >= 2 and dev[1].has_key('uname'): - # dev[0] is type, i.e. 'vbd' - if devices_equal(dev[1]['uname'], resource, mustexist=False): - log.info("RESOURCE IN USE: Domain %d uses %s." % - (dominfo.domid, resource)) - return True - return False - - -def get_domain_resources(dominfo): - """ Collect all resources of a domain in a map where each entry of - the map is a list. - Entries are strored in the following formats: - tap:qcow:/path/xyz.qcow - """ - resources = { 'vbd' : [], 'tap' : [], 'vif' : []} - devs = dominfo.info['devices'] - uuids = devs.keys() - for uuid in uuids: - dev = devs[uuid] - typ = dev[0] - if typ in [ 'vbd', 'tap' ]: - resources[typ].append(dev[1]['uname']) - if typ in [ 'vif' ]: - sec_lab = dev[1].get('security_label') - if sec_lab: - resources[typ].append(sec_lab) - else: - # !!! This should really get the label of the domain - # or at least a resource label that has the same STE type - # as the domain has - from xen.util.acmpolicy import ACM_LABEL_UNLABELED - resources[typ].append("%s:%s:%s" % - (xsconstants.ACM_POLICY_ID, - active_policy, - ACM_LABEL_UNLABELED)) - - return resources - - -def resources_compatible_with_vmlabel(xspol, dominfo, vmlabel): - """ - Check whether the resources' labels are compatible with the - given VM label. This is a function to be used when for example - a running domain is to get the new label 'vmlabel' - """ - if not xspol: - return False - - try: - resfile_lock() - try: - access_control = dictio.dict_read("resources", - res_label_filename) - except: - # No labeled resources -> must be compatible - return True - return __resources_compatible_with_vmlabel(xspol, dominfo, vmlabel, - access_control) - finally: - resfile_unlock() - return False - - -def __resources_compatible_with_vmlabel(xspol, dominfo, vmlabel, - access_control, - is_policy_update=False): - """ - Check whether the resources' labels are compatible with the - given VM label. The access_control parameter provides a - dictionary of the resource name to resource label mappings - under which the evaluation should be done. - Call this only for a paused or running domain. - """ - def collect_labels(reslabels, s_label, polname): - if len(s_label) != 3 or polname != s_label[1]: - return False - label = s_label[2] - if not label in reslabels: - reslabels.append(label) - return True - - resources = get_domain_resources(dominfo) - reslabels = [] # all resource labels - - polname = xspol.get_name() - for key, value in resources.items(): - if key in [ 'vbd', 'tap' ]: - for res in resources[key]: - if not res in access_control: - label = [xsconstants.ACM_POLICY_ID, - xspol.get_name(), - ACM_LABEL_UNLABELED] - else: - label = access_control[res] - if not collect_labels(reslabels, label, polname): - return False - elif key in [ 'vif' ]: - for xapi_label in value: - label = xapi_label.split(":") - from xen.util.acmpolicy import ACM_LABEL_UNLABELED - if not (is_policy_update and \ - label[2] == ACM_LABEL_UNLABELED): - if not collect_labels(reslabels, label, polname): - return False - else: - log.error("Unhandled device type: %s" % key) - return False - - # Check that all resource labes have a common STE type with the - # vmlabel - if len(reslabels) > 0: - rc = xspol.policy_check_vmlabel_against_reslabels(vmlabel, reslabels) - else: - rc = True - log.info("vmlabel=%s, reslabels=%s, rc=%s" % - (vmlabel, reslabels, str(rc))) - return rc; - -def set_resource_label(resource, policytype, policyref, reslabel, \ - oreslabel = None): - """ - Xend exports this function via XML-RPC. - - Assign a label to a resource - If the old label (oreslabel) is given, then the resource must have - that old label. - A resource label may be changed if - - the resource is not in use - @param resource : The name of a resource, i.e., "phy:/dev/hda" - @param policyref : The name of the policy - @param reslabel : the resource label within the policy - @param oreslabel : optional current resource label - - @rtype: int - @return Success (0) or failure value (< 0) - """ - - - try: - resource = unify_resname(resource, mustexist=False) - except Exception: - return -xsconstants.XSERR_BAD_RESOURCE_FORMAT - - try: - resfile_lock() - mapfile_lock() - - if reslabel not in [ '', xsconstants.XS_INACCESSIBLE_LABEL ]: - ssidref = label2ssidref(reslabel, policyref, 'res') - - domains = is_resource_in_use(resource) - if len(domains) > 0: - return -xsconstants.XSERR_RESOURCE_IN_USE - - access_control = {} - try: - access_control = dictio.dict_read("resources", res_label_filename) - except: - pass - if oreslabel: - if not access_control.has_key(resource): - return -xsconstants.XSERR_BAD_LABEL - tmp = access_control[resource] - if len(tmp) != 3: - return -xsconstants.XSERR_BAD_LABEL - if tmp[2] != oreslabel: - return -xsconstants.XSERR_BAD_LABEL - if resource.startswith('vlan:'): - for key, value in access_control.items(): - if value == tuple([policytype, policyref, reslabel]) and \ - key.startswith('vlan:'): - return -xsconstants.XSERR_BAD_LABEL - - if reslabel == xsconstants.XS_INACCESSIBLE_LABEL: - policytype = xsconstants.ACM_POLICY_ID - policyref = '*' - - if reslabel != "": - new_entry = { resource : tuple([policytype, policyref, reslabel])} - access_control.update(new_entry) - command = "add" - reslbl = ":".join([policytype, policyref, reslabel]) - else: - if access_control.has_key(resource): - del access_control[resource] - command = "remove" - reslbl = "" - run_resource_label_change_script(resource, reslbl, command) - dictio.dict_write(access_control, "resources", res_label_filename) - finally: - resfile_unlock() - mapfile_unlock() - return xsconstants.XSERR_SUCCESS - -def rm_resource_label(resource, oldlabel_xapi): - """Remove a resource label from a physical resource - @param resource: The name of a resource, i.e., "phy:/dev/hda" - - @rtype: int - @return Success (0) or failure value (< 0) - """ - tmp = oldlabel_xapi.split(":") - if len(tmp) != 3: - return -xsconstants.XSERR_BAD_LABEL_FORMAT - otyp, opolicyref, olabel = tmp - # Only ACM is supported - if otyp != xsconstants.ACM_POLICY_ID and \ - otyp != xsconstants.INVALID_POLICY_PREFIX + xsconstants.ACM_POLICY_ID: - return -xsconstants.XSERR_WRONG_POLICY_TYPE - return set_resource_label(resource, "", "", "", olabel) - -def get_resource_label_xapi(resource): - """Get the assigned resource label of a physical resource - in the format used by then Xen-API, i.e., "ACM:xm-test:blue" - - @rtype: string - @return the string representing policy type, policy name and label of - the resource - """ - res = get_resource_label(resource) - return format_resource_label(res) - -def format_resource_label(res): - if res: - if len(res) == 2: - return xsconstants.ACM_POLICY_ID + ":" + res[0] + ":" + res[1] - if len(res) == 3: - return ":".join(res) - return "" - -def get_resource_label(resource): - """ - Xend exports this function via XML-RPC. - - Get the assigned resource label of a given resource - @param resource: The name of a resource, i.e., "phy:/dev/hda" - - @rtype: list - @return tuple of (policy name, resource label), i.e., (xm-test, blue) - """ - try: - resource = unify_resname(resource, mustexist=False) - except Exception: - return [] - - reslabel_map = get_labeled_resources() - - if reslabel_map.has_key(resource): - return list(reslabel_map[resource]) - else: - #Try to resolve each label entry - for key, value in reslabel_map.items(): - try: - if resource == unify_resname(key): - return list(value) - except: - pass - - return [] - - -def get_labeled_resources_xapi(): - """ Get a map of all labeled resource with the labels formatted in the - xen-api resource label format. - """ - reslabel_map = get_labeled_resources() - for key, labeldata in reslabel_map.items(): - reslabel_map[key] = format_resource_label(labeldata) - return reslabel_map - - -def get_labeled_resources(): - """ - Xend exports this function via XML-RPC - - Get a map of all labeled resources. - @rtype: list - @return list of labeled resources - """ - try: - resfile_lock() - try: - access_control = dictio.dict_read("resources", res_label_filename) - except: - return {} - finally: - resfile_unlock() - return access_control - - -def relabel_domains(relabel_list): - """ - Relabel the given domains to have a new ssidref. - @param relabel_list: a list containing tuples of domid, ssidref - example: [ [0, 0x00020002] ] - """ - rc = -xsconstants.XSERR_GENERAL_FAILURE - errors = "" - return rc, errors - - -def __update_label_policy_change(sec_lab, - cur_poltype, - cur_polname, - new_poltype, - new_polname, - polnew_labels, - label_map): - """ - Determine a new resource label given the new policy's type - and name and the new policy's (resource/VM) labels and the - (resource/VM) label map that indicates renaming rules for - labels. - """ - is_deleted = False - policytype, policy, label = sec_lab - - if cur_poltype != policytype or \ - cur_polname != policy: - return sec_lab, is_deleted - - if policytype != xsconstants.ACM_POLICY_ID: - return sec_lab, is_deleted - elif label_map.has_key(label) and policy == cur_polname: - # renaming of an active label; policy may have been renamed - label = label_map[label] - polname = new_polname - elif label not in polnew_labels: - # label been removed - policytype = xsconstants.INVALID_POLICY_PREFIX + policytype - polname = policy - is_deleted = True - else: - # no change to label - policytype = xsconstants.ACM_POLICY_ID - polname = new_polname - - return tuple( [ policytype, polname, label ] ), is_deleted - - -def change_acm_policy(bin_pol, del_array, chg_array, - vmlabel_map, reslabel_map, cur_acmpol, new_acmpol, - is_reset): - """ - Change the ACM policy of the system by relabeling - domains and resources first and doing some access checks. - Then update the policy in the hypervisor. If this is all successful, - relabel the domains permanently and commit the relabed resources. - - Need to do / check the following: - - relabel all resources where there is a 'from' field in - the policy. [ NOT DOING THIS: and mark those as unlabeled where the label - does not appear in the new policy anymore (deletion) ] - - relabel all VMs where there is a 'from' field in the - policy and mark those as unlabeled where the label - does not appear in the new policy anymore; no running - or paused VM may be unlabeled through this - - check that under the new labeling conditions the VMs - still have access to their resources as before. Unlabeled - resources are inaccessible. If this check fails, the - update failed. - - Attempt changes in the hypervisor; if this step fails, - roll back the relabeling of resources and VMs - - Make the relabeling of resources and VMs permanent - - This function should be called with the lock to the domains - held (XendDomain.instance().domains_lock) - """ - from xen.util.acmpolicy import ACM_LABEL_UNLABELED - rc = xsconstants.XSERR_SUCCESS - - domain_label_map = {} - new_policyname = new_acmpol.get_name() - new_policytype = new_acmpol.get_type_name() - cur_policyname = cur_acmpol.get_name() - cur_policytype = cur_acmpol.get_type_name() - polnew_reslabels = new_acmpol.policy_get_resourcelabel_names() - errors="" - - try: - resfile_lock() - mapfile_lock() - - # Get all domains' dominfo. - from xen.xend import XendDomain - dominfos = XendDomain.instance().list('all') - - log.info("----------------------------------------------") - - label_changes = [] - # relabel resources - - access_control = {} - try: - access_control = dictio.dict_read("resources", res_label_filename) - except: - pass - - for key, labeldata in access_control.items(): - if len(labeldata) == 2: - policy, label = labeldata - policytype = xsconstants.ACM_POLICY_ID - elif len(labeldata) == 3: - policytype, policy, label = labeldata - else: - return -xsconstants.XSERR_BAD_LABEL_FORMAT, "" - - new_sec_lab, is_deleted = \ - __update_label_policy_change( tuple([policytype, - policy, - label]), - cur_policytype, - cur_policyname, - new_policytype, - new_policyname, - polnew_reslabels, - reslabel_map) - - if is_deleted: - label_changes.append(key) - # Update entry - access_control[key] = new_sec_lab - - # All resources have new labels in the access_control map - # There may still be labels in there that are invalid now. - - # Do this in memory without writing to disk: - # - Relabel all domains independent of whether they are running - # or not - # - later write back to config files - polnew_vmlabels = new_acmpol.policy_get_virtualmachinelabel_names() - - for dominfo in dominfos: - sec_lab = dominfo.get_security_label() - if not sec_lab: - continue - policytype, policy, vmlabel = sec_lab.split(":") - name = dominfo.getName() - - if policytype != cur_policytype or \ - policy != cur_policyname: - continue - - new_vmlabel = vmlabel - if vmlabel_map.has_key(vmlabel) and \ - (not is_reset or name == "Domain-0") : - # renaming of the label; this is only allowed if it's - # not a reset of the policy or if it is a reset, then - # only for Domain-0 - new_vmlabel = vmlabel_map[vmlabel] - polname = new_policyname - elif new_vmlabel not in polnew_vmlabels and \ - vmlabel != ACM_LABEL_UNLABELED: - # removal of VM label and not the 'unlabeled' label - policytype = xsconstants.INVALID_POLICY_PREFIX + policytype - polname = policy - else: - polname = new_policyname - - new_seclab = "%s:%s:%s" % \ - (policytype, polname, new_vmlabel) - - domain_label_map[dominfo] = [ sec_lab, new_seclab ] - - if dominfo._stateGet() in (DOM_STATE_PAUSED, DOM_STATE_RUNNING): - compatible = __resources_compatible_with_vmlabel(new_acmpol, - dominfo, - new_vmlabel, - access_control, - is_policy_update=True) - log.info("Domain %s with new label '%s' can access its " - "resources? : %s" % - (name, new_vmlabel, str(compatible))) - log.info("VM labels in new policy: %s" % - new_acmpol.policy_get_virtualmachinelabel_names()) - if not compatible: - return (-xsconstants.XSERR_RESOURCE_ACCESS, "") - - for dominfo in dominfos: - # relabel the VIF interfaces - changed = False - for vif_uuid in dominfo.get_vifs(): - sec_lab = dominfo.info['devices'][vif_uuid][1]\ - .get('security_label') - if sec_lab: - result, _ = \ - __update_label_policy_change(tuple(sec_lab.split(':')), - cur_policytype, - cur_policyname, - new_policytype, - new_policyname, - polnew_reslabels, - reslabel_map) - new_sec_lab = ':'.join(list(result)) - if new_sec_lab != sec_lab: - changed = True - dominfo.info['devices'][vif_uuid][1]\ - ['security_label'] = new_sec_lab - if changed: - XendDomain.instance().managed_config_save(dominfo) - - rc, errors = hv_chg_policy(bin_pol, del_array, chg_array) - if rc == 0: - for key in label_changes: - run_resource_label_change_script(key, "", "remove") - # Write the relabeled resources back into the file - dictio.dict_write(access_control, "resources", res_label_filename) - # Properly update all VMs to their new labels - for dominfo, labels in domain_label_map.items(): - sec_lab, new_seclab = labels - if sec_lab != new_seclab: - log.info("Updating domain %s to new label '%s'." % \ - (dominfo.getName(), new_seclab)) - # This better be working! - res = dominfo.set_security_label(new_seclab, - sec_lab, - new_acmpol, - cur_acmpol) - if res[0] != xsconstants.XSERR_SUCCESS: - log.info("ERROR: Could not chg label on domain %s: %s" % - (dominfo.getName(), - xsconstants.xserr2string(-int(res[0])))) - finally: - log.info("----------------------------------------------") - mapfile_unlock() - resfile_unlock() - - return rc, errors - -def parse_security_label(security_label): - tmp = security_label.split(":") - if len(tmp) != 3: - return "" - else: - return security_label - -def set_security_label(policy, label): - if label and policy and label != "" and policy != "": - return "%s:%s:%s" % (xsconstants.ACM_POLICY_ID, policy, label) - else: - return "" - -def ssidref2security_label(ssidref): - from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance - return XSPolicyAdminInstance().ssidref_to_vmlabel(ssidref) - -def get_security_label(self, xspol=None): - """ - Get the security label of a domain - @param xspol The policy to use when converting the ssid into - a label; only to be passed during the updating - of the policy - """ - domid = self.getDomid() - - if not xspol: - from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance - xspol = XSPolicyAdminInstance().get_loaded_policy() - - label = "" - if xspol: - label = xspol.policy_get_domain_label_formatted(domid) - if domid != 0: - label = self.info.get('security_label', label) - return label - - -def check_can_run(sec_label): - """ Check whether a VM could run, given its vm label. A VM can run if - - it is authorized - - is not in conflict with any running domain - """ - try: - mapfile_lock() - - if sec_label == None or sec_label == "": - vm_label = ACM_LABEL_UNLABELED - else: - poltype, policy, vm_label = sec_label.split(':') - if policy != get_active_policy_name(): - return -xsconstants.XSERR_BAD_POLICY_NAME - ssidref = label2ssidref(vm_label, policy, 'dom') - if ssidref != xsconstants.INVALID_SSIDREF: - if not has_authorization(ssidref): - return -xsconstants.XSERR_VM_NOT_AUTHORIZED - if is_in_conflict(ssidref): - return -xsconstants.XSERR_VM_IN_CONFLICT - return -xsconstants.XSERR_SUCCESS - else: - return -xsconstants.XSERR_BAD_LABEL - finally: - mapfile_unlock() - - -__cond = threading.Condition() -__script_runner = None -__orders = [] - -def run_resource_label_change_script(resource, label, command): - global __cond, __orders, __script_runner - - def __run_resource_label_change_script(): - global __cond, __orders - script = XendOptions.instance().get_resource_label_change_script() - if script: - parms = {} - while True: - __cond.acquire() - if len(__orders) == 0: - __cond.wait() - - parms['label'], \ - parms['command'], \ - parms['resource'] = __orders[0] - - __orders = __orders[1:] - __cond.release() - - log.info("Running resource label change script %s: %s" % - (script, parms)) - parms.update(os.environ) - xpopen.call(" ".join(script, params)) - else: - log.info("No script given for relabeling of resources.") - if not __script_runner: - __script_runner = \ - threading.Thread(target=__run_resource_label_change_script, - args=()) - __script_runner.start() - - __cond.acquire() - __orders.append((label,command,resource)) - __cond.notify() - __cond.release() diff --git a/tools/python/xen/util/xsm/dummy/__init__.py b/tools/python/xen/util/xsm/dummy/__init__.py deleted file mode 100644 index 8d1c8b69c3..0000000000 --- a/tools/python/xen/util/xsm/dummy/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tools/python/xen/util/xsm/dummy/dummy.py b/tools/python/xen/util/xsm/dummy/dummy.py deleted file mode 100644 index 795d637df7..0000000000 --- a/tools/python/xen/util/xsm/dummy/dummy.py +++ /dev/null @@ -1,136 +0,0 @@ -import sys -from xen.util import xsconstants -from xen.xend.XendLogging import log - -class XSMError(Exception): - def __init__(self,value): - self.value = value - def __str__(self): - return repr(self.value) - - -security_dir_prefix = ""; -policy_dir_prefix = ""; -active_policy = ""; -NULL_SSIDREF = 0; - -#Functions exported through XML-RPC -xmlrpc_exports = [ - 'set_resource_label', - 'get_resource_label', - 'list_labels', - 'get_labeled_resources', - 'set_policy', - 'reset_policy', - 'get_policy', - 'activate_policy', - 'rm_bootpolicy', - 'get_xstype', - 'get_domain_label', - 'set_domain_label' -] - -def err(msg): - """Raise XSM-dummy exception. - """ - raise XSMError(msg) - -def on(): - return 0 - -def ssidref2label(ssidref): - return 0 - -def label2ssidref(label, policy, type): - return 0 - -def res_security_check(resource, domain_label): - return 1 - -def get_res_security_details(resource): - return ("","","") - -def get_res_label(resource): - return ("","") - -def res_security_check_xapi(rlabel, rssidref, rpolicy, xapi_dom_label): - return 1 - -def parse_security_label(security_label): - return "" - -def calc_dom_ssidref_from_info(info): - return "" - -def set_security_label(policy, label): - return "" - -def ssidref2security_label(ssidref): - return "" - -def has_authorization(ssidref): - return True - -def get_security_label(self, xspol=None): - return "" - -def get_resource_label_xapi(resource): - return "" - -def get_labeled_resources_xapi(): - return {} - -def set_resource_label_xapi(resource, reslabel_xapi, oldlabel_xapi): - err("Command not supported under XSM 'dummy' module.") - -def format_resource_label(res): - return "" - -def set_resource_label(resource, policytype, policyref, reslabel, - oreslabel = None): - err("Command not supported under XSM 'dummy' module.") - -def get_resource_label(resource): - return "" - -def list_labels(policy_name, ltype): - return [] - -def get_labeled_resources(): - return {} - -def set_policy(xs_type, xml, flags, overwrite): - err("Command not supported under xsm 'dummy' module.") - -def reset_policy(): - err("Command not supported under xsm 'dummy' module.") - -def get_policy(): - return "", 0 - -def activate_policy(): - err("Command not supported under xsm 'dummy' module.") - -def rm_bootpolicy(): - err("Command not supported under xsm 'dummy' module.") - -def get_xstype(): - return 0 - -def get_domain_label(domain): - return "" - -def set_domain_label(): - err("Command not supported under xsm 'dummy' module.") - -def dump_policy(): - pass - -def dump_policy_file(): - pass - -def get_ssid(domain): - err("No ssid has been assigned to any domain under xsm dummy module.") - -def security_label_to_details(res_label): - return ("","","") diff --git a/tools/python/xen/util/xsm/flask/__init__.py b/tools/python/xen/util/xsm/flask/__init__.py deleted file mode 100644 index 8d1c8b69c3..0000000000 --- a/tools/python/xen/util/xsm/flask/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tools/python/xen/util/xsm/flask/flask.py b/tools/python/xen/util/xsm/flask/flask.py deleted file mode 100644 index 83d662d98a..0000000000 --- a/tools/python/xen/util/xsm/flask/flask.py +++ /dev/null @@ -1,65 +0,0 @@ -import sys -import base64 -from xen.lowlevel import flask -from xen.util import xsconstants -from xen.xend import sxp - -#Functions exported through XML-RPC -xmlrpc_exports = [ - 'on', - 'set_policy', - 'getenforce', - 'setenforce' -] - -def err(msg): - """Raise XSM-Flask exception. - """ - sys.stderr.write("XSM-FlaskError: " + msg + "\n") - raise XSMError(msg) - -def on(): - return xsconstants.XS_POLICY_FLASK - -def ssidref2label(ssidref): - try: - return flask.flask_sid_to_context(ssidref) - except: - return "" - -def label2ssidref(label, policy, type): - try: - return flask.flask_context_to_sid(label) - except: - raise XSMError('Invalid context %s' % label) - -def parse_security_label(security_label): - return security_label - -def calc_dom_ssidref_from_info(info): - ssidref = label2ssidref(info['security_label'], "", "") - return ssidref - -def set_security_label(policy, label): - if label: - return label - else: - return "" - -def ssidref2security_label(ssidref): - label = ssidref2label(ssidref) - return label - -def get_security_label(self, xspol=None): - label = self.info['security_label'] - return label - -def set_policy(xs_type, policy_b64, flags=None, overwrite=None): - policy = base64.b64decode(policy_b64); - return flask.flask_load(policy), "" - -def getenforce(): - return flask.flask_getenforce() - -def setenforce(mode): - return flask.flask_setenforce(mode) diff --git a/tools/python/xen/util/xsm/xsm.py b/tools/python/xen/util/xsm/xsm.py deleted file mode 100644 index 1c093c627f..0000000000 --- a/tools/python/xen/util/xsm/xsm.py +++ /dev/null @@ -1,20 +0,0 @@ -import sys -import string -from xen.xend import XendOptions -from xen.util import xsconstants -from xsm_core import xsm_init - -xoptions = XendOptions.instance() -xsm_module_name = xoptions.get_xsm_module_name() - -xsconstants.XS_POLICY_USE = eval("xsconstants.XS_POLICY_" + - string.upper(xsm_module_name)) - -xsm_module_path = "xen.util.xsm." + xsm_module_name + "." + xsm_module_name -xsm_module = __import__(xsm_module_path, globals(), locals(), ['*']) - -xsm_init(xsm_module) - -for op in dir(xsm_module): - if not hasattr(sys.modules[__name__], op): - setattr(sys.modules[__name__], op, getattr(xsm_module, op, None)) diff --git a/tools/python/xen/util/xsm/xsm_core.py b/tools/python/xen/util/xsm/xsm_core.py deleted file mode 100644 index f40af12edb..0000000000 --- a/tools/python/xen/util/xsm/xsm_core.py +++ /dev/null @@ -1,7 +0,0 @@ -import sys -import xen.util.xsm.dummy.dummy as dummy - -def xsm_init(self): - for op in dir(dummy): - if not hasattr(self, op): - setattr(self, op, getattr(dummy, op, None)) diff --git a/tools/python/xen/util/xspolicy.py b/tools/python/xen/util/xspolicy.py deleted file mode 100644 index 7cd5656dad..0000000000 --- a/tools/python/xen/util/xspolicy.py +++ /dev/null @@ -1,66 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2006,2007 International Business Machines Corp. -# Author: Stefan Berger -#============================================================================ - -import threading -import xsconstants - -class XSPolicy: - """ - The base policy class for all policies administered through - XSPolicyAdmin. - """ - - def __init__(self, name=None, ref=None): - self.lock = threading.Lock() - self.ref = ref - self.name = name - if ref: - from xen.xend.XendXSPolicy import XendXSPolicy - self.xendxspolicy = XendXSPolicy(self, {}, ref) - else: - self.xendxspolicy = None - - def grab_lock(self): - self.lock.acquire() - - def unlock(self): - self.lock.release() - - def get_ref(self): - return self.ref - - def destroy(self): - if self.xendxspolicy: - self.xendxspolicy.destroy() - - # All methods below should be overwritten by the inheriting class - - def isloaded(self): - return False - - def loadintohv(self): - return xsconstants.XSERR_POLICY_LOAD_FAILED - - def get_type(self): - return xsconstants.XS_POLICY_NONE - - def get_type_name(self): - return "" - - def update(self, repr_new): - return -xsconstants.XSERR_GENERAL_FAILURE, "" diff --git a/tools/python/xen/web/SrvBase.py b/tools/python/xen/web/SrvBase.py deleted file mode 100644 index cabb7b119f..0000000000 --- a/tools/python/xen/web/SrvBase.py +++ /dev/null @@ -1,98 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -#============================================================================ - -import types - - -from xen.xend import sxp -from xen.xend import PrettyPrint -from xen.xend.Args import ArgError -from xen.xend.XendError import XendError -from xen.xend.XendLogging import log - -import resource -import http -import httpserver - -def uri_pathlist(p): - """Split a path into a list. - p path - return list of path elements - """ - l = [] - for x in p.split('/'): - if x == '': continue - l.append(x) - return l - -class SrvBase(resource.Resource): - """Base class for services. - """ - - - def use_sxp(self, req): - return req.useSxp() - - def get_op_method(self, op): - """Get the method for an operation. - For operation 'foo' looks for 'op_foo'. - - op operation name - returns method or None - """ - op_method_name = 'op_' + op - return getattr(self, op_method_name, None) - - def perform(self, req): - """General operation handler for posted operations. - For operation 'foo' looks for a method op_foo and calls - it with op_foo(op, req). Replies with code 500 if op_foo - is not found. - - The method must return a list when req.use_sxp is true - and an HTML string otherwise (or list). - Methods may also return a ThreadRequest (for incomplete processing). - - req request - """ - op = req.args.get('op') - if op is None or len(op) != 1: - req.setResponseCode(http.NOT_ACCEPTABLE, "Invalid request") - return '' - op = op[0] - op_method = self.get_op_method(op) - if op_method is None: - req.setResponseCode(http.NOT_IMPLEMENTED, "Operation not implemented: " + op) - req.setHeader("Content-Type", "text/plain") - req.write("Operation not implemented: " + op) - return '' - else: - try: - return op_method(op, req) - except Exception, exn: - req.setResponseCode(http.INTERNAL_SERVER_ERROR, "Request failed: " + op) - log.exception("Request %s failed.", op) - if req.useSxp(): - return ['xend.err', str(exn)] - else: - return "

%s

" % str(exn) - - def print_path(self, req): - """Print the path with hyperlinks. - """ - req.printPath() - diff --git a/tools/python/xen/web/SrvDir.py b/tools/python/xen/web/SrvDir.py deleted file mode 100644 index 006975ef79..0000000000 --- a/tools/python/xen/web/SrvDir.py +++ /dev/null @@ -1,126 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -#============================================================================ - -import types - -from xen.xend import sxp -from xen.xend import PrettyPrint -from xen.xend.Args import ArgError -from xen.xend.XendError import XendError, XendInvalidDomain -#from xen.xend.XendLogging import log - -import resource -import http - -from xen.web.SrvBase import SrvBase - -class SrvConstructor: - """Delayed constructor for sub-servers. - Does not import the sub-server class or create the object until needed. - """ - - def __init__(self, klass): - """Create a constructor. It is assumed that the class - should be imported as 'from xen.xend.server.klass import klass'. - - klass name of its class - """ - self.klass = klass - self.obj = None - - def getobj(self): - """Get the sub-server object, importing its class and instantiating it if - necessary. - """ - if not self.obj: - exec 'from xen.xend.server.%s import %s' % (self.klass, self.klass) - klassobj = eval(self.klass) - self.obj = klassobj() - return self.obj - -class SrvDir(SrvBase): - """Base class for directory servlets. - """ - isLeaf = False - - def __init__(self): - SrvBase.__init__(self) - self.table = {} - self.order = [] - - def noChild(self, msg): - return resource.ErrorPage(http.NOT_FOUND, msg=msg) - - def getChild(self, x, req): - if x == '': return self - try: - val = self.get(x) - except XendError, ex: - return self.noChild(str(ex)) - except XendInvalidDomain, ex: - return self.noChild(str(ex)) - if val is None: - return self.noChild('Not found: ' + str(x)) - else: - return val - - def get(self, x): - val = self.table.get(x) - if isinstance(val, SrvConstructor): - val = val.getobj() - return val - - def add(self, x, v=None): - if v is None: - v = 'SrvDir' - if isinstance(v, types.StringType): - v = SrvConstructor(v) - self.table[x] = v - self.order.append(x) - return v - - def render_GET(self, req): - if self.use_sxp(req): - req.setHeader("Content-type", sxp.mime_type) - self.ls(req, 1) - else: - req.write('') - self.print_path(req) - self.ls(req) - self.form(req) - req.write('') - return '' - - def ls(self, req, use_sxp=0): - url = req.prePathURL() - if not url.endswith('/'): - url += '/' - if use_sxp: - req.write('(ls ') - for k in self.order: - req.write(' ' + k) - req.write(')') - else: - req.write('
    ') - for k in self.order: - v = self.get(k) - req.write('
  • %s
  • ' - % (url, k, k)) - req.write('
') - - def form(self, req): - pass diff --git a/tools/python/xen/web/__init__.py b/tools/python/xen/web/__init__.py deleted file mode 100644 index 718ac55974..0000000000 --- a/tools/python/xen/web/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2005 Mike Wray -#============================================================================ - diff --git a/tools/python/xen/web/connection.py b/tools/python/xen/web/connection.py deleted file mode 100644 index 17e1762085..0000000000 --- a/tools/python/xen/web/connection.py +++ /dev/null @@ -1,333 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2005 Mike Wray -# Copyright (C) 2005 XenSource Ltd. -#============================================================================ - -import sys -import os -import threading -import socket -import fcntl - -from errno import EAGAIN, EINTR, EWOULDBLOCK - -try: - from OpenSSL import SSL -except ImportError: - pass - -from xen.xend.XendLogging import log - -"""General classes to support server and client sockets, without -specifying what kind of socket they are. There are subclasses -for TCP and unix-domain sockets (see tcp.py and unix.py). -""" - -BUFFER_SIZE = 16384 -BACKLOG = 5 - - -class SocketServerConnection: - """An accepted connection to a server. - """ - - def __init__(self, sock, protocol_class): - self.sock = sock - self.protocol = protocol_class() - self.protocol.setTransport(self) - threading.Thread(target=self.main).start() - - - def main(self): - try: - while True: - try: - data = self.sock.recv(BUFFER_SIZE) - if data == '': - break - if self.protocol.dataReceived(data): - break - except socket.error, ex: - if ex.args[0] not in (EWOULDBLOCK, EAGAIN, EINTR): - break - finally: - try: - self.sock.close() - except: - pass - - - def close(self): - self.sock.close() - - - def write(self, data): - self.sock.send(data) - - -class SocketListener: - """A server socket, running listen in a thread. - Accepts connections and runs a thread for each one. - """ - - def __init__(self, protocol_class): - self.protocol_class = protocol_class - self.sock = self.createSocket() - threading.Thread(target=self.main).start() - - - def close(self): - try: - self.sock.close() - except: - pass - - - def createSocket(self): - raise NotImplementedError() - - - def acceptConnection(self, sock, protocol, addr): - raise NotImplementedError() - - - def main(self): - try: - fcntl.fcntl(self.sock.fileno(), fcntl.F_SETFD, fcntl.FD_CLOEXEC) - self.sock.listen(BACKLOG) - - while True: - try: - (sock, addr) = self.sock.accept() - self.acceptConnection(sock, addr) - except socket.error, ex: - if ex.args[0] not in (EWOULDBLOCK, EAGAIN, EINTR): - break - finally: - self.close() - - -class SSLSocketServerConnection(SocketServerConnection): - """An SSL aware accepted connection to a server. - - As pyOpenSSL SSL.Connection fileno() method just retrieve the file - descriptor number for the underlying socket, direct read/write to the file - descriptor will result no data encrypted. - - recv2fd() and fd2send() are simple wrappers for functions who need direct - read/write to a file descriptor rather than a socket like object. - - To use recv2fd(), you can create a pipe and start a thread to transfer all - received data to one end of the pipe, then read from the other end: - - p2cread, p2cwrite = os.pipe() - threading.Thread(target=connection.SSLSocketServerConnection.recv2fd, - args=(sock, p2cwrite)).start() - os.read(p2cread, 1024) - - To use fd2send(): - - p2cread, p2cwrite = os.pipe() - threading.Thread(target=connection.SSLSocketServerConnection.fd2send, - args=(sock, p2cread)).start() - os.write(p2cwrite, "data") - """ - - def __init__(self, sock, protocol_class): - SocketServerConnection.__init__(self, sock, protocol_class) - - - def main(self): - try: - while True: - try: - data = self.sock.recv(BUFFER_SIZE) - if data == "": - break - if self.protocol.dataReceived(data): - break - except socket.error, ex: - if ex.args[0] not in (EWOULDBLOCK, EAGAIN, EINTR): - break - except (SSL.WantReadError, SSL.WantWriteError, \ - SSL.WantX509LookupError): - # The operation did not complete; the same I/O method - # should be called again. - continue - except SSL.ZeroReturnError: - # The SSL Connection has been closed. - break - except SSL.SysCallError, (retval, desc): - if ((retval == -1 and desc == "Unexpected EOF") - or retval > 0): - # The SSL Connection is lost. - break - log.debug("SSL SysCallError:%d:%s" % (retval, desc)) - break - except SSL.Error, e: - # other SSL errors - log.debug("SSL Error:%s" % e) - break - finally: - try: - self.sock.close() - except: - pass - - - def recv2fd(sock, fd): - try: - while True: - try: - data = sock.recv(BUFFER_SIZE) - if data == "": - break - count = 0 - while count < len(data): - try: - nbytes = os.write(fd, data[count:]) - count += nbytes - except os.error, ex: - if ex.args[0] not in (EWOULDBLOCK, EAGAIN, EINTR): - raise - except socket.error, ex: - if ex.args[0] not in (EWOULDBLOCK, EAGAIN, EINTR): - break - except (SSL.WantReadError, SSL.WantWriteError, \ - SSL.WantX509LookupError): - # The operation did not complete; the same I/O method - # should be called again. - continue - except SSL.ZeroReturnError: - # The SSL Connection has been closed. - break - except SSL.SysCallError, (retval, desc): - if ((retval == -1 and desc == "Unexpected EOF") - or retval > 0): - # The SSL Connection is lost. - break - log.debug("SSL SysCallError:%d:%s" % (retval, desc)) - break - except SSL.Error, e: - # other SSL errors - log.debug("SSL Error:%s" % e) - break - finally: - try: - sock.close() - os.close(fd) - except: - pass - - recv2fd = staticmethod(recv2fd) - - - def fd2send(sock, fd): - try: - while True: - try: - data = os.read(fd, BUFFER_SIZE) - if data == "": - break - count = 0 - while count < len(data): - try: - nbytes = sock.send(data[count:]) - count += nbytes - except socket.error, ex: - if ex.args[0] not in (EWOULDBLOCK, EAGAIN, EINTR): - raise - except (SSL.WantReadError, SSL.WantWriteError, \ - SSL.WantX509LookupError): - # The operation did not complete; the same I/O method - # should be called again. - continue - except SSL.ZeroReturnError: - # The SSL Connection has been closed. - raise - except SSL.SysCallError, (retval, desc): - if not (retval == -1 and data == ""): - # errors when writing empty strings are expected - # and can be ignored - log.debug("SSL SysCallError:%d:%s" % (retval, desc)) - raise - except SSL.Error, e: - # other SSL errors - log.debug("SSL Error:%s" % e) - raise - except os.error, ex: - if ex.args[0] not in (EWOULDBLOCK, EAGAIN, EINTR): - break - finally: - try: - sock.close() - os.close(fd) - except: - pass - - fd2send = staticmethod(fd2send) - - -def hostAllowed(addrport, hosts_allowed): - if hosts_allowed is None: - return True - else: - fqdn = socket.getfqdn(addrport[0]) - for h in hosts_allowed: - if h.match(fqdn) or h.match(addrport[0]): - return True - log.warn("Rejected connection from %s (%s).", addrport[0], fqdn) - return False - - -class SocketDgramListener: - """A connectionless server socket, running listen in a thread. - """ - - def __init__(self, protocol_class): - self.protocol = protocol_class() - self.sock = self.createSocket() - threading.Thread(target=self.main).start() - - - def close(self): - try: - self.sock.close() - except: - pass - - - def createSocket(self): - raise NotImplementedError() - - - def main(self): - try: - fcntl.fcntl(self.sock.fileno(), fcntl.F_SETFD, fcntl.FD_CLOEXEC) - - while True: - try: - data = self.sock.recv(BUFFER_SIZE) - self.protocol.dataReceived(data) - except socket.error, ex: - if ex.args[0] not in (EWOULDBLOCK, EAGAIN, EINTR): - break - finally: - try: - self.close() - except: - pass diff --git a/tools/python/xen/web/http.py b/tools/python/xen/web/http.py deleted file mode 100644 index e11d8d29bd..0000000000 --- a/tools/python/xen/web/http.py +++ /dev/null @@ -1,518 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -#============================================================================ -# Parts of this library are derived from Twisted: -# Copyright (C) 2001 Matthew W. Lefkowitz -# -# Copyright (C) 2005 Mike Wray -#============================================================================ - -from mimetools import Message -from cStringIO import StringIO -import math -import socket -import time -import cgi - -CONTINUE = 100 -SWITCHING_PROTOCOLS = 101 - -OK = 200 -CREATED = 201 -ACCEPTED = 202 -NON_AUTHORITATIVE_INFORMATION = 203 -NO_CONTENT = 204 -RESET_CONTENT = 205 -PARTIAL_CONTENT = 206 -MULTI_STATUS = 207 - -MULTIPLE_CHOICE = 300 -MOVED_PERMANENTLY = 301 -FOUND = 302 -SEE_OTHER = 303 -NOT_MODIFIED = 304 -USE_PROXY = 305 -TEMPORARY_REDIRECT = 307 - -BAD_REQUEST = 400 -UNAUTHORIZED = 401 -PAYMENT_REQUIRED = 402 -FORBIDDEN = 403 -NOT_FOUND = 404 -NOT_ALLOWED = 405 -NOT_ACCEPTABLE = 406 -PROXY_AUTH_REQUIRED = 407 -REQUEST_TIMEOUT = 408 -CONFLICT = 409 -GONE = 410 -LENGTH_REQUIRED = 411 -PRECONDITION_FAILED = 412 -REQUEST_ENTITY_TOO_LARGE = 413 -REQUEST_URI_TOO_LONG = 414 -UNSUPPORTED_MEDIA_TYPE = 415 -REQUESTED_RANGE_NOT_SATISFIABLE = 416 -EXPECTATION_FAILED = 417 - -INTERNAL_SERVER_ERROR = 500 -NOT_IMPLEMENTED = 501 -BAD_GATEWAY = 502 -SERVICE_UNAVAILABLE = 503 -GATEWAY_TIMEOUT = 504 -VERSION_NOT_SUPPORTED = 505 -INSUFFICIENT_STORAGE_SPACE = 507 -NOT_EXTENDED = 510 - -NO_BODY_CODES = [ NO_CONTENT, NOT_MODIFIED ] - - -STATUS = { - CONTINUE : "Continue", - SWITCHING_PROTOCOLS : "Switching protocols", - - OK : "OK", - CREATED : "Created", - ACCEPTED : "Accepted", - NON_AUTHORITATIVE_INFORMATION : "Non-authoritative information", - NO_CONTENT : "No content", - RESET_CONTENT : "Reset content", - PARTIAL_CONTENT : "Partial content", - MULTI_STATUS : "Multi-status", - - MULTIPLE_CHOICE : "Multiple choice", - MOVED_PERMANENTLY : "Moved permanently", - FOUND : "Found", - SEE_OTHER : "See other", - NOT_MODIFIED : "Not modified", - USE_PROXY : "Use proxy", - TEMPORARY_REDIRECT : "Temporary redirect", - - BAD_REQUEST : "Bad request", - UNAUTHORIZED : "Unauthorized", - PAYMENT_REQUIRED : "Payment required", - FORBIDDEN : "Forbidden", - NOT_FOUND : "Not found", - NOT_ALLOWED : "Not allowed", - NOT_ACCEPTABLE : "Not acceptable", - PROXY_AUTH_REQUIRED : "Proxy authentication required", - REQUEST_TIMEOUT : "Request timeout", - CONFLICT : "Conflict", - GONE : "Gone", - LENGTH_REQUIRED : "Length required", - PRECONDITION_FAILED : "Precondition failed", - REQUEST_ENTITY_TOO_LARGE : "Request entity too large", - REQUEST_URI_TOO_LONG : "Request URI too long", - UNSUPPORTED_MEDIA_TYPE : "Unsupported media type", - REQUESTED_RANGE_NOT_SATISFIABLE : "Requested range not satisfiable", - EXPECTATION_FAILED : "Expectation failed", - - INTERNAL_SERVER_ERROR : "Internal server error", - NOT_IMPLEMENTED : "Not implemented", - BAD_GATEWAY : "Bad gateway", - SERVICE_UNAVAILABLE : "Service unavailable", - GATEWAY_TIMEOUT : "Gateway timeout", - VERSION_NOT_SUPPORTED : "HTTP version not supported", - INSUFFICIENT_STORAGE_SPACE : "Insufficient storage space", - NOT_EXTENDED : "Not extended", - } - -def getStatus(code): - return STATUS.get(code, "unknown") - -MULTIPART_FORM_DATA = 'multipart/form-data' -URLENCODED = 'application/x-www-form-urlencoded' - -parseQueryArgs = cgi.parse_qs - -def timegm(year, month, day, hour, minute, second): - """Convert time tuple in GMT to seconds since epoch, GMT""" - EPOCH = 1970 - assert year >= EPOCH - assert 1 <= month <= 12 - days = 365*(year-EPOCH) + calendar.leapdays(EPOCH, year) - for i in range(1, month): - days = days + calendar.mdays[i] - if month > 2 and calendar.isleap(year): - days = days + 1 - days = days + day - 1 - hours = days*24 + hour - minutes = hours*60 + minute - seconds = minutes*60 + second - return seconds - -def stringToDatetime(dateString): - """Convert an HTTP date string to seconds since epoch.""" - parts = dateString.split(' ') - day = int(parts[1]) - month = int(monthname.index(parts[2])) - year = int(parts[3]) - hour, min, sec = map(int, parts[4].split(':')) - return int(timegm(year, month, day, hour, min, sec)) - -class HttpRequest: - - http_version = (1, 1) - - http_version_string = ("HTTP/%d.%d" % http_version) - - max_content_length = 10000 - max_headers = 500 - - request_line = None - request_method = None - request_uri = None - request_path = None - request_query = None - request_version = None - content_length = 0 - content = None - etag = None - close_connection = True - response_code = 200 - response_status = "OK" - response_sent = False - cached = False - last_modified = None - - forceSSL = False - - def __init__(self, host, rin, out): - self.host = host - self.rin = rin - self.out = out - self.request_args = {} - self.args = self.request_args - self.request_headers = {} - self.request_cookies = {} - self.response_headers = {} - self.response_cookies = {} - self.output = StringIO() - self.parseRequest() - - def isSecure(self): - return self.forceSSL - - def getRequestMethod(self): - return self.request_method - - def trim(self, str, ends): - for end in ends: - if str.endswith(end): - str = str[ : -len(end) ] - break - return str - - def requestError(self, code, msg=None): - self.sendError(code, msg) - raise ValueError(self.response_status) - - def sendError(self, code, msg=None): - self.setResponseCode(code, msg=msg) - self.sendResponse() - - def parseRequestVersion(self, version): - try: - if not version.startswith('HTTP/'): - raise ValueError - version_string = version.split('/', 1)[1] - version_codes = version_string.split('.') - if len(version_codes) != 2: - raise ValueError - request_version = (int(version_codes[0]), int(version_codes[1])) - except (ValueError, IndexError): - self.requestError(400, "Bad request version (%s)" % `version`) - - def parseRequestLine(self): - line = self.trim(self.request_line, ['\r\n', '\n']) - line_fields = line.split() - n = len(line_fields) - if n == 3: - [method, uri, version] = line_fields - elif n == 2: - [method, uri] = line_fields - version = 'HTTP/0.9' - else: - self.requestError(BAD_REQUEST, - "Bad request (%s)" % `line`) - - request_version = self.parseRequestVersion(version) - - if request_version > (2, 0): - self.requestError(VERSION_NOT_SUPPORTED, - "HTTP version not supported (%s)" % `version`) - #if request_version >= (1, 1) and self.http_version >= (1, 1): - # self.close_connection = False - #else: - # self.close_connection = True - - self.request_method = method - self.method = method - self.request_uri = uri - self.request_version = version - - uri_query = uri.split('?') - if len(uri_query) == 1: - self.request_path = uri - else: - self.request_path = uri_query[0] - self.request_query = uri_query[1] - self.request_args = parseQueryArgs(self.request_query) - self.args = self.request_args - - - def parseRequestHeaders(self): - header_bytes = "" - header_count = 0 - while True: - if header_count >= self.max_headers: - self.requestError(BAD_REQUEST, - "Bad request (too many headers)") - line = self.rin.readline() - header_bytes += line - header_count += 1 - if line == '\r\n' or line == '\n' or line == '': - break - header_input = StringIO(header_bytes) - self.request_headers = Message(header_input) - - def parseRequestCookies(self): - cookie_hdr = self.getHeader("cookie") - if not cookie_hdr: return - for cookie in cookie_hdr.split(';'): - try: - cookie = cookie.lstrip() - (k, v) = cookie.split('=', 1) - self.request_cookies[k] = v - except ValueError: - pass - - def parseRequestArgs(self): - if ((self.content is None) or - (self.request_method != "POST")): - return - content_type = self.getHeader('content-type') - if not content_type: - return - (encoding, params) = cgi.parse_header(content_type) - if encoding == URLENCODED: - xargs = cgi.parse_qs(self.content.getvalue(), - keep_blank_values=True) - elif encoding == MULTIPART_FORM_DATA: - xargs = cgi.parse_multipart(self.content, params) - else: - xargs = {} - self.request_args.update(xargs) - - def getCookie(self, k): - return self.request_cookies[k] - - def readContent(self): - try: - self.content_length = int(self.getHeader("Content-Length")) - except: - return - if self.content_length > self.max_content_length: - self.requestError(REQUEST_ENTITY_TOO_LARGE) - self.content = self.rin.read(self.content_length) - self.content = StringIO(self.content) - self.content.seek(0,0) - - def parseRequest(self): - self.request_line = self.rin.readline() - self.parseRequestLine() - self.parseRequestHeaders() - self.parseRequestCookies() - connection_mode = self.getHeader('Connection') - self.setCloseConnection(connection_mode) - self.readContent() - self.parseRequestArgs() - - def setCloseConnection(self, mode): - if not mode: return - mode = mode.lower() - if mode == 'close': - self.close_connection = True - elif (mode == 'keep-alive') and (self.http_version >= (1, 1)): - self.close_connection = False - - def getCloseConnection(self): - return self.close_connection - - def getHeader(self, k, v=None): - return self.request_headers.get(k, v) - - def getRequestMethod(self): - return self.request_method - - def getRequestPath(self): - return self.request_path - - def setResponseCode(self, code, status=None, msg=None): - self.response_code = code - if not status: - status = getStatus(code) - self.response_status = status - - def setResponseHeader(self, k, v): - k = k.lower() - self.response_headers[k] = v - if k == 'connection': - self.setCloseConnection(v) - - setHeader = setResponseHeader - - def setLastModified(self, when): - # time.time() may be a float, but the HTTP-date strings are - # only good for whole seconds. - when = long(math.ceil(when)) - if (not self.last_modified) or (self.last_modified < when): - self.lastModified = when - - modified_since = self.getHeader('if-modified-since') - if modified_since: - modified_since = stringToDatetime(modified_since) - if modified_since >= when: - self.setResponseCode(NOT_MODIFIED) - self.cached = True - - def setContentType(self, ty): - self.setResponseHeader("Content-Type", ty) - - def setEtag(self, etag): - if etag: - self.etag = etag - - tags = self.getHeader("if-none-match") - if tags: - tags = tags.split() - if (etag in tags) or ('*' in tags): - if self.request_method in ("HEAD", "GET"): - code = NOT_MODIFIED - else: - code = PRECONDITION_FAILED - self.setResponseCode(code) - self.cached = True - - def addCookie(self, k, v, expires=None, domain=None, path=None, - max_age=None, comment=None, secure=None): - cookie = v - if expires != None: - cookie += "; Expires=%s" % expires - if domain != None: - cookie += "; Domain=%s" % domain - if path != None: - cookie += "; Path=%s" % path - if max_age != None: - cookie += "; Max-Age=%s" % max_age - if comment != None: - cookie += "; Comment=%s" % comment - if secure: - cookie += "; Secure" - self.response_cookies[k] = cookie - - def sendResponseHeaders(self): - if self.etag: - self.setResponseHeader("ETag", self.etag) - for (k, v) in self.response_headers.items(): - self.send("%s: %s\r\n" % (k.capitalize(), v)) - for (k, v) in self.response_cookies.items(): - self.send("Set-Cookie: %s=%s\r\n" % (k, v)) - self.send("\r\n") - - def sendResponse(self): - if self.response_sent: - return - self.response_sent = True - send_body = self.hasBody() - if not self.close_connection: - self.setResponseHeader("Connection", "keep-alive") - self.setResponseHeader("Pragma", "no-cache") - self.setResponseHeader("Cache-Control", "no-cache") - self.setResponseHeader("Expires", "-1") - if send_body: - self.output.seek(0, 0) - body = self.output.getvalue() - body_length = len(body) - self.setResponseHeader("Content-Length", body_length) - if self.http_version > (0, 9): - self.send("%s %d %s\r\n" % (self.http_version_string, - self.response_code, - self.response_status)) - self.sendResponseHeaders() - if send_body: - self.send(body) - self.flush() - - def write(self, data): - self.output.write(data) - - def send(self, data): - #print 'send>', data - self.out.write(data) - - def flush(self): - self.out.flush() - - def hasNoBody(self): - return ((self.request_method == "HEAD") or - (self.response_code in NO_BODY_CODES) or - self.cached) - - def hasBody(self): - return not self.hasNoBody() - - def process(self): - pass - return self.close_connection - - def getRequestHostname(self): - """Get the hostname that the user passed in to the request. - - Uses the 'Host:' header if it is available, and the - host we are listening on otherwise. - """ - return (self.getHeader('host') or - socket.gethostbyaddr(self.getHostAddr())[0] - ).split(':')[0] - - def getHost(self): - return self.host - - def getHostAddr(self): - return self.host[0] - - def getPort(self): - return self.host[1] - - def setHost(self, host, port, ssl=0): - """Change the host and port the request thinks it's using. - - This method is useful for working with reverse HTTP proxies (e.g. - both Squid and Apache's mod_proxy can do this), when the address - the HTTP client is using is different than the one we're listening on. - - For example, Apache may be listening on https://www.example.com, and then - forwarding requests to http://localhost:8080, but we don't want HTML produced - to say 'http://localhost:8080', they should say 'https://www.example.com', - so we do:: - - request.setHost('www.example.com', 443, ssl=1) - - """ - self.forceSSL = ssl - self.received_headers["host"] = host - self.host = (host, port) - - - diff --git a/tools/python/xen/web/httpserver.py b/tools/python/xen/web/httpserver.py deleted file mode 100644 index d8a1f78a56..0000000000 --- a/tools/python/xen/web/httpserver.py +++ /dev/null @@ -1,367 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2005 Mike Wray -# Copyright (C) 2006 XenSource Ltd. -#============================================================================ - -import threading - -import string -import socket -import types -from urllib import quote, unquote -import os -import os.path -import fcntl - -from xen.xend import sxp -from xen.xend.Args import ArgError -from xen.xend.XendError import XendError - -import http -import unix -from resource import Resource, ErrorPage -from SrvDir import SrvDir - -class ThreadRequest: - """A request to complete processing using a thread. - """ - - def __init__(self, processor, req, fn, args, kwds): - self.processor = processor - self.req = req - self.fn = fn - self.args = args - self.kwds = kwds - - def run(self): - self.processor.setInThread() - thread = threading.Thread(target=self.main) - thread.setDaemon(True) - thread.start() - - def call(self): - try: - self.fn(*self.args, **self.kwds) - except SystemExit: - raise - except Exception, ex: - self.req.resultErr(ex) - self.req.finish() - - def main(self): - self.call() - self.processor.process() - - -class RequestProcessor: - """Processor for requests on a connection to an http server. - Requests are executed synchonously unless they ask for a thread by returning - a ThreadRequest. - """ - - done = False - - inThread = False - - def __init__(self, server, sock, addr): - self.server = server - self.sock = sock - self.srd = sock.makefile('rb') - self.srw = sock.makefile('wb') - self.srvaddr = server.getServerAddr() - - def isInThread(self): - return self.inThread - - def setInThread(self): - self.inThread = True - - def getServer(self): - return self.server - - def getRequest(self): - return HttpServerRequest(self, self.srvaddr, self.srd, self.srw) - - def close(self): - try: - self.sock.close() - except: - pass - - def finish(self): - self.done = True - self.close() - - def process(self): - while not self.done: - req = self.getRequest() - res = req.process() - if isinstance(res, ThreadRequest): - if self.isInThread(): - res.call() - else: - res.run() - break - else: - req.finish() - -class HttpServerRequest(http.HttpRequest): - """A single request to an http server. - """ - - def __init__(self, processor, addr, srd, srw): - self.processor = processor - self.prepath = '' - http.HttpRequest.__init__(self, addr, srd, srw) - - def getServer(self): - return self.processor.getServer() - - def process(self): - """Process the request. If the return value is a ThreadRequest - it is evaluated in a thread. - """ - try: - self.prepath = [] - self.postpath = map(unquote, string.split(self.request_path[1:], '/')) - resource = self.getResource() - return self.render(resource) - except SystemExit: - raise - except Exception, ex: - self.processError(ex) - - def processError(self, ex): - import traceback; traceback.print_exc() - self.sendError(http.INTERNAL_SERVER_ERROR, msg=str(ex)) - self.setCloseConnection('close') - - def finish(self): - self.sendResponse() - if self.close_connection: - self.processor.finish() - - def prePathURL(self): - url_host = self.getRequestHostname() - port = self.getPort() - if self.isSecure(): - url_proto = "https" - default_port = 443 - else: - url_proto = "http" - default_port = 80 - if port != default_port: - url_host += (':%d' % port) - url_path = quote(string.join(self.prepath, '/')) - return ('%s://%s/%s' % (url_proto, url_host, url_path)) - - def getResource(self): - return self.getServer().getResource(self) - - def render(self, resource): - val = None - if resource is None: - self.sendError(http.NOT_FOUND) - else: - try: - while True: - val = resource.render(self) - if not isinstance(val, Resource): - break - val = self.result(val) - except SystemExit: - raise - except Exception, ex: - self.resultErr(ex) - return val - - def threadRequest(self, _fn, *_args, **_kwds): - """Create a request to finish request processing in a thread. - Use this to create a ThreadRequest to return from rendering a - resource if you need a thread to complete processing. - """ - return ThreadRequest(self.processor, self, _fn, _args, _kwds) - - def result(self, val): - if isinstance(val, Exception): - return self.resultErr(val) - else: - return self.resultVal(val) - - def resultVal(self, val): - """Callback to complete the request. - - @param val: the value - """ - if val is None: - return val - elif isinstance(val, ThreadRequest): - return val - elif self.useSxp(): - self.setHeader("Content-Type", sxp.mime_type) - sxp.show(val, out=self) - else: - self.write('') - self.printPath() - if isinstance(val, types.ListType): - self.write('
')
-                PrettyPrint.prettyprint(val, out=self)
-                self.write('
') - else: - self.write(str(val)) - self.write('') - return None - - def resultErr(self, err): - """Error callback to complete a request. - - @param err: the error - """ - if not isinstance(err, (ArgError, sxp.ParseError, XendError)): - raise - #log.exception("op=%s: %s", op, str(err)) - if self.useSxp(): - self.setHeader("Content-Type", sxp.mime_type) - sxp.show(['xend.err', str(err)], out=self) - else: - self.setHeader("Content-Type", "text/plain") - self.write('Error ') - self.write(': ') - self.write(str(err)) - return None - - def useSxp(self): - """Determine whether to send an SXP response to a request. - Uses SXP if there is no User-Agent, no Accept, or application/sxp is in Accept. - - returns 1 for SXP, 0 otherwise - """ - ok = 0 - user_agent = self.getHeader('User-Agent') - accept = self.getHeader('Accept') - if (not user_agent) or (not accept) or (accept.find(sxp.mime_type) >= 0): - ok = 1 - return ok - - def printPath(self): - pathlist = [x for x in self.prepath if x != '' ] - s = "/" - self.write('

/') - for x in pathlist: - s += x + "/" - self.write(' %s/' % (s, x)) - self.write("

") - -class HttpServerClient: - - def __init__(self, server, sock, addr): - self.server = server - self.sock = sock - self.addr = addr - - def process(self): - thread = threading.Thread(target=self.doProcess) - thread.setDaemon(True) - thread.start() - - def doProcess(self): - try: - rp = RequestProcessor(self.server, self.sock, self.addr) - rp.process() - except SystemExit: - raise - except Exception, ex: - print 'HttpServer>processRequest> exception: ', ex - try: - self.sock.close() - except: - pass - -class HttpServer: - - backlog = 5 - - def __init__(self, root, interface, port=8080): - self.root = root - self.interface = interface - self.port = port - # ready indicates when we are ready to begin accept connections - # it should be set after a successful bind - self.ready = False - self.closed = False - - def run(self): - self.bind() - self.listen() - self.ready = True - - while not self.closed: - (sock, addr) = self.accept() - cl = HttpServerClient(self, sock, addr) - cl.process() - - def stop(self): - self.close() - - def bind(self): - self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - flags = fcntl.fcntl(self.socket.fileno(), fcntl.F_GETFD) - flags |= fcntl.FD_CLOEXEC - fcntl.fcntl(self.socket.fileno(), fcntl.F_SETFD, flags) - self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - self.socket.bind((self.interface, self.port)) - - def listen(self): - self.socket.listen(self.backlog) - - def accept(self): - return self.socket.accept() - - def close(self): - self.closed = True - self.ready = False - # shutdown socket explicitly to allow reuse - try: - self.socket.shutdown(2) - except socket.error: - pass - - try: - self.socket.close() - except socket.error: - pass - - def getServerAddr(self): - return (socket.gethostname(), self.port) - - def getResource(self, req): - return self.root.getRequestResource(req) - - def shutdown(self): - self.close() - - -class UnixHttpServer(HttpServer): - - def __init__(self, root, path): - HttpServer.__init__(self, root, 'localhost') - self.path = path - - def bind(self): - self.socket = unix.bind(self.path) - flags = fcntl.fcntl(self.socket.fileno(), fcntl.F_GETFD) - flags |= fcntl.FD_CLOEXEC - fcntl.fcntl(self.socket.fileno(), fcntl.F_SETFD, flags) diff --git a/tools/python/xen/web/protocol.py b/tools/python/xen/web/protocol.py deleted file mode 100644 index 603973a3fd..0000000000 --- a/tools/python/xen/web/protocol.py +++ /dev/null @@ -1,40 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2005 Mike Wray -# Copyright (C) 2005 XenSource Ltd. -#============================================================================ - -class Protocol: - - def __init__(self): - self.transport = None - - def setTransport(self, transport): - self.transport = transport - - def dataReceived(self, data): - raise NotImplementedError() - - def write(self, data): - if self.transport: - return self.transport.write(data) - else: - return 0 - - def read(self): - if self.transport: - return self.transport.read() - else: - return None diff --git a/tools/python/xen/web/resource.py b/tools/python/xen/web/resource.py deleted file mode 100644 index 6c226bb10e..0000000000 --- a/tools/python/xen/web/resource.py +++ /dev/null @@ -1,108 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2005 Mike Wray -#============================================================================ - -import http - -def findResource(resource, request): - """Traverse resource tree to find who will handle the request.""" - while request.postpath and not resource.isLeaf: - #print 'findResource:', resource, request.postpath - pathElement = request.postpath.pop(0) - request.prepath.append(pathElement) - next = resource.getPathResource(pathElement, request) - if not next: break - resource = next - return resource - -class Resource: - - isLeaf = False - - def __init__(self): - self.children = {} - - def getRequestResource(self, req): - return findResource(self, req) - - def getChild(self, path, request): - return None - - def getPathResource(self, path, request): - #print 'getPathResource>', self, path - if self.children.has_key(path): - val = self.children[path] - else: - val = self.getChild(path, request) - #print 'getPathResource<', val - return val - - def putChild(self, path, child): - self.children[path] = child - #child.server = self.server - - def render(self, req): - meth = getattr(self, 'render_' + req.getRequestMethod(), self.unsupported) - return meth(req) - - def supportedMethods(self): - l = [] - s = 'render_' - for x in dir(self): - if x.startswith(s): - l.append(x[len(s):]) - return l - - def render_HEAD(self, req): - return self.render_GET(req) - - def render_GET(self, req): - req.setContentType("text/plain") - req.write("GET") - - def render_POST(self, req): - req.setContentType("text/plain") - req.write("POST") - - def unsupported(self, req): - req.setHeader("Accept", ",".join(self.supportedMethods())) - req.setResponseCode(http.NOT_IMPLEMENTED) - req.setContentType("text/plain") - req.write("Request method not supported (%s)" % req.getRequestMethod()) - -class ErrorPage(Resource): - - isLeaf = True - - def __init__(self, code, status=None, msg=None): - Resource.__init__(self) - if status is None: - status = http.getStatus(code) - if msg is None: - msg = status - self.code = code - self.status = status - self.msg = msg - - def render(self, req): - req.setResponseCode(self.code, self.status) - req.setContentType("text/plain") - req.write(self.msg) - - - - - diff --git a/tools/python/xen/web/static.py b/tools/python/xen/web/static.py deleted file mode 100644 index 70cb7d66ff..0000000000 --- a/tools/python/xen/web/static.py +++ /dev/null @@ -1,61 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2005 Mike Wray -#============================================================================ -import os - -from resource import Resource - -class File(Resource): - - isLeaf = True - - def __init__(self, filename, defaultType=None): - if defaultType is None: - defaultType = "text/plain" - self.filename = filename - self.type = defaultType - self.encoding = None - - def getFileSize(self): - try: - info = os.stat(self.filename) - return info.st_size - except: - return 0 - - def render(self, req): - if self.type: - req.setHeader('Content-Type', self.type) - if self.encoding: - req.setHeader('Content-Encoding', self.encoding) - req.setHeader('Content-Length', self.getFileSize()) - try: - io = file(self.filename, "r") - while True: - buf = io.read(1024) - if not buf: - break - req.write(buf) - except IOError: - pass - try: - if io: - io.close() - except: - pass - - - diff --git a/tools/python/xen/web/tcp.py b/tools/python/xen/web/tcp.py deleted file mode 100644 index 222737514a..0000000000 --- a/tools/python/xen/web/tcp.py +++ /dev/null @@ -1,212 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2005 Mike Wray -# Copyright (C) 2005 XenSource Ltd. -#============================================================================ - - -import errno -import re -import socket -import time -import fcntl # For get_interface_addr -import struct # For get_interface_addr - -import connection - -from xen.xend.XendLogging import log - - -class TCPListener(connection.SocketListener): - - def __init__(self, protocol_class, port, interface, hosts_allow): - self.port = port - self.interface = interface - self.hosts_allow = hosts_allow - connection.SocketListener.__init__(self, protocol_class) - - def isValidHex(self, word): - # If we have empty word we treat it as valid - if len(word) == 0: - return True - try: - int(word, 16) - return True - except ValueError: - return False - - def isValidIP(self, ipaddr): - # Check for IPv4 address - numValid = 0 - tmp = ipaddr.split('.') - for byte in tmp: - if byte.isdigit(): - numValid += 1 - - if numValid == len(tmp): - return True - - # Check for IPv6 address - numValid = 0 - tmp = ipaddr.split(':') - for word in tmp: - if self.isValidHex(word): - numValid += 1 - - return numValid == len(tmp) - - def getIfAddr(self, ifname): - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - try: - x = socket.inet_ntoa(fcntl.ioctl( - s.fileno(), - 0x8915, # SIOCGIFADDR - struct.pack('256s', ifname[:15]) - )[20:24]) - s.close() - except Exception, e: - x = ifname - - return x - - def createSocket(self): - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - - # SO_REUSEADDR does not always ensure that we do not get an address - # in use error when restarted quickly - # we implement a timeout to try and avoid failing unnecessarily - timeout = time.time() + 30 - while True: - try: - if not self.isValidIP(self.interface): - self.interface = self.getIfAddr(self.interface) - log.debug("Listening on %s:%s" % (self.interface, self.port)) - sock.bind((self.interface, self.port)) - return sock - except socket.error, (_errno, strerrno): - if _errno == errno.EADDRINUSE and time.time() < timeout: - time.sleep(0.5) - else: - raise - - - def acceptConnection(self, sock, addrport): - addr = addrport[0] - if connection.hostAllowed(addrport, self.hosts_allow): - connection.SocketServerConnection(sock, self.protocol_class) - else: - try: - sock.close() - except: - pass - -class SSLTCPListener(TCPListener): - - def __init__(self, protocol_class, port, interface, hosts_allow, - ssl_key_file = None, ssl_cert_file = None): - if not ssl_key_file or not ssl_cert_file: - raise ValueError("SSLXMLRPCServer requires ssl_key_file " - "and ssl_cert_file to be set.") - - self.ssl_key_file = ssl_key_file - self.ssl_cert_file = ssl_cert_file - - TCPListener.__init__(self, protocol_class, port, interface, hosts_allow) - - def isValidHex(self, word): - # If we have empty word we treat it as valid - if len(word) == 0: - return True - try: - int(word, 16) - return True - except ValueError: - return False - - def isValidIP(self, ipaddr): - # Check for IPv4 address - numValid = 0 - tmp = ipaddr.split('.') - for byte in tmp: - if byte.isdigit(): - numValid += 1 - - if numValid == len(tmp): - return True - - # Check for IPv6 address - numValid = 0 - tmp = ipaddr.split(':') - for word in tmp: - if self.isValidHex(word): - numValid += 1 - - return numValid == len(tmp) - - def getIfAddr(self, ifname): - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - try: - x = socket.inet_ntoa(fcntl.ioctl( - s.fileno(), - 0x8915, # SIOCGIFADDR - struct.pack('256s', ifname[:15]) - )[20:24]) - s.close() - except Exception, e: - x = ifname - - return x - - def createSocket(self): - from OpenSSL import SSL - # make a SSL socket - ctx = SSL.Context(SSL.SSLv23_METHOD) - ctx.set_options(SSL.OP_NO_SSLv2) - ctx.use_privatekey_file (self.ssl_key_file) - ctx.use_certificate_file(self.ssl_cert_file) - sock = SSL.Connection(ctx, - socket.socket(socket.AF_INET, socket.SOCK_STREAM)) - sock.set_accept_state() - sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - - # SO_REUSEADDR does not always ensure that we do not get an address - # in use error when restarted quickly - # we implement a timeout to try and avoid failing unnecessarily - timeout = time.time() + 30 - while True: - try: - if not self.isValidIP(self.interface): - self.interface = self.getIfAddr(self.interface) - log.debug("Listening on %s:%s" % (self.interface, self.port)) - sock.bind((self.interface, self.port)) - return sock - except socket.error, (_errno, strerrno): - if _errno == errno.EADDRINUSE and time.time() < timeout: - time.sleep(0.5) - else: - raise - - - def acceptConnection(self, sock, addrport): - addr = addrport[0] - if connection.hostAllowed(addrport, self.hosts_allow): - connection.SSLSocketServerConnection(sock, self.protocol_class) - else: - try: - sock.close() - except: - pass - diff --git a/tools/python/xen/web/unix.py b/tools/python/xen/web/unix.py deleted file mode 100644 index 180c0858eb..0000000000 --- a/tools/python/xen/web/unix.py +++ /dev/null @@ -1,69 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2005 Mike Wray -# Copyright (C) 2005-2006 XenSource Ltd. -#============================================================================ - - -import os -import os.path -import socket -import stat - -from xen.util import mkdir - -import connection - - -def bind(path, type = socket.SOCK_STREAM): - """Create a Unix socket, and bind it to the given path. - The socket is created such that only the current user may access it.""" - - if path[0] == '\0': # Abstract namespace is used for the path - pass - else: - parent = os.path.dirname(path) - mkdir.parents(parent, stat.S_IRWXU, True) - if os.path.exists(path): - os.unlink(path) - - sock = socket.socket(socket.AF_UNIX, type) - sock.bind(path) - return sock - - -class UnixListener(connection.SocketListener): - def __init__(self, path, protocol_class): - self.path = path - connection.SocketListener.__init__(self, protocol_class) - - - def createSocket(self): - return bind(self.path, socket.SOCK_STREAM) - - - def acceptConnection(self, sock, _): - connection.SocketServerConnection(sock, self.protocol_class) - - -class UnixDgramListener(connection.SocketDgramListener): - def __init__(self, path, protocol_class): - self.path = path - connection.SocketDgramListener.__init__(self, protocol_class) - - - def createSocket(self): - return bind(self.path, socket.SOCK_DGRAM) - diff --git a/tools/python/xen/xend/Args.py b/tools/python/xen/xend/Args.py deleted file mode 100644 index e2193b6069..0000000000 --- a/tools/python/xen/xend/Args.py +++ /dev/null @@ -1,166 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -#============================================================================ - -import types -import StringIO - -from xen.xend import sxp - -class ArgError(StandardError): - pass - -class Args: - """Argument encoding support for HTTP. - """ - - def __init__(self, paramspec, keyspec): - self.arg_ord = [] - self.arg_dict = {} - self.key_ord = [] - self.key_dict = {} - for (name, typ) in paramspec: - self.arg_ord.append(name) - self.arg_dict[name] = typ - for (name, typ) in keyspec: - self.key_ord.append(name) - self.key_dict[name] = typ - - def get_args(self, d, xargs=None): - args = {} - keys = {} - params = [] - if xargs: - self.split_args(xargs, args, keys) - self.split_args(d, args, keys) - for a in self.arg_ord: - if a in args: - params.append(args[a]) - else: - raise ArgError('Missing parameter: %s' % a) - return (params, keys) - - def split_args(self, d, args, keys): - for (k, v) in d.items(): - if k in self.arg_dict: - typ = self.arg_dict[k] - val = self.coerce(typ, v) - args[k] = val - elif k in self.key_dict: - typ = self.key_dict[k] - val = self.coerce(typ, v) - keys[k] = val - else: - raise ArgError('Invalid parameter: %s' % k) - - def get_form_args(self, f, xargs=None): - d = {} - for (k, v) in f.items(): - if ((k not in self.arg_dict) and - (k not in self.key_dict)): - continue - if isinstance(v, types.ListType): - n = len(v) - if n == 0: - continue - elif n == 1: - val = v[0] - else: - raise ArgError('Too many values for %s' % k) - else: - val = v - d[k] = val - return self.get_args(d, xargs=xargs) - - def coerce(self, typ, v): - try: - if typ == 'int': - val = int(v) - elif typ == 'long': - val = long(v) - elif typ == 'str': - val = str(v) - elif typ == 'sxpr': - val = self.sxpr(v) - elif typ == 'bool': - val = self.bool(v) - else: - raise ArgError('invalid type:' + str(typ)) - return val - except ArgError: - raise - except StandardError, ex: - raise ArgError(str(ex)) - - def bool(self, v): - return (v.lower() in ['on', 'yes', '1', 'true']) - - def sxpr(self, v): - if isinstance(v, types.ListType): - val = v - elif isinstance(v, types.FileType) or hasattr(v, 'readline'): - val = self.sxpr_file(v) - elif isinstance(v, types.StringType): - val = self.sxpr_file(StringIO.StringIO(v)) - else: - val = str(v) - return val - - def sxpr_file(self, fin): - try: - vals = sxp.parse(fin) - except: - raise ArgError('Coercion to sxpr failed') - if len(vals) == 1: - return vals[0] - else: - raise ArgError('Too many sxprs') - - def call_with_args(self, fn, args, xargs=None): - (params, keys) = self.get_args(args, xargs=xargs) - return fn(*params, **keys) - - def call_with_form_args(self, fn, fargs, xargs=None): - (params, keys) = self.get_form_args(fargs, xargs=xargs) - return fn(*params, **keys) - -class ArgFn(Args): - """Represent a remote HTTP operation as a function. - Used on the client. - """ - - def __init__(self, fn, paramspec, keyspec = None): - if keyspec == None: - keyspec = {} - Args.__init__(self, paramspec, keyspec) - self.fn = fn - - def __call__(self, fargs, xargs=None): - return self.call_with_args(self.fn, fargs, xargs=xargs) - -class FormFn(Args): - """Represent an operation as a function over a form. - Used in the HTTP server. - """ - - def __init__(self, fn, paramspec, keyspec = None): - if keyspec == None: - keyspec = {} - Args.__init__(self, paramspec, keyspec) - self.fn = fn - - def __call__(self, fargs, xargs=None): - return self.call_with_form_args(self.fn, fargs, xargs=xargs) diff --git a/tools/python/xen/xend/MemoryPool.py b/tools/python/xen/xend/MemoryPool.py deleted file mode 100644 index 1a9add6f87..0000000000 --- a/tools/python/xen/xend/MemoryPool.py +++ /dev/null @@ -1,118 +0,0 @@ -#=========================================================================== -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2009 Novell, Inc. -# Author: James (Song Wei) -#============================================================================ - -import xen.lowlevel.xc -import XendDomain -import XendOptions -from XendLogging import log -from XendError import VmError - -class MemoryPool: - - def init(self): - xoptions = XendOptions.instance() - self.default_reserved_memory = xoptions.get_reserved_memory() * 1024 * 1024 #KiB - if self.default_reserved_memory <= 0: - return - self.enable_memory_pool = 1 - self.dom0_ballooning = xoptions.get_enable_dom0_ballooning() - if not self.dom0_ballooning: - return - self.reserve_memory = 0 - self.untouched_memory = 0 - #init reserved memory - #if not reserve_memory_size: - xc = xen.lowlevel.xc.xc() - physinfo = xc.physinfo() - total_mem = physinfo['total_memory'] - if total_mem < self.reserve_memory: - self.default_reserved_memory = total_mem - self.reserve_memory = self.default_reserved_memory - self.untouched_memory = self.default_reserved_memory - log.debug("MemoryPool: init reserved_memory %d KiB" %self.reserve_memory) - - def __init__(self): - self.reserve_memory = 0 - self.untouched_memory = 0 - self.default_reserved_memory = 0 - self.enable_memory_pool = 0 - self.dom0_ballooning = 0 - def available_memory_check(self, need_mem): - return self.is_enabled() and self.reserved_memory > need_mem - - def decrease_memory(self, value): - if not self.is_enabled() or value <= 4096: #4M for PV guest kernel and ramdisk unzip - return - elif self.reserve_memory < value: - raise VMError(('I need %d KiB, but only have %d KiB in Memory Pool') %(value,self.reserve_memory)) - else: - self.reserve_memory -= value - log.debug("MemoryPool: decrease_memory: decrease: %d reserved_memory %d KiB" %(value,self.reserve_memory)) - return - - def decrease_untouched_memory(self, value): - if not self.is_enabled(): - return - elif self.untouched_memory < value: - raise VmError(('I need %d KiB untouch mem, but only have %d KiB untouched mem in Memory Pool') %(value,self.reserve_memory)) - else: - self.untouched_memory -= value - log.debug("MemoryPool: decrease_untouched_memory: untouched_memory %d KiB" %self.untouched_memory) - return - - def increase_memory(self, value): - if not self.is_enabled(): - return - else: - self.reserve_memory += value - if self.reserve_memory > self.default_reserved_memory: - raise VmError(('the maxsize of memory pool is %d KiB, but current is %d KiB') %(value,self.reserve_memory)) - log.debug("MemoryPool: increase_memory:%d, reserved_memory %d KiB" %(value,self.reserve_memory)) - return - - def is_enabled(self): - return self.enable_memory_pool and self.dom0_ballooning - - def get_pool_size(self): - if self.is_enabled(): - return self.default_reserved_memory - else: - return 0 - - def get_left_memory(self): - if self.is_enabled(): - return self.reserve_memory - else: - return 0 - - def get_untouched_memory(self): - if self.is_enabled(): - return self.untouched_memory - else: - return 0 - -def instance(): - """Singleton constructor. Use this instead of the class constructor. - """ - global MP_inst - try: - MP_inst - except: - MP_inst = MemoryPool() - MP_inst.init() - return MP_inst diff --git a/tools/python/xen/xend/PrettyPrint.py b/tools/python/xen/xend/PrettyPrint.py deleted file mode 100644 index 22a78fb3f2..0000000000 --- a/tools/python/xen/xend/PrettyPrint.py +++ /dev/null @@ -1,323 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2005 XenSource Ltd -#============================================================================ - -"""General pretty-printer, including support for SXP. - -""" -import sys -import types -import StringIO -from xen.xend import sxp - -class PrettyItem: - - def __init__(self, width): - self.width = width - - def insert(self, block): - block.addtoline(self) - - def get_width(self): - return self.width - - def output(self, _): - print '***PrettyItem>output>', self - pass - - def prettyprint(self, _): - print '***PrettyItem>prettyprint>', self - return self.width - -class PrettyString(PrettyItem): - - def __init__(self, x): - PrettyItem.__init__(self, len(x)) - self.value = x - - def output(self, out): - out.write(self.value) - - def prettyprint(self, line): - line.output(self) - - def show(self, out): - print >> out, ("(string (width %d) '%s')" % (self.width, self.value)) - -class PrettySpace(PrettyItem): - - def output(self, out): - out.write(' ' * self.width) - - def prettyprint(self, line): - line.output(self) - - def show(self, out): - print >> out, ("(space (width %d))" % self.width) - -class PrettyBreak(PrettyItem): - - def __init__(self, width, indent): - PrettyItem.__init__(self, width) - self.indent = indent - self.space = 0 - self.active = 0 - - def output(self, out): - out.write(' ' * self.width) - - def prettyprint(self, line): - if line.breaks(self.space): - self.active = 1 - line.newline(self.indent) - else: - line.output(self) - - def show(self, out): - print >> out, ("(break (width %d) (indent %d) (space %d) (active %d))" - % (self.width, self.indent, self.space, self.active)) - -class PrettyNewline(PrettySpace): - - def insert(self, block): - block.newline() - block.addtoline(self) - - def prettyprint(self, line): - line.newline(0) - line.output(self) - - def show(self, out): - print >> out, ("(nl (width %d))" % self.width) - -class PrettyLine(PrettyItem): - def __init__(self): - PrettyItem.__init__(self, 0) - self.content = [] - - def write(self, x): - self.content.append(x) - - def end(self): - width = 0 - lastwidth = 0 - lastbreak = None - for x in self.content: - if isinstance(x, PrettyBreak): - if lastbreak: - lastbreak.space = (width - lastwidth) - lastbreak = x - lastwidth = width - width += x.get_width() - if lastbreak: - lastbreak.space = (width - lastwidth) - self.width = width - - def prettyprint(self, line): - for x in self.content: - x.prettyprint(line) - - def show(self, out): - print >> out, '(LINE (width %d)' % self.width - for x in self.content: - x.show(out) - print >> out, ')' - -class PrettyBlock(PrettyItem): - - def __init__(self, all=0, parent=None): - PrettyItem.__init__(self, 0) - - self.lines = [] - self.parent = parent - self.indent = 0 - self.all = all - self.broken = 0 - self.newline() - - def add(self, item): - item.insert(self) - - def end(self): - self.width = 0 - for l in self.lines: - l.end() - if self.width < l.width: - self.width = l.width - - def breaks(self, _): - return self.all and self.broken - - def newline(self): - self.lines.append(PrettyLine()) - - def addtoline(self, x): - self.lines[-1].write(x) - - def prettyprint(self, line): - self.indent = line.used - line.block = self - if not line.fits(self.width): - self.broken = 1 - for l in self.lines: - l.prettyprint(line) - line.block = self.parent - - def show(self, out): - print >> out, ('(BLOCK (width %d) (indent %d) (all %d) (broken %d)' % - (self.width, self.indent, self.all, self.broken)) - for l in self.lines: - l.show(out) - print >> out, ')' - -class Line: - - def __init__(self, out, width): - self.block = None - self.out = out - self.width = width - self.used = 0 - self.space = self.width - - def newline(self, indent): - indent += self.block.indent - self.out.write('\n') - self.out.write(' ' * indent) - self.used = indent - self.space = self.width - self.used - - def fits(self, n): - return self.space - n >= 0 - - def breaks(self, n): - return self.block.breaks(n) or not self.fits(n) - - def output(self, x): - n = x.get_width() - self.space -= n - self.used += n - if self.space < 0: - self.space = 0 - x.output(self.out) - -class PrettyPrinter: - """A prettyprinter based on what I remember of Derek Oppen's - prettyprint algorithm from TOPLAS way back. - """ - - def __init__(self, width=40): - self.width = width - self.block = None - self.top = None - - def write(self, x): - self.block.add(PrettyString(x)) - - def add(self, item): - self.block.add(item) - - def addbreak(self, width=1, indent=4): - self.add(PrettyBreak(width, indent)) - - def addspace(self, width=1): - self.add(PrettySpace(width)) - - def addnl(self, indent=0): - self.add(PrettyNewline(indent)) - - def begin(self, all=0): - block = PrettyBlock(all=all, parent=self.block) - self.block = block - - def end(self): - self.block.end() - if self.block.parent: - self.block.parent.add(self.block) - else: - self.top = self.block - self.block = self.block.parent - - def prettyprint(self, out=sys.stdout): - self.top.prettyprint(Line(out, self.width)) - -class SXPPrettyPrinter(PrettyPrinter): - """An SXP prettyprinter. - """ - - def pstring(self, x): - io = StringIO.StringIO() - sxp.show(x, out=io) - io.seek(0) - val = io.getvalue() - io.close() - return val - - def pprint(self, l): - if isinstance(l, types.ListType): - self.begin(all=1) - self.write('(') - i = 0 - for x in l: - if(i): self.addbreak() - self.pprint(x) - i += 1 - self.addbreak(width=0, indent=0) - self.write(')') - self.end() - else: - self.write(self.pstring(l)) - -def prettyprint(sxpr, out=sys.stdout, width=80): - """Prettyprint an SXP form. - - sxpr s-expression - out destination - width maximum output width - """ - if isinstance(sxpr, types.ListType): - pp = SXPPrettyPrinter(width=width) - pp.pprint(sxpr) - pp.prettyprint(out=out) - else: - sxp.show(sxpr, out=out) - print >> out - -def prettyprintstring(sxpr, width=80): - """Prettyprint an SXP form to a string. - - sxpr s-expression - width maximum output width - """ - io = StringIO.StringIO() - prettyprint(sxpr, out=io, width=width) - io.seek(0) - val = io.getvalue() - io.close() - return val - -def main(): - pin = sxp.Parser() - while 1: - buf = sys.stdin.read(100) - pin.input(buf) - if buf == '': break - l = pin.get_val() - prettyprint(l, width=80) - -if __name__ == "__main__": - main() - diff --git a/tools/python/xen/xend/Vifctl.py b/tools/python/xen/xend/Vifctl.py deleted file mode 100644 index 58d4ae7c1e..0000000000 --- a/tools/python/xen/xend/Vifctl.py +++ /dev/null @@ -1,35 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2005 XenSource Ltd -#============================================================================ - -"""Xend interface to networking control scripts. -""" - -import XendOptions -from xen.util import xpopen - -def network(op): - """Call a network control script. - - @param op: operation (start, stop) - """ - if op not in ['start', 'stop']: - raise ValueError('Invalid operation: ' + op) - script = XendOptions.instance().get_network_script() - if script: - script.insert(1, op) - xpopen.call(script) diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py deleted file mode 100644 index 359a26b7da..0000000000 --- a/tools/python/xen/xend/XendAPI.py +++ /dev/null @@ -1,2812 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2006-2007 XenSource Ltd. -#============================================================================ - -import inspect -import os -import Queue -import string -import sys -import traceback -import threading -import time -import xmlrpclib - -# sets is deprecated as of python 2.6, but set is unavailable in 2.3 -try: - set -except NameError: - from sets import Set as set - -import XendDomain, XendDomainInfo, XendNode, XendDmesg -import XendLogging, XendTaskManager, XendAPIStore - -from xen.xend import uuid as genuuid -from XendAPIVersion import * -from XendAuthSessions import instance as auth_manager -from XendError import * -from XendClient import ERROR_INVALID_DOMAIN -from XendLogging import log -from XendNetwork import XendNetwork -from XendTask import XendTask -from XendPIFMetrics import XendPIFMetrics -from XendVMMetrics import XendVMMetrics -from XendPIF import XendPIF -from XendPBD import XendPBD -from XendPPCI import XendPPCI -from XendDPCI import XendDPCI -from XendPSCSI import XendPSCSI, XendPSCSI_HBA -from XendDSCSI import XendDSCSI, XendDSCSI_HBA -from XendXSPolicy import XendXSPolicy, XendACMPolicy -from xen.xend.XendCPUPool import XendCPUPool - -from XendAPIConstants import * -from xen.util.xmlrpclib2 import stringify - -from xen.util.blkif import blkdev_name_to_number -from xen.util import xsconstants - - -AUTH_NONE = 'none' -AUTH_PAM = 'pam' - -argcounts = {} - -# ------------------------------------------ -# Utility Methods for Xen API Implementation -# ------------------------------------------ - -def xen_api_success(value): - """Wraps a return value in XenAPI format.""" - if value is None: - s = '' - else: - s = stringify(value) - return {"Status": "Success", "Value": s} - -def xen_api_success_void(): - """Return success, but caller expects no return value.""" - return xen_api_success("") - -def xen_api_error(error): - """Wraps an error value in XenAPI format.""" - if type(error) == tuple: - error = list(error) - if type(error) != list: - error = [error] - if len(error) == 0: - error = ['INTERNAL_ERROR', 'Empty list given to xen_api_error'] - - return { "Status": "Failure", - "ErrorDescription": [str(x) for x in error] } - - -def xen_api_todo(): - """Temporary method to make sure we track down all the TODOs""" - return {"Status": "Error", "ErrorDescription": XEND_ERROR_TODO} - - -def now(): - return datetime() - - -def datetime(when = None): - """Marshall the given time as a Xen-API DateTime. - - @param when The time in question, given as seconds since the epoch, UTC. - May be None, in which case the current time is used. - """ - if when is None: - return xmlrpclib.DateTime(time.gmtime()) - else: - return xmlrpclib.DateTime(time.gmtime(when)) - - -# --------------------------------------------------- -# Event dispatch -# --------------------------------------------------- - -EVENT_QUEUE_LENGTH = 50 -event_registrations = {} - -def event_register(session, reg_classes): - if session not in event_registrations: - event_registrations[session] = { - 'classes' : set(), - 'queue' : Queue.Queue(EVENT_QUEUE_LENGTH), - 'next-id' : 1 - } - if not reg_classes: - reg_classes = classes - sessionclasses = event_registrations[session]['classes'] - if hasattr(sessionclasses, 'union_update'): - sessionclasses.union_update(reg_classes) - else: - sessionclasses.update(reg_classes) - - - -def event_unregister(session, unreg_classes): - if session not in event_registrations: - return - - if unreg_classes: - event_registrations[session]['classes'].intersection_update( - unreg_classes) - if len(event_registrations[session]['classes']) == 0: - del event_registrations[session] - else: - del event_registrations[session] - - -def event_next(session): - if session not in event_registrations: - return xen_api_error(['SESSION_NOT_REGISTERED', session]) - queue = event_registrations[session]['queue'] - events = [queue.get()] - try: - while True: - events.append(queue.get(False)) - except Queue.Empty: - pass - - return xen_api_success(events) - - -def _ctor_event_dispatch(xenapi, ctor, api_cls, session, args): - result = ctor(xenapi, session, *args) - if result['Status'] == 'Success': - ref = result['Value'] - event_dispatch('add', api_cls, ref, '') - return result - - -def _dtor_event_dispatch(xenapi, dtor, api_cls, session, ref, args): - result = dtor(xenapi, session, ref, *args) - if result['Status'] == 'Success': - event_dispatch('del', api_cls, ref, '') - return result - - -def _setter_event_dispatch(xenapi, setter, api_cls, attr_name, session, ref, - args): - result = setter(xenapi, session, ref, *args) - if result['Status'] == 'Success': - event_dispatch('mod', api_cls, ref, attr_name) - return result - - -def event_dispatch(operation, api_cls, ref, attr_name): - assert operation in ['add', 'del', 'mod'] - event = { - 'timestamp' : now(), - 'class' : api_cls, - 'operation' : operation, - 'ref' : ref, - 'obj_uuid' : ref, - 'field' : attr_name, - } - for reg in event_registrations.values(): - if api_cls in reg['classes']: - event['id'] = reg['next-id'] - reg['next-id'] += 1 - reg['queue'].put(event) - - -# --------------------------------------------------- -# Python Method Decorators for input value validation -# --------------------------------------------------- - -def trace(func, api_name = ''): - """Decorator to trace XMLRPC Xen API methods. - - @param func: function with any parameters - @param api_name: name of the api call for debugging. - """ - if hasattr(func, 'api'): - api_name = func.api - def trace_func(self, *args, **kwargs): - log.debug('%s: %s' % (api_name, args)) - return func(self, *args, **kwargs) - trace_func.api = api_name - return trace_func - - -def catch_typeerror(func): - """Decorator to catch any TypeErrors and translate them into Xen-API - errors. - - @param func: function with params: (self, ...) - @rtype: callable object - """ - def f(self, *args, **kwargs): - try: - return func(self, *args, **kwargs) - except TypeError, exn: - #log.exception('catch_typeerror') - if hasattr(func, 'api') and func.api in argcounts: - # Assume that if the argument count was wrong and if the - # exception was thrown inside this file, then it is due to an - # invalid call from the client, otherwise it's an internal - # error (which will be handled further up). - expected = argcounts[func.api] - actual = len(args) + len(kwargs) - if expected != actual: - tb = sys.exc_info()[2] - try: - sourcefile = traceback.extract_tb(tb)[-1][0] - if sourcefile == inspect.getsourcefile(XendAPI): - return xen_api_error( - ['MESSAGE_PARAMETER_COUNT_MISMATCH', - func.api, expected, actual]) - finally: - del tb - raise - except XendAPIError, exn: - return xen_api_error(exn.get_api_error()) - - return f - - -def session_required(func): - """Decorator to verify if session is valid before calling method. - - @param func: function with params: (self, session, ...) - @rtype: callable object - """ - def check_session(self, session, *args, **kwargs): - if auth_manager().is_session_valid(session): - return func(self, session, *args, **kwargs) - else: - return xen_api_error(['SESSION_INVALID', session]) - - return check_session - - -def _is_valid_ref(ref, validator): - return type(ref) == str and validator(ref) - -def _check_ref(validator, clas, func, api, session, ref, *args, **kwargs): - if _is_valid_ref(ref, validator): - return func(api, session, ref, *args, **kwargs) - else: - return xen_api_error(['HANDLE_INVALID', clas, ref]) - - -def valid_host(func): - """Decorator to verify if host_ref is valid before calling method. - - @param func: function with params: (self, session, host_ref, ...) - @rtype: callable object - """ - return lambda *args, **kwargs: \ - _check_ref(XendNode.instance().is_valid_host, - 'host', func, *args, **kwargs) - -def valid_host_metrics(func): - """Decorator to verify if host_metrics_ref is valid before calling - method. - - @param func: function with params: (self, session, host_metrics_ref) - @rtype: callable object - """ - return lambda *args, **kwargs: \ - _check_ref(lambda r: r == XendNode.instance().host_metrics_uuid, - 'host_metrics', func, *args, **kwargs) - -def valid_host_cpu(func): - """Decorator to verify if host_cpu_ref is valid before calling method. - - @param func: function with params: (self, session, host_cpu_ref, ...) - @rtype: callable object - """ - return lambda *args, **kwargs: \ - _check_ref(XendNode.instance().is_valid_cpu, - 'host_cpu', func, *args, **kwargs) - -def valid_vm(func): - """Decorator to verify if vm_ref is valid before calling method. - - @param func: function with params: (self, session, vm_ref, ...) - @rtype: callable object - """ - return lambda *args, **kwargs: \ - _check_ref(XendDomain.instance().is_valid_vm, - 'VM', func, *args, **kwargs) - -def valid_vbd(func): - """Decorator to verify if vbd_ref is valid before calling method. - - @param func: function with params: (self, session, vbd_ref, ...) - @rtype: callable object - """ - return lambda *args, **kwargs: \ - _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r), - 'VBD', func, *args, **kwargs) - -def valid_vbd_metrics(func): - """Decorator to verify if ref is valid before calling method. - - @param func: function with params: (self, session, ref, ...) - @rtype: callable object - """ - return lambda *args, **kwargs: \ - _check_ref(lambda r: XendDomain.instance().is_valid_dev('vbd', r), - 'VBD_metrics', func, *args, **kwargs) - -def valid_vif(func): - """Decorator to verify if vif_ref is valid before calling method. - - @param func: function with params: (self, session, vif_ref, ...) - @rtype: callable object - """ - return lambda *args, **kwargs: \ - _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r), - 'VIF', func, *args, **kwargs) - -def valid_vif_metrics(func): - """Decorator to verify if ref is valid before calling method. - - @param func: function with params: (self, session, ref, ...) - @rtype: callable object - """ - return lambda *args, **kwargs: \ - _check_ref(lambda r: XendDomain.instance().is_valid_dev('vif', r), - 'VIF_metrics', func, *args, **kwargs) - -def valid_vdi(func): - """Decorator to verify if vdi_ref is valid before calling method. - - @param func: function with params: (self, session, vdi_ref, ...) - @rtype: callable object - """ - return lambda *args, **kwargs: \ - _check_ref(XendNode.instance().is_valid_vdi, - 'VDI', func, *args, **kwargs) - -def valid_console(func): - """Decorator to verify if console_ref is valid before calling method. - - @param func: function with params: (self, session, console_ref, ...) - @rtype: callable object - """ - return lambda *args, **kwargs: \ - _check_ref(lambda r: XendDomain.instance().is_valid_dev('console', - r), - 'console', func, *args, **kwargs) - -def valid_sr(func): - """Decorator to verify if sr_ref is valid before calling method. - - @param func: function with params: (self, session, sr_ref, ...) - @rtype: callable object - """ - return lambda *args, **kwargs: \ - _check_ref(lambda r: XendNode.instance().is_valid_sr, - 'SR', func, *args, **kwargs) - -def valid_task(func): - """Decorator to verify if task_ref is valid before calling - method. - - @param func: function with params: (self, session, task_ref) - @rtype: callable object - """ - return lambda *args, **kwargs: \ - _check_ref(XendTaskManager.get_task, - 'task', func, *args, **kwargs) - -def valid_debug(func): - """Decorator to verify if task_ref is valid before calling - method. - - @param func: function with params: (self, session, task_ref) - @rtype: callable object - """ - return lambda *args, **kwargs: \ - _check_ref(lambda r: r in XendAPI._debug, - 'debug', func, *args, **kwargs) - - -def valid_object(class_name): - """Decorator to verify if object is valid before calling - method. - - @param func: function with params: (self, session, pif_ref) - @rtype: callable object - """ - return lambda func: \ - lambda *args, **kwargs: \ - _check_ref(lambda r: \ - XendAPIStore.get(r, class_name) is not None, - class_name, func, *args, **kwargs) - -# ----------------------------- -# Bridge to Legacy XM API calls -# ----------------------------- - -def do_vm_func(fn_name, vm_ref, *args, **kwargs): - """Helper wrapper func to abstract away from repetitive code. - - @param fn_name: function name for XendDomain instance - @type fn_name: string - @param vm_ref: vm_ref - @type vm_ref: string - @param *args: more arguments - @type *args: tuple - """ - try: - xendom = XendDomain.instance() - fn = getattr(xendom, fn_name) - xendom.do_legacy_api_with_uuid(fn, vm_ref, *args, **kwargs) - return xen_api_success_void() - except VMBadState, exn: - return xen_api_error(['VM_BAD_POWER_STATE', vm_ref, exn.expected, - exn.actual]) - - -classes = { - 'session' : None, - 'event' : None, - 'host' : valid_host, - 'host_cpu' : valid_host_cpu, - 'host_metrics' : valid_host_metrics, - 'VM' : valid_vm, - 'VBD' : valid_vbd, - 'VBD_metrics' : valid_vbd_metrics, - 'VIF' : valid_vif, - 'VIF_metrics' : valid_vif_metrics, - 'VDI' : valid_vdi, - 'console' : valid_console, - 'SR' : valid_sr, - 'task' : valid_task, - 'XSPolicy' : valid_object("XSPolicy"), - 'ACMPolicy' : valid_object("ACMPolicy"), - 'debug' : valid_debug, - 'network' : valid_object("network"), - 'PIF' : valid_object("PIF"), - 'VM_metrics' : valid_object("VM_metrics"), - 'PBD' : valid_object("PBD"), - 'PIF_metrics' : valid_object("PIF_metrics"), - 'PPCI' : valid_object("PPCI"), - 'DPCI' : valid_object("DPCI"), - 'PSCSI' : valid_object("PSCSI"), - 'PSCSI_HBA' : valid_object("PSCSI_HBA"), - 'DSCSI' : valid_object("DSCSI"), - 'DSCSI_HBA' : valid_object("DSCSI_HBA"), - 'cpu_pool' : valid_object("cpu_pool"), -} - -autoplug_classes = { - 'network' : XendNetwork, - 'PIF' : XendPIF, - 'VM_metrics' : XendVMMetrics, - 'PBD' : XendPBD, - 'PIF_metrics' : XendPIFMetrics, - 'PPCI' : XendPPCI, - 'DPCI' : XendDPCI, - 'PSCSI' : XendPSCSI, - 'PSCSI_HBA' : XendPSCSI_HBA, - 'DSCSI' : XendDSCSI, - 'DSCSI_HBA' : XendDSCSI_HBA, - 'XSPolicy' : XendXSPolicy, - 'ACMPolicy' : XendACMPolicy, - 'cpu_pool' : XendCPUPool, -} - -class XendAPI(object): - """Implementation of the Xen-API in Xend. Expects to be - used via XMLRPCServer. - - All methods that need a valid session are marked with - a L{session_required} decorator that will - transparently perform the required session authentication. - - We need to support Python <2.4, so we use the old decorator syntax. - - All XMLRPC accessible methods require an 'api' attribute and - is set to the XMLRPC function name which the method implements. - """ - - __decorated__ = False - __init_lock__ = threading.Lock() - _debug = {} - - def __new__(cls, *args, **kwds): - """ Override __new__ to decorate the class only once. - - Lock to make sure the classes are not decorated twice. - """ - cls.__init_lock__.acquire() - try: - if not cls.__decorated__: - cls._decorate() - cls.__decorated__ = True - - return object.__new__(cls, *args, **kwds) - finally: - cls.__init_lock__.release() - - def _decorate(cls): - """ Decorate all the object methods to have validators - and appropriate function attributes. - - This should only be executed once for the duration of the - server. - """ - global_validators = [session_required, catch_typeerror] - - - # Cheat methods - # ------------- - # Methods that have a trivial implementation for all classes. - # 1. get_by_uuid == getting by ref, so just return uuid for - # all get_by_uuid() methods. - - for api_cls in classes.keys(): - # We'll let the autoplug classes implement these functions - # themselves - its much cleaner to do it in the base class - if api_cls == 'session' or api_cls in autoplug_classes.keys(): - continue - - get_by_uuid = '%s_get_by_uuid' % api_cls - get_uuid = '%s_get_uuid' % api_cls - get_all_records = '%s_get_all_records' % api_cls - - def _get_by_uuid(_1, _2, ref): - return xen_api_success(ref) - - def _get_uuid(_1, _2, ref): - return xen_api_success(ref) - - def unpack(v): - return v.get('Value') - - def _get_all_records(_api_cls): - return lambda s, session: \ - xen_api_success(dict([(ref, unpack(getattr(cls, '%s_get_record' % _api_cls)(s, session, ref)))\ - for ref in unpack(getattr(cls, '%s_get_all' % _api_cls)(s, session))])) - - setattr(cls, get_by_uuid, _get_by_uuid) - setattr(cls, get_uuid, _get_uuid) - setattr(cls, get_all_records, _get_all_records(api_cls)) - - # Autoplugging classes - # -------------------- - # These have all of their methods grabbed out from the implementation - # class, and wrapped up to be compatible with the Xen-API. - - def getter(ref, type): - return XendAPIStore.get(ref, type) - - for api_cls, impl_cls in autoplug_classes.items(): - def doit(n): - dot_n = '%s.%s' % (api_cls, n) - full_n = '%s_%s' % (api_cls, n) - if not hasattr(cls, full_n): - f = getattr(impl_cls, n) - argcounts[dot_n] = f.func_code.co_argcount + 1 - g = lambda api_cls: \ - setattr(cls, full_n, \ - lambda s, session, ref, *args: \ - xen_api_success( \ - f(getter(ref, api_cls), *args))) - g(api_cls) # Force api_cls to be captured - - def doit_func(n): - dot_n = '%s.%s' % (api_cls, n) - full_n = '%s_%s' % (api_cls, n) - if not hasattr(cls, full_n): - f = getattr(impl_cls, n) - argcounts[dot_n] = f.func_code.co_argcount - setattr(cls, full_n, \ - lambda s, session, *args: \ - xen_api_success( \ - f(*args))) - - ro_attrs = impl_cls.getAttrRO() - rw_attrs = impl_cls.getAttrRW() - methods = impl_cls.getMethods() - funcs = impl_cls.getFuncs() - - for attr_name in ro_attrs + rw_attrs: - doit('get_%s' % attr_name) - for attr_name in rw_attrs: - doit('set_%s' % attr_name) - for method in methods: - doit('%s' % method) - for func in funcs: - doit_func('%s' % func) - - def wrap_method(name, new_f): - try: - f = getattr(cls, name) - wrapped_f = (lambda *args: new_f(f, *args)) - wrapped_f.api = f.api - wrapped_f.async = f.async - setattr(cls, name, wrapped_f) - except AttributeError: - # Logged below (API call: %s not found) - pass - - - def setter_event_wrapper(api_cls, attr_name): - setter_name = '%s_set_%s' % (api_cls, attr_name) - wrap_method( - setter_name, - lambda setter, s, session, ref, *args: - _setter_event_dispatch(s, setter, api_cls, attr_name, - session, ref, args)) - - - def ctor_event_wrapper(api_cls): - ctor_name = '%s_create' % api_cls - wrap_method( - ctor_name, - lambda ctor, s, session, *args: - _ctor_event_dispatch(s, ctor, api_cls, session, args)) - - - def dtor_event_wrapper(api_cls): - dtor_name = '%s_destroy' % api_cls - wrap_method( - dtor_name, - lambda dtor, s, session, ref, *args: - _dtor_event_dispatch(s, dtor, api_cls, session, ref, args)) - - - # Wrapping validators around XMLRPC calls - # --------------------------------------- - - for api_cls, validator in classes.items(): - def doit(n, takes_instance, async_support = False, - return_type = None): - n_ = n.replace('.', '_') - try: - f = getattr(cls, n_) - if n not in argcounts: - argcounts[n] = f.func_code.co_argcount - 1 - - validators = takes_instance and validator and \ - [validator] or [] - - validators += global_validators - for v in validators: - f = v(f) - f.api = n - f.async = async_support - if return_type: - f.return_type = return_type - - setattr(cls, n_, f) - except AttributeError: - log.warn("API call: %s not found" % n) - - if api_cls in autoplug_classes.keys(): - impl_cls = autoplug_classes[api_cls] - ro_attrs = impl_cls.getAttrRO() - rw_attrs = impl_cls.getAttrRW() - methods = map(lambda x: (x, ""), impl_cls.getMethods()) - funcs = map(lambda x: (x, ""), impl_cls.getFuncs()) - else: - ro_attrs = getattr(cls, '%s_attr_ro' % api_cls, []) \ - + cls.Base_attr_ro - rw_attrs = getattr(cls, '%s_attr_rw' % api_cls, []) \ - + cls.Base_attr_rw - methods = getattr(cls, '%s_methods' % api_cls, []) \ - + cls.Base_methods - funcs = getattr(cls, '%s_funcs' % api_cls, []) \ - + cls.Base_funcs - - # wrap validators around readable class attributes - for attr_name in ro_attrs + rw_attrs: - doit('%s.get_%s' % (api_cls, attr_name), True, - async_support = False) - - # wrap validators around writable class attrributes - for attr_name in rw_attrs: - doit('%s.set_%s' % (api_cls, attr_name), True, - async_support = False) - setter_event_wrapper(api_cls, attr_name) - - # wrap validators around methods - for method_name, return_type in methods: - doit('%s.%s' % (api_cls, method_name), True, - async_support = True) - - # wrap validators around class functions - for func_name, return_type in funcs: - doit('%s.%s' % (api_cls, func_name), False, - async_support = True, - return_type = return_type) - - ctor_event_wrapper(api_cls) - dtor_event_wrapper(api_cls) - - - _decorate = classmethod(_decorate) - - def __init__(self, auth): - self.auth = auth - - Base_attr_ro = ['uuid'] - Base_attr_rw = [] - Base_methods = [('get_record', 'Struct')] - Base_funcs = [('get_all', 'Set'), ('get_by_uuid', None), ('get_all_records', 'Set')] - - # Xen API: Class Session - # ---------------------------------------------------------------- - # NOTE: Left unwrapped by __init__ - - session_attr_ro = ['this_host', 'this_user', 'last_active'] - session_methods = [('logout', None)] - - def session_get_all(self, session): - return xen_api_success([session]) - - def session_login_with_password(self, *args): - if len(args) != 2: - return xen_api_error( - ['MESSAGE_PARAMETER_COUNT_MISMATCH', - 'session.login_with_password', 2, len(args)]) - username = args[0] - password = args[1] - try: - session = ((self.auth == AUTH_NONE and - auth_manager().login_unconditionally(username)) or - auth_manager().login_with_password(username, password)) - return xen_api_success(session) - except XendError, e: - return xen_api_error(['SESSION_AUTHENTICATION_FAILED']) - session_login_with_password.api = 'session.login_with_password' - - # object methods - def session_logout(self, session): - auth_manager().logout(session) - return xen_api_success_void() - - def session_get_record(self, session, self_session): - if self_session != session: - return xen_api_error(['PERMISSION_DENIED']) - record = {'uuid' : session, - 'this_host' : XendNode.instance().uuid, - 'this_user' : auth_manager().get_user(session), - 'last_active': now()} - return xen_api_success(record) - - def session_get_uuid(self, session, self_session): - return xen_api_success(self_session) - - def session_get_by_uuid(self, session, self_session): - return xen_api_success(self_session) - - # attributes (ro) - def session_get_this_host(self, session, self_session): - if self_session != session: - return xen_api_error(['PERMISSION_DENIED']) - return xen_api_success(XendNode.instance().uuid) - - def session_get_this_user(self, session, self_session): - if self_session != session: - return xen_api_error(['PERMISSION_DENIED']) - user = auth_manager().get_user(session) - if user is not None: - return xen_api_success(user) - return xen_api_error(['SESSION_INVALID', session]) - - def session_get_last_active(self, session, self_session): - if self_session != session: - return xen_api_error(['PERMISSION_DENIED']) - return xen_api_success(now()) - - - # Xen API: Class User - # ---------------------------------------------------------------- - # TODO: NOT IMPLEMENTED YET - - # Xen API: Class Tasks - # ---------------------------------------------------------------- - - task_attr_ro = ['name_label', - 'name_description', - 'status', - 'progress', - 'type', - 'result', - 'error_info', - 'allowed_operations', - 'session' - ] - - task_attr_rw = [] - - task_funcs = [('get_by_name_label', 'Set(task)'), - ('cancel', None)] - - def task_get_name_label(self, session, task_ref): - task = XendTaskManager.get_task(task_ref) - return xen_api_success(task.name_label) - - def task_get_name_description(self, session, task_ref): - task = XendTaskManager.get_task(task_ref) - return xen_api_success(task.name_description) - - def task_get_status(self, session, task_ref): - task = XendTaskManager.get_task(task_ref) - return xen_api_success(task.get_status()) - - def task_get_progress(self, session, task_ref): - task = XendTaskManager.get_task(task_ref) - return xen_api_success(task.progress) - - def task_get_type(self, session, task_ref): - task = XendTaskManager.get_task(task_ref) - return xen_api_success(task.type) - - def task_get_result(self, session, task_ref): - task = XendTaskManager.get_task(task_ref) - return xen_api_success(task.result) - - def task_get_error_info(self, session, task_ref): - task = XendTaskManager.get_task(task_ref) - return xen_api_success(task.error_info) - - def task_get_allowed_operations(self, session, task_ref): - return xen_api_success({}) - - def task_get_session(self, session, task_ref): - task = XendTaskManager.get_task(task_ref) - return xen_api_success(task.session) - - def task_get_all(self, session): - tasks = XendTaskManager.get_all_tasks() - return xen_api_success(tasks) - - def task_get_record(self, session, task_ref): - task = XendTaskManager.get_task(task_ref) - return xen_api_success(task.get_record()) - - def task_cancel(self, session, task_ref): - return xen_api_error('OPERATION_NOT_ALLOWED') - - def task_get_by_name_label(self, session, name): - return xen_api_success(XendTaskManager.get_task_by_name(name)) - - # Xen API: Class host - # ---------------------------------------------------------------- - - host_attr_ro = ['software_version', - 'resident_VMs', - 'PBDs', - 'PIFs', - 'PPCIs', - 'PSCSIs', - 'PSCSI_HBAs', - 'host_CPUs', - 'cpu_configuration', - 'metrics', - 'capabilities', - 'supported_bootloaders', - 'sched_policy', - 'API_version_major', - 'API_version_minor', - 'API_version_vendor', - 'API_version_vendor_implementation', - 'enabled', - 'resident_cpu_pools'] - - host_attr_rw = ['name_label', - 'name_description', - 'other_config', - 'logging'] - - host_methods = [('disable', None), - ('enable', None), - ('reboot', None), - ('shutdown', None), - ('add_to_other_config', None), - ('remove_from_other_config', None), - ('dmesg', 'String'), - ('dmesg_clear', 'String'), - ('get_log', 'String'), - ('send_debug_keys', None), - ('tmem_thaw', None), - ('tmem_freeze', None), - ('tmem_flush', None), - ('tmem_destroy', None), - ('tmem_list', None), - ('tmem_set_weight', None), - ('tmem_set_cap', None), - ('tmem_set_compress', None), - ('tmem_query_freeable_mb', None), - ('tmem_shared_auth', None)] - - host_funcs = [('get_by_name_label', None), - ('list_methods', None)] - - # attributes - def host_get_name_label(self, session, host_ref): - return xen_api_success(XendNode.instance().name) - def host_set_name_label(self, session, host_ref, new_name): - XendNode.instance().set_name(new_name) - return xen_api_success_void() - def host_get_name_description(self, session, host_ref): - return xen_api_success(XendNode.instance().get_description()) - def host_set_name_description(self, session, host_ref, new_desc): - XendNode.instance().set_description(new_desc) - return xen_api_success_void() - def host_get_other_config(self, session, host_ref): - return xen_api_success(XendNode.instance().other_config) - def host_set_other_config(self, session, host_ref, other_config): - node = XendNode.instance() - node.other_config = dict(other_config) - node.save() - return xen_api_success_void() - def host_add_to_other_config(self, session, host_ref, key, value): - node = XendNode.instance() - node.other_config[key] = value - node.save() - return xen_api_success_void() - def host_remove_from_other_config(self, session, host_ref, key): - node = XendNode.instance() - if key in node.other_config: - del node.other_config[key] - node.save() - return xen_api_success_void() - def host_get_API_version_major(self, _, ref): - return xen_api_success(XEN_API_VERSION_MAJOR) - def host_get_API_version_minor(self, _, ref): - return xen_api_success(XEN_API_VERSION_MINOR) - def host_get_API_version_vendor(self, _, ref): - return xen_api_success(XEN_API_VERSION_VENDOR) - def host_get_API_version_vendor_implementation(self, _, ref): - return xen_api_success(XEN_API_VERSION_VENDOR_IMPLEMENTATION) - def host_get_software_version(self, session, host_ref): - return xen_api_success(XendNode.instance().xen_version()) - def host_get_enabled(self, _1, _2): - return xen_api_success(XendDomain.instance().allow_new_domains()) - def host_get_resident_VMs(self, session, host_ref): - return xen_api_success(XendDomain.instance().get_domain_refs()) - def host_get_PBDs(self, _, ref): - return xen_api_success(XendPBD.get_all()) - def host_get_PIFs(self, session, ref): - return xen_api_success(XendNode.instance().get_PIF_refs()) - def host_get_PPCIs(self, session, ref): - return xen_api_success(XendNode.instance().get_PPCI_refs()) - def host_get_PSCSIs(self, session, ref): - return xen_api_success(XendNode.instance().get_PSCSI_refs()) - def host_get_PSCSI_HBAs(self, session, ref): - return xen_api_success(XendNode.instance().get_PSCSI_HBA_refs()) - def host_get_host_CPUs(self, session, host_ref): - return xen_api_success(XendNode.instance().get_host_cpu_refs()) - def host_get_metrics(self, _, ref): - return xen_api_success(XendNode.instance().host_metrics_uuid) - def host_get_capabilities(self, session, host_ref): - return xen_api_success(XendNode.instance().get_capabilities()) - def host_get_supported_bootloaders(self, session, host_ref): - return xen_api_success(['pygrub']) - def host_get_sched_policy(self, _, host_ref): - return xen_api_success(XendNode.instance().get_vcpus_policy()) - def host_get_cpu_configuration(self, _, host_ref): - return xen_api_success(XendNode.instance().get_cpu_configuration()) - def host_set_logging(self, _, host_ref, logging): - return xen_api_todo() - def host_get_logging(self, _, host_ref): - return xen_api_todo() - def host_get_resident_cpu_pools(self, _, host_ref): - return xen_api_success(XendCPUPool.get_all()) - - # object methods - def host_disable(self, session, host_ref): - XendDomain.instance().set_allow_new_domains(False) - return xen_api_success_void() - def host_enable(self, session, host_ref): - XendDomain.instance().set_allow_new_domains(True) - return xen_api_success_void() - def host_reboot(self, session, host_ref): - if not XendDomain.instance().allow_new_domains(): - return xen_api_error(XEND_ERROR_HOST_RUNNING) - return xen_api_error(XEND_ERROR_UNSUPPORTED) - def host_shutdown(self, session, host_ref): - if not XendDomain.instance().allow_new_domains(): - return xen_api_error(XEND_ERROR_HOST_RUNNING) - return xen_api_error(XEND_ERROR_UNSUPPORTED) - - def host_dmesg(self, session, host_ref): - return xen_api_success(XendDmesg.instance().info()) - - def host_dmesg_clear(self, session, host_ref): - return xen_api_success(XendDmesg.instance().clear()) - - def host_get_log(self, session, host_ref): - log_file = open(XendLogging.getLogFilename()) - log_buffer = log_file.read() - log_buffer = log_buffer.replace('\b', ' ') - log_buffer = log_buffer.replace('\f', '\n') - log_file.close() - return xen_api_success(log_buffer) - - def host_send_debug_keys(self, _, host_ref, keys): - node = XendNode.instance() - node.send_debug_keys(keys) - return xen_api_success_void() - - def host_get_record(self, session, host_ref): - node = XendNode.instance() - dom = XendDomain.instance() - record = {'uuid': node.uuid, - 'name_label': node.name, - 'name_description': '', - 'API_version_major': XEN_API_VERSION_MAJOR, - 'API_version_minor': XEN_API_VERSION_MINOR, - 'API_version_vendor': XEN_API_VERSION_VENDOR, - 'API_version_vendor_implementation': - XEN_API_VERSION_VENDOR_IMPLEMENTATION, - 'software_version': node.xen_version(), - 'enabled': XendDomain.instance().allow_new_domains(), - 'other_config': node.other_config, - 'resident_VMs': dom.get_domain_refs(), - 'host_CPUs': node.get_host_cpu_refs(), - 'cpu_configuration': node.get_cpu_configuration(), - 'metrics': node.host_metrics_uuid, - 'capabilities': node.get_capabilities(), - 'supported_bootloaders': ['pygrub'], - 'sched_policy': node.get_vcpus_policy(), - 'logging': {}, - 'PIFs': XendPIF.get_all(), - 'PBDs': XendPBD.get_all(), - 'PPCIs': XendPPCI.get_all(), - 'PSCSIs': XendPSCSI.get_all(), - 'PSCSI_HBAs': XendPSCSI_HBA.get_all(), - 'resident_cpu_pools': XendCPUPool.get_all(), - } - return xen_api_success(record) - - def host_tmem_thaw(self, _, host_ref, cli_id): - node = XendNode.instance() - try: - node.tmem_thaw(cli_id) - except Exception, e: - return xen_api_error(e) - return xen_api_success_void() - - def host_tmem_freeze(self, _, host_ref, cli_id): - node = XendNode.instance() - try: - node.tmem_freeze(cli_id) - except Exception, e: - return xen_api_error(e) - return xen_api_success_void() - - def host_tmem_flush(self, _, host_ref, cli_id, pages): - node = XendNode.instance() - try: - node.tmem_flush(cli_id, pages) - except Exception, e: - return xen_api_error(e) - return xen_api_success_void() - - def host_tmem_destroy(self, _, host_ref, cli_id): - node = XendNode.instance() - try: - node.tmem_destroy(cli_id) - except Exception, e: - return xen_api_error(e) - return xen_api_success_void() - - def host_tmem_list(self, _, host_ref, cli_id, use_long): - node = XendNode.instance() - try: - info = node.tmem_list(cli_id, use_long) - except Exception, e: - return xen_api_error(e) - return xen_api_success(info) - - def host_tmem_set_weight(self, _, host_ref, cli_id, value): - node = XendNode.instance() - try: - node.tmem_set_weight(cli_id, value) - except Exception, e: - return xen_api_error(e) - return xen_api_success_void() - - def host_tmem_set_cap(self, _, host_ref, cli_id, value): - node = XendNode.instance() - try: - node.tmem_set_cap(cli_id, value) - except Exception, e: - return xen_api_error(e) - return xen_api_success_void() - - def host_tmem_set_compress(self, _, host_ref, cli_id, value): - node = XendNode.instance() - try: - node.tmem_set_compress(cli_id, value) - except Exception, e: - return xen_api_error(e) - return xen_api_success_void() - - def host_tmem_query_freeable_mb(self, _, host_ref): - node = XendNode.instance() - try: - pages = node.tmem_query_freeable_mb() - except Exception, e: - return xen_api_error(e) - return xen_api_success(pages is None and -1 or pages) - - def host_tmem_shared_auth(self, _, host_ref, cli_id, uuid_str, auth): - node = XendNode.instance() - try: - node.tmem_shared_auth(cli_id, uuid_str, auth) - except Exception, e: - return xen_api_error(e) - return xen_api_success_void() - - # class methods - def host_get_all(self, session): - return xen_api_success((XendNode.instance().uuid,)) - def host_get_by_name_label(self, session, name): - if XendNode.instance().name == name: - return xen_api_success((XendNode.instance().uuid,)) - return xen_api_success([]) - - def host_list_methods(self, _): - def _funcs(): - return [getattr(XendAPI, x) for x in XendAPI.__dict__] - - return xen_api_success([x.api for x in _funcs() - if hasattr(x, 'api')]) - - # Xen API: Class host_CPU - # ---------------------------------------------------------------- - - host_cpu_attr_ro = ['host', - 'number', - 'vendor', - 'speed', - 'modelname', - 'stepping', - 'flags', - 'utilisation', - 'features', - 'cpu_pool'] - - host_cpu_funcs = [('get_unassigned_cpus', 'Set(host_cpu)')] - - # attributes - def _host_cpu_get(self, ref, field): - return xen_api_success( - XendNode.instance().get_host_cpu_field(ref, field)) - - def host_cpu_get_host(self, _, ref): - return xen_api_success(XendNode.instance().uuid) - def host_cpu_get_features(self, _, ref): - return self._host_cpu_get(ref, 'features') - def host_cpu_get_number(self, _, ref): - return self._host_cpu_get(ref, 'number') - def host_cpu_get_vendor(self, _, ref): - return self._host_cpu_get(ref, 'vendor') - def host_cpu_get_speed(self, _, ref): - return self._host_cpu_get(ref, 'speed') - def host_cpu_get_modelname(self, _, ref): - return self._host_cpu_get(ref, 'modelname') - def host_cpu_get_stepping(self, _, ref): - return self._host_cpu_get(ref, 'stepping') - def host_cpu_get_flags(self, _, ref): - return self._host_cpu_get(ref, 'flags') - def host_cpu_get_utilisation(self, _, ref): - return xen_api_success(XendNode.instance().get_host_cpu_load(ref)) - def host_cpu_get_cpu_pool(self, _, ref): - return xen_api_success(XendCPUPool.get_cpu_pool_by_cpu_ref(ref)) - - # object methods - def host_cpu_get_record(self, _, ref): - node = XendNode.instance() - record = dict([(f, node.get_host_cpu_field(ref, f)) - for f in self.host_cpu_attr_ro - if f not in ['uuid', 'host', 'utilisation', 'cpu_pool']]) - record['uuid'] = ref - record['host'] = node.uuid - record['utilisation'] = node.get_host_cpu_load(ref) - record['cpu_pool'] = XendCPUPool.get_cpu_pool_by_cpu_ref(ref) - return xen_api_success(record) - - # class methods - def host_cpu_get_all(self, session): - return xen_api_success(XendNode.instance().get_host_cpu_refs()) - def host_cpu_get_unassigned_cpus(self, session): - return xen_api_success( - [ref for ref in XendNode.instance().get_host_cpu_refs() - if len(XendCPUPool.get_cpu_pool_by_cpu_ref(ref)) == 0]) - - - # Xen API: Class host_metrics - # ---------------------------------------------------------------- - - host_metrics_attr_ro = ['memory_total', - 'memory_free', - 'last_updated'] - host_metrics_attr_rw = [] - host_metrics_methods = [] - - def host_metrics_get_all(self, _): - return xen_api_success([XendNode.instance().host_metrics_uuid]) - - def _host_metrics_get(self, ref, f): - return xen_api_success(getattr(node, f)()) - - def host_metrics_get_record(self, _, ref): - return xen_api_success({ - 'uuid' : ref, - 'memory_total' : self._host_metrics_get_memory_total(), - 'memory_free' : self._host_metrics_get_memory_free(), - 'last_updated' : now(), - }) - - def host_metrics_get_memory_total(self, _1, _2): - return xen_api_success(self._host_metrics_get_memory_total()) - - def host_metrics_get_memory_free(self, _1, _2): - return xen_api_success(self._host_metrics_get_memory_free()) - - def host_metrics_get_last_updated(self, _1, _2): - return xen_api_success(now()) - - def _host_metrics_get_memory_total(self): - node = XendNode.instance() - return node.xc.physinfo()['total_memory'] * 1024 - - def _host_metrics_get_memory_free(self): - node = XendNode.instance() - return node.xc.physinfo()['free_memory'] * 1024 - - # Xen API: Class VM - # ---------------------------------------------------------------- - - VM_attr_ro = ['power_state', - 'resident_on', - 'consoles', - 'VIFs', - 'VBDs', - 'DPCIs', - 'DSCSIs', - 'DSCSI_HBAs', - 'tools_version', - 'domid', - 'is_control_domain', - 'metrics', - 'crash_dumps', - 'cpu_pool', - ] - - VM_attr_rw = ['name_label', - 'name_description', - 'user_version', - 'is_a_template', - 'auto_power_on', - 'memory_dynamic_max', - 'memory_dynamic_min', - 'memory_static_max', - 'memory_static_min', - 'VCPUs_max', - 'VCPUs_at_startup', - 'VCPUs_params', - 'actions_after_shutdown', - 'actions_after_reboot', - 'actions_after_suspend', - 'actions_after_crash', - 'PV_bootloader', - 'PV_kernel', - 'PV_ramdisk', - 'PV_args', - 'PV_bootloader_args', - 'HVM_boot_policy', - 'HVM_boot_params', - 'platform', - 'PCI_bus', - 'other_config', - 'security_label', - 'pool_name', - ] - - VM_methods = [('clone', 'VM'), - ('start', None), - ('pause', None), - ('unpause', None), - ('clean_shutdown', None), - ('clean_reboot', None), - ('hard_shutdown', None), - ('hard_reboot', None), - ('suspend', None), - ('resume', None), - ('send_sysrq', None), - ('set_VCPUs_number_live', None), - ('add_to_HVM_boot_params', None), - ('remove_from_HVM_boot_params', None), - ('add_to_VCPUs_params', None), - ('add_to_VCPUs_params_live', None), - ('remove_from_VCPUs_params', None), - ('add_to_platform', None), - ('remove_from_platform', None), - ('add_to_other_config', None), - ('remove_from_other_config', None), - ('save', None), - ('set_memory_dynamic_max_live', None), - ('set_memory_dynamic_min_live', None), - ('send_trigger', None), - ('migrate', None), - ('destroy', None), - ('cpu_pool_migrate', None), - ] - - VM_funcs = [('create', 'VM'), - ('restore', None), - ('get_by_name_label', 'Set(VM)')] - - # parameters required for _create() - VM_attr_inst = [ - 'name_label', - 'name_description', - 'user_version', - 'is_a_template', - 'memory_static_max', - 'memory_dynamic_max', - 'memory_dynamic_min', - 'memory_static_min', - 'VCPUs_max', - 'VCPUs_at_startup', - 'VCPUs_params', - 'actions_after_shutdown', - 'actions_after_reboot', - 'actions_after_suspend', - 'actions_after_crash', - 'PV_bootloader', - 'PV_kernel', - 'PV_ramdisk', - 'PV_args', - 'PV_bootloader_args', - 'HVM_boot_policy', - 'HVM_boot_params', - 'platform', - 'PCI_bus', - 'other_config', - 'security_label'] - - def VM_get(self, name, session, vm_ref): - return xen_api_success( - XendDomain.instance().get_vm_by_uuid(vm_ref).info[name]) - - def VM_set(self, name, session, vm_ref, value): - xd = XendDomain.instance() - dominfo = xd.get_vm_by_uuid(vm_ref) - dominfo.info[name] = value - return self._VM_save(dominfo) - - def _VM_save(self, dominfo): - XendDomain.instance().managed_config_save(dominfo) - return xen_api_success_void() - - # attributes (ro) - def VM_get_power_state(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_power_state()) - - def VM_get_resident_on(self, session, vm_ref): - return xen_api_success(XendNode.instance().uuid) - - def VM_get_memory_static_max(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_memory_static_max()) - - def VM_get_memory_static_min(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_memory_static_min()) - - def VM_get_VIFs(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_vifs()) - - def VM_get_VBDs(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_vbds()) - - def VM_get_consoles(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_consoles()) - - def VM_get_DPCIs(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_dpcis()) - - def VM_get_DSCSIs(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_dscsis()) - - def VM_get_DSCSI_HBAs(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_dscsi_HBAs()) - - def VM_get_tools_version(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return dom.get_tools_version() - - def VM_get_metrics(self, _, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_metrics()) - - def VM_get_VCPUs_max(self, _, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() - - def VM_get_VCPUs_at_startup(self, _, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() - - # attributes (rw) - def VM_get_name_label(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.getName()) - - def VM_get_name_description(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() - - def VM_get_user_version(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() - - def VM_get_is_a_template(self, session, ref): - return self.VM_get('is_a_template', session, ref) - - def VM_get_auto_power_on(self, session, vm_ref): - return self.VM_get('auto_power_on', session, vm_ref) - - def VM_get_memory_dynamic_max(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_memory_dynamic_max()) - - def VM_get_memory_dynamic_min(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_memory_dynamic_min()) - - def VM_get_VCPUs_params(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_vcpus_params()) - - def VM_get_actions_after_shutdown(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_on_shutdown()) - - def VM_get_actions_after_reboot(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_on_reboot()) - - def VM_get_actions_after_suspend(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_on_suspend()) - - def VM_get_actions_after_crash(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_on_crash()) - - def VM_get_PV_bootloader(self, session, vm_ref): - return self.VM_get('PV_bootloader', session, vm_ref) - - def VM_get_PV_kernel(self, session, vm_ref): - return self.VM_get('PV_kernel', session, vm_ref) - - def VM_get_PV_ramdisk(self, session, vm_ref): - return self.VM_get('PV_ramdisk', session, vm_ref) - - def VM_get_PV_args(self, session, vm_ref): - return self.VM_get('PV_args', session, vm_ref) - - def VM_get_PV_bootloader_args(self, session, vm_ref): - return self.VM_get('PV_bootloader_args', session, vm_ref) - - def VM_get_HVM_boot_policy(self, session, vm_ref): - return self.VM_get('HVM_boot_policy', session, vm_ref) - - def VM_get_HVM_boot_params(self, session, vm_ref): - return self.VM_get('HVM_boot_params', session, vm_ref) - - def VM_get_platform(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_success(dom.get_platform()) - - def VM_get_PCI_bus(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return dom.get_pci_bus() - - def VM_set_PCI_bus(self, session, vm_ref, val): - return self.VM_set('PCI_bus', session, vm_ref, val) - - def VM_get_other_config(self, session, vm_ref): - return self.VM_get('other_config', session, vm_ref) - - def VM_get_domid(self, _, ref): - domid = XendDomain.instance().get_vm_by_uuid(ref).getDomid() - return xen_api_success(domid is None and -1 or domid) - - def VM_get_is_control_domain(self, session, vm_ref): - xd = XendDomain.instance() - return xen_api_success( - xd.get_vm_by_uuid(vm_ref) == xd.privilegedDomain()) - - def VM_get_cpu_pool(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - pool_ref = XendCPUPool.query_pool_ref(dom.get_cpu_pool()) - return xen_api_success(pool_ref) - - def VM_get_pool_name(self, session, vm_ref): - return self.VM_get('pool_name', session, vm_ref) - - def VM_set_pool_name(self, session, vm_ref, value): - return self.VM_set('pool_name', session, vm_ref, value) - - def VM_set_name_label(self, session, vm_ref, label): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - dom.setName(label) - return self._VM_save(dom) - - def VM_set_name_description(self, session, vm_ref, desc): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() - - def VM_set_user_version(self, session, vm_ref, ver): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() - - def VM_set_is_a_template(self, session, vm_ref, is_template): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() - - def VM_set_auto_power_on(self, session, vm_ref, val): - return self.VM_set('auto_power_on', session, vm_ref, val) - - def VM_set_memory_dynamic_max(self, session, vm_ref, mem): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - dom.set_memory_dynamic_max(int(mem)) - return self._VM_save(dom) - - def VM_set_memory_dynamic_min(self, session, vm_ref, mem): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - dom.set_memory_dynamic_min(int(mem)) - return self._VM_save(dom) - - def VM_set_memory_static_max(self, session, vm_ref, mem): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - dom.set_memory_static_max(int(mem)) - return self._VM_save(dom) - - def VM_set_memory_static_min(self, session, vm_ref, mem): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - dom.set_memory_static_min(int(mem)) - return self._VM_save(dom) - - def VM_set_memory_dynamic_max_live(self, session, vm_ref, mem): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - dom.set_memory_dynamic_max(int(mem)) - # need to pass target as MiB - dom.setMemoryTarget(int(mem)/1024/1024) - return xen_api_success_void() - - def VM_set_memory_dynamic_min_live(self, session, vm_ref, mem): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - dom.set_memory_dynamic_min(int(mem)) - # need to pass target as MiB - dom.setMemoryTarget(int(mem)/1024/1024) - return xen_api_success_void() - - def VM_set_VCPUs_params(self, session, vm_ref, value): - return self.VM_set('vcpus_params', session, vm_ref, value) - - def VM_add_to_VCPUs_params(self, session, vm_ref, key, value): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - if 'vcpus_params' not in dom.info: - dom.info['vcpus_params'] = {} - dom.info['vcpus_params'][key] = value - return self._VM_save(dom) - - def VM_add_to_VCPUs_params_live(self, session, vm_ref, key, value): - self.VM_add_to_VCPUs_params(session, vm_ref, key, value) - self._VM_VCPUs_params_refresh(vm_ref) - return xen_api_success_void() - - def _VM_VCPUs_params_refresh(self, vm_ref): - xendom = XendDomain.instance() - xeninfo = xendom.get_vm_by_uuid(vm_ref) - - #update the cpumaps - for key, value in xeninfo.info['vcpus_params'].items(): - if key.startswith("cpumap"): - vcpu = int(key[6:]) - try: - cpus = map(int, value.split(",")) - xendom.domain_pincpu(xeninfo.getDomid(), vcpu, cpus) - except Exception, ex: - log.exception(ex) - - #need to update sched params aswell - if 'weight' in xeninfo.info['vcpus_params'] \ - and 'cap' in xeninfo.info['vcpus_params']: - weight = xeninfo.info['vcpus_params']['weight'] - xendom.domain_sched_credit2_set(xeninfo.getDomid(), weight) - - def VM_set_VCPUs_number_live(self, _, vm_ref, num): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - dom.setVCpuCount(int(num)) - return xen_api_success_void() - - def VM_remove_from_VCPUs_params(self, session, vm_ref, key): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - if 'vcpus_params' in dom.info \ - and key in dom.info['vcpus_params']: - del dom.info['vcpus_params'][key] - return self._VM_save(dom) - else: - return xen_api_success_void() - - def VM_set_VCPUs_at_startup(self, session, vm_ref, num): - return self.VM_set('VCPUs_at_startup', session, vm_ref, num) - - def VM_set_VCPUs_max(self, session, vm_ref, num): - return self.VM_set('VCPUs_max', session, vm_ref, num) - - def VM_set_actions_after_shutdown(self, session, vm_ref, action): - if action not in XEN_API_ON_NORMAL_EXIT: - return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref]) - return self.VM_set('actions_after_shutdown', session, vm_ref, action) - - def VM_set_actions_after_reboot(self, session, vm_ref, action): - if action not in XEN_API_ON_NORMAL_EXIT: - return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref]) - return self.VM_set('actions_after_reboot', session, vm_ref, action) - - def VM_set_actions_after_suspend(self, session, vm_ref, action): - if action not in XEN_API_ON_NORMAL_EXIT: - return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref]) - return self.VM_set('actions_after_suspend', session, vm_ref, action) - - def VM_set_actions_after_crash(self, session, vm_ref, action): - if action not in XEN_API_ON_CRASH_BEHAVIOUR: - return xen_api_error(['VM_ON_CRASH_BEHAVIOUR_INVALID', vm_ref]) - return self.VM_set('actions_after_crash', session, vm_ref, - XEN_API_ON_CRASH_BEHAVIOUR_LEGACY[action]) - - def VM_set_HVM_boot_policy(self, session, vm_ref, value): - if value != "" and value != "BIOS order": - return xen_api_error( - ['VALUE_NOT_SUPPORTED', 'VM.HVM_boot_policy', value, - 'Xend supports only the "BIOS order" boot policy.']) - else: - return self.VM_set('HVM_boot_policy', session, vm_ref, value) - - def VM_set_HVM_boot_params(self, session, vm_ref, value): - return self.VM_set('HVM_boot_params', session, vm_ref, value) - - def VM_add_to_HVM_boot_params(self, session, vm_ref, key, value): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - if 'HVM_boot_params' not in dom.info: - dom.info['HVM_boot_params'] = {} - dom.info['HVM_boot_params'][key] = value - return self._VM_save(dom) - - def VM_remove_from_HVM_boot_params(self, session, vm_ref, key): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - if 'HVM_boot_params' in dom.info \ - and key in dom.info['HVM_boot_params']: - del dom.info['HVM_boot_params'][key] - return self._VM_save(dom) - else: - return xen_api_success_void() - - def VM_set_PV_bootloader(self, session, vm_ref, value): - return self.VM_set('PV_bootloader', session, vm_ref, value) - - def VM_set_PV_kernel(self, session, vm_ref, value): - return self.VM_set('PV_kernel', session, vm_ref, value) - - def VM_set_PV_ramdisk(self, session, vm_ref, value): - return self.VM_set('PV_ramdisk', session, vm_ref, value) - - def VM_set_PV_args(self, session, vm_ref, value): - return self.VM_set('PV_args', session, vm_ref, value) - - def VM_set_PV_bootloader_args(self, session, vm_ref, value): - return self.VM_set('PV_bootloader_args', session, vm_ref, value) - - def VM_set_platform(self, session, vm_ref, value): - return self.VM_set('platform', session, vm_ref, value) - - def VM_add_to_platform(self, session, vm_ref, key, value): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - plat = dom.get_platform() - plat[key] = value - return self.VM_set_platform(session, vm_ref, plat) - - def VM_remove_from_platform(self, session, vm_ref, key): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - plat = dom.get_platform() - if key in plat: - del plat[key] - return self.VM_set_platform(session, vm_ref, plat) - else: - return xen_api_success_void() - - def VM_set_other_config(self, session, vm_ref, value): - return self.VM_set('other_config', session, vm_ref, value) - - def VM_add_to_other_config(self, session, vm_ref, key, value): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - if dom and 'other_config' in dom.info: - dom.info['other_config'][key] = value - return self._VM_save(dom) - - def VM_remove_from_other_config(self, session, vm_ref, key): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - if dom and 'other_config' in dom.info \ - and key in dom.info['other_config']: - del dom.info['other_config'][key] - return self._VM_save(dom) - else: - return xen_api_success_void() - - def VM_get_crash_dumps(self, _, vm_ref): - return xen_api_todo() - - # class methods - def VM_get_all(self, session): - refs = [d.get_uuid() for d in XendDomain.instance().list('all')] - return xen_api_success(refs) - - def VM_get_by_name_label(self, session, label): - xendom = XendDomain.instance() - dom = xendom.domain_lookup_nr(label) - if dom: - return xen_api_success([dom.get_uuid()]) - return xen_api_success([]) - - def VM_get_security_label(self, session, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - label = dom.get_security_label() - return xen_api_success(label) - - def VM_set_security_label(self, session, vm_ref, sec_label, old_label): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - (rc, errors, oldlabel, new_ssidref) = \ - dom.set_security_label(sec_label, old_label) - if rc != xsconstants.XSERR_SUCCESS: - return xen_api_error(['SECURITY_ERROR', rc, - xsconstants.xserr2string(-rc)]) - if rc == 0: - rc = new_ssidref - return xen_api_success(rc) - - def VM_create(self, session, vm_struct): - xendom = XendDomain.instance() - domuuid = XendTask.log_progress(0, 100, - xendom.create_domain, vm_struct) - return xen_api_success(domuuid) - - # object methods - def VM_get_record(self, session, vm_ref): - xendom = XendDomain.instance() - xeninfo = xendom.get_vm_by_uuid(vm_ref) - if not xeninfo: - return xen_api_error(['HANDLE_INVALID', 'VM', vm_ref]) - - domid = xeninfo.getDomid() - - record = { - 'uuid': xeninfo.get_uuid(), - 'power_state': xeninfo.get_power_state(), - 'name_label': xeninfo.getName(), - 'name_description': xeninfo.getName(), - 'user_version': 1, - 'is_a_template': xeninfo.info['is_a_template'], - 'auto_power_on': xeninfo.info['auto_power_on'], - 'resident_on': XendNode.instance().uuid, - 'memory_static_min': xeninfo.get_memory_static_min(), - 'memory_static_max': xeninfo.get_memory_static_max(), - 'memory_dynamic_min': xeninfo.get_memory_dynamic_min(), - 'memory_dynamic_max': xeninfo.get_memory_dynamic_max(), - 'VCPUs_params': xeninfo.get_vcpus_params(), - 'VCPUs_at_startup': xeninfo.getVCpuCount(), - 'VCPUs_max': xeninfo.getVCpuCount(), - 'actions_after_shutdown': xeninfo.get_on_shutdown(), - 'actions_after_reboot': xeninfo.get_on_reboot(), - 'actions_after_suspend': xeninfo.get_on_suspend(), - 'actions_after_crash': xeninfo.get_on_crash(), - 'consoles': xeninfo.get_consoles(), - 'VIFs': xeninfo.get_vifs(), - 'VBDs': xeninfo.get_vbds(), - 'DPCIs': xeninfo.get_dpcis(), - 'DSCSIs': xeninfo.get_dscsis(), - 'DSCSI_HBAs': xeninfo.get_dscsi_HBAs(), - 'PV_bootloader': xeninfo.info.get('PV_bootloader'), - 'PV_kernel': xeninfo.info.get('PV_kernel'), - 'PV_ramdisk': xeninfo.info.get('PV_ramdisk'), - 'PV_args': xeninfo.info.get('PV_args'), - 'PV_bootloader_args': xeninfo.info.get('PV_bootloader_args'), - 'HVM_boot_policy': xeninfo.info.get('HVM_boot_policy'), - 'HVM_boot_params': xeninfo.info.get('HVM_boot_params'), - 'platform': xeninfo.get_platform(), - 'PCI_bus': xeninfo.get_pci_bus(), - 'tools_version': xeninfo.get_tools_version(), - 'other_config': xeninfo.info.get('other_config', {}), - 'domid': domid is None and -1 or domid, - 'is_control_domain': xeninfo.info['is_control_domain'], - 'metrics': xeninfo.get_metrics(), - 'security_label': xeninfo.get_security_label(), - 'crash_dumps': [], - 'pool_name': xeninfo.info.get('pool_name'), - 'cpu_pool' : XendCPUPool.query_pool_ref(xeninfo.get_cpu_pool()), - } - return xen_api_success(record) - - def VM_clean_reboot(self, session, vm_ref): - xendom = XendDomain.instance() - xeninfo = xendom.get_vm_by_uuid(vm_ref) - XendTask.log_progress(0, 100, xeninfo.shutdown, "reboot") - return xen_api_success_void() - - def VM_clean_shutdown(self, session, vm_ref): - xendom = XendDomain.instance() - xeninfo = xendom.get_vm_by_uuid(vm_ref) - XendTask.log_progress(0, 100, xeninfo.shutdown, "poweroff") - return xen_api_success_void() - - def VM_clone(self, session, vm_ref): - return xen_api_error(XEND_ERROR_UNSUPPORTED) - - def VM_destroy(self, session, vm_ref): - return XendTask.log_progress(0, 100, do_vm_func, - "domain_delete", vm_ref) - - def VM_hard_reboot(self, session, vm_ref): - return XendTask.log_progress(0, 100, do_vm_func, - "domain_reset", vm_ref) - - def VM_hard_shutdown(self, session, vm_ref): - return XendTask.log_progress(0, 100, do_vm_func, - "domain_destroy", vm_ref) - - def VM_pause(self, session, vm_ref): - return XendTask.log_progress(0, 100, do_vm_func, - "domain_pause", vm_ref) - - def VM_resume(self, session, vm_ref, start_paused): - return XendTask.log_progress(0, 100, do_vm_func, - "domain_resume", vm_ref, - start_paused = start_paused) - - def VM_start(self, session, vm_ref, start_paused): - try: - return XendTask.log_progress(0, 100, do_vm_func, - "domain_start", vm_ref, - start_paused = start_paused) - except HVMRequired, exn: - return xen_api_error(['VM_HVM_REQUIRED', vm_ref]) - - def VM_suspend(self, session, vm_ref): - return XendTask.log_progress(0, 100, do_vm_func, - "domain_suspend", vm_ref) - - def VM_unpause(self, session, vm_ref): - return XendTask.log_progress(0, 100, do_vm_func, - "domain_unpause", vm_ref) - - def VM_send_sysrq(self, _, vm_ref, req): - xeninfo = XendDomain.instance().get_vm_by_uuid(vm_ref) - if xeninfo.state == XEN_API_VM_POWER_STATE_RUNNING \ - or xeninfo.state == XEN_API_VM_POWER_STATE_PAUSED: - xeninfo.send_sysrq(req) - return xen_api_success_void() - else: - return xen_api_error( - ['VM_BAD_POWER_STATE', vm_ref, - XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_RUNNING], - XendDomain.POWER_STATE_NAMES[xeninfo.state]]) - - def VM_send_trigger(self, _, vm_ref, trigger, vcpu): - xendom = XendDomain.instance() - xeninfo = xendom.get_vm_by_uuid(vm_ref) - xendom.domain_send_trigger(xeninfo.getDomid(), trigger, vcpu) - return xen_api_success_void() - - def VM_migrate(self, _, vm_ref, destination_url, live, other_config): - xendom = XendDomain.instance() - xeninfo = xendom.get_vm_by_uuid(vm_ref) - - port = other_config.get("port", 0) - node = other_config.get("node", -1) - ssl = other_config.get("ssl", None) - chs = other_config.get("change_home_server", False) - - xendom.domain_migrate(xeninfo.getDomid(), destination_url, - bool(live), port, node, ssl, bool(chs)) - return xen_api_success_void() - - def VM_save(self, _, vm_ref, dest, checkpoint): - xendom = XendDomain.instance() - xeninfo = xendom.get_vm_by_uuid(vm_ref) - xendom.domain_save(xeninfo.getDomid(), dest, checkpoint) - return xen_api_success_void() - - def VM_restore(self, _, src, paused): - xendom = XendDomain.instance() - xendom.domain_restore(src, bool(paused)) - return xen_api_success_void() - - def VM_cpu_pool_migrate(self, session, vm_ref, cpu_pool_ref): - xendom = XendDomain.instance() - xeninfo = xendom.get_vm_by_uuid(vm_ref) - domid = xeninfo.getDomid() - pool = XendAPIStore.get(cpu_pool_ref, XendCPUPool.getClass()) - if pool == None: - return xen_api_error(['HANDLE_INVALID', 'cpu_pool', cpu_pool_ref]) - if domid is not None: - if domid == 0: - return xen_api_error(['OPERATION_NOT_ALLOWED', - 'could not move Domain-0']) - try: - XendCPUPool.move_domain(cpu_pool_ref, domid) - except Exception, ex: - return xen_api_error(['INTERNAL_ERROR', - 'could not move domain']) - self.VM_set('pool_name', session, vm_ref, pool.get_name_label()) - return xen_api_success_void() - - - # Xen API: Class VBD - # ---------------------------------------------------------------- - - VBD_attr_ro = ['VM', - 'VDI', - 'metrics', - 'runtime_properties'] - VBD_attr_rw = ['device', - 'bootable', - 'mode', - 'type'] - - VBD_attr_inst = VBD_attr_rw - - VBD_methods = [('media_change', None), ('destroy', None)] - VBD_funcs = [('create', 'VBD')] - - # object methods - def VBD_get_record(self, session, vbd_ref): - xendom = XendDomain.instance() - vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref) - if not vm: - return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref]) - cfg = vm.get_dev_xenapi_config('vbd', vbd_ref) - if not cfg: - return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref]) - - valid_vbd_keys = self.VBD_attr_ro + self.VBD_attr_rw + \ - self.Base_attr_ro + self.Base_attr_rw - - return_cfg = {} - for k in cfg.keys(): - if k in valid_vbd_keys: - return_cfg[k] = cfg[k] - - return_cfg['metrics'] = vbd_ref - return_cfg['runtime_properties'] = {} #todo - - return xen_api_success(return_cfg) - - def VBD_media_change(self, session, vbd_ref, new_vdi_ref): - xendom = XendDomain.instance() - xennode = XendNode.instance() - - vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref) - if not vm: - return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref]) - cur_vbd_struct = vm.get_dev_xenapi_config('vbd', vbd_ref) - if not cur_vbd_struct: - return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref]) - if cur_vbd_struct['type'] != XEN_API_VBD_TYPE[0]: # Not CD - return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref]) - if cur_vbd_struct['mode'] != 'RO': # Not read only - return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref]) - - new_vdi = xennode.get_vdi_by_uuid(new_vdi_ref) - if not new_vdi: - return xen_api_error(['HANDLE_INVALID', 'VDI', new_vdi_ref]) - new_vdi_image = new_vdi.get_location() - - valid_vbd_keys = self.VBD_attr_ro + self.VBD_attr_rw + \ - self.Base_attr_ro + self.Base_attr_rw - - new_vbd_struct = {} - for k in cur_vbd_struct.keys(): - if k in valid_vbd_keys: - new_vbd_struct[k] = cur_vbd_struct[k] - new_vbd_struct['VDI'] = new_vdi_ref - - try: - XendTask.log_progress(0, 100, - vm.change_vdi_of_vbd, - new_vbd_struct, new_vdi_image) - except XendError, e: - log.exception("Error in VBD_media_change") - return xen_api_error(['INTERNAL_ERROR', str(e)]) - - return xen_api_success_void() - - # class methods - def VBD_create(self, session, vbd_struct): - xendom = XendDomain.instance() - xennode = XendNode.instance() - - if not xendom.is_valid_vm(vbd_struct['VM']): - return xen_api_error(['HANDLE_INVALID', 'VM', vbd_struct['VM']]) - - dom = xendom.get_vm_by_uuid(vbd_struct['VM']) - vdi = xennode.get_vdi_by_uuid(vbd_struct['VDI']) - if not vdi: - return xen_api_error(['HANDLE_INVALID', 'VDI', vbd_struct['VDI']]) - - # new VBD via VDI/SR - vdi_image = vdi.get_location() - - try: - vbd_ref = XendTask.log_progress(0, 100, - dom.create_vbd, - vbd_struct, vdi_image) - except XendError, e: - log.exception("Error in VBD_create") - return xen_api_error(['INTERNAL_ERROR', str(e)]) - - xendom.managed_config_save(dom) - return xen_api_success(vbd_ref) - - - def VBD_destroy(self, session, vbd_ref): - xendom = XendDomain.instance() - vm = xendom.get_vm_with_dev_uuid('vbd', vbd_ref) - if not vm: - return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref]) - - vdi_ref = XendDomain.instance()\ - .get_dev_property_by_uuid('vbd', vbd_ref, "VDI") - vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref) - - XendTask.log_progress(0, 100, vm.destroy_vbd, vbd_ref) - - xendom.managed_config_save(vm) - return xen_api_success_void() - - def _VBD_get(self, vbd_ref, prop): - return xen_api_success( - XendDomain.instance().get_dev_property_by_uuid( - 'vbd', vbd_ref, prop)) - - # attributes (ro) - def VBD_get_metrics(self, _, vbd_ref): - return xen_api_success(vbd_ref) - - def VBD_get_runtime_properties(self, _, vbd_ref): - xendom = XendDomain.instance() - dominfo = xendom.get_vm_with_dev_uuid('vbd', vbd_ref) - device = dominfo.get_dev_config_by_uuid('vbd', vbd_ref) - - try: - devid = int(device['id']) - device_sxps = dominfo.getDeviceSxprs('vbd') - device_dicts = [dict(device_sxp[1][0:]) for device_sxp in device_sxps] - device_dict = [device_dict - for device_dict in device_dicts - if int(device_dict['virtual-device']) == devid][0] - - return xen_api_success(device_dict) - except Exception, exn: - log.exception(exn) - return xen_api_success({}) - - # attributes (rw) - def VBD_get_VM(self, session, vbd_ref): - return self._VBD_get(vbd_ref, 'VM') - - def VBD_get_VDI(self, session, vbd_ref): - return self._VBD_get(vbd_ref, 'VDI') - - def VBD_get_device(self, session, vbd_ref): - return self._VBD_get(vbd_ref, 'device') - - def VBD_get_bootable(self, session, vbd_ref): - return self._VBD_get(vbd_ref, 'bootable') - - def VBD_get_mode(self, session, vbd_ref): - return self._VBD_get(vbd_ref, 'mode') - - def VBD_get_type(self, session, vbd_ref): - return self._VBD_get(vbd_ref, 'type') - - def VBD_set_bootable(self, session, vbd_ref, bootable): - bootable = bool(bootable) - xd = XendDomain.instance() - vm = xd.get_vm_with_dev_uuid('vbd', vbd_ref) - vm.set_dev_property('vbd', vbd_ref, 'bootable', int(bootable)) - xd.managed_config_save(vm) - return xen_api_success_void() - - def VBD_set_mode(self, session, vbd_ref, mode): - if mode == 'RW': - mode = 'w' - else: - mode = 'r' - xd = XendDomain.instance() - vm = xd.get_vm_with_dev_uuid('vbd', vbd_ref) - vm.set_dev_property('vbd', vbd_ref, 'mode', mode) - xd.managed_config_save(vm) - return xen_api_success_void() - - def VBD_get_all(self, session): - xendom = XendDomain.instance() - vbds = [d.get_vbds() for d in XendDomain.instance().list('all')] - vbds = reduce(lambda x, y: x + y, vbds) - return xen_api_success(vbds) - - - # Xen API: Class VBD_metrics - # ---------------------------------------------------------------- - - VBD_metrics_attr_ro = ['io_read_kbs', - 'io_write_kbs', - 'last_updated'] - VBD_metrics_attr_rw = [] - VBD_metrics_methods = [] - - def VBD_metrics_get_all(self, session): - return self.VBD_get_all(session) - - def VBD_metrics_get_record(self, _, ref): - vm = XendDomain.instance().get_vm_with_dev_uuid('vbd', ref) - if not vm: - return xen_api_error(['HANDLE_INVALID', 'VBD_metrics', ref]) - return xen_api_success( - { 'io_read_kbs' : vm.get_dev_property('vbd', ref, 'io_read_kbs'), - 'io_write_kbs' : vm.get_dev_property('vbd', ref, 'io_write_kbs'), - 'last_updated' : now() - }) - - def VBD_metrics_get_io_read_kbs(self, _, ref): - return self._VBD_get(ref, 'io_read_kbs') - - def VBD_metrics_get_io_write_kbs(self, session, ref): - return self._VBD_get(ref, 'io_write_kbs') - - def VBD_metrics_get_last_updated(self, _1, _2): - return xen_api_success(now()) - - - # Xen API: Class VIF - # ---------------------------------------------------------------- - - VIF_attr_ro = ['network', - 'VM', - 'metrics', - 'runtime_properties'] - VIF_attr_rw = ['device', - 'MAC', - 'MTU', - 'security_label'] - - VIF_attr_inst = VIF_attr_rw - - VIF_methods = [('destroy', None)] - VIF_funcs = [('create', 'VIF')] - - - # object methods - def VIF_get_record(self, session, vif_ref): - xendom = XendDomain.instance() - vm = xendom.get_vm_with_dev_uuid('vif', vif_ref) - if not vm: - return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref]) - cfg = vm.get_dev_xenapi_config('vif', vif_ref) - if not cfg: - return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref]) - - valid_vif_keys = self.VIF_attr_ro + self.VIF_attr_rw + \ - self.Base_attr_ro + self.Base_attr_rw - - return_cfg = {} - for k in cfg.keys(): - if k in valid_vif_keys: - return_cfg[k] = cfg[k] - - return_cfg['metrics'] = vif_ref - - return xen_api_success(return_cfg) - - # class methods - def VIF_create(self, session, vif_struct): - xendom = XendDomain.instance() - if not xendom.is_valid_vm(vif_struct['VM']): - return xen_api_error(['HANDLE_INVALID', 'VM', vif_struct['VM']]) - - dom = xendom.get_vm_by_uuid(vif_struct['VM']) - try: - vif_ref = dom.create_vif(vif_struct) - xendom.managed_config_save(dom) - return xen_api_success(vif_ref) - except XendError, exn: - return xen_api_error(['INTERNAL_ERROR', str(exn)]) - - def VIF_destroy(self, session, vif_ref): - xendom = XendDomain.instance() - vm = xendom.get_vm_with_dev_uuid('vif', vif_ref) - if not vm: - return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref]) - - vm.destroy_vif(vif_ref) - - xendom.managed_config_save(vm) - return xen_api_success_void() - - def _VIF_get(self, ref, prop): - return xen_api_success( - XendDomain.instance().get_dev_property_by_uuid('vif', ref, prop)) - - # getters/setters - def VIF_get_metrics(self, _, vif_ref): - return xen_api_success(vif_ref) - - def VIF_get_VM(self, session, vif_ref): - xendom = XendDomain.instance() - vm = xendom.get_vm_with_dev_uuid('vif', vif_ref) - return xen_api_success(vm.get_uuid()) - - def VIF_get_MTU(self, session, vif_ref): - return self._VIF_get(vif_ref, 'MTU') - - def VIF_get_MAC(self, session, vif_ref): - return self._VIF_get(vif_ref, 'MAC') - - def VIF_get_device(self, session, vif_ref): - return self._VIF_get(vif_ref, 'device') - - def VIF_get_network(self, session, vif_ref): - return self._VIF_get(vif_ref, 'network') - - def VIF_get_all(self, session): - xendom = XendDomain.instance() - vifs = [d.get_vifs() for d in XendDomain.instance().list('all')] - vifs = reduce(lambda x, y: x + y, vifs) - return xen_api_success(vifs) - - def VIF_get_runtime_properties(self, _, vif_ref): - xendom = XendDomain.instance() - dominfo = xendom.get_vm_with_dev_uuid('vif', vif_ref) - device = dominfo.get_dev_config_by_uuid('vif', vif_ref) - - try: - devid = int(device['id']) - - device_sxps = dominfo.getDeviceSxprs('vif') - device_dicts = [dict(device_sxp[1][1:]) - for device_sxp in device_sxps] - - device_dict = [device_dict - for device_dict in device_dicts - if int(device_dict['handle']) == devid][0] - - return xen_api_success(device_dict) - - except Exception, exn: - log.exception(exn) - return xen_api_success({}) - - def VIF_get_security_label(self, session, vif_ref): - return self._VIF_get(vif_ref, 'security_label') - - def _VIF_set(self, ref, prop, val, old_val): - return XendDomain.instance().set_dev_property_by_uuid( - 'vif', ref, prop, val, old_val) - - def VIF_set_security_label(self, session, vif_ref, sec_lab, old_lab): - xendom = XendDomain.instance() - dom = xendom.get_vm_with_dev_uuid('vif', vif_ref) - if not dom: - return xen_api_error(['HANDLE_INVALID', 'VIF', vif_ref]) - - if dom._stateGet() == XEN_API_VM_POWER_STATE_RUNNING: - raise SecurityError(-xsconstants.XSERR_RESOURCE_IN_USE) - - rc = self._VIF_set(vif_ref, 'security_label', sec_lab, old_lab) - if rc == False: - raise SecurityError(-xsconstants.XSERR_BAD_LABEL) - return xen_api_success(xsconstants.XSERR_SUCCESS) - - - # Xen API: Class VIF_metrics - # ---------------------------------------------------------------- - - VIF_metrics_attr_ro = ['io_read_kbs', - 'io_write_kbs', - 'io_total_read_kbs', - 'io_total_write_kbs', - 'last_updated'] - VIF_metrics_attr_rw = [] - VIF_metrics_methods = [] - - def VIF_metrics_get_all(self, session): - return self.VIF_get_all(session) - - def VIF_metrics_get_record(self, _, ref): - vm = XendDomain.instance().get_vm_with_dev_uuid('vif', ref) - if not vm: - return xen_api_error(['HANDLE_INVALID', 'VIF_metrics', ref]) - return xen_api_success( - { 'io_read_kbs' : vm.get_dev_property('vif', ref, 'io_read_kbs'), - 'io_write_kbs' : vm.get_dev_property('vif', ref, 'io_write_kbs'), - 'io_total_read_kbs' : vm.get_dev_property('vif', ref, 'io_total_read_kbs'), - 'io_total_write_kbs' : vm.get_dev_property('vif', ref, 'io_total_write_kbs'), - 'last_updated' : now() - }) - - def VIF_metrics_get_io_read_kbs(self, _, ref): - return self._VIF_get(ref, 'io_read_kbs') - - def VIF_metrics_get_io_write_kbs(self, session, ref): - return self._VIF_get(ref, 'io_write_kbs') - - def VIF_metrics_get_io_total_read_kbs(self, _, ref): - return self._VIF_get(ref, 'io_total_read_kbs') - - def VIF_metrics_get_io_total_write_kbs(self, session, ref): - return self._VIF_get(ref, 'io_total_write_kbs') - - def VIF_metrics_get_last_updated(self, _1, _2): - return xen_api_success(now()) - - - # Xen API: Class VDI - # ---------------------------------------------------------------- - VDI_attr_ro = ['SR', - 'VBDs', - 'physical_utilisation', - 'type'] - VDI_attr_rw = ['name_label', - 'name_description', - 'virtual_size', - 'sharable', - 'read_only', - 'other_config', - 'security_label'] - VDI_attr_inst = VDI_attr_ro + VDI_attr_rw - - VDI_methods = [('destroy', None)] - VDI_funcs = [('create', 'VDI'), - ('get_by_name_label', 'Set(VDI)')] - - def _get_VDI(self, ref): - return XendNode.instance().get_vdi_by_uuid(ref) - - def VDI_get_VBDs(self, session, vdi_ref): - vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref) - return xen_api_success(vdi.getVBDs()) - - def VDI_get_physical_utilisation(self, session, vdi_ref): - return xen_api_success(self._get_VDI(vdi_ref). - get_physical_utilisation()) - - def VDI_get_type(self, session, vdi_ref): - return xen_api_success(self._get_VDI(vdi_ref).type) - - def VDI_get_name_label(self, session, vdi_ref): - return xen_api_success(self._get_VDI(vdi_ref).name_label) - - def VDI_get_name_description(self, session, vdi_ref): - return xen_api_success(self._get_VDI(vdi_ref).name_description) - - def VDI_get_SR(self, session, vdi_ref): - return xen_api_success(self._get_VDI(vdi_ref).sr_uuid) - - def VDI_get_virtual_size(self, session, vdi_ref): - return xen_api_success(self._get_VDI(vdi_ref).virtual_size) - - def VDI_get_sharable(self, session, vdi_ref): - return xen_api_success(self._get_VDI(vdi_ref).sharable) - - def VDI_get_read_only(self, session, vdi_ref): - return xen_api_success(self._get_VDI(vdi_ref).read_only) - - def VDI_set_name_label(self, session, vdi_ref, value): - self._get_VDI(vdi_ref).name_label = value - return xen_api_success_void() - - def VDI_set_name_description(self, session, vdi_ref, value): - self._get_VDI(vdi_ref).name_description = value - return xen_api_success_void() - - def VDI_set_virtual_size(self, session, vdi_ref, value): - return xen_api_error(XEND_ERROR_UNSUPPORTED) - - def VDI_set_sharable(self, session, vdi_ref, value): - self._get_VDI(vdi_ref).sharable = bool(value) - return xen_api_success_void() - - def VDI_set_read_only(self, session, vdi_ref, value): - self._get_VDI(vdi_ref).read_only = bool(value) - return xen_api_success_void() - - def VDI_get_other_config(self, session, vdi_ref): - return xen_api_success( - self._get_VDI(vdi_ref).other_config) - - def VDI_set_other_config(self, session, vdi_ref, other_config): - self._get_VDI(vdi_ref).other_config = other_config - return xen_api_success_void() - - # Object Methods - - def VDI_destroy(self, session, vdi_ref): - # check no VBDs attached - image = XendNode.instance().get_vdi_by_uuid(vdi_ref) - if image.getVBDs(): - raise VDIError("Cannot destroy VDI with VBDs attached", - image.name_label) - - sr = XendNode.instance().get_sr_containing_vdi(vdi_ref) - sr.destroy_vdi(vdi_ref) - return xen_api_success_void() - - def VDI_get_record(self, session, vdi_ref): - image = XendNode.instance().get_vdi_by_uuid(vdi_ref) - return xen_api_success({ - 'uuid': vdi_ref, - 'name_label': image.name_label, - 'name_description': image.name_description, - 'SR': image.sr_uuid, - 'VBDs': image.getVBDs(), - 'virtual_size': image.virtual_size, - 'physical_utilisation': image.physical_utilisation, - 'type': image.type, - 'sharable': image.sharable, - 'read_only': image.read_only, - 'other_config': image.other_config, - 'security_label' : image.get_security_label() - }) - - # Class Functions - def VDI_create(self, session, vdi_struct): - sr_ref = vdi_struct.get('SR') - xennode = XendNode.instance() - if not xennode.is_valid_sr(sr_ref): - return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref]) - - vdi_uuid = xennode.srs[sr_ref].create_vdi(vdi_struct) - return xen_api_success(vdi_uuid) - - def VDI_get_all(self, session): - xennode = XendNode.instance() - vdis = [sr.get_vdis() for sr in xennode.srs.values()] - return xen_api_success(reduce(lambda x, y: x + y, vdis)) - - def VDI_get_by_name_label(self, session, name): - xennode = XendNode.instance() - return xen_api_success(xennode.get_vdi_by_name_label(name)) - - def VDI_set_security_label(self, session, vdi_ref, sec_lab, old_lab): - vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref) - rc = vdi.set_security_label(sec_lab, old_lab) - if rc < 0: - return xen_api_error(['SECURITY_ERROR', rc, - xsconstants.xserr2string(-rc)]) - return xen_api_success(rc) - - def VDI_get_security_label(self, session, vdi_ref): - vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref) - return xen_api_success(vdi.get_security_label()) - - # Xen API: Class console - # ---------------------------------------------------------------- - - - console_attr_ro = ['location', 'protocol', 'VM'] - console_attr_rw = ['other_config'] - console_funcs = [('create', 'console')] - - def console_get_all(self, session): - xendom = XendDomain.instance() - cons = [d.get_consoles() for d in XendDomain.instance().list('all')] - cons = reduce(lambda x, y: x + y, cons) - return xen_api_success(cons) - - def console_get_location(self, session, console_ref): - xendom = XendDomain.instance() - return xen_api_success(xendom.get_dev_property_by_uuid('console', - console_ref, - 'location')) - - def console_get_protocol(self, session, console_ref): - xendom = XendDomain.instance() - return xen_api_success(xendom.get_dev_property_by_uuid('console', - console_ref, - 'protocol')) - - def console_get_VM(self, session, console_ref): - xendom = XendDomain.instance() - vm = xendom.get_vm_with_dev_uuid('console', console_ref) - return xen_api_success(vm.get_uuid()) - - def console_get_other_config(self, session, console_ref): - xendom = XendDomain.instance() - return xen_api_success(xendom.get_dev_property_by_uuid('console', - console_ref, - 'other_config')) - - # object methods - def console_get_record(self, session, console_ref): - xendom = XendDomain.instance() - vm = xendom.get_vm_with_dev_uuid('console', console_ref) - if not vm: - return xen_api_error(['HANDLE_INVALID', 'console', console_ref]) - cfg = vm.get_dev_xenapi_config('console', console_ref) - if not cfg: - return xen_api_error(['HANDLE_INVALID', 'console', console_ref]) - - valid_console_keys = self.console_attr_ro + self.console_attr_rw + \ - self.Base_attr_ro + self.Base_attr_rw - - return_cfg = {} - for k in cfg.keys(): - if k in valid_console_keys: - return_cfg[k] = cfg[k] - - return xen_api_success(return_cfg) - - def console_create(self, session, console_struct): - xendom = XendDomain.instance() - if not xendom.is_valid_vm(console_struct['VM']): - return xen_api_error(['HANDLE_INVALID', 'VM', - console_struct['VM']]) - - dom = xendom.get_vm_by_uuid(console_struct['VM']) - try: - if 'protocol' not in console_struct: - return xen_api_error(['CONSOLE_PROTOCOL_INVALID', - 'No protocol specified']) - - console_ref = dom.create_console(console_struct) - xendom.managed_config_save(dom) - return xen_api_success(console_ref) - except XendError, exn: - return xen_api_error(['INTERNAL_ERROR', str(exn)]) - - def console_set_other_config(self, session, console_ref, other_config): - xd = XendDomain.instance() - vm = xd.get_vm_with_dev_uuid('console', console_ref) - vm.set_console_other_config(console_ref, other_config) - xd.managed_config_save(vm) - return xen_api_success_void() - - # Xen API: Class SR - # ---------------------------------------------------------------- - SR_attr_ro = ['VDIs', - 'PBDs', - 'virtual_allocation', - 'physical_utilisation', - 'physical_size', - 'type', - 'content_type'] - - SR_attr_rw = ['name_label', - 'name_description'] - - SR_attr_inst = ['physical_size', - 'type', - 'name_label', - 'name_description'] - - SR_methods = [] - SR_funcs = [('get_by_name_label', 'Set(SR)'), - ('get_by_uuid', 'SR')] - - # Class Functions - def SR_get_all(self, session): - return xen_api_success(XendNode.instance().get_all_sr_uuid()) - - def SR_get_by_name_label(self, session, label): - return xen_api_success(XendNode.instance().get_sr_by_name(label)) - - def SR_get_supported_types(self, _): - return xen_api_success(['local', 'qcow_file']) - - # Class Methods - - def SR_get_record(self, session, sr_ref): - sr = XendNode.instance().get_sr(sr_ref) - if sr: - return xen_api_success(sr.get_record()) - return xen_api_error(['HANDLE_INVALID', 'SR', sr_ref]) - - # Attribute acceess - - def _get_SR_func(self, sr_ref, func): - return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref), - func)()) - - def _get_SR_attr(self, sr_ref, attr): - return xen_api_success(getattr(XendNode.instance().get_sr(sr_ref), - attr)) - - def SR_get_VDIs(self, _, ref): - return self._get_SR_func(ref, 'list_images') - - def SR_get_PBDs(self, _, ref): - return xen_api_success(XendPBD.get_by_SR(ref)) - - def SR_get_virtual_allocation(self, _, ref): - return self._get_SR_func(ref, 'virtual_allocation') - - def SR_get_physical_utilisation(self, _, ref): - return self._get_SR_func(ref, 'physical_utilisation') - - def SR_get_physical_size(self, _, ref): - return self._get_SR_attr(ref, 'physical_size') - - def SR_get_type(self, _, ref): - return self._get_SR_attr(ref, 'type') - - def SR_get_content_type(self, _, ref): - return self._get_SR_attr(ref, 'content_type') - - def SR_get_name_label(self, _, ref): - return self._get_SR_attr(ref, 'name_label') - - def SR_get_name_description(self, _, ref): - return self._get_SR_attr(ref, 'name_description') - - def SR_set_name_label(self, session, sr_ref, value): - sr = XendNode.instance.get_sr(sr_ref) - if sr: - sr.name_label = value - XendNode.instance().save() - return xen_api_success_void() - - def SR_set_name_description(self, session, sr_ref, value): - sr = XendNode.instance.get_sr(sr_ref) - if sr: - sr.name_description = value - XendNode.instance().save() - return xen_api_success_void() - - - # Xen API: Class event - # ---------------------------------------------------------------- - - event_attr_ro = [] - event_attr_rw = [] - event_funcs = [('register', None), - ('unregister', None), - ('next', None)] - - def event_register(self, session, reg_classes): - event_register(session, reg_classes) - return xen_api_success_void() - - def event_unregister(self, session, unreg_classes): - event_unregister(session, unreg_classes) - return xen_api_success_void() - - def event_next(self, session): - return event_next(session) - - # Xen API: Class debug - # ---------------------------------------------------------------- - - debug_methods = [('destroy', None), - ('get_record', 'debug')] - debug_funcs = [('wait', None), - ('return_failure', None)] - - def debug_wait(self, session, wait_secs): - import time - prog_units = 100/float(wait_secs) - for i in range(int(wait_secs)): - XendTask.log_progress(prog_units * i, prog_units * (i + 1), - time.sleep, 1) - return xen_api_success_void() - - - def debug_return_failure(self, session): - return xen_api_error(['DEBUG_FAIL', session]) - - def debug_create(self, session): - debug_uuid = genuuid.createString() - self._debug[debug_uuid] = None - return xen_api_success(debug_uuid) - - def debug_destroy(self, session, debug_ref): - del self._debug[debug_ref] - return xen_api_success_void() - - def debug_get_record(self, session, debug_ref): - return xen_api_success({'uuid': debug_ref}) - - -class XendAPIAsyncProxy: - """ A redirector for Async.Class.function calls to XendAPI - but wraps the call for use with the XendTaskManager. - - @ivar xenapi: Xen API instance - @ivar method_map: Mapping from XMLRPC method name to callable objects. - """ - - method_prefix = 'Async.' - - def __init__(self, xenapi): - """Initialises the Async Proxy by making a map of all - implemented Xen API methods for use with XendTaskManager. - - @param xenapi: XendAPI instance - """ - self.xenapi = xenapi - self.method_map = {} - for method_name in dir(self.xenapi): - method = getattr(self.xenapi, method_name) - if method_name[0] != '_' and hasattr(method, 'async') \ - and method.async == True: - self.method_map[method.api] = method - - def _dispatch(self, method, args): - """Overridden method so that SimpleXMLRPCServer will - resolve methods through this method rather than through - inspection. - - @param method: marshalled method name from XMLRPC. - @param args: marshalled arguments from XMLRPC. - """ - - # Only deal with method names that start with "Async." - if not method.startswith(self.method_prefix): - return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method]) - - # Lookup synchronous version of the method - synchronous_method_name = method[len(self.method_prefix):] - if synchronous_method_name not in self.method_map: - return xen_api_error(['MESSAGE_METHOD_UNKNOWN', method]) - - method = self.method_map[synchronous_method_name] - - # Check that we've got enough arguments before issuing a task ID. - needed = argcounts[method.api] - if len(args) != needed: - return xen_api_error(['MESSAGE_PARAMETER_COUNT_MISMATCH', - self.method_prefix + method.api, needed, - len(args)]) - - # Validate the session before proceeding - session = args[0] - if not auth_manager().is_session_valid(session): - return xen_api_error(['SESSION_INVALID', session]) - - # create and execute the task, and return task_uuid - return_type = getattr(method, 'return_type', None) - task_uuid = XendTaskManager.create_task(method, args, - synchronous_method_name, - return_type, - synchronous_method_name, - session) - return xen_api_success(task_uuid) diff --git a/tools/python/xen/xend/XendAPIConstants.py b/tools/python/xen/xend/XendAPIConstants.py deleted file mode 100644 index b3d2f9ea9c..0000000000 --- a/tools/python/xen/xend/XendAPIConstants.py +++ /dev/null @@ -1,82 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2006-2007 XenSource Ltd. -#============================================================================ - -# -# Xen API Enums -# - -XEN_API_VM_POWER_STATE = [ - 'Halted', - 'Paused', - 'Running', - 'Suspended', - 'Halted', - 'Crashed', - 'Unknown' -] - -XEN_API_VM_POWER_STATE_HALTED = 0 -XEN_API_VM_POWER_STATE_PAUSED = 1 -XEN_API_VM_POWER_STATE_RUNNING = 2 -XEN_API_VM_POWER_STATE_SUSPENDED = 3 -XEN_API_VM_POWER_STATE_SHUTTINGDOWN = 4 -XEN_API_VM_POWER_STATE_CRASHED = 5 -XEN_API_VM_POWER_STATE_UNKNOWN = 6 - -XEN_API_ON_NORMAL_EXIT = [ - 'destroy', - 'restart', -] - -XEN_API_ON_CRASH_BEHAVIOUR = [ - 'destroy', - 'coredump_and_destroy', - 'restart', - 'coredump_and_restart', - 'preserve', - 'rename_restart' -] - -XEN_API_ON_CRASH_BEHAVIOUR_FILTER = { - 'destroy' : 'destroy', - 'coredump-destroy' : 'coredump_and_destroy', - 'coredump_and_destroy' : 'coredump_and_destroy', - 'restart' : 'restart', - 'coredump-restart' : 'coredump_and_restart', - 'coredump_and_restart' : 'coredump_and_restart', - 'preserve' : 'preserve', - 'rename-restart' : 'rename_restart', - 'rename_restart' : 'rename_restart', -} - -XEN_API_ON_CRASH_BEHAVIOUR_LEGACY = { - 'destroy' : 'destroy', - 'coredump-destroy' : 'coredump-destroy', - 'coredump_and_destroy' : 'coredump-destroy', - 'restart' : 'restart', - 'coredump-restart' : 'coredump-restart', - 'coredump_and_restart' : 'coredump-restart', - 'preserve' : 'preserve', - 'rename-restart' : 'rename-restart', - 'rename_restart' : 'rename-restart', -} - -XEN_API_VBD_MODE = ['RO', 'RW'] -XEN_API_VDI_TYPE = ['system', 'user', 'ephemeral'] -XEN_API_VBD_TYPE = ['CD', 'Disk'] -XEN_API_TASK_STATUS_TYPE = ['pending', 'success', 'failure'] -XEN_API_CONSOLE_PROTOCOL = ['vt100', 'rfb', 'rdp'] diff --git a/tools/python/xen/xend/XendAPIStore.py b/tools/python/xen/xend/XendAPIStore.py deleted file mode 100644 index 6876f2e6fb..0000000000 --- a/tools/python/xen/xend/XendAPIStore.py +++ /dev/null @@ -1,83 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2007 Tom Wilkie -#============================================================================ -""" -This is a place to put instances of XenAPI objects, -instead of just holding them in arbitrary places. - -All objects which subclass XendBase should use this -mechanism. - -You must register both the uuid and type, and get objects -by type, to ensure safety -""" - -import threading - -__classes = {} -__classes_lock = threading.RLock() - -def register(uuid, type, inst): - __classes_lock.acquire() - try: - __classes[(uuid, type)] = inst - return inst - finally: - __classes_lock.release() - -def deregister(uuid, type): - __classes_lock.acquire() - try: - old = get(uuid, type) - if old is not None: - del __classes[(uuid, type)] - return old - finally: - __classes_lock.release() - -def get(uuid, type): - """ - Get the instances by uuid and type - """ - __classes_lock.acquire() - try: - return __classes.get((uuid, type), None) - finally: - __classes_lock.release() - -def get_all(all_type): - """ - Get all instances by type - """ - __classes_lock.acquire() - try: - return [inst - for ((uuid, t), inst) in __classes.items() - if t == all_type] - finally: - __classes_lock.release() - -def get_all_uuid(all_type): - """ - Get all uuids by type - """ - __classes_lock.acquire() - try: - return [uuid - for (uuid, t) in __classes.keys() - if t == all_type] - finally: - __classes_lock.release() diff --git a/tools/python/xen/xend/XendAPIVersion.py b/tools/python/xen/xend/XendAPIVersion.py deleted file mode 100644 index 2659108c99..0000000000 --- a/tools/python/xen/xend/XendAPIVersion.py +++ /dev/null @@ -1,22 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (c) 2007 XenSource Inc. -#============================================================================ - - -XEN_API_VERSION_MAJOR = 1 -XEN_API_VERSION_MINOR = 0 -XEN_API_VERSION_VENDOR = 'xenbits' -XEN_API_VERSION_VENDOR_IMPLEMENTATION = {} diff --git a/tools/python/xen/xend/XendAuthSessions.py b/tools/python/xen/xend/XendAuthSessions.py deleted file mode 100644 index fb28e3f0ba..0000000000 --- a/tools/python/xen/xend/XendAuthSessions.py +++ /dev/null @@ -1,131 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2006 XenSource Ltd. -#============================================================================ - -import time - -from xen.xend import uuid -from xen.xend.XendError import * -from xen.xend.XendLogging import log - -class XendAuthSessions: - """Keeps track of Xen API Login Sessions using PAM. - - Note: Login sessions are not valid across instances of Xend. - """ - def __init__(self): - self.sessions = {} - - def init(self): - pass - - def login_unconditionally(self, username): - """Returns a session UUID if valid. - - @rtype: string - @return: Session UUID - """ - new_session = uuid.createString() - self.sessions[new_session] = (username, time.time()) - return new_session - - def login_with_password(self, username, password): - """Returns a session UUID if valid, otherwise raises an error. - - @raises XendError: If login fails. - @rtype: string - @return: Session UUID - """ - if self.is_authorized(username, password): - return self.login_unconditionally(username) - - raise XendError("Login failed") - - def logout(self, session): - """Delete session of it exists.""" - if self.is_session_valid(session): - del self.sessions[session] - - def is_session_valid(self, session): - """Returns true is session is valid.""" - if type(session) == type(str()): - return (session in self.sessions) - return False - - def is_authorized(self, username, password): - """Returns true is a user is authorised via PAM. - - Note: We use the 'login' PAM stack rather than inventing - our own. - - @rtype: boolean - """ - pam_auth = None - try: - import PAM - pam_auth = PAM.pam() - except ImportError: - log.warn("python-pam is required for XenAPI support.") - return False - except NameError: - # if PAM doesn't exist, let's ignore it - return False - - pam_auth.start("login") - pam_auth.set_item(PAM.PAM_USER, username) - - def _pam_conv(auth, query_list, user_data = None): - resp = [] - for i in range(len(query_list)): - query, qtype = query_list[i] - if qtype == PAM.PAM_PROMPT_ECHO_ON: - resp.append((username, 0)) - elif qtype == PAM.PAM_PROMPT_ECHO_OFF: - resp.append((password, 0)) - else: - return None - return resp - - pam_auth.set_item(PAM.PAM_CONV, _pam_conv) - - try: - pam_auth.authenticate() - pam_auth.acct_mgmt() - except PAM.error, resp: - return False - except Exception, e: - log.warn("Error with PAM: %s" % str(e)) - return False - else: - return True - - def get_user(self, session): - try: - return self.sessions[session][0] - except (KeyError, IndexError): - return None - - -def instance(): - """Singleton constructor. Use this instead of the class constructor. - """ - global inst - try: - inst - except: - inst = XendAuthSessions() - inst.init() - return inst diff --git a/tools/python/xen/xend/XendBase.py b/tools/python/xen/xend/XendBase.py deleted file mode 100644 index 924477669a..0000000000 --- a/tools/python/xen/xend/XendBase.py +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/python -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2007 Tom Wilkie -#============================================================================ -""" -Base class for all XenAPI classes -""" - -from xen.xend.XendError import * -from xen.xend import XendAPIStore - -class XendBase: - # - # These functions describe the object, and what is exposed via the API - # - def getClass(self): - return "Base" - - def getAttrRO(self): - return ['uuid'] - - def getAttrRW(self): - return [] - - def getAttrInst(self): - return [] - - def getMethods(self): - return ["get_record"] - - def getFuncs(self): - return ["get_all", "get_by_uuid", "get_all_records"] - - getClass = classmethod(getClass) - getAttrRO = classmethod(getAttrRO) - getAttrRW = classmethod(getAttrRW) - getAttrInst = classmethod(getAttrInst) - getMethods = classmethod(getMethods) - getFuncs = classmethod(getFuncs) - - def __init__(self, uuid, record): - self.__uuid = uuid - - # First check this class implements all the correct methods: - for attr_ro in self.getAttrRO() + self.getAttrRW(): - if not hasattr(self, "get_%s" % attr_ro): - raise ImplementationError(self.getClass(), - "get_%s" % attr_ro) - - for attr_rw in self.getAttrRW(): - if not hasattr(self, "set_%s" % attr_rw): - raise ImplementationError(self.getClass(), - "set_%s" % attr_rw) - - for method in self.getMethods(): - if not hasattr(self, method): - raise ImplementationError(self.getClass(), - method) - - for func in self.getFuncs(): - if not hasattr(self.__class__, func): - raise ImplementationError(self.getClass(), - func) - - # Next check that the class is being created with the correct - # parameters - if not isinstance(record, dict): - raise CreateUnspecifiedAttributeError( - "record" , self.getClass()) - - for attr_inst in self.getAttrInst(): - if attr_inst not in record: - raise CreateUnspecifiedAttributeError( - attr_inst, self.getClass()) - setattr(self, attr_inst, record[attr_inst]) - - # Finally register it - XendAPIStore.register(uuid, self.getClass(), self) - - def destroy(self): - XendAPIStore.deregister(self.get_uuid(), self.getClass()) - - def get_uuid(self): - return self.__uuid - - def get_record(self): - keys = self.getAttrRO() + self.getAttrRW() - return dict([(key, getattr(self, "get_%s" % key)()) - for key in keys]) - - # - # Class methods - # - - def get_all(cls): - return XendAPIStore.get_all_uuid(cls.getClass()) - - def get_by_uuid(cls, uuid): - # Sanity check the uuid is one of us - me = XendAPIStore.get(uuid, cls.getClass()) - if me is not None and me.getClass() == cls.getClass(): - # In OSS, ref == uuid - return uuid - else: - raise ValueError("Big Error.. TODO!") - - def get_all_records(cls): - return dict([(inst.get_uuid(), inst.get_record()) - for inst in XendAPIStore.get_all(cls.getClass())]) - - get_all = classmethod(get_all) - get_by_uuid = classmethod(get_by_uuid) - get_all_records = classmethod(get_all_records) diff --git a/tools/python/xen/xend/XendBootloader.py b/tools/python/xen/xend/XendBootloader.py deleted file mode 100644 index f17428eaa4..0000000000 --- a/tools/python/xen/xend/XendBootloader.py +++ /dev/null @@ -1,230 +0,0 @@ -# -# XendBootloader.py - Framework to run a boot loader for picking the kernel -# -# Copyright 2005-2006 Red Hat, Inc. -# Jeremy Katz -# -# This software may be freely redistributed under the terms of the GNU -# general public license. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -# - -import os, select, errno, stat, signal, tty -import random -import shlex -from xen.xend import sxp - -from xen.util import mkdir, oshelp -from XendLogging import log -from XendError import VmError - -import pty, termios, fcntl -from xen.lowlevel import ptsname - -def bootloader(blexec, disk, dom, quiet = False, blargs = '', kernel = '', - ramdisk = '', kernel_args = ''): - """Run the boot loader executable on the given disk and return a - config image. - @param blexec Binary to use as the boot loader - @param disk Disk to run the boot loader on. - @param dom DomainInfo representing the domain being booted. - @param quiet Run in non-interactive mode, just booting the default. - @param blargs Arguments to pass to the bootloader.""" - - if not os.access(blexec, os.X_OK): - msg = "Bootloader isn't executable" - log.error(msg) - raise VmError(msg) - if not os.access(disk, os.R_OK): - msg = "Disk isn't accessible" - log.error(msg) - raise VmError(msg) - - if os.uname()[0] == "NetBSD" and disk.startswith('/dev/'): - disk = "/r".join(disk.rsplit("/",1)) - - mkdir.parents("/var/run/xend/boot/", stat.S_IRWXU) - - while True: - fifo = "/var/run/xend/boot/xenbl.%s" %(random.randint(0, 32000),) - try: - os.mkfifo(fifo, 0600) - except OSError, e: - if (e.errno != errno.EEXIST): - raise - break - - # We need to present the bootloader's tty as a pty slave that xenconsole - # can access. Since the bootloader itself needs a pty slave, - # we end up with a connection like this: - # - # xenconsole -- (slave pty1 master) <-> (master pty2 slave) -- bootloader - # - # where we copy characters between the two master fds, as well as - # listening on the bootloader's fifo for the results. - - (m1, s1) = pty.openpty() - - # On Solaris, the pty master side will get cranky if we try - # to write to it while there is no slave. To work around this, - # keep the slave descriptor open until we're done. Set it - # to raw terminal parameters, otherwise it will echo back - # characters, which will confuse the I/O loop below. - # Furthermore, a raw master pty device has no terminal - # semantics on Solaris, so don't try to set any attributes - # for it. - if os.uname()[0] != 'SunOS' and os.uname()[0] != 'NetBSD': - tty.setraw(m1) - os.close(s1) - else: - tty.setraw(s1) - - fcntl.fcntl(m1, fcntl.F_SETFL, os.O_NDELAY) - - slavename = ptsname.ptsname(m1) - dom.storeDom("console/tty", slavename) - - # Release the domain lock here, because we definitely don't want - # a stuck bootloader to deny service to other xend clients. - from xen.xend import XendDomain - domains = XendDomain.instance() - domains.domains_lock.release() - - (child, m2) = pty.fork() - if (not child): - args = [ blexec ] - if kernel: - args.append("--kernel=%s" % kernel) - if ramdisk: - args.append("--ramdisk=%s" % ramdisk) - if kernel_args: - args.append("--args=%s" % kernel_args) - if quiet: - args.append("-q") - args.append("--output=%s" % fifo) - if blargs: - args.extend(shlex.split(blargs)) - args.append(disk) - - try: - log.debug("Launching bootloader as %s." % str(args)) - env = os.environ.copy() - env['TERM'] = 'vt100' - oshelp.close_fds() - os.execvpe(args[0], args, env) - except OSError, e: - print e - pass - os._exit(1) - - # record that this domain is bootloading - dom.bootloader_pid = child - - # On Solaris, the master pty side does not have terminal semantics, - # so don't try to set any attributes, as it will fail. - if os.uname()[0] != 'SunOS': - tty.setraw(m2); - - fcntl.fcntl(m2, fcntl.F_SETFL, os.O_NDELAY); - while True: - try: - r = os.open(fifo, os.O_RDONLY) - except OSError, e: - if e.errno == errno.EINTR: - continue - break - - fcntl.fcntl(r, fcntl.F_SETFL, os.O_NDELAY); - - ret = "" - inbuf=""; outbuf=""; - # filedescriptors: - # r - input from the bootloader (bootstring output) - # m1 - input/output from/to xenconsole - # m2 - input/output from/to pty that controls the bootloader - # The filedescriptors are NDELAY, so it's ok to try to read - # bigger chunks than may be available, to keep e.g. curses - # screen redraws in the bootloader efficient. m1 is the side that - # gets xenconsole input, which will be keystrokes, so a small number - # is sufficient. m2 is pygrub output, which will be curses screen - # updates, so a larger number (1024) is appropriate there. - # - # For writeable descriptors, only include them in the set for select - # if there is actual data to write, otherwise this would loop too fast, - # eating up CPU time. - - while True: - wsel = [] - if len(outbuf) != 0: - wsel = wsel + [m1] - if len(inbuf) != 0: - wsel = wsel + [m2] - sel = select.select([r, m1, m2], wsel, []) - try: - if m1 in sel[0]: - s = os.read(m1, 16) - inbuf += s - if m2 in sel[1]: - n = os.write(m2, inbuf) - inbuf = inbuf[n:] - except OSError, e: - if e.errno == errno.EIO: - pass - try: - if m2 in sel[0]: - s = os.read(m2, 1024) - outbuf += s - if m1 in sel[1]: - n = os.write(m1, outbuf) - outbuf = outbuf[n:] - except OSError, e: - if e.errno == errno.EIO: - pass - if r in sel[0]: - s = os.read(r, 128) - ret = ret + s - if len(s) == 0: - break - del inbuf - del outbuf - os.waitpid(child, 0) - os.close(r) - os.close(m2) - os.close(m1) - if os.uname()[0] == 'SunOS' or os.uname()[0] == 'NetBSD': - os.close(s1) - os.unlink(fifo) - - # Re-acquire the lock to cover the changes we're about to make - # when we return to domain creation. - domains.domains_lock.acquire() - - if dom.bootloader_pid is None: - msg = "Domain was died while the bootloader was running." - log.error(msg) - raise VmError, msg - - dom.bootloader_pid = None - - if len(ret) == 0: - msg = "Boot loader didn't return any data!" - log.error(msg) - raise VmError, msg - - pin = sxp.Parser() - pin.input(ret) - pin.input_eof() - blcfg = pin.val - return blcfg - - -def bootloader_tidy(dom): - if hasattr(dom, "bootloader_pid") and dom.bootloader_pid is not None: - pid = dom.bootloader_pid - dom.bootloader_pid = None - os.kill(pid, signal.SIGKILL) - - diff --git a/tools/python/xen/xend/XendCPUPool.py b/tools/python/xen/xend/XendCPUPool.py deleted file mode 100644 index d26cbd6068..0000000000 --- a/tools/python/xen/xend/XendCPUPool.py +++ /dev/null @@ -1,910 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (c) 2009 Fujitsu Technology Solutions. -#============================================================================ - -""" CPU Pool support including XEN-API and Legacy API. -""" - -import types -import threading -import re -import xen.lowlevel.xc -import XendNode -import XendDomain -from xen.xend.XendLogging import log -from xen.xend.XendBase import XendBase -from xen.xend import XendAPIStore -from xen.xend.XendConstants import XS_POOLROOT -from xen.xend import uuid as genuuid -from xen.xend.XendError import VmError, XendAPIError, PoolError -from xen.xend.xenstore.xstransact import xstransact -from xen.util.sxputils import sxp2map, map2sxp - - -XEND_ERROR_INTERNAL = 'INTERNAL_ERROR' -XEND_ERROR_UNKOWN_SCHED_POLICY = 'UNKOWN_SCHED_POLICY' -XEND_ERROR_BAD_POOL_STATE = 'POOL_BAD_STATE' -XEND_ERROR_POOL_PARAM = 'PARAMETER_ERROR' -XEND_ERROR_INSUFFICIENT_CPUS = 'INSUFFICIENT_CPUS' -XEND_ERROR_POOL_RECONF = 'POOL_RECONF' -XEND_ERROR_INVALID_CPU = 'INVAILD_CPU' -XEND_ERROR_LAST_CPU_NOT_REM = 'LAST_CPU_NOT_REMOVEABLE' - - -XEN_SCHEDULER_TO_ID = { - 'credit2': xen.lowlevel.xc.XEN_SCHEDULER_CREDIT2, - 'credit' : xen.lowlevel.xc.XEN_SCHEDULER_CREDIT, - 'sedf' : xen.lowlevel.xc.XEN_SCHEDULER_SEDF, - } - -xc = xen.lowlevel.xc.xc() - -class XendCPUPool(XendBase): - """ CPU Pool management. - @ivar pool_lock: Lock to secure modification of pool data - @type pool_lock: Rlock - """ - - pool_lock = threading.RLock() - - def getClass(cls): - return "cpu_pool" - - def getAttrRO(cls): - attrRO = ['resident_on', - 'started_VMs', - 'host_CPUs', - 'activated', - ] - return XendBase.getAttrRO() + attrRO - - def getAttrRW(cls): - attrRW = ['name_label', - 'name_description', - 'auto_power_on', - 'ncpu', - 'sched_policy', - 'proposed_CPUs', - 'other_config', - ] - return XendBase.getAttrRW() + attrRW - - def getMethods(cls): - methods = ['destroy', - 'activate', - 'deactivate', - 'add_host_CPU_live', - 'remove_host_CPU_live', - 'add_to_proposed_CPUs', - 'remove_from_proposed_CPUs', - 'add_to_other_config', - 'remove_from_other_config', - ] - return XendBase.getMethods() + methods - - def getFuncs(cls): - funcs = ['create', - 'get_by_name_label', - ] - return XendBase.getFuncs() + funcs - - getClass = classmethod(getClass) - getAttrRO = classmethod(getAttrRO) - getAttrRW = classmethod(getAttrRW) - getMethods = classmethod(getMethods) - getFuncs = classmethod(getFuncs) - - - # - # XenAPI function calls - # - - def create(cls, record): - """ Create a new managed pool instance. - @param record: attributes of pool - @type record: dict - @return: uuid of created pool - @rtype: str - """ - new_uuid = genuuid.createString() - XendCPUPool(record, new_uuid) - XendNode.instance().save_cpu_pools() - return new_uuid - - create = classmethod(create) - - - def get_by_name_label(cls, name_label): - """ Query a Pool(ref) by its name. - @return: ref of pool - @rtype: str - """ - cls.pool_lock.acquire() - try: - return [ inst.get_uuid() - for inst in XendAPIStore.get_all(cls.getClass()) - if inst.name_label == name_label - ] - finally: - cls.pool_lock.release() - - get_by_name_label = classmethod(get_by_name_label) - - - def get_cpu_pool_by_cpu_ref(cls, host_cpu): - """ Query cpu_pool ref the given cpu belongs to. - @param host_cpu: ref of host_cpu to lookup - @type host_cpu: str - @return: list cpu_pool refs (list contains not more than one element) - @rtype: list of str - """ - node = XendNode.instance() - cpu_nr = node.get_host_cpu_field(host_cpu, 'number') - for pool_rec in xc.cpupool_getinfo(): - if cpu_nr in pool_rec['cpulist']: - # pool found; return the ref - return cls.query_pool_ref(pool_rec['cpupool']) - return [] - - get_cpu_pool_by_cpu_ref = classmethod(get_cpu_pool_by_cpu_ref) - - - def get_all_managed(cls): - """ Query all managed pools. - @return: uuids of all managed pools - @rtype: list of str - """ - cls.pool_lock.acquire() - try: - managed_pools = [ inst.get_uuid() - for inst in XendAPIStore.get_all(cls.getClass()) - if inst.is_managed() ] - finally: - cls.pool_lock.release() - return managed_pools - - get_all_managed = classmethod(get_all_managed) - - - # - # XenAPI methods calls - # - - def __init__(self, record, new_uuid, managed_pool=True): - XendBase.__init__(self, new_uuid, record) - try: - self._managed = managed_pool - self.name_label = None - - name = record.get('name_label', 'Pool-Unnamed') - self._checkName(name) - self.name_label = name - self.name_description = record.get('name_description', - self.name_label) - self.proposed_cpus = [ int(cpu) - for cpu in record.get('proposed_CPUs', []) ] - self.auto_power_on = bool(record.get('auto_power_on', False)) - self.ncpu = int(record.get('ncpu', 1)) - self.sched_policy = record.get('sched_policy', '') - self.other_config = record.get('other_config', {}) - except Exception, ex: - XendBase.destroy(self) - raise ex - - - def get_resident_on(self): - """ Always return uuid of own node. - @return: uuid of this node - @rytpe: str - """ - return XendNode.instance().uuid - - def get_started_VMs(self): - """ Query all VMs currently assigned to pool. - @return: ref of all VMs assigned to pool; if pool is not active, - an empty list will be returned - @rtype: list of str - """ - if self.get_activated(): - # search VMs related to this pool - pool_id = self.query_pool_id() - started_VMs = [ vm.get_uuid() - for vm in XendDomain.instance().list('all') - if vm.get_cpu_pool() == pool_id ] - else: - # pool not active, so it couldn't have any started VMs - started_VMs = [] - - return started_VMs - - def get_host_CPUs(self): - """ Query all cpu refs of this pool currently asisgned . - - Read pool id of this pool from xenstore - - Read cpu configuration from hypervisor - - lookup cpu number -> cpu ref - @return: host_cpu refs - @rtype: list of str - """ - if self.get_activated(): - node = XendNode.instance() - pool_id = self.query_pool_id() - if pool_id == None: - raise PoolError(XEND_ERROR_INTERNAL, - [self.getClass(), 'get_host_CPUs']) - cpus = [] - for pool_rec in xc.cpupool_getinfo(): - if pool_rec['cpupool'] == pool_id: - cpus = pool_rec['cpulist'] - - # query host_cpu ref for any cpu of the pool - host_CPUs = [ cpu_ref - for cpu_ref in node.get_host_cpu_refs() - if node.get_host_cpu_field(cpu_ref, 'number') - in cpus ] - else: - # pool not active, so it couldn't have any assigned cpus - host_CPUs = [] - - return host_CPUs - - def get_activated(self): - """ Query if the pool is registered in XendStore. - If pool uuid is not in XenStore, the pool is not activated. - @return: True, if activated - @rtype: bool - """ - return self.query_pool_id() != None - - def get_name_label(self): - return self.name_label - - def get_name_description(self): - return self.name_description - - def get_auto_power_on(self): - return self.auto_power_on - - def get_ncpu(self): - return self.ncpu - - def get_sched_policy(self): - if len(self.sched_policy) == 0: - # default scheduler selected - return XendNode.instance().get_vcpus_policy() - else: - return self.sched_policy - - def get_proposed_CPUs(self): - return [ str(cpu) for cpu in self.proposed_cpus ] - - def get_other_config(self): - return self.other_config - - def set_name_label(self, name_label): - self._checkName(name_label) - self.name_label = name_label - if self._managed: - XendNode.instance().save_cpu_pools() - - def set_name_description(self, name_descr): - self.name_description = name_descr - if self._managed: - XendNode.instance().save_cpu_pools() - - def set_auto_power_on(self, auto_power_on): - self.auto_power_on = bool(int(auto_power_on)) - if self._managed: - XendNode.instance().save_cpu_pools() - - def set_ncpu(self, ncpu): - _ncpu = int(ncpu) - if _ncpu < 1: - raise PoolError(XEND_ERROR_POOL_PARAM, 'ncpu') - self.ncpu = _ncpu - if self._managed: - XendNode.instance().save_cpu_pools() - - def set_sched_policy(self, sched_policy): - if self.get_activated(): - raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'activated') - self.sched_policy = sched_policy - if self._managed: - XendNode.instance().save_cpu_pools() - - def set_proposed_CPUs(self, proposed_cpus): - if self.get_activated(): - raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'activated') - self.proposed_cpus = [ int(cpu) for cpu in proposed_cpus ] - if self._managed: - XendNode.instance().save_cpu_pools() - - def set_other_config(self, other_config): - self.other_config = other_config - if self._managed: - XendNode.instance().save_cpu_pools() - - def destroy(self): - """ In order to destroy a cpu pool, it must be deactivated """ - self.pool_lock.acquire() - try: - if self.get_activated(): - raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'activated') - XendBase.destroy(self) - finally: - self.pool_lock.release() - XendNode.instance().save_cpu_pools() - - def activate(self): - """ Create pool in hypervisor and add cpus. - Preconditions: - - pool not already active - - enough unbound cpus available - Actions: - - create pool in hypervisor - - select free cpus (preferred from proposed_CPUs list) and bind it to - the pool - - create entries in Xenstore - """ - self.pool_lock.acquire() - try: - if self.get_activated(): - raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'activated') - sched_policy = self.get_sched_policy() - if sched_policy not in XEN_SCHEDULER_TO_ID.keys(): - raise PoolError(XEND_ERROR_UNKOWN_SCHED_POLICY) - unbound_cpus = set(self.unbound_cpus()) - if len(unbound_cpus) < self.ncpu: - raise PoolError(XEND_ERROR_INSUFFICIENT_CPUS, - [str(self.ncpu), str(len(unbound_cpus))]) - - # build list of cpu numbers to bind to pool - cpu_set = set(self.proposed_cpus).intersection(unbound_cpus) - if len(cpu_set) < self.ncpu: - pool_cpus = (list(cpu_set) + - list(unbound_cpus.difference(cpu_set))) - else: - pool_cpus = list(cpu_set) - pool_cpus = pool_cpus[0:self.ncpu] - - # create pool in hypervisor - pool_id = xc.cpupool_create( - sched = XEN_SCHEDULER_TO_ID.get(sched_policy, 0)) - - self.update_XS(pool_id) - # add cpus - for cpu in pool_cpus: - xc.cpupool_addcpu(pool_id, cpu) - - finally: - self.pool_lock.release() - - def deactivate(self): - """ Delete pool in hypervisor - Preconditions: - - pool is activated - - no running VMs in pool - Actions: - - call hypervisor for deletion - - remove path of pool in xenstore - """ - self.pool_lock.acquire() - try: - if not self.get_activated(): - raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'deactivated') - if len(self.get_started_VMs()) != 0: - raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'in use') - - pool_id = self.query_pool_id() - # remove cpus from pool - cpus = [] - for pool_rec in xc.cpupool_getinfo(): - if pool_rec['cpupool'] == pool_id: - cpus = pool_rec['cpulist'] - for cpu_number in cpus: - xc.cpupool_removecpu(pool_id, cpu_number) - xc.cpupool_destroy(pool_id) - - # update XenStore - xs_path = XS_POOLROOT + "%s/" % pool_id - xstransact.Remove(xs_path) - finally: - self.pool_lock.release() - - def add_host_CPU_live(self, cpu_ref): - """ Add cpu to pool, if it is currently not assigned to a pool. - @param cpu_ref: reference of host_cpu instance to add - @type cpu_ref: str - """ - if not self.get_activated(): - raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'deactivated') - node = XendNode.instance() - number = node.get_host_cpu_field(cpu_ref, 'number') - - self.pool_lock.acquire() - try: - pool_id = self.query_pool_id() - other_pool_ref = self.get_cpu_pool_by_cpu_ref(cpu_ref) - if len(other_pool_ref) != 0: - raise PoolError(XEND_ERROR_INVALID_CPU, - 'cpu already assigned to pool "%s"' % other_pool_ref[0]) - xc.cpupool_addcpu(pool_id, number) - finally: - self.pool_lock.release() - - if number not in self.proposed_cpus: - self.proposed_cpus.append(number) - self._update_ncpu(pool_id) - if self._managed: - XendNode.instance().save_cpu_pools() - - def remove_host_CPU_live(self, cpu_ref): - """ Remove cpu from pool. - After successfull call, the cpu is free. - Remove of the last cpu of the pool is rejected. - @param cpu_ref: reference of host_cpu instance to remove - @type cpu_ref: str - """ - if not self.get_activated(): - raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'deactivated') - node = XendNode.instance() - number = node.get_host_cpu_field(cpu_ref, 'number') - - self.pool_lock.acquire() - try: - pool_id = self.query_pool_id() - pool_rec = {} - for pool in xc.cpupool_getinfo(): - if pool['cpupool'] == pool_id: - pool_rec = pool - break - - if number in pool_rec['cpulist']: - if len(pool_rec['cpulist']) < 2 and pool_rec['n_dom'] > 0: - raise PoolError(XEND_ERROR_LAST_CPU_NOT_REM, - 'could not remove last cpu') - xc.cpupool_removecpu(pool_id, number) - else: - raise PoolError(XEND_ERROR_INVALID_CPU, - 'CPU not assigned to pool') - finally: - self.pool_lock.release() - - if number in self.proposed_cpus: - self.proposed_cpus.remove(number) - self._update_ncpu(pool_id) - if self._managed: - XendNode.instance().save_cpu_pools() - - def add_to_proposed_CPUs(self, cpu): - if self.get_activated(): - raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'activated') - - _cpu = int(cpu) - if _cpu not in self.proposed_cpus: - self.proposed_cpus.append(_cpu) - self.proposed_cpus.sort() - if self._managed: - XendNode.instance().save_cpu_pools() - - def remove_from_proposed_CPUs(self, cpu): - if self.get_activated(): - raise PoolError(XEND_ERROR_BAD_POOL_STATE, 'activated') - _cpu = int(cpu) - if _cpu in self.proposed_cpus: - self.proposed_cpus.remove(_cpu) - if self._managed: - XendNode.instance().save_cpu_pools() - - def add_to_other_config(self, key, value): - self.other_config[key] = value - if self._managed: - XendNode.instance().save_cpu_pools() - - def remove_from_other_config(self, key): - if key in self.other_config: - del self.other_config[key] - if self._managed: - XendNode.instance().save_cpu_pools() - - - # - # Legacy RPC calls - # - def pool_new(cls, config): - try: - record = sxp2map(config) - if record.has_key('proposed_CPUs') and \ - not isinstance(record['proposed_CPUs'], types.ListType): - record['proposed_CPUs'] = [record['proposed_CPUs']] - new_uuid = cls.create(record) - except XendAPIError, ex: - raise VmError(ex.get_api_error()) - return new_uuid - - def pool_create(cls, config): - try: - record = sxp2map(config) - if record.has_key('proposed_CPUs') and \ - not isinstance(record['proposed_CPUs'], types.ListType): - record['proposed_CPUs'] = [record['proposed_CPUs']] - new_uuid = genuuid.createString() - pool = XendCPUPool(record, new_uuid, False) - pool.activate() - except XendAPIError, ex: - raise VmError(ex.get_api_error()) - - def pool_start(cls, poolname): - pool = cls.lookup_pool(poolname) - if not pool: - raise VmError('unknown pool %s' % poolname) - try: - pool.activate() - except XendAPIError, ex: - raise VmError(ex.get_api_error()) - - def pool_list(cls, names): - sxprs = [] - try: - node = XendNode.instance() - xd = XendDomain.instance() - pools = cls.get_all_records() - for (pool_uuid, pool_vals) in pools.items(): - if pool_vals['name_label'] in names or len(names) == 0: - # conv host_cpu refs to cpu number - cpus = [ node.get_host_cpu_field(cpu_ref, 'number') - for cpu_ref in pool_vals['host_CPUs'] ] - cpus.sort() - pool_vals['host_CPU_numbers'] = cpus - # query VMs names. Take in account, that a VM - # returned by get_all_records could be destroy, now - vm_names = [ vm.getName() - for vm in map(xd.get_vm_by_uuid, - pool_vals['started_VMs']) - if vm ] - pool_vals['started_VM_names'] = vm_names - pool_vals['auto_power_on'] = int(pool_vals['auto_power_on']) - sxprs += [[pool_uuid] + map2sxp(pool_vals)] - except XendAPIError, ex: - raise VmError(ex.get_api_error()) - return sxprs - - def pool_destroy(cls, poolname): - pool = cls.lookup_pool(poolname) - if not pool: - raise VmError('unknown pool %s' % poolname) - try: - pool.deactivate() - if not pool.is_managed(): - pool.destroy() - except XendAPIError, ex: - raise VmError(ex.get_api_error()) - - def pool_delete(cls, poolname): - pool = cls.lookup_pool(poolname) - if not pool: - raise VmError('unknown pool %s' % poolname) - try: - pool.destroy() - except XendAPIError, ex: - raise VmError(ex.get_api_error()) - - def pool_cpu_add(cls, poolname, cpu): - pool = cls.lookup_pool(poolname) - if not pool: - raise VmError('unknown pool %s' % poolname) - try: - cpu_ref = cls._cpu_number_to_ref(int(cpu)) - if cpu_ref: - pool.add_host_CPU_live(cpu_ref) - else: - raise PoolError(XEND_ERROR_INVALID_CPU, - 'CPU unknown') - except XendAPIError, ex: - raise VmError(ex.get_api_error()) - - def pool_cpu_remove(cls, poolname, cpu): - pool = cls.lookup_pool(poolname) - if not pool: - raise VmError('unknown pool %s' % poolname) - try: - cpu_ref = cls._cpu_number_to_ref(int(cpu)) - if cpu_ref: - pool.remove_host_CPU_live(cpu_ref) - else: - raise PoolError(XEND_ERROR_INVALID_CPU, - 'CPU unknown') - except XendAPIError, ex: - raise VmError(ex.get_api_error()) - - def pool_migrate(cls, domname, poolname): - dom = XendDomain.instance() - pool = cls.lookup_pool(poolname) - if not pool: - raise VmError('unknown pool %s' % poolname) - dominfo = dom.domain_lookup_nr(domname) - if not dominfo: - raise VmError('unknown domain %s' % domname) - domid = dominfo.getDomid() - if domid is not None: - if domid == 0: - raise VmError('could not move Domain-0') - try: - cls.move_domain(pool.get_uuid(), domid) - except Exception, ex: - raise VmError('could not move domain') - dominfo.info['pool_name'] = poolname - dom.managed_config_save(dominfo) - - pool_new = classmethod(pool_new) - pool_create = classmethod(pool_create) - pool_start = classmethod(pool_start) - pool_list = classmethod(pool_list) - pool_destroy = classmethod(pool_destroy) - pool_delete = classmethod(pool_delete) - pool_cpu_add = classmethod(pool_cpu_add) - pool_cpu_remove = classmethod(pool_cpu_remove) - pool_migrate = classmethod(pool_migrate) - - - # - # methods - # - - def is_managed(self): - """ Check, if pool is managed. - @return: True, if managed - @rtype: bool - """ - return self._managed - - def query_pool_id(self): - """ Get corresponding pool-id of pool instance from XenStore. - @return: pool id or None - @rytpe: int - """ - self.pool_lock.acquire() - try: - for pool_id in xstransact.List(XS_POOLROOT): - uuid = xstransact.Read(XS_POOLROOT + "%s/" % pool_id, 'uuid') - if uuid == self.get_uuid(): - return int(pool_id) - finally: - self.pool_lock.release() - - return None - - def update_XS(self, pool_id): - """ Write (or update) data in xenstore taken from instance. - @param pool_id: Pool id to build path to pool data in xenstore - @type pool_id: int - """ - self.pool_lock.acquire() - try: - xs_path = XS_POOLROOT + "%s/" % pool_id - xs_entries = { 'uuid' : self.get_uuid(), - 'name' : self.name_label, - 'description' : self.name_description - } - xstransact.Mkdir(xs_path) - xstransact.Mkdir(xs_path, 'other_config') - xstransact.Write(xs_path, xs_entries) - xstransact.Write('%s%s' % (xs_path, 'other_config'), - self.other_config) - finally: - self.pool_lock.release() - - def _update_ncpu(self, pool_id): - for pool_rec in xc.cpupool_getinfo(): - if pool_rec['cpupool'] == pool_id: - self.ncpu = len(pool_rec['cpulist']) - - def _checkName(self, name): - """ Check if a pool name is valid. Valid names contain alphabetic - characters, digits, or characters in '_-.:/+'. - The same name cannot be used for more than one pool at the same - time. - @param name: name - @type name: str - @raise: PoolError if invalid - """ - if name is None or name == '': - raise PoolError(XEND_ERROR_POOL_PARAM, 'Missing Pool Name') - if not re.search(r'^[A-Za-z0-9_\-\.\:\/\+]+$', name): - raise PoolError(XEND_ERROR_POOL_PARAM, 'Invalid Pool Name') - - pool = self.lookup_pool(name) - if pool and pool.get_uuid() != self.get_uuid(): - raise PoolError(XEND_ERROR_POOL_PARAM, - 'Pool name "%s" already exists' % name) - - - # - # class methods - # - - def recreate_active_pools(cls): - """ Read active pool config from hypervisor and create pool instances. - - Query pool ids and assigned CPUs from hypervisor. - - Query additional information for any pool from xenstore. - If an entry for a pool id is missing in xenstore, it will be - recreated with a new uuid and generic name (this is an error case) - - Create an XendCPUPool instance for any pool id - Function have to be called after recreation of managed pools. - """ - log.debug('recreate_active_pools') - - for pool_rec in xc.cpupool_getinfo(): - pool = pool_rec['cpupool'] - - # read pool data from xenstore - path = XS_POOLROOT + "%s/" % pool - uuid = xstransact.Read(path, 'uuid') - if not uuid: - # xenstore entry missing / invaild; create entry with new uuid - uuid = genuuid.createString() - name = "Pool-%s" % pool - try: - inst = XendCPUPool( { 'name_label' : name }, uuid, False ) - inst.update_XS(pool) - except PoolError, ex: - # log error and skip domain - log.error('cannot recreate pool %s; skipping (reason: %s)' \ - % (name, ex)) - else: - (name, descr) = xstransact.Read(path, 'name', 'description') - other_config = {} - for key in xstransact.List(path + 'other_config'): - other_config[key] = xstransact.Read( - path + 'other_config/%s' % key) - - # check existance of pool instance - inst = XendAPIStore.get(uuid, cls.getClass()) - if inst: - # update attributes of existing instance - inst.name_label = name - inst.name_description = descr - inst.other_config = other_config - else: - # recreate instance - try: - inst = XendCPUPool( - { 'name_label' : name, - 'name_description' : descr, - 'other_config' : other_config, - 'proposed_CPUs' : pool_rec['cpulist'], - 'ncpu' : len(pool_rec['cpulist']), - }, - uuid, False ) - except PoolError, ex: - # log error and skip domain - log.error( - 'cannot recreate pool %s; skipping (reason: %s)' \ - % (name, ex)) - - recreate_active_pools = classmethod(recreate_active_pools) - - - def recreate(cls, record, current_uuid): - """ Recreate a pool instance while xend restart. - @param record: attributes of pool - @type record: dict - @param current_uuid: uuid of pool to create - @type current_uuid: str - """ - XendCPUPool(record, current_uuid) - - recreate = classmethod(recreate) - - - def autostart_pools(cls): - """ Start managed pools that are marked as autostart pools. - Function is called after recreation of managed domains while - xend restart. - """ - cls.pool_lock.acquire() - try: - for inst in XendAPIStore.get_all(cls.getClass()): - if inst.is_managed() and inst.auto_power_on and \ - inst.query_pool_id() == None: - inst.activate() - finally: - cls.pool_lock.release() - - autostart_pools = classmethod(autostart_pools) - - - def move_domain(cls, pool_ref, domid): - cls.pool_lock.acquire() - try: - pool = XendAPIStore.get(pool_ref, cls.getClass()) - pool_id = pool.query_pool_id() - - xc.cpupool_movedomain(pool_id, domid) - finally: - cls.pool_lock.release() - - move_domain = classmethod(move_domain) - - - def query_pool_ref(cls, pool_id): - """ Get pool ref by pool id. - Take the ref from xenstore. - @param pool_id: - @type pool_id: int - @return: ref - @rtype: str - """ - uuid = xstransact.Read(XS_POOLROOT + "%s/" % pool_id, 'uuid') - if uuid: - return [uuid] - else: - return [] - - query_pool_ref = classmethod(query_pool_ref) - - - def lookup_pool(cls, id_or_name): - """ Search XendCPUPool instance with given id_or_name. - @param id_or_name: pool id or pool nameto search - @type id_or_name: [int, str] - @return: instane or None if not found - @rtype: XendCPUPool - """ - pool_uuid = None - try: - pool_id = int(id_or_name) - # pool id given ? - pool_uuid = cls.query_pool_ref(pool_id) - if not pool_uuid: - # not found -> search name - pool_uuid = cls.get_by_name_label(id_or_name) - except ValueError: - # pool name given - pool_uuid = cls.get_by_name_label(id_or_name) - - if len(pool_uuid) > 0: - return XendAPIStore.get(pool_uuid[0], cls.getClass()) - else: - return None - - lookup_pool = classmethod(lookup_pool) - - - def number_of_pools(cls): - return len(xc.cpupool_getinfo()) - - number_of_pools = classmethod(number_of_pools) - - def _cpu_number_to_ref(cls, number): - node = XendNode.instance() - for cpu_ref in node.get_host_cpu_refs(): - if node.get_host_cpu_field(cpu_ref, 'number') == number: - return cpu_ref - return None - - _cpu_number_to_ref = classmethod(_cpu_number_to_ref) - - - def unbound_cpus(cls): - """ Build list containing the numbers of all cpus not bound to a pool. - Info is taken from Hypervisor. - @return: list of cpu numbers - @rytpe: list of int - """ - return xc.cpupool_freeinfo() - - unbound_cpus = classmethod(unbound_cpus) - diff --git a/tools/python/xen/xend/XendCheckpoint.py b/tools/python/xen/xend/XendCheckpoint.py deleted file mode 100644 index b8caf0221b..0000000000 --- a/tools/python/xen/xend/XendCheckpoint.py +++ /dev/null @@ -1,425 +0,0 @@ -# Copyright (C) 2005 Christian Limpach -# Copyright (C) 2005 XenSource Ltd - -# This file is subject to the terms and conditions of the GNU General -# Public License. See the file "COPYING" in the main directory of -# this archive for more details. - -import os -import os.path -import re -import string -import threading -import fcntl -from struct import pack, unpack, calcsize - -from xen.util.xpopen import xPopen3 -import xen.util.auxbin -import xen.lowlevel.xc - -from xen.xend import balloon, sxp, image -from xen.xend.XendError import XendError, VmError -from xen.xend.XendLogging import log -from xen.xend.XendConfig import XendConfig -from xen.xend.XendConstants import * -from xen.xend import XendNode - -SIGNATURE = "LinuxGuestRecord" -QEMU_SIGNATURE = "QemuDeviceModelRecord" -dm_batch = 512 -XC_SAVE = "xc_save" -XC_RESTORE = "xc_restore" - - -sizeof_int = calcsize("i") -sizeof_unsigned_int = calcsize("I") -sizeof_unsigned_long = calcsize("L") - - -xc = xen.lowlevel.xc.xc() - - -def write_exact(fd, buf, errmsg): - if os.write(fd, buf) != len(buf): - raise XendError(errmsg) - - -def read_exact(fd, size, errmsg): - buf = '' - while size != 0: - readstr = os.read(fd, size) - if not len(readstr): - log.error("read_exact: EOF trying to read %d (buf='%s')" % \ - (size, buf)) - raise XendError(errmsg) - size = size - len(readstr) - buf = buf + readstr - return buf - - -def insert_after(list, pred, value): - for i,k in enumerate(list): - if type(k) == type([]): - if k[0] == pred: - list.insert (i+1, value) - return - - -def save(fd, dominfo, network, live, dst, checkpoint=False, node=-1,sock=None): - from xen.xend import XendDomain - - try: - if not os.path.isdir("/var/lib/xen"): - os.makedirs("/var/lib/xen") - except Exception, exn: - log.exception("Can't create directory '/var/lib/xen'") - raise XendError("Can't create directory '/var/lib/xen'") - - write_exact(fd, SIGNATURE, "could not write guest state file: signature") - - sxprep = dominfo.sxpr() - - if node > -1: - insert_after(sxprep,'vcpus',['node', str(node)]) - - for device_sxp in sxp.children(sxprep, 'device'): - backend = sxp.child(device_sxp[1], 'backend') - if backend == None: - continue - bkdominfo = XendDomain.instance().domain_lookup_nr(backend[1]) - if bkdominfo == None: - raise XendError("Could not find backend: %s" % backend[1]) - if bkdominfo.getDomid() == XendDomain.DOM0_ID: - # Skip for compatibility of checkpoint data format - continue - backend[1] = bkdominfo.getName() - - config = sxp.to_string(sxprep) - - domain_name = dominfo.getName() - # Rename the domain temporarily, so that we don't get a name clash if this - # domain is migrating (live or non-live) to the local host. Doing such a - # thing is useful for debugging. - dominfo.setName('migrating-' + domain_name) - - try: - dominfo.migrateDevices(network, dst, DEV_MIGRATE_STEP1, domain_name) - - write_exact(fd, pack("!i", len(config)), - "could not write guest state file: config len") - write_exact(fd, config, "could not write guest state file: config") - - image_cfg = dominfo.info.get('image', {}) - hvm = dominfo.info.is_hvm() - - # xc_save takes three customization parameters: maxit, max_f, and - # flags the last controls whether or not save is 'live', while the - # first two further customize behaviour when 'live' save is - # enabled. Passing "0" simply uses the defaults compiled into - # libxenguest; see the comments and/or code in xc_linux_save() for - # more information. - cmd = [xen.util.auxbin.pathTo(XC_SAVE), str(fd), - str(dominfo.getDomid()), "0", "0", - str(int(live) | (int(hvm) << 2)) ] - log.debug("[xc_save]: %s", string.join(cmd)) - - def saveInputHandler(line, tochild): - log.debug("In saveInputHandler %s", line) - if line == "suspend": - log.debug("Suspending %d ...", dominfo.getDomid()) - dominfo.shutdown('suspend') - dominfo.waitForSuspend() - if line in ('suspend', 'suspended'): - dominfo.migrateDevices(network, dst, DEV_MIGRATE_STEP2, - domain_name) - log.info("Domain %d suspended.", dominfo.getDomid()) - dominfo.migrateDevices(network, dst, DEV_MIGRATE_STEP3, - domain_name) - if hvm: - dominfo.image.saveDeviceModel() - - if line == "suspend": - tochild.write("done\n") - tochild.flush() - log.debug('Written done') - - forkHelper(cmd, fd, saveInputHandler, False) - - # put qemu device model state - if os.path.exists("/var/lib/xen/qemu-save.%d" % dominfo.getDomid()): - write_exact(fd, QEMU_SIGNATURE, "could not write qemu signature") - qemu_fd = os.open("/var/lib/xen/qemu-save.%d" % dominfo.getDomid(), - os.O_RDONLY) - while True: - buf = os.read(qemu_fd, dm_batch) - if len(buf): - write_exact(fd, buf, "could not write device model state") - else: - break - os.close(qemu_fd) - os.remove("/var/lib/xen/qemu-save.%d" % dominfo.getDomid()) - - if checkpoint: - dominfo.resumeDomain() - else: - if live and sock != None: - try: - sock.shutdown(2) - except: - pass - sock.close() - - dominfo.destroy() - dominfo.testDeviceComplete() - try: - dominfo.setName(domain_name, False) - except VmError: - # Ignore this. The name conflict (hopefully) arises because we - # are doing localhost migration; if we are doing a suspend of a - # persistent VM, we need the rename, and don't expect the - # conflict. This needs more thought. - pass - - except Exception, exn: - log.exception("Save failed on domain %s (%s) - resuming.", domain_name, - dominfo.getDomid()) - dominfo.resumeDomain() - - try: - dominfo.setName(domain_name) - except: - log.exception("Failed to reset the migrating domain's name") - - raise exn - - -def restore(xd, fd, dominfo = None, paused = False, relocating = False): - try: - if not os.path.isdir("/var/lib/xen"): - os.makedirs("/var/lib/xen") - except Exception, exn: - log.exception("Can't create directory '/var/lib/xen'") - raise XendError("Can't create directory '/var/lib/xen'") - - signature = read_exact(fd, len(SIGNATURE), - "not a valid guest state file: signature read") - if signature != SIGNATURE: - raise XendError("not a valid guest state file: found '%s'" % - signature) - - l = read_exact(fd, sizeof_int, - "not a valid guest state file: config size read") - vmconfig_size = unpack("!i", l)[0] - vmconfig_buf = read_exact(fd, vmconfig_size, - "not a valid guest state file: config read") - - p = sxp.Parser() - p.input(vmconfig_buf) - if not p.ready: - raise XendError("not a valid guest state file: config parse") - - vmconfig = p.get_val() - - if not relocating: - domconfig = XendConfig(sxp_obj = vmconfig) - othervm = xd.domain_lookup_nr(domconfig["name_label"]) - if othervm is None or othervm.domid is None: - othervm = xd.domain_lookup_nr(domconfig["uuid"]) - if othervm is not None and othervm.domid is not None: - raise VmError("Domain '%s' already exists with ID '%d'" % (domconfig["name_label"], othervm.domid)) - - if dominfo: - dominfo.resume() - else: - dominfo = xd.restore_(vmconfig) - - image_cfg = dominfo.info.get('image', {}) - is_hvm = dominfo.info.is_hvm() - - if is_hvm: - nomigrate = dominfo.info['platform'].get('nomigrate', 0) - else: - nomigrate = dominfo.info['platform'].get('nomigrate') - if nomigrate is None: - nomigrate = 0 - if int(nomigrate) != 0: - dominfo.destroy() - raise XendError("cannot restore non-migratable domain") - - store_port = dominfo.getStorePort() - console_port = dominfo.getConsolePort() - - # if hvm, pass mem size to calculate the store_mfn - if is_hvm: - apic = int(dominfo.info['platform'].get('apic', 0)) - pae = int(dominfo.info['platform'].get('pae', 0)) - log.info("restore hvm domain %d, apic=%d, pae=%d", - dominfo.domid, apic, pae) - else: - apic = 0 - pae = 0 - - try: - assert store_port - assert console_port - - restore_image = image.create(dominfo, dominfo.info) - memory = restore_image.getRequiredAvailableMemory( - dominfo.info['memory_dynamic_max'] / 1024) - maxmem = restore_image.getRequiredAvailableMemory( - dominfo.info['memory_static_max'] / 1024) - shadow = restore_image.getRequiredShadowMemory( - dominfo.info['shadow_memory'] * 1024, - dominfo.info['memory_static_max'] / 1024) - - log.debug("restore:shadow=0x%x, _static_max=0x%x, _static_min=0x%x, ", - dominfo.info['shadow_memory'], - dominfo.info['memory_static_max'], - dominfo.info['memory_static_min']) - - # Round shadow up to a multiple of a MiB, as shadow_mem_control - # takes MiB and we must not round down and end up under-providing. - shadow = ((shadow + 1023) / 1024) * 1024 - - # set memory limit - xc.domain_setmaxmem(dominfo.getDomid(), maxmem) - - vtd_mem = 0 - info = xc.physinfo() - if 'hvm_directio' in info['virt_caps']: - # Reserve 1 page per MiB of RAM for separate VT-d page table. - vtd_mem = 4 * (dominfo.info['memory_static_max'] / 1024 / 1024) - # Round vtd_mem up to a multiple of a MiB. - vtd_mem = ((vtd_mem + 1023) / 1024) * 1024 - - balloon.free(memory + shadow + vtd_mem, dominfo) - - shadow_cur = xc.shadow_mem_control(dominfo.getDomid(), shadow / 1024) - dominfo.info['shadow_memory'] = shadow_cur - - superpages = restore_image.superpages - - cmd = map(str, [xen.util.auxbin.pathTo(XC_RESTORE), - fd, dominfo.getDomid(), - store_port, console_port, int(is_hvm), pae, apic, superpages, 1]) - log.debug("[xc_restore]: %s", string.join(cmd)) - - handler = RestoreInputHandler() - - forkHelper(cmd, fd, handler.handler, True) - - # We don't want to pass this fd to any other children -- we - # might need to recover the disk space that backs it. - try: - flags = fcntl.fcntl(fd, fcntl.F_GETFD) - flags |= fcntl.FD_CLOEXEC - fcntl.fcntl(fd, fcntl.F_SETFD, flags) - except: - pass - - if handler.store_mfn is None: - raise XendError('Could not read store MFN') - - if not is_hvm and handler.console_mfn is None: - raise XendError('Could not read console MFN') - - restore_image.setCpuid() - - # xc_restore will wait for source to close connection - - dominfo.completeRestore(handler.store_mfn, handler.console_mfn) - - # - # We shouldn't hold the domains_lock over a waitForDevices - # As this function sometime gets called holding this lock, - # we must release it and re-acquire it appropriately - # - from xen.xend import XendDomain - - lock = True; - try: - XendDomain.instance().domains_lock.release() - except: - lock = False; - - try: - dominfo.waitForDevices() # Wait for backends to set up - finally: - if lock: - XendDomain.instance().domains_lock.acquire() - - if not paused: - dominfo.unpause() - - return dominfo - except Exception, exn: - dominfo.destroy() - log.exception(exn) - raise exn - - -class RestoreInputHandler: - def __init__(self): - self.store_mfn = None - self.console_mfn = None - - - def handler(self, line, _): - m = re.match(r"^(store-mfn) (\d+)$", line) - if m: - self.store_mfn = int(m.group(2)) - else: - m = re.match(r"^(console-mfn) (\d+)$", line) - if m: - self.console_mfn = int(m.group(2)) - - -def forkHelper(cmd, fd, inputHandler, closeToChild): - child = xPopen3(cmd, True, -1, [fd]) - - if closeToChild: - child.tochild.close() - - thread = threading.Thread(target = slurp, args = (child.childerr,)) - thread.start() - - try: - try: - while 1: - line = child.fromchild.readline() - if line == "": - break - else: - line = line.rstrip() - log.debug('%s', line) - inputHandler(line, child.tochild) - - except IOError, exn: - raise XendError('Error reading from child process for %s: %s' % - (cmd, exn)) - finally: - child.fromchild.close() - if not closeToChild: - child.tochild.close() - thread.join() - child.childerr.close() - status = child.wait() - - if status >> 8 == 127: - raise XendError("%s failed: popen failed" % string.join(cmd)) - elif status != 0: - raise XendError("%s failed" % string.join(cmd)) - - -def slurp(infile): - while 1: - line = infile.readline() - if line == "": - break - else: - line = line.strip() - m = re.match(r"^ERROR: (.*)", line) - if m is None: - log.info('%s', line) - else: - log.error('%s', m.group(1)) diff --git a/tools/python/xen/xend/XendClient.py b/tools/python/xen/xend/XendClient.py deleted file mode 100644 index ef16699c4b..0000000000 --- a/tools/python/xen/xend/XendClient.py +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env python -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2006 Anthony Liguori -#============================================================================ - -from xen.util.xmlrpcclient import ServerProxy -import os -import sys - -XML_RPC_SOCKET = "/var/run/xend/xmlrpc.sock" -XEN_API_SOCKET = "/var/run/xend/xen-api.sock" - -ERROR_INTERNAL = 1 -ERROR_GENERIC = 2 -ERROR_INVALID_DOMAIN = 3 - -uri = 'httpu:///var/run/xend/xmlrpc.sock' -if os.environ.has_key('XM_SERVER'): - uri = os.environ['XM_SERVER'] - -try: - server = ServerProxy(uri) -except ValueError, exn: - print >>sys.stderr, exn - sys.exit(1) - diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py deleted file mode 100644 index 4a226a7155..0000000000 --- a/tools/python/xen/xend/XendConfig.py +++ /dev/null @@ -1,2265 +0,0 @@ -#=========================================================================== -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2006-2007 XenSource Ltd -#============================================================================ - -import logging -import os -import re -import time -import types - -from xen.xend import sxp -from xen.xend import uuid -from xen.xend import XendOptions -from xen.xend import XendAPIStore -from xen.xend.XendPPCI import XendPPCI -from xen.xend.XendDPCI import XendDPCI -from xen.xend.XendPSCSI import XendPSCSI -from xen.xend.XendDSCSI import XendDSCSI, XendDSCSI_HBA -from xen.xend.XendError import VmError -from xen.xend.XendDevices import XendDevices -from xen.xend.PrettyPrint import prettyprintstring -from xen.xend.XendConstants import DOM_STATE_HALTED, AUTO_PHP_SLOT -from xen.xend.xenstore.xstransact import xstransact -from xen.xend.server.BlktapController import blktap_disk_types -from xen.xend.server.netif import randomMAC -from xen.util.blkif import blkdev_name_to_number, blkdev_uname_to_file -from xen.util.pci import pci_opts_list_from_sxp, pci_convert_sxp_to_dict -from xen.xend.XendSXPDev import dev_dict_to_sxp -from xen.util import xsconstants -from xen.util import auxbin -from xen.xend.XendAPIConstants import * -import xen.util.fileuri - -log = logging.getLogger("xend.XendConfig") -log.setLevel(logging.WARN) - - -""" -XendConfig API - - XendConfig will try to mirror as closely the Xen API VM Struct - with extra parameters for those options that are not supported. - -""" - -def reverse_dict(adict): - """Return the reverse mapping of a dictionary.""" - return dict([(v, k) for k, v in adict.items()]) - -def bool0(v): - return v != '0' and v != 'False' and bool(v) - -def convert_on_crash(v): - v = str(v) - if v in XEN_API_ON_CRASH_BEHAVIOUR: - return XEN_API_ON_CRASH_BEHAVIOUR_LEGACY[v] - else: - return v - -# Recursively copy a data struct, scrubbing out VNC passwords. -# Will scrub any dict entry with a key of 'vncpasswd' or any -# 2-element list whose first member is 'vncpasswd'. It will -# also scrub a string matching '(vncpasswd XYZ)'. Everything -# else is no-op passthrough -def scrub_password(data): - if type(data) == dict or type(data) == XendConfig: - scrubbed = {} - for key in data.keys(): - if key == "vncpasswd": - scrubbed[key] = "XXXXXXXX" - else: - scrubbed[key] = scrub_password(data[key]) - return scrubbed - elif type(data) == list: - if len(data) == 2 and type(data[0]) == str and data[0] == 'vncpasswd': - return ['vncpasswd', 'XXXXXXXX'] - else: - scrubbed = [] - for entry in data: - scrubbed.append(scrub_password(entry)) - return scrubbed - elif type(data) == tuple: - scrubbed = [] - for entry in data: - scrubbed.append(scrub_password(entry)) - return tuple(scrubbed) - elif type(data) == str: - return re.sub(r'\(vncpasswd\s+[^\)]+\)','(vncpasswd XXXXXX)', data) - else: - return data - -# -# CPU fields: -# -# VCPUs_max -- the maximum number of vcpus that this domain may ever have. -# aka XendDomainInfo.getVCpuCount(). -# vcpus -- the legacy configuration name for above. -# max_vcpu_id -- vcpus_number - 1. This is given to us by Xen. -# -# cpus -- the list of pCPUs available to each vCPU. -# -# vcpu_avail -- a bitmap telling the guest domain whether it may use each of -# its VCPUs. This is translated to -# /cpu//availability = {online,offline} for use -# by the guest domain. -# VCPUs_live -- the number of VCPUs currently up, as reported by Xen. This -# is changed by changing vcpu_avail, and waiting for the -# domain to respond. -# - - -# Mapping from XendConfig configuration keys to the old -# legacy configuration keys that map directly. - -XENAPI_CFG_TO_LEGACY_CFG = { - 'uuid': 'uuid', - 'VCPUs_max': 'vcpus', - 'cpus': 'cpus', - 'name_label': 'name', - 'actions_after_shutdown': 'on_poweroff', - 'actions_after_reboot': 'on_reboot', - 'actions_after_crash': 'on_crash', - 'PV_bootloader': 'bootloader', - 'PV_bootloader_args': 'bootloader_args', - 'Description': 'description', - 'pool_name' : 'pool_name', -} - -LEGACY_CFG_TO_XENAPI_CFG = reverse_dict(XENAPI_CFG_TO_LEGACY_CFG) - -# Platform configuration keys and their types. -XENAPI_PLATFORM_CFG_TYPES = { - 'acpi': int, - 'apic': int, - 'boot': str, - 'device_model': str, - 'loader': str, - 'display' : str, - 'fda': str, - 'fdb': str, - 'keymap': str, - 'isa' : int, - 'localtime': int, - 'monitor': int, - 'monitor_path': str, - 'nographic': int, - 'nomigrate': int, - 'pae' : int, - 'rtc_timeoffset': int, - 'parallel': str, - 'serial': str, - 'sdl': int, - 'opengl': int, - 'soundhw': str, - 'stdvga': int, - 'videoram': int, - 'usb': int, - 'usbdevice': str, - 'hpet': int, - 'vnc': int, - 'vncconsole': int, - 'vncdisplay': int, - 'vnclisten': str, - 'timer_mode': int, - 'tsc_mode': int, - 'vpt_align': int, - 'viridian': int, - 'vncpasswd': str, - 'vncunused': int, - 'xauthority': str, - 'pci': str, - 'vhpt': int, - 'guest_os_type': str, - 'hap': int, - 'nestedhvm' : int, - 'xen_extended_power_mgmt': int, - 'pci_msitranslate': int, - 'pci_power_mgmt': int, - 'xen_platform_pci': int, - "gfx_passthru": int, - 'oos' : int, -} - -# Xen API console 'other_config' keys. -XENAPI_CONSOLE_OTHER_CFG = ['vncunused', 'vncdisplay', 'vnclisten', - 'vncpasswd', 'sdl', 'vnc', 'display', 'xauthority', - 'keymap', 'opengl'] - -# List of XendConfig configuration keys that have no direct equivalent -# in the old world. - -XENAPI_CFG_TYPES = { - 'uuid': str, - 'name_label': str, - 'name_description': str, - 'user_version': str, - 'is_a_template': bool0, - 'auto_power_on': bool0, - 'resident_on': str, - 'memory_static_min': int, # note these are stored in bytes, not KB! - 'memory_static_max': int, - 'memory_dynamic_min': int, - 'memory_dynamic_max': int, - 'cpus': list, - 'vcpus_params': dict, - 'VCPUs_max': int, - 'VCPUs_at_startup': int, - 'VCPUs_live': int, - 'actions_after_shutdown': str, - 'actions_after_reboot': str, - 'actions_after_crash': convert_on_crash, - 'PV_bootloader': str, - 'PV_kernel': str, - 'PV_ramdisk': str, - 'PV_args': str, - 'PV_bootloader_args': str, - 'HVM_boot_policy': str, - 'HVM_boot_params': dict, - 'PCI_bus': str, - 'platform': dict, - 'tools_version': dict, - 'other_config': dict, - 'target': int, - 'security_label': str, - 'pci': str, - 'cpuid' : dict, - 'cpuid_check' : dict, - 'machine_address_size': int, - 'suppress_spurious_page_faults': bool0, - 's3_integrity' : int, - 'superpages' : int, - 'memory_sharing': int, - 'pool_name' : str, - 'Description': str, -} - -# List of legacy configuration keys that have no equivalent in the -# Xen API, but are still stored in XendConfig. - -LEGACY_UNSUPPORTED_BY_XENAPI_CFG = [ - # roundtripped (dynamic, unmodified) - 'shadow_memory', - 'vcpu_avail', - 'features', - # read/write - 'on_xend_start', - 'on_xend_stop', - # read-only - 'domid', - 'start_time', - 'cpu_time', - 'online_vcpus', - # write-once - 'cpu', - 'cpus', -] - -LEGACY_CFG_TYPES = { - 'uuid': str, - 'name': str, - 'vcpus': int, - 'vcpu_avail': long, - 'memory': int, - 'shadow_memory': int, - 'maxmem': int, - 'start_time': float, - 'cpu_time': float, - 'features': str, - 'localtime': int, - 'on_poweroff': str, - 'on_reboot': str, - 'on_crash': str, - 'on_xend_stop': str, - 'on_xend_start': str, - 'online_vcpus': int, - 'rtc/timeoffset': str, - 'bootloader': str, - 'bootloader_args': str, - 'description': str, - 'pool_name': str, -} - -# Values that should be stored in xenstore's /vm/ that is used -# by Xend. Used in XendDomainInfo to restore running VM state from -# xenstore. -LEGACY_XENSTORE_VM_PARAMS = [ - 'uuid', - 'name', - 'vcpus', - 'vcpu_avail', - 'memory', - 'shadow_memory', - 'maxmem', - 'start_time', - 'on_poweroff', - 'on_crash', - 'on_reboot', - 'on_xend_start', - 'on_xend_stop', - 'bootloader', - 'bootloader_args', - 'pool_name', -] - -## -## Config Choices -## - -CONFIG_RESTART_MODES = ('restart', 'destroy', 'preserve', 'rename-restart', - 'coredump-destroy', 'coredump-restart') -CONFIG_OLD_DOM_STATES = ('running', 'blocked', 'paused', 'shutdown', - 'crashed', 'dying') - -class XendConfigError(VmError): - def __str__(self): - return 'Invalid Configuration: %s' % str(self.value) - -## -## XendConfig Class (an extended dictionary) -## - -class XendConfig(dict): - """ The new Xend VM Configuration. - - Stores the configuration in xenapi compatible format but retains - import and export functions for SXP. - """ - def __init__(self, filename = None, sxp_obj = None, - xapi = None, dominfo = None): - - dict.__init__(self) - self.update(self._defaults()) - - if filename: - try: - sxp_obj = sxp.parse(open(filename,'r')) - sxp_obj = sxp_obj[0] - except IOError, e: - raise XendConfigError("Unable to read file: %s" % filename) - - if sxp_obj: - self._sxp_to_xapi(sxp_obj) - self._sxp_to_xapi_unsupported(sxp_obj) - elif xapi: - self.update_with_xenapi_config(xapi) - elif dominfo: - # output from xc.domain_getinfo - self._dominfo_to_xapi(dominfo, update_mem = True) - - self.handle_fileuris() - - log.debug('XendConfig.init: %s' % scrub_password(self)) - - # validators go here - self.validate() - - """ In time, we should enable this type checking addition. It is great - also for tracking bugs and unintended writes to XendDomainInfo.info - def __setitem__(self, key, value): - type_conv = XENAPI_CFG_TYPES.get(key) - if callable(type_conv): - try: - dict.__setitem__(self, key, type_conv(value)) - except (ValueError, TypeError): - raise XendConfigError("Wrong type for configuration value " + - "%s. Expected %s" % - (key, type_conv.__name__)) - else: - dict.__setitem__(self, key, value) - """ - - def _defaults(self): - defaults = { - 'name_label': 'Domain-Unnamed', - 'actions_after_shutdown': 'destroy', - 'actions_after_reboot': 'restart', - 'actions_after_crash': 'restart', - 'actions_after_suspend': '', - 'is_a_template': False, - 'auto_power_on': False, - 'is_control_domain': False, - 'features': '', - 'PV_bootloader': '', - 'PV_kernel': '', - 'PV_ramdisk': '', - 'PV_args': '', - 'PV_bootloader_args': '', - 'HVM_boot_policy': '', - 'HVM_boot_params': {}, - 'memory_static_min': 0, - 'memory_dynamic_min': 0, - 'shadow_memory': 0, - 'memory_static_max': 0, - 'memory_dynamic_max': 0, - 'memory_sharing': 0, - 'devices': {}, - 'on_xend_start': 'ignore', - 'on_xend_stop': 'ignore', - 'cpus': [], - 'VCPUs_max': 1, - 'VCPUs_live': 1, - 'VCPUs_at_startup': 1, - 'vcpus_params': {}, - 'console_refs': [], - 'vif_refs': [], - 'vbd_refs': [], - 'other_config': {}, - 'platform': {}, - 'target': 0, - 'pool_name' : 'Pool-0', - 'superpages': 0, - 'description': '', - } - - return defaults - - # - # Here we assume these values exist in the dict. - # If they don't we have a bigger problem, lets not - # try and 'fix it up' but acutually fix the cause ;-) - # - def _memory_sanity_check(self): - log.trace("_memory_sanity_check memory_static_min: %s, " - "memory_static_max: %i, " - "memory_dynamic_min: %i, " - "memory_dynamic_max: %i", - self["memory_static_min"], - self["memory_static_max"], - self["memory_dynamic_min"], - self["memory_dynamic_max"]) - - if not self["memory_static_min"] <= self["memory_static_max"]: - raise XendConfigError("memory_static_min must be less " \ - "than or equal to memory_static_max") - if not self["memory_static_min"] <= self["memory_dynamic_min"]: - raise XendConfigError("memory_static_min must be less " \ - "than or equal to memory_dynamic_min") - if not self["memory_dynamic_max"] <= self["memory_static_max"]: - raise XendConfigError("memory_dynamic_max must be less " \ - "than or equal to memory_static_max") - if not self["memory_dynamic_max"] > 0: - raise XendConfigError("memory_dynamic_max must be greater " \ - "than zero") - if not self["memory_static_max"] > 0: - raise XendConfigError("memory_static_max must be greater " \ - "than zero") - if self["memory_sharing"] and not self.is_hvm(): - raise XendConfigError("memory_sharing can only be enabled " \ - "for HVM domains") - if self["memory_sharing"] and not self.is_hap(): - raise XendConfigError("memory_sharing can only be enabled " \ - "for HAP enabled boxes") - - def _actions_sanity_check(self): - for event in ['shutdown', 'reboot', 'crash']: - if self['actions_after_' + event] not in CONFIG_RESTART_MODES: - raise XendConfigError('Invalid event handling mode: ' + - event) - - def _vcpus_sanity_check(self): - if 'VCPUs_max' in self and 'vcpu_avail' not in self: - self['vcpu_avail'] = (1 << self['VCPUs_max']) - 1 - if 'online_vcpus' in self: - self['VCPUs_live'] = self['online_vcpus'] - - def _uuid_sanity_check(self): - """Make sure UUID is in proper string format with hyphens.""" - if 'uuid' not in self or not self['uuid']: - self['uuid'] = uuid.createString() - else: - self['uuid'] = uuid.toString(uuid.fromString(self['uuid'])) - - def _name_sanity_check(self): - if 'name_label' not in self: - self['name_label'] = 'Domain-' + self['uuid'] - - def _platform_sanity_check(self): - if 'keymap' not in self['platform'] and XendOptions.instance().get_keymap(): - self['platform']['keymap'] = XendOptions.instance().get_keymap() - - if self.is_hvm() or self.has_rfb(): - if 'device_model' not in self['platform']: - self['platform']['device_model'] = auxbin.pathTo("qemu-dm") - # device_model may be set to 'qemu-dm' or 'stubdom-dm' w/o a path - if os.path.dirname(self['platform']['device_model']) == "": - self['platform']['device_model'] = \ - auxbin.pathTo(self['platform']['device_model']) - # If the device_model is not set the os.path.exists() would raise - # an exception so we return our error message instead if applicable - if not self['platform']['device_model']: - raise VmError("No valid device model specified") - if not os.path.exists(self['platform']['device_model']): - raise VmError("device model '%s' not found" % str(self['platform']['device_model'])) - - if 'tsc_mode' not in self['platform']: - self['platform']['tsc_mode'] = 0 - - if 'nomigrate' not in self['platform']: - self['platform']['nomigrate'] = 0 - - if self.is_hvm(): - if 'timer_mode' not in self['platform']: - self['platform']['timer_mode'] = 1 - if 'viridian' not in self['platform']: - self['platform']['viridian'] = 0 - if 'rtc_timeoffset' not in self['platform']: - self['platform']['rtc_timeoffset'] = 0 - if 'hpet' not in self['platform']: - self['platform']['hpet'] = 0 - if 'xen_platform_pci' not in self['platform']: - self['platform']['xen_platform_pci'] = 1 - if 'vpt_align' not in self['platform']: - self['platform']['vpt_align'] = 1 - if 'loader' not in self['platform']: - # Old configs may have hvmloader set as PV_kernel param - if self.has_key('PV_kernel') and self['PV_kernel'] != '': - if self['PV_kernel'] == 'hvmloader': - self['PV_kernel'] = auxbin.pathTo("hvmloader") - self['platform']['loader'] = self['PV_kernel'] - self['PV_kernel'] = '' - else: - self['platform']['loader'] = auxbin.pathTo("hvmloader") - log.debug("Loader is %s" % str(self['platform']['loader'])) - elif self['platform']['loader'] == 'hvmloader': - self['platform']['loader'] = auxbin.pathTo("hvmloader") - if not os.path.exists(self['platform']['loader']): - raise VmError("kernel '%s' not found" % str(self['platform']['loader'])) - - # Compatibility hack, can go away soon. - if 'soundhw' not in self['platform'] and \ - self['platform'].get('enable_audio'): - self['platform']['soundhw'] = 'sb16' - - def _vfb_sanity_check(self): - if 'keymap' in self['platform']: - for con in self['console_refs']: - if self['devices'][con][0] == 'vfb': - if 'keymap' not in self['devices'][con][1]: - self['devices'][con][1]['keymap'] = \ - self['platform']['keymap'] - - def validate(self): - self._uuid_sanity_check() - self._name_sanity_check() - self._memory_sanity_check() - self._actions_sanity_check() - self._vcpus_sanity_check() - self._platform_sanity_check() - self._vfb_sanity_check() - - def _dominfo_to_xapi(self, dominfo, update_mem = False): - self['domid'] = dominfo['domid'] - self['online_vcpus'] = dominfo['online_vcpus'] - self['VCPUs_max'] = dominfo['max_vcpu_id'] + 1 - - if update_mem: - self['memory_dynamic_min'] = dominfo['mem_kb'] * 1024 - self['memory_dynamic_max'] = dominfo['mem_kb'] * 1024 - self['memory_static_min'] = 0 - self['memory_static_max'] = dominfo['maxmem_kb'] * 1024 - self._memory_sanity_check() - - self['cpu_time'] = dominfo['cpu_time']/1e9 - if dominfo.get('ssidref'): - ssidref = int(dominfo.get('ssidref')) - import xen.util.xsm.xsm as security - self['security_label'] = security.ssidref2security_label(ssidref) - - self['shutdown_reason'] = dominfo['shutdown_reason'] - - # parse state into Xen API states - self['running'] = dominfo['running'] - self['crashed'] = dominfo['crashed'] - self['dying'] = dominfo['dying'] - self['shutdown'] = dominfo['shutdown'] - self['paused'] = dominfo['paused'] - self['blocked'] = dominfo['blocked'] - - if 'name' in dominfo: - self['name_label'] = dominfo['name'] - - if 'handle' in dominfo: - self['uuid'] = uuid.toString(dominfo['handle']) - - def _convert_cpus_to_list(self, s): - # Convert the following string to list of ints. - # The string supports a list of ranges (0-3), - # seperated by commas, and negation (^1). - # Precedence is settled by order of the string: - # "0-3,^1" -> [0,2,3] - # "0-3,^1,1" -> [0,1,2,3] - l = [] - if s == "": - return l - for c in s.split(','): - if c.find('-') != -1: - (x, y) = c.split('-') - for i in range(int(x), int(y)+1): - l.append(int(i)) - else: - # remove this element from the list - if c[0] == '^': - l = [x for x in l if x != int(c[1:])] - else: - l.append(int(c)) - return l - - def parse_cpuid(self, cfg, field): - def int2bin(n, count=32): - return "".join([str((n >> y) & 1) for y in range(count-1, -1, -1)]) - - for input, regs in cfg[field].iteritems(): - if not regs is dict: - cfg[field][input] = dict(regs) - - cpuid = {} - for input in cfg[field]: - inputs = input.split(',') - if inputs[0][0:2] == '0x': - inputs[0] = str(int(inputs[0], 16)) - if len(inputs) == 2: - if inputs[1][0:2] == '0x': - inputs[1] = str(int(inputs[1], 16)) - new_input = ','.join(inputs) - cpuid[new_input] = {} # new input - for reg in cfg[field][input]: - val = cfg[field][input][reg] - if val[0:2] == '0x': - cpuid[new_input][reg] = int2bin(int(val, 16)) - else: - cpuid[new_input][reg] = val - cfg[field] = cpuid - - def _parse_sxp(self, sxp_cfg): - """ Populate this XendConfig using the parsed SXP. - - @param sxp_cfg: Parsed SXP Configuration - @type sxp_cfg: list of lists - @rtype: dictionary - @return: A dictionary containing the parsed options of the SXP. - """ - cfg = {} - - for key, typ in XENAPI_CFG_TYPES.items(): - val = sxp.child_value(sxp_cfg, key) - if val is not None: - try: - cfg[key] = typ(val) - except (ValueError, TypeError), e: - log.warn('Unable to convert type value for key: %s' % key) - - # Convert deprecated options to current equivalents. - - restart = sxp.child_value(sxp_cfg, 'restart') - if restart: - if restart == 'onreboot': - cfg['on_poweroff'] = 'destroy' - cfg['on_reboot'] = 'restart' - cfg['on_crash'] = 'destroy' - elif restart == 'always': - for opt in ('on_poweroff', 'on_reboot', 'on_crash'): - cfg[opt] = 'restart' - elif restart == 'never': - for opt in ('on_poweroff', 'on_reboot', 'on_crash'): - cfg[opt] = 'never' - else: - log.warn('Ignoring unrecognised value for deprecated option:' - 'restart = \'%s\'', restart) - - # Handle memory, passed in as MiB - - if sxp.child_value(sxp_cfg, "memory") != None: - cfg["memory"] = int(sxp.child_value(sxp_cfg, "memory")) - if sxp.child_value(sxp_cfg, "maxmem") != None: - cfg["maxmem"] = int(sxp.child_value(sxp_cfg, "maxmem")) - - # Convert scheduling parameters to vcpus_params - if 'vcpus_params' not in cfg: - cfg['vcpus_params'] = {} - if not cfg["vcpus_params"].has_key("weight"): - cfg["vcpus_params"]["weight"] = \ - int(sxp.child_value(sxp_cfg, "cpu_weight", 256)) - else: - cfg["vcpus_params"]["weight"] = int(cfg["vcpus_params"]["weight"]) - - if not cfg["vcpus_params"].has_key("cap"): - cfg["vcpus_params"]["cap"] = \ - int(sxp.child_value(sxp_cfg, "cpu_cap", 0)) - else: - cfg["vcpus_params"]["cap"] = int(cfg["vcpus_params"]["cap"]) - - # Only extract options we know about. - extract_keys = LEGACY_UNSUPPORTED_BY_XENAPI_CFG + \ - XENAPI_CFG_TO_LEGACY_CFG.values() - - for key in extract_keys: - val = sxp.child_value(sxp_cfg, key) - if val != None: - try: - cfg[key] = LEGACY_CFG_TYPES[key](val) - except KeyError: - cfg[key] = val - except (TypeError, ValueError), e: - log.warn("Unable to parse key %s: %s: %s" % - (key, str(val), e)) - - if 'platform' not in cfg: - cfg['platform'] = {} - localtime = sxp.child_value(sxp_cfg, 'localtime') - if localtime is not None: - cfg['platform']['localtime'] = localtime - - # Compatibility hack -- can go soon. - for key in XENAPI_PLATFORM_CFG_TYPES.keys(): - val = sxp.child_value(sxp_cfg, "platform_" + key, None) - if val is not None: - self['platform'][key] = val - - # Compatibility hack -- can go soon. - boot_order = sxp.child_value(sxp_cfg, 'HVM_boot') - if boot_order: - cfg['HVM_boot_policy'] = 'BIOS order' - cfg['HVM_boot_params'] = { 'order' : boot_order } - - - # Parsing the device SXP's. - cfg['devices'] = {} - for dev in sxp.children(sxp_cfg, 'device'): - config = sxp.child0(dev) - dev_type = sxp.name(config) - self.device_add(dev_type, cfg_sxp = config, target = cfg) - - # Extract missing data from configuration entries - image_sxp = sxp.child_value(sxp_cfg, 'image', []) - if image_sxp: - image_vcpus = sxp.child_value(image_sxp, 'vcpus') - if image_vcpus != None: - try: - if 'VCPUs_max' not in cfg: - cfg['VCPUs_max'] = int(image_vcpus) - elif cfg['VCPUs_max'] != int(image_vcpus): - cfg['VCPUs_max'] = int(image_vcpus) - log.warn('Overriding vcpus from %d to %d using image' - 'vcpus value.', cfg['VCPUs_max']) - except ValueError, e: - raise XendConfigError('integer expeceted: %s: %s' % - image_sxp, e) - - # Deprecated cpu configuration - if 'cpu' in cfg: - if 'cpus' in cfg: - cfg['cpus'] = "%s,%s" % (str(cfg['cpu']), cfg['cpus']) - else: - cfg['cpus'] = str(cfg['cpu']) - - # Convert 'cpus' to list of list of ints - cpus_list = [] - if 'cpus' in cfg: - if type(cfg['cpus']) == list: - if len(cfg['cpus']) > 0 and type(cfg['cpus'][0]) == list: - # If sxp_cfg was created from config.sxp, - # the form of 'cpus' is list of list of string. - # Convert 'cpus' to list of list of ints. - # Conversion examples: - # [['1']] -> [[1]] - # [['0','2'],['1','3']] -> [[0,2],[1,3]] - try: - for c1 in cfg['cpus']: - cpus = [] - for c2 in c1: - cpus.append(int(c2)) - cpus_list.append(cpus) - except ValueError, e: - raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e)) - else: - # Conversion examples: - # ["1"] -> [[1]] - # ["0,2","1,3"] -> [[0,2],[1,3]] - # ["0-3,^1","1-4,^2"] -> [[0,2,3],[1,3,4]] - try: - for c in cfg['cpus']: - cpus = self._convert_cpus_to_list(c) - cpus_list.append(cpus) - except ValueError, e: - raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e)) - - if len(cpus_list) != cfg['vcpus']: - raise XendConfigError('vcpus and the item number of cpus are not same') - else: - # Conversion examples: - # vcpus=1: - # "1" -> [[1]] - # "0-3,^1" -> [[0,2,3]] - # vcpus=2: - # "1" -> [[1],[1]] - # "0-3,^1" -> [[0,2,3],[0,2,3]] - try: - cpus = self._convert_cpus_to_list(cfg['cpus']) - for v in range(0, cfg['vcpus']): - cpus_list.append(cpus) - except ValueError, e: - raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e)) - else: - # Generation examples: - # vcpus=1: - # -> [[]] - # vcpus=2: - # -> [[],[]] - for v in range(0, cfg['vcpus']): - cpus_list.append(list()) - - cfg['cpus'] = cpus_list - - # Parse cpuid - if 'cpuid' in cfg: - self.parse_cpuid(cfg, 'cpuid') - if 'cpuid_check' in cfg: - self.parse_cpuid(cfg, 'cpuid_check') - - import xen.util.xsm.xsm as security - if security.on() == xsconstants.XS_POLICY_USE: - from xen.util.acmpolicy import ACM_LABEL_UNLABELED - if not 'security' in cfg and sxp.child_value(sxp_cfg, 'security'): - cfg['security'] = sxp.child_value(sxp_cfg, 'security') - elif not cfg.get('security_label'): - cfg['security'] = [['access_control', - ['policy', security.get_active_policy_name() ], - ['label', ACM_LABEL_UNLABELED ]]] - - if 'security' in cfg and not cfg.get('security_label'): - secinfo = cfg['security'] - # The xm command sends a list formatted like this: - # [['access_control', ['policy', 'xm-test'],['label', 'red']], - # ['ssidref', 196611]] - policy = "" - label = "" - for idx in range(0, len(secinfo)): - if secinfo[idx][0] == "access_control": - for aidx in range(1, len(secinfo[idx])): - if secinfo[idx][aidx][0] == "policy": - policy = secinfo[idx][aidx][1] - if secinfo[idx][aidx][0] == "label": - label = secinfo[idx][aidx][1] - cfg['security_label'] = \ - security.set_security_label(policy, label) - if not sxp.child_value(sxp_cfg, 'security_label'): - del cfg['security'] - - old_state = sxp.child_value(sxp_cfg, 'state') - if old_state: - for i in range(len(CONFIG_OLD_DOM_STATES)): - cfg[CONFIG_OLD_DOM_STATES[i]] = int(old_state[i] != '-') - - return cfg - - - def _sxp_to_xapi(self, sxp_cfg): - """Read in an SXP Configuration object and - populate at much of the Xen API with valid values. - """ - log.debug('_sxp_to_xapi(%s)' % scrub_password(sxp_cfg)) - - # _parse_sxp() below will call device_add() and construct devices. - # Some devices may require VM's uuid, so setup self['uuid'] - # beforehand. - self['uuid'] = sxp.child_value(sxp_cfg, 'uuid', uuid.createString()) - - cfg = self._parse_sxp(sxp_cfg) - - for key, typ in XENAPI_CFG_TYPES.items(): - val = cfg.get(key) - if val is not None: - self[key] = typ(val) - - # Convert parameters that can be directly mapped from - # the Legacy Config to Xen API Config - - for apikey, cfgkey in XENAPI_CFG_TO_LEGACY_CFG.items(): - try: - type_conv = XENAPI_CFG_TYPES.get(apikey) - if callable(type_conv): - self[apikey] = type_conv(cfg[cfgkey]) - else: - log.warn("Unconverted key: " + apikey) - self[apikey] = cfg[cfgkey] - except KeyError: - pass - - # Lets try and handle memory correctly - - MiB = 1024 * 1024 - - if "memory" in cfg: - self["memory_static_min"] = 0 - self["memory_static_max"] = int(cfg["memory"]) * MiB - self["memory_dynamic_min"] = int(cfg["memory"]) * MiB - self["memory_dynamic_max"] = int(cfg["memory"]) * MiB - - if "maxmem" in cfg: - self["memory_static_max"] = int(cfg["maxmem"]) * MiB - - self._memory_sanity_check() - - def update_with(n, o): - if not self.get(n): - self[n] = cfg.get(o, '') - - update_with('PV_bootloader', 'bootloader') - update_with('PV_bootloader_args', 'bootloader_args') - update_with('Description', 'description') - - image_sxp = sxp.child_value(sxp_cfg, 'image', []) - if image_sxp: - self.update_with_image_sxp(image_sxp) - - # Convert Legacy HVM parameters to Xen API configuration - for key in XENAPI_PLATFORM_CFG_TYPES.keys(): - if key in cfg: - self['platform'][key] = cfg[key] - - # set device references in the configuration - self['devices'] = cfg.get('devices', {}) - self['console_refs'] = cfg.get('console_refs', []) - self['vif_refs'] = cfg.get('vif_refs', []) - self['vbd_refs'] = cfg.get('vbd_refs', []) - - # coalesce hvm vnc frame buffer with vfb config - if self.is_hvm() and int(self['platform'].get('vnc', 0)) != 0: - # add vfb device if it isn't there already - if not self.has_rfb(): - dev_config = ['vfb'] - dev_config.append(['vnc', '1']) - # copy VNC related params from platform config to vfb dev conf - for key in ['vncpasswd', 'vncunused', 'vncdisplay', - 'vnclisten', 'keymap']: - if key in self['platform']: - dev_config.append([key, self['platform'][key]]) - - self.device_add('vfb', cfg_sxp = dev_config) - - - def has_rfb(self): - for console_uuid in self['console_refs']: - if self['devices'][console_uuid][1].get('protocol') == 'rfb': - return True - if self['devices'][console_uuid][0] == 'vfb': - return True - return False - - def _sxp_to_xapi_unsupported(self, sxp_cfg): - """Read in an SXP configuration object and populate - values are that not related directly supported in - the Xen API. - """ - - log.debug('_sxp_to_xapi_unsupported(%s)' % scrub_password(sxp_cfg)) - - # Parse and convert parameters used to configure - # the image (as well as HVM images) - image_sxp = sxp.child_value(sxp_cfg, 'image', []) - if image_sxp: - image_type = sxp.name(image_sxp) - if image_type != 'hvm' and image_type != 'linux': - self['platform']['image_type'] = image_type - - for key in XENAPI_PLATFORM_CFG_TYPES.keys(): - val = sxp.child_value(image_sxp, key, None) - if val is not None and val != '': - self['platform'][key] = val - - notes = sxp.children(image_sxp, 'notes') - if notes: - self['notes'] = self.notes_from_sxp(notes[0]) - - self._hvm_boot_params_from_sxp(image_sxp) - - # extract backend value - - backend = [] - for c in sxp.children(sxp_cfg, 'backend'): - backend.append(sxp.name(sxp.child0(c))) - if backend: - self['backend'] = backend - - # Parse and convert other Non Xen API parameters. - def _set_cfg_if_exists(sxp_arg): - val = sxp.child_value(sxp_cfg, sxp_arg) - if val != None: - if LEGACY_CFG_TYPES.get(sxp_arg): - self[sxp_arg] = LEGACY_CFG_TYPES[sxp_arg](val) - else: - self[sxp_arg] = val - - _set_cfg_if_exists('shadow_memory') - _set_cfg_if_exists('features') - _set_cfg_if_exists('on_xend_stop') - _set_cfg_if_exists('on_xend_start') - _set_cfg_if_exists('vcpu_avail') - _set_cfg_if_exists('change_home_server') - _set_cfg_if_exists('description') - - # Parse and store runtime configuration - _set_cfg_if_exists('start_time') - _set_cfg_if_exists('cpu_time') - _set_cfg_if_exists('shutdown_reason') - _set_cfg_if_exists('up_time') - _set_cfg_if_exists('status') # TODO, deprecated - - def _get_old_state_string(self): - """Returns the old xm state string. - @rtype: string - @return: old state string - """ - state_string = '' - for state_name in CONFIG_OLD_DOM_STATES: - on_off = self.get(state_name, 0) - if on_off: - state_string += state_name[0] - else: - state_string += '-' - - return state_string - - - def update_config(self, dominfo): - """Update configuration with the output from xc.domain_getinfo(). - - @param dominfo: Domain information via xc.domain_getinfo() - @type dominfo: dict - """ - self._dominfo_to_xapi(dominfo) - self.validate() - - def update_with_xenapi_config(self, xapi): - """Update configuration with a Xen API VM struct - - @param xapi: Xen API VM Struct - @type xapi: dict - """ - - log.debug('update_with_xenapi_config: %s' % scrub_password(xapi)) - - for key, val in xapi.items(): - type_conv = XENAPI_CFG_TYPES.get(key) - if type_conv is None: - key = key.lower() - type_conv = XENAPI_CFG_TYPES.get(key) - if callable(type_conv): - self[key] = type_conv(val) - else: - self[key] = val - - # XenAPI defines platform as a string-string map. If platform - # configuration exists, convert values to appropriate type. - if 'platform' in xapi: - for key, val in xapi['platform'].items(): - type_conv = XENAPI_PLATFORM_CFG_TYPES.get(key) - if type_conv is None: - key = key.lower() - type_conv = XENAPI_PLATFORM_CFG_TYPES.get(key) - if callable(type_conv): - self['platform'][key] = type_conv(val) - else: - self['platform'][key] = val - - self['vcpus_params']['weight'] = \ - int(self['vcpus_params'].get('weight', 256)) - self['vcpus_params']['cap'] = \ - int(self['vcpus_params'].get('cap', 0)) - - for key, val in self['vcpus_params'].items(): - if key.startswith('cpumap'): - self['vcpus_params'][key] = \ - ','.join(map(str, self._convert_cpus_to_list(val))) - - def cpuid_to_sxp(self, sxpr, field): - regs_list = [] - for input, regs in self[field].iteritems(): - reg_list = [] - for reg, val in regs.iteritems(): - reg_list.append([reg, val]) - regs_list.append([input, reg_list]) - sxpr.append([field, regs_list]) - - - def to_sxp(self, domain = None, ignore_devices = False, ignore = [], - legacy_only = True): - """ Get SXP representation of this config object. - - Incompat: removed store_mfn, console_mfn - - @keyword domain: (optional) XendDomainInfo to get extra information - from such as domid and running devices. - @type domain: XendDomainInfo - @keyword ignore: (optional) list of 'keys' that we do not want - to export. - @type ignore: list of strings - @rtype: list of list (SXP representation) - """ - sxpr = ['domain'] - - # TODO: domid/dom is the same thing but called differently - # depending if it is from xenstore or sxpr. - - if domain.getDomid() is not None: - sxpr.append(['domid', domain.getDomid()]) - - if legacy_only: - sxpr.append(['cpu_weight', int(self['vcpus_params'].get('weight', 256))]) - sxpr.append(['cpu_cap', int(self['vcpus_params'].get('cap', 0))]) - else: - for name, typ in XENAPI_CFG_TYPES.items(): - if name in self and self[name] not in (None, []): - # Skip cpuid and cpuid_check. Custom conversion - # methods for these are called below. - if name in ("cpuid", "cpuid_check"): - continue - if typ == dict: - s = self[name].items() - elif typ == list: - s = self[name] - else: - s = str(self[name]) - sxpr.append([name, s]) - - for xenapi, legacy in XENAPI_CFG_TO_LEGACY_CFG.items(): - if self.has_key(xenapi) and self[xenapi] not in (None, []): - if type(self[xenapi]) == bool: - # convert booleans to ints before making an sxp item - sxpr.append([legacy, int(self[xenapi])]) - else: - sxpr.append([legacy, self[xenapi]]) - - MiB = 1024*1024 - - sxpr.append(["maxmem", int(self["memory_static_max"])/MiB]) - sxpr.append(["memory", int(self["memory_dynamic_max"])/MiB]) - - for legacy in LEGACY_UNSUPPORTED_BY_XENAPI_CFG: - if legacy in ('domid', 'uuid', 'cpus'): # skip these - continue - if self.has_key(legacy) and self[legacy] not in (None, []): - sxpr.append([legacy, self[legacy]]) - - if self.has_key('security_label'): - sxpr.append(['security_label', self['security_label']]) - - sxpr.append(['image', self.image_sxpr()]) - sxpr.append(['status', domain._stateGet()]) - - if domain.getDomid() is not None: - sxpr.append(['state', self._get_old_state_string()]) - - if domain: - if domain.store_mfn: - sxpr.append(['store_mfn', domain.store_mfn]) - if domain.console_mfn: - sxpr.append(['console_mfn', domain.console_mfn]) - - - # Marshall devices (running or from configuration) - if not ignore_devices: - txn = xstransact() - try: - for cls in XendDevices.valid_devices(): - found = False - - # figure if there is a dev controller is valid and running - if domain and domain.getDomid() != None: - try: - controller = domain.getDeviceController(cls) - configs = controller.configurations(txn) - for config in configs: - if sxp.name(config) in ('vbd', 'tap', 'tap2'): - dev_uuid = sxp.child_value(config, 'uuid') - dev_type, dev_cfg = self['devices'][dev_uuid] - if sxp.child_value(config, 'bootable', None) is None: - is_bootable = dev_cfg.get('bootable', 0) - config.append(['bootable', int(is_bootable)]) - config.append(['VDI', dev_cfg.get('VDI', '')]) - - sxpr.append(['device', config]) - found = True - - except: - log.exception("dumping sxp from device controllers") - pass - - # if we didn't find that device, check the existing config - # for a device in the same class - if not found: - for dev_type, dev_info in self.all_devices_sxpr(): - if dev_type == cls: - sxpr.append(['device', dev_info]) - - txn.commit() - except: - txn.abort() - raise - - if 'cpuid' in self: - self.cpuid_to_sxp(sxpr, 'cpuid') - if 'cpuid_check' in self: - self.cpuid_to_sxp(sxpr, 'cpuid_check') - - if self.has_key('change_home_server'): - sxpr.append(['change_home_server', self['change_home_server']]) - - log.debug(sxpr) - - return sxpr - - def _blkdev_name_to_number(self, dev): - if 'ioemu:' in dev: - _, dev = dev.split(':', 1) - try: - dev, _ = dev.split(':', 1) - except ValueError: - pass - - try: - devid = int(dev) - except ValueError: - # devid is not a number but a string containing either device - # name (e.g. xvda) or device_type/device_id (e.g. vbd/51728) - dev2 = type(dev) is str and dev.split('/')[-1] or None - if dev2 == None: - log.debug("Could not check the device %s", dev) - return None - try: - devid = int(dev2) - except ValueError: - (xenbus, devid) = blkdev_name_to_number(dev2) - if devid == None: - log.debug("The device %s is not device name", dev2) - return None - return devid - - def device_duplicate_check(self, dev_type, dev_info, defined_config, config): - defined_devices_sxpr = self.all_devices_sxpr(target = defined_config) - - if dev_type == 'vbd' or dev_type == 'tap' or dev_type == 'tap2': - dev_uname = dev_info.get('uname') - blkdev_name = dev_info.get('dev') - devid = self._blkdev_name_to_number(blkdev_name) - if devid == None or dev_uname == None: - return - - for o_dev_type, o_dev_info in defined_devices_sxpr: - if o_dev_type == 'vbd' or o_dev_type == 'tap' or o_dev_type == 'tap2': - blkdev_file = blkdev_uname_to_file(dev_uname) - o_dev_uname = sxp.child_value(o_dev_info, 'uname') - if o_dev_uname and o_dev_uname != None: - o_blkdev_file = blkdev_uname_to_file(o_dev_uname) - if blkdev_file == o_blkdev_file: - raise XendConfigError('The file "%s" is already used' % - blkdev_file) - if dev_uname and dev_uname == o_dev_uname: - raise XendConfigError('The uname "%s" is already defined' % - dev_uname) - o_blkdev_name = sxp.child_value(o_dev_info, 'dev') - o_devid = self._blkdev_name_to_number(o_blkdev_name) - if o_devid != None and devid == o_devid: - name_array = blkdev_name.split(':', 2) - if len(name_array) == 2 and name_array[1] == 'cdrom': - # - # Since the device is a cdrom, we are most likely - # inserting, changing, or removing a cd. We can - # update the old device instead of creating a new - # one. - # - if o_dev_uname != None and dev_uname == None: - # - # We are removing a cd. We can simply update - # the uname on the existing device. - # - merge_sxp = sxp.from_string("('vbd' ('uname' ''))") - else: - merge_sxp = config - - dev_uuid = sxp.child_value(o_dev_info, 'uuid') - if dev_uuid != None and \ - self.device_update(dev_uuid, cfg_sxp = merge_sxp): - return dev_uuid - - raise XendConfigError('The device "%s" is already defined' % - blkdev_name) - - elif dev_type == 'vif': - dev_mac = dev_info.get('mac') - - for o_dev_type, o_dev_info in defined_devices_sxpr: - if dev_type == o_dev_type: - if dev_mac.lower() == sxp.child_value(o_dev_info, 'mac').lower(): - raise XendConfigError('The mac "%s" is already defined' % - dev_mac) - return None - - def create_dpci_from_sxp(self, pci_devs): - for pci_dev in pci_devs: - dpci_uuid = pci_dev.get('uuid') - log.debug("create_dpci_from_sxp: %s" % pci_dev) - ppci_uuid = XendPPCI.get_by_sbdf(pci_dev['domain'], - pci_dev['bus'], - pci_dev['slot'], - pci_dev['func']) - if ppci_uuid is None: - continue - dpci_record = { - 'VM': self['uuid'], - 'PPCI': ppci_uuid, - 'hotplug_slot': pci_dev.get('vdevfn', '0x%02x' % AUTO_PHP_SLOT), - 'key': pci_dev['key'] - } - - dpci_opts = pci_dev.get('opts') - if dpci_opts and len(dpci_opts) > 0: - dpci_record['options'] = dpci_opts - - XendDPCI(dpci_uuid, dpci_record) - - def device_add(self, dev_type, cfg_sxp = None, cfg_xenapi = None, - target = None): - """Add a device configuration in SXP format or XenAPI struct format. - - For SXP, it could be either: - - [device, [vbd, [uname ...]] - - or: - - [vbd, [uname ..]] - - @type cfg_sxp: list of lists (parsed sxp object) - @param cfg_sxp: SXP configuration object - @type cfg_xenapi: dict - @param cfg_xenapi: A device configuration from Xen API (eg. vbd,vif) - @param target: write device information to - @type target: None or a dictionary - @rtype: string - @return: Assigned UUID of the device. - """ - if target == None: - target = self - - if dev_type not in XendDevices.valid_devices(): - raise XendConfigError("XendConfig: %s not a valid device type" % - dev_type) - - if cfg_sxp == None and cfg_xenapi == None: - raise XendConfigError("XendConfig: device_add requires some " - "config.") - - #if cfg_sxp: - # log.debug("XendConfig.device_add: %s" % str(cfg_sxp)) - #if cfg_xenapi: - # log.debug("XendConfig.device_add: %s" % str(cfg_xenapi)) - - if cfg_sxp: - if sxp.child0(cfg_sxp) == 'device': - config = sxp.child0(cfg_sxp) - else: - config = cfg_sxp - - dev_type = sxp.name(config) - dev_info = {} - - if dev_type == 'pci': - pci_devs_uuid = sxp.child_value(config, 'uuid', - uuid.createString()) - - pci_dict = pci_convert_sxp_to_dict(config) - pci_devs = pci_dict['devs'] - - # create XenAPI DPCI objects. - self.create_dpci_from_sxp(pci_devs) - - target['devices'][pci_devs_uuid] = (dev_type, - {'devs': pci_devs, - 'uuid': pci_devs_uuid}) - - log.debug("XendConfig: reading device: %s" % pci_devs) - - return pci_devs_uuid - - if dev_type == 'vscsi': - vscsi_devs_uuid = sxp.child_value(config, 'uuid', - uuid.createString()) - vscsi_dict = self.vscsi_convert_sxp_to_dict(config) - vscsi_devs = vscsi_dict['devs'] - vscsi_mode = vscsi_dict['feature-host'] - vscsi_be = vscsi_dict.get('backend', None) - - # create XenAPI DSCSI_HBA objects. - dscsi_HBA_record = { - 'VM': self['uuid'], - 'virtual_host': int(vscsi_devs[0]['v-dev'].split(':')[0]), - 'assignment_mode': vscsi_mode and 'HOST' or 'LUN' - } - XendDSCSI_HBA(vscsi_devs_uuid, dscsi_HBA_record) - - # create XenAPI DSCSI objects. - for vscsi_dev in vscsi_devs: - dscsi_uuid = vscsi_dev.get('uuid') - pscsi_uuid = XendPSCSI.get_by_HCTL(vscsi_dev['p-dev']) - if pscsi_uuid is None: - continue - dscsi_record = { - 'VM': self['uuid'], - 'PSCSI': pscsi_uuid, - 'HBA': vscsi_devs_uuid, - 'virtual_HCTL': vscsi_dev.get('v-dev') - } - XendDSCSI(dscsi_uuid, dscsi_record) - - vscsi_info = { - 'devs': vscsi_devs, - 'feature-host': vscsi_mode, - 'uuid': vscsi_devs_uuid - } - if vscsi_be is not None: - vscsi_info['backend'] = vscsi_be - target['devices'][vscsi_devs_uuid] = (dev_type, vscsi_info) - log.debug("XendConfig: reading device: %s,%s" % \ - (vscsi_devs, vscsi_mode)) - return vscsi_devs_uuid - - if dev_type == 'vusb': - vusb_devs_uuid = sxp.child_value(config, 'uuid', - uuid.createString()) - vusb_dict = self.vusb_convert_sxp_to_dict(config) - vusb_dict['uuid'] = vusb_devs_uuid - target['devices'][vusb_devs_uuid] = (dev_type, vusb_dict) - return vusb_devs_uuid - - for opt_val in config[1:]: - try: - opt, val = opt_val - dev_info[opt] = val - except (TypeError, ValueError): # unpack error - pass - - if dev_type == 'vbd': - if dev_info.get('dev', '').startswith('ioemu:'): - dev_info['driver'] = 'ioemu' - else: - dev_info['driver'] = 'paravirtualised' - - if dev_type == 'tap' or dev_type == 'tap2': - tap_disk_type = dev_info['uname'].split(':')[1] - # tapdisk uname may be 'tap:' or 'tap:tapdisk:' - if tap_disk_type == 'tapdisk': - tap_disk_type = dev_info['uname'].split(':')[2] - if tap_disk_type not in blktap_disk_types: - raise XendConfigError("tap:%s not a valid disk type" % - tap_disk_type) - - if dev_type == 'vif': - if not dev_info.get('mac'): - dev_info['mac'] = randomMAC() - - ret_uuid = self.device_duplicate_check(dev_type, dev_info, target, config) - if ret_uuid != None: - return ret_uuid - - if dev_type == 'vif': - if dev_info.get('policy') and dev_info.get('label'): - dev_info['security_label'] = "%s:%s:%s" % \ - (xsconstants.ACM_POLICY_ID, - dev_info['policy'],dev_info['label']) - - # create uuid if it doesn't exist - dev_uuid = dev_info.get('uuid', None) - if not dev_uuid: - dev_uuid = uuid.createString() - dev_info['uuid'] = dev_uuid - - # store dev references by uuid for certain device types - target['devices'][dev_uuid] = (dev_type, dev_info) - if dev_type in ('vif', 'vbd'): - param = '%s_refs' % dev_type - if param not in target: - target[param] = [] - if dev_uuid not in target[param]: - if dev_type == 'vbd': - if 'bootable' not in dev_info: - # Compat hack -- mark first disk bootable - dev_info['bootable'] = int(not target[param]) - else: - # ensure type of bootable is int (on xend restart - # it's of type str) - dev_info['bootable'] = int(dev_info['bootable']) - target[param].append(dev_uuid) - elif dev_type == 'tap' or dev_type == 'tap2': - if 'vbd_refs' not in target: - target['vbd_refs'] = [] - if dev_uuid not in target['vbd_refs']: - if 'bootable' not in dev_info: - # Compat hack -- mark first disk bootable - dev_info['bootable'] = int(not target['vbd_refs']) - else: - # ensure type of bootable is int (on xend restart it's - # of type str) - dev_info['bootable'] = int(dev_info['bootable']) - target['vbd_refs'].append(dev_uuid) - - elif dev_type == 'vfb': - # Populate other config with aux data that is associated - # with vfb - - other_config = {} - for key in XENAPI_CONSOLE_OTHER_CFG: - if key in dev_info: - other_config[key] = dev_info[key] - target['devices'][dev_uuid][1]['other_config'] = other_config - - - if 'console_refs' not in target: - target['console_refs'] = [] - - # Treat VFB devices as console devices so they are found - # through Xen API - if dev_uuid not in target['console_refs']: - target['console_refs'].append(dev_uuid) - - # Cope with old-format save files which say under vfb - # (type vfb) rather than (vfb 1) - try: - vfb_type = dev_info['type'] - except KeyError: - vfb_type = None - log.debug("iwj dev_type=%s vfb type %s" % - (dev_type, `vfb_type`)) - - if vfb_type == 'vnc' or vfb_type == 'sdl': - dev_info[vfb_type] = 1 - del dev_info['type'] - log.debug("iwj dev_type=%s vfb setting dev_info['%s']" % - (dev_type, vfb_type)) - # Create serial backends now, the location value is bogus, but does not matter - i=0 - chardev=0 - if dev_info.get('serial') is not None : - chardev = chardev + 1 - if dev_info.get('monitor') is not None : - chardev = chardev + 1 - if chardev > 0 : - chardev = chardev + 1 - while i < chardev : - cfg = self.console_add('vt100', str(i)) - c_uuid = uuid.createString() - target['devices'][c_uuid] = ('console', cfg) - target['console_refs'].append(c_uuid) - i = i + 1 - elif dev_type == 'console': - if 'console_refs' not in target: - target['console_refs'] = [] - if dev_uuid not in target['console_refs']: - target['console_refs'].append(dev_uuid) - - log.debug("XendConfig: reading device: %s" % scrub_password(dev_info)) - return dev_uuid - - if cfg_xenapi: - dev_info = {} - dev_uuid = '' - if dev_type == 'vif': - dev_info['mac'] = cfg_xenapi.get('MAC') - if not dev_info['mac']: - dev_info['mac'] = randomMAC() - # vifname is the name on the guest, not dom0 - # TODO: we don't have the ability to find that out or - # change it from dom0 - #if cfg_xenapi.get('device'): # don't add if blank - # dev_info['vifname'] = cfg_xenapi.get('device') - if cfg_xenapi.get('type'): - dev_info['type'] = cfg_xenapi.get('type') - if cfg_xenapi.get('name'): - dev_info['name'] = cfg_xenapi.get('name') - if cfg_xenapi.get('network'): - network = XendAPIStore.get( - cfg_xenapi.get('network'), 'network') - dev_info['bridge'] = network.get_name_label() - - if cfg_xenapi.get('security_label'): - dev_info['security_label'] = \ - cfg_xenapi.get('security_label') - - dev_uuid = cfg_xenapi.get('uuid', None) - if not dev_uuid: - dev_uuid = uuid.createString() - dev_info['uuid'] = dev_uuid - target['devices'][dev_uuid] = (dev_type, dev_info) - target['vif_refs'].append(dev_uuid) - - elif dev_type in ('vbd', 'tap', 'tap2'): - dev_info['type'] = cfg_xenapi.get('type', 'Disk') - if dev_info['type'] == 'CD': - old_vbd_type = 'cdrom' - else: - old_vbd_type = 'disk' - - dev_info['uname'] = cfg_xenapi.get('image', '') - dev_info['dev'] = '%s:%s' % (cfg_xenapi.get('device'), - old_vbd_type) - dev_info['bootable'] = int(cfg_xenapi.get('bootable', 0)) - dev_info['driver'] = cfg_xenapi.get('driver', '') - dev_info['VDI'] = cfg_xenapi.get('VDI', '') - - if cfg_xenapi.get('mode') == 'RW': - dev_info['mode'] = 'w' - else: - dev_info['mode'] = 'r' - - dev_uuid = cfg_xenapi.get('uuid', None) - if not dev_uuid: - dev_uuid = uuid.createString() - dev_info['uuid'] = dev_uuid - target['devices'][dev_uuid] = (dev_type, dev_info) - target['vbd_refs'].append(dev_uuid) - - elif dev_type == 'console': - dev_uuid = cfg_xenapi.get('uuid', None) - if not dev_uuid: - dev_uuid = uuid.createString() - dev_info['uuid'] = dev_uuid - dev_info['protocol'] = cfg_xenapi.get('protocol', 'rfb') - console_other_config = cfg_xenapi.get('other_config', {}) - dev_info['other_config'] = console_other_config - if dev_info['protocol'] == 'rfb': - # collapse other config into devinfo for things - # such as vncpasswd, vncunused, etc. - dev_info.update(console_other_config) - dev_info['vnc'] = console_other_config.get('vnc', '0') - dev_info['sdl'] = console_other_config.get('sdl', '0') - target['devices'][dev_uuid] = ('vfb', dev_info) - target['console_refs'].append(dev_uuid) - - # if console is rfb, set device_model ensuring qemu - # is invoked for pvfb services - if 'device_model' not in target['platform']: - target['platform']['device_model'] = \ - auxbin.pathTo("qemu-dm") - - # Finally, if we are a pvfb, we need to make a vkbd - # as well that is not really exposed to Xen API - vkbd_uuid = uuid.createString() - target['devices'][vkbd_uuid] = ('vkbd', {}) - - elif dev_info['protocol'] == 'vt100': - # if someone tries to create a VT100 console - # via the Xen API, we'll have to ignore it - # because we create one automatically in - # XendDomainInfo._update_consoles - raise XendConfigError('Creating vt100 consoles via ' - 'Xen API is unsupported') - - return dev_uuid - - # no valid device to add - return '' - - def phantom_device_add(self, dev_type, cfg_xenapi = None, - target = None): - """Add a phantom tap device configuration in XenAPI struct format. - """ - - if target == None: - target = self - - if dev_type not in XendDevices.valid_devices() and \ - dev_type not in XendDevices.pseudo_devices(): - raise XendConfigError("XendConfig: %s not a valid device type" % - dev_type) - - if cfg_xenapi == None: - raise XendConfigError("XendConfig: device_add requires some " - "config.") - - if cfg_xenapi: - log.debug("XendConfig.phantom_device_add: %s" % str(cfg_xenapi)) - - if cfg_xenapi: - dev_info = {} - if dev_type in ('vbd', 'tap'): - if dev_type == 'vbd': - dev_info['uname'] = cfg_xenapi.get('image', '') - dev_info['dev'] = '%s:disk' % cfg_xenapi.get('device') - elif dev_type == 'tap': - if cfg_xenapi.get('image').find('tap:') == -1: - dev_info['uname'] = 'tap:qcow:%s' % cfg_xenapi.get('image') - dev_info['dev'] = '/dev/%s' % cfg_xenapi.get('device') - dev_info['uname'] = cfg_xenapi.get('image') - dev_info['mode'] = cfg_xenapi.get('mode') - dev_info['backend'] = '0' - dev_uuid = cfg_xenapi.get('uuid', uuid.createString()) - dev_info['uuid'] = dev_uuid - self['devices'][dev_uuid] = (dev_type, dev_info) - self['vbd_refs'].append(dev_uuid) - return dev_uuid - - return '' - - def vscsi_convert_sxp_to_dict(self, dev_sxp): - """Convert vscsi device sxp to dict - @param dev_sxp: device configuration - @type dev_sxp: SXP object (parsed config) - @return: dev_config - @rtype: dictionary - """ - # Parsing the device SXP's. In most cases, the SXP looks - # like this: - # - # [device, [vif, [mac, xx:xx:xx:xx:xx:xx], [ip 1.3.4.5]]] - # - # However, for SCSI devices it looks like this: - # - # [device, - # [vscsi, - # [feature-host, 0], - # [backend, 0], - # [dev, - # [devid, 0], [p-devname, sdb], [p-dev, 1:0:0:1], - # [v-dev, 0:0:0:0], [state, 1] - # ], - # [dev, - # [devid, 0], [p-devname, sdc], [p-dev, 1:0:0:2], - # [v-dev, 0:0:0:1], [satet, 1] - # ] - # ], - # [vscsi, - # [feature-host, 1], - # [backend, 0], - # [dev, - # [devid, 1], [p-devname, sdg], [p-dev, 2:0:0:0], - # [v-dev, 1:0:0:0], [state, 1] - # ], - # [dev, - # [devid, 1], [p-devname, sdh], [p-dev, 2:0:0:1], - # [v-dev, 1:0:0:1], [satet, 1] - # ] - # ] - # ] - # - # It seems the reasoning for this difference is because - # vscsiif.py needs all the SCSI device configurations with - # same host number at the same time when creating the devices. - - # For SCSI device hotplug support, the SXP of SCSI devices is - # extendend like this: - # - # [device, - # [vscsi, - # [feature-host, 0], - # [backend, 0], - # [dev, - # [devid, 0], [p-devname, sdd], [p-dev, 1:0:0:3], - # [v-dev, 0:0:0:2], [state, 1] - # ] - # ] - # ] - # - # state xenbusState['Initialising'] indicates that the device is - # being attached, while state xenbusState['Closing'] indicates - # that the device is being detached. - # - # The Dict looks like this: - # - # { devs: [ {devid: 0, p-devname: sdd, p-dev: 1:0:0:3, - # v-dev: 0:0:0:2, state: 1} ], - # feature-host: 1 , backend: 0 } - - dev_config = {} - - vscsi_devs = [] - for vscsi_dev in sxp.children(dev_sxp, 'dev'): - vscsi_dev_info = {} - for opt_val in vscsi_dev[1:]: - try: - opt, val = opt_val - vscsi_dev_info[opt] = val - except TypeError: - pass - # append uuid for each vscsi device. - vscsi_uuid = vscsi_dev_info.get('uuid', uuid.createString()) - vscsi_dev_info['uuid'] = vscsi_uuid - vscsi_devs.append(vscsi_dev_info) - dev_config['devs'] = vscsi_devs - - vscsi_mode = sxp.children(dev_sxp, 'feature-host')[0] - dev_config['feature-host'] = vscsi_mode[1] - try: - vscsi_be = sxp.children(dev_sxp, 'backend')[0] - dev_config['backend'] = vscsi_be[1] - except IndexError: - pass - - return dev_config - - def vusb_convert_sxp_to_dict(self, dev_sxp): - """Convert vusb device sxp to dict - @param dev_sxp: device configuration - @type dev_sxp: SXP object (parsed config) - @return: dev_config - @rtype: dictionary - """ - # Parsing USB devices SXP. - # - # USB device's SXP looks like this: - # - # [device, - # [vusb, - # [usb-ver, 2], - # [num-ports, 8], - # [port, - # [1, 1-1], - # [2, 1-2], - # [3, ''], - # [4, ''], - # [5, ''], - # [6, ''], - # [7, 6-2.1], - # [8, ''] - # ] - # ], - # [vusb, - # [usb-ver, 1], - # [num-ports, 2], - # [port, - # [1, 4-1], - # [2, 4-2] - # ] - # ] - # ] - # - # The dict looks like this - # - # { usb-ver: 2, - # num-ports: 8, - # port-1: 1-1, - # port-2: 1-2, - # port-3: "", - # port-4: "", - # port-5: "", - # port-6: "", - # port-7: "", - # port-8: "" } - - dev_config = {} - dev_config['usb-ver'] = sxp.child(dev_sxp, 'usb-ver')[1] - dev_config['num-ports'] = sxp.child(dev_sxp, 'num-ports')[1] - ports = sxp.child(dev_sxp, 'port') - for port in ports[1:]: - try: - num, bus = port - dev_config['port-%i' % int(num)] = str(bus) - except TypeError: - pass - - return dev_config - - def console_add(self, protocol, location, other_config = {}): - dev_uuid = uuid.createString() - if protocol == 'vt100': - dev_info = { - 'uuid': dev_uuid, - 'protocol': protocol, - 'location': location, - 'other_config': other_config, - } - - if 'devices' not in self: - self['devices'] = {} - - self['devices'][dev_uuid] = ('console', dev_info) - self['console_refs'].append(dev_uuid) - return dev_info - - return {} - - def console_update(self, console_uuid, key, value): - for dev_uuid, (dev_type, dev_info) in self['devices'].items(): - if dev_uuid == console_uuid: - dev_info[key] = value - # collapse other_config into dev_info for things - # such as vncpasswd, vncunused, etc. - if key == 'other_config': - for k in XENAPI_CONSOLE_OTHER_CFG: - if k in dev_info and k not in value: - del dev_info[k] - dev_info.update(value) - break - - def console_get_all(self, protocol): - if protocol == 'vt100': - consoles = [dinfo for dtype, dinfo in self['devices'].values() - if dtype == 'console'] - return [c for c in consoles if c.get('protocol') == protocol] - - elif protocol == 'rfb': - vfbs = [dinfo for dtype, dinfo in self['devices'].values() - if dtype == 'vfb'] - - # move all non-console key values to other_config before - # returning console config - valid_keys = ['uuid', 'location'] - for vfb in vfbs: - other_config = {} - for key, val in vfb.items(): - if key not in valid_keys: - other_config[key] = vfb[key] - del vfb[key] - vfb['other_config'] = other_config - vfb['protocol'] = 'rfb' - - return vfbs - - else: - return [] - - def device_update(self, dev_uuid, cfg_sxp = [], cfg_xenapi = {}): - """Update an existing device with the new configuration. - - @rtype: boolean - @return: Returns True if succesfully found and updated a device conf - """ - if dev_uuid in self['devices'] and cfg_sxp: - if sxp.child0(cfg_sxp) == 'device': - config = sxp.child0(cfg_sxp) - else: - config = cfg_sxp - - dev_type, dev_info = self['devices'][dev_uuid] - - if dev_type == 'pci': # Special case for pci - pci_dict = pci_convert_sxp_to_dict(config) - pci_devs = pci_dict['devs'] - - # destroy existing XenAPI DPCI objects - for dpci_uuid in XendDPCI.get_by_VM(self['uuid']): - XendAPIStore.deregister(dpci_uuid, "DPCI") - - # create XenAPI DPCI objects. - self.create_dpci_from_sxp(pci_devs) - - self['devices'][dev_uuid] = (dev_type, - {'devs': pci_devs, - 'uuid': dev_uuid}) - return True - - if dev_type == 'vscsi': # Special case for vscsi - vscsi_dict = self.vscsi_convert_sxp_to_dict(config) - vscsi_devs = vscsi_dict['devs'] - vscsi_mode = vscsi_dict['feature-host'] - vscsi_be = vscsi_dict.get('backend', None) - - # destroy existing XenAPI DSCSI objects - vscsi_devid = int(dev_info['devs'][0]['devid']) - for dscsi_uuid in XendDSCSI.get_by_VM(self['uuid']): - dscsi_inst = XendAPIStore.get(dscsi_uuid, 'DSCSI') - if vscsi_devid == dscsi_inst.get_virtual_host(): - XendAPIStore.deregister(dscsi_uuid, "DSCSI") - - # destroy existing XenAPI DSCSI_HBA objects - if not vscsi_devs: - XendAPIStore.deregister(dev_uuid, 'DSCSI_HBA') - - # create XenAPI DSCSI objects. - for vscsi_dev in vscsi_devs: - dscsi_uuid = vscsi_dev.get('uuid') - pscsi_uuid = XendPSCSI.get_by_HCTL(vscsi_dev['p-dev']) - if pscsi_uuid is None: - continue - dscsi_record = { - 'VM': self['uuid'], - 'PSCSI': pscsi_uuid, - 'HBA': dev_uuid, - 'virtual_HCTL': vscsi_dev.get('v-dev') - } - XendDSCSI(dscsi_uuid, dscsi_record) - - vscsi_info = { - 'devs': vscsi_devs, - 'feature-host': vscsi_mode, - 'uuid': dev_uuid - } - if vscsi_be is not None: - vscsi_info['backend'] = vscsi_be - self['devices'][dev_uuid] = (dev_type, vscsi_info) - return True - - for opt_val in config[1:]: - try: - opt, val = opt_val - dev_info[opt] = val - except (TypeError, ValueError): - pass # no value for this config option - - self['devices'][dev_uuid] = (dev_type, dev_info) - return True - - elif dev_uuid in self['devices'] and cfg_xenapi: - dev_type, dev_info = self['devices'][dev_uuid] - for key, val in cfg_xenapi.items(): - dev_info[key] = val - self['devices'][dev_uuid] = (dev_type, dev_info) - return True - - return False - - - def device_sxpr(self, dev_uuid = None, dev_type = None, dev_info = None, target = None): - """Get Device SXPR by either giving the device UUID or (type, config). - - @rtype: list of lists - @return: device config sxpr - """ - sxpr = [] - - if target == None: - target = self - - if dev_uuid != None and dev_uuid in target['devices']: - dev_type, dev_info = target['devices'][dev_uuid] - - if dev_type == None or dev_info == None: - raise XendConfigError("Required either UUID or device type and " - "configuration dictionary.") - - sxpr.append(dev_type) - if dev_type in ('console', 'vfb'): - config = [(opt, val) for opt, val in dev_info.items() - if opt != 'other_config'] - else: - config = [(opt, val) for opt, val in dev_info.items()] - - sxpr += config - - return sxpr - - def ordered_device_refs(self, target = None): - result = [] - - if target == None: - target = self - - # vkbd devices *must* be before vfb devices, otherwise - # there is a race condition when setting up devices - # where the daemon spawned for the vfb may write stuff - # into xenstore vkbd backend, before DevController has - # setup permissions on the vkbd backend path. This race - # results in domain creation failing with 'device already - # connected' messages - result.extend([u for u in target['devices'].keys() if target['devices'][u][0] == 'vkbd']) - - result.extend(target.get('console_refs', []) + - target.get('vbd_refs', []) + - target.get('vif_refs', [])) - - result.extend([u for u in target['devices'].keys() if u not in result]) - return result - - def all_devices_sxpr(self, target = None): - """Returns the SXPR for all devices in the current configuration.""" - sxprs = [] - - if target == None: - target = self - - if 'devices' not in target: - return sxprs - - ordered_refs = self.ordered_device_refs(target = target) - for dev_uuid in ordered_refs: - dev_type, dev_info = target['devices'][dev_uuid] - if dev_type == 'pci' or dev_type == 'vscsi': # special case for pci devices - if dev_type == 'pci': - sxpr = ['pci', ['uuid', dev_info['uuid']]] - elif dev_type == 'vscsi': - sxpr = ['vscsi', ['uuid', dev_info['uuid']], - ['feature-host', dev_info['feature-host']]] - if dev_info.has_key('backend'): - sxpr.append(['backend', dev_info['backend']]) - for pci_dev_info in dev_info['devs']: - sxpr.append(dev_dict_to_sxp(pci_dev_info)) - sxprs.append((dev_type, sxpr)) - elif dev_type == 'vusb': - sxpr = ['vusb', ['uuid', dev_info['uuid']], - ['usb-ver', dev_info['usb-ver']], - ['num-ports', dev_info['num-ports']]] - port_sxpr = ['port'] - for i in range(1, int(dev_info['num-ports']) + 1): - if dev_info.has_key('port-%i' % i): - port_sxpr.append([i, str(dev_info['port-%i' % i])]) - else: - port_sxpr.append([i, ""]) - sxpr.append(port_sxpr) - sxprs.append((dev_type, sxpr)) - else: - sxpr = self.device_sxpr(dev_type = dev_type, - dev_info = dev_info, - target = target) - sxprs.append((dev_type, sxpr)) - - return sxprs - - def image_sxpr(self): - """Returns a backwards compatible image SXP expression that is - used in xenstore's /vm//image value and xm list.""" - image = [self.image_type()] - if self.has_key('PV_kernel'): - image.append(['kernel', self['PV_kernel']]) - if self.has_key('PV_ramdisk') and self['PV_ramdisk']: - image.append(['ramdisk', self['PV_ramdisk']]) - if self.has_key('PV_args') and self['PV_args']: - image.append(['args', self['PV_args']]) - if self.has_key('superpages'): - image.append(['superpages', self['superpages']]) - - for key in XENAPI_PLATFORM_CFG_TYPES.keys(): - if key in self['platform']: - image.append([key, self['platform'][key]]) - - if 'notes' in self: - image.append(self.notes_sxp(self['notes'])) - - return image - - def update_with_image_sxp(self, image_sxp, bootloader = False): - # Convert Legacy "image" config to Xen API PV_* - # configuration - log.debug("update_with_image_sxp(%s)" % scrub_password(image_sxp)) - - # user-specified args must come last: previous releases did this and - # some domU kernels rely upon the ordering. - kernel_args = sxp.child_value(image_sxp, 'args', '') - - # attempt to extract extra arguments from SXP config - arg_ip = sxp.child_value(image_sxp, 'ip') - if arg_ip and not re.search(r'ip=[^ ]+', kernel_args): - kernel_args = 'ip=%s ' % arg_ip + kernel_args - arg_root = sxp.child_value(image_sxp, 'root') - if arg_root and not re.search(r'root=', kernel_args): - kernel_args = 'root=%s ' % arg_root + kernel_args - - if bootloader: - self['_temp_using_bootloader'] = '1' - self['_temp_kernel'] = sxp.child_value(image_sxp, 'kernel','') - self['_temp_ramdisk'] = sxp.child_value(image_sxp, 'ramdisk','') - self['_temp_args'] = kernel_args - self['use_tmp_kernel'] = True - self['use_tmp_ramdisk'] = True - else: - self['PV_kernel'] = sxp.child_value(image_sxp, 'kernel','') - self['PV_ramdisk'] = sxp.child_value(image_sxp, 'ramdisk','') - self['PV_args'] = kernel_args - self['use_tmp_kernel'] = False - self['use_tmp_ramdisk'] = False - - val = sxp.child_value(image_sxp, 'superpages') - if val is not None: - self['superpages'] = val - - val = sxp.child_value(image_sxp, 'memory_sharing') - if val is not None: - self['memory_sharing'] = val - - for key in XENAPI_PLATFORM_CFG_TYPES.keys(): - val = sxp.child_value(image_sxp, key, None) - if val is not None and val != '': - self['platform'][key] = val - - notes = sxp.children(image_sxp, 'notes') - if notes: - self['notes'] = self.notes_from_sxp(notes[0]) - - self._hvm_boot_params_from_sxp(image_sxp) - - def set_notes(self, notes): - 'Add parsed elfnotes to image' - self['notes'] = notes - - def get_notes(self): - try: - return self['notes'] or {} - except KeyError: - return {} - - def notes_from_sxp(self, nsxp): - notes = {} - for note in sxp.children(nsxp): - notes[note[0]] = note[1] - return notes - - def notes_sxp(self, notes): - nsxp = ['notes'] - for k, v in notes.iteritems(): - nsxp.append([k, str(v)]) - return nsxp - - def _hvm_boot_params_from_sxp(self, image_sxp): - boot = sxp.child_value(image_sxp, 'boot', None) - if boot is not None: - self['HVM_boot_policy'] = 'BIOS order' - self['HVM_boot_params'] = { 'order' : boot } - - def is_hvm(self): - return self['HVM_boot_policy'] != '' - - def is_stubdom(self): - return (self['PV_kernel'].find('ioemu') >= 0) - - def target(self): - return self['target'] - - def image_type(self): - stored_type = self['platform'].get('image_type') - return stored_type or (self.is_hvm() and 'hvm' or 'linux') - - def is_hap(self): - return self['platform'].get('hap', 0) - - def is_pv_and_has_pci(self): - for dev_type, dev_info in self.all_devices_sxpr(): - if dev_type != 'pci': - continue - return not self.is_hvm() - return False - - def update_platform_pci(self): - pci = [] - for dev_type, dev_info in self.all_devices_sxpr(): - if dev_type != 'pci': - continue - for dev in sxp.children(dev_info, 'dev'): - domain = sxp.child_value(dev, 'domain') - bus = sxp.child_value(dev, 'bus') - slot = sxp.child_value(dev, 'slot') - func = sxp.child_value(dev, 'func') - vdevfn = sxp.child_value(dev, 'vdevfn') - opts = pci_opts_list_from_sxp(dev) - pci.append([domain, bus, slot, func, vdevfn, opts]) - self['platform']['pci'] = pci - - def handle_fileuris(self): - for arg in [('PV_kernel', 'use_tmp_kernel'), - ('PV_ramdisk', 'use_tmp_ramdisk')]: - if arg[0] in self and self[arg[0]]!='': - self[arg[0]], self[arg[1]] \ - = xen.util.fileuri.schemes.decode(self[arg[0]]) - log.debug("fileuri '%s' = '%s'" % (arg[0], self[arg[0]][:100])) - diff --git a/tools/python/xen/xend/XendConstants.py b/tools/python/xen/xend/XendConstants.py deleted file mode 100644 index bc1c400422..0000000000 --- a/tools/python/xen/xend/XendConstants.py +++ /dev/null @@ -1,164 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2006 XenSource Ltd. -#============================================================================ - -from xen.xend.XendAPIConstants import * -from xen.util import auxbin - -# -# Shutdown codes and reasons. -# - -DOMAIN_POWEROFF = 0 -DOMAIN_REBOOT = 1 -DOMAIN_SUSPEND = 2 -DOMAIN_CRASH = 3 -DOMAIN_HALT = 4 - -DOMAIN_SHUTDOWN_REASONS = { - DOMAIN_POWEROFF: "poweroff", - DOMAIN_REBOOT : "reboot", - DOMAIN_SUSPEND : "suspend", - DOMAIN_CRASH : "crash", - DOMAIN_HALT : "halt" -} -REVERSE_DOMAIN_SHUTDOWN_REASONS = \ - dict([(y, x) for x, y in DOMAIN_SHUTDOWN_REASONS.items()]) - -HVM_PARAM_CALLBACK_IRQ = 0 -HVM_PARAM_STORE_PFN = 1 -HVM_PARAM_STORE_EVTCHN = 2 -HVM_PARAM_PAE_ENABLED = 4 -HVM_PARAM_IOREQ_PFN = 5 -HVM_PARAM_BUFIOREQ_PFN = 6 -HVM_PARAM_NVRAM_FD = 7 # ia64 -HVM_PARAM_VHPT_SIZE = 8 # ia64 -HVM_PARAM_BUFPIOREQ_PFN = 9 # ia64 -HVM_PARAM_VIRIDIAN = 9 # x86 -HVM_PARAM_TIMER_MODE = 10 -HVM_PARAM_HPET_ENABLED = 11 -HVM_PARAM_ACPI_S_STATE = 14 -HVM_PARAM_VPT_ALIGN = 16 -HVM_PARAM_CONSOLE_PFN = 17 -HVM_PARAM_NESTEDHVM = 24 # x86 - -restart_modes = [ - "restart", - "destroy", - "preserve", - "rename-restart", - "coredump-destroy", - "coredump-restart" - ] - -DOM_STATES = [ - 'halted', - 'paused', - 'running', - 'suspended', - 'shutdown', - 'crashed', - 'unknown', -] - -DOM_STATE_HALTED = XEN_API_VM_POWER_STATE_HALTED -DOM_STATE_PAUSED = XEN_API_VM_POWER_STATE_PAUSED -DOM_STATE_RUNNING = XEN_API_VM_POWER_STATE_RUNNING -DOM_STATE_SUSPENDED = XEN_API_VM_POWER_STATE_SUSPENDED -DOM_STATE_SHUTDOWN = XEN_API_VM_POWER_STATE_SHUTTINGDOWN -DOM_STATE_CRASHED = XEN_API_VM_POWER_STATE_CRASHED -DOM_STATE_UNKNOWN = XEN_API_VM_POWER_STATE_UNKNOWN - -DOM_STATES_OLD = [ - 'running', - 'blocked', - 'paused', - 'shutdown', - 'crashed', - 'dying' - ] - -SHUTDOWN_TIMEOUT = (60.0 * 5) - -"""Minimum time between domain restarts in seconds.""" -MINIMUM_RESTART_TIME = 60 - -RESTART_IN_PROGRESS = 'xend/restart_in_progress' -DUMPCORE_IN_PROGRESS = 'xend/dumpcore_in_progress' -LAST_SHUTDOWN_REASON = 'xend/last_shutdown_reason' - -TRIGGER_NMI = 0 -TRIGGER_RESET = 1 -TRIGGER_INIT = 2 -TRIGGER_POWER = 3 -TRIGGER_S3RESUME = 4 - -TRIGGER_TYPE = { - "nmi" : TRIGGER_NMI, - "reset" : TRIGGER_RESET, - "init" : TRIGGER_INIT, - "s3resume": TRIGGER_S3RESUME, - "power": TRIGGER_POWER -} - -# -# Device migration stages (eg. XendDomainInfo, XendCheckpoint) -# - -DEV_MIGRATE_TEST = 0 -DEV_MIGRATE_STEP1 = 1 -DEV_MIGRATE_STEP2 = 2 -DEV_MIGRATE_STEP3 = 3 - -# -# Xenstore Constants -# - -XS_VMROOT = "/vm/" - -XS_POOLROOT = "/local/pool/" - -NR_PCI_FUNC = 8 -NR_PCI_DEV = 32 -NR_PCI_DEVFN = NR_PCI_FUNC * NR_PCI_DEV -AUTO_PHP_SLOT = 0x100 - -# -# tmem -# - -TMEM_CONTROL = 0 -TMEM_NEW_POOL = 1 -TMEM_DESTROY_POOL = 2 -TMEM_NEW_PAGE = 3 -TMEM_PUT_PAGE = 4 -TMEM_GET_PAGE = 5 -TMEM_FLUSH_PAGE = 6 -TMEM_FLUSH_OBJECT = 7 -TMEM_READ = 8 -TMEM_WRITE = 9 -TMEM_XCHG = 10 - -TMEMC_THAW = 0 -TMEMC_FREEZE = 1 -TMEMC_FLUSH = 2 -TMEMC_DESTROY = 3 -TMEMC_LIST = 4 -TMEMC_SET_WEIGHT = 5 -TMEMC_SET_CAP = 6 -TMEMC_SET_COMPRESS = 7 -TMEMC_QUERY_FREEABLE_MB = 8 - diff --git a/tools/python/xen/xend/XendDPCI.py b/tools/python/xen/xend/XendDPCI.py deleted file mode 100644 index e7507f0a40..0000000000 --- a/tools/python/xen/xend/XendDPCI.py +++ /dev/null @@ -1,165 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (c) 2008 NEC Corporation -# Yosuke Iwamatsu -#============================================================================ - -from xen.xend.XendBase import XendBase -from xen.xend.XendPPCI import XendPPCI -from xen.xend import XendAPIStore -from xen.xend import uuid as genuuid - -import XendDomain, XendNode - -from XendError import * -from XendTask import XendTask -from XendLogging import log - -class XendDPCI(XendBase): - """Representation of a passthrough PCI device.""" - - def getClass(self): - return "DPCI" - - def getAttrRO(self): - attrRO = ['virtual_domain', - 'virtual_bus', - 'virtual_slot', - 'virtual_func', - 'virtual_name', - 'VM', - 'PPCI', - 'hotplug_slot', - 'key', - 'options'] - return XendBase.getAttrRO() + attrRO - - def getAttrRW(self): - attrRW = [] - return XendBase.getAttrRW() + attrRW - - def getAttrInst(self): - attrInst = ['VM', - 'PPCI', - 'hotplug_slot', - 'key'] - return XendBase.getAttrInst() + attrInst - - def getMethods(self): - methods = ['destroy'] - return XendBase.getMethods() + methods - - def getFuncs(self): - funcs = ['create'] - return XendBase.getFuncs() + funcs - - getClass = classmethod(getClass) - getAttrRO = classmethod(getAttrRO) - getAttrRW = classmethod(getAttrRW) - getAttrInst = classmethod(getAttrInst) - getMethods = classmethod(getMethods) - getFuncs = classmethod(getFuncs) - - def create(self, dpci_struct): - - # Check if VM is valid - xendom = XendDomain.instance() - if not xendom.is_valid_vm(dpci_struct['VM']): - raise InvalidHandleError('VM', dpci_struct['VM']) - dom = xendom.get_vm_by_uuid(dpci_struct['VM']) - - # Check if PPCI is valid - xennode = XendNode.instance() - ppci_uuid = xennode.get_ppci_by_uuid(dpci_struct['PPCI']) - if not ppci_uuid: - raise InvalidHandleError('PPCI', dpci_struct['PPCI']) - for existing_dpci in XendAPIStore.get_all('DPCI'): - if ppci_uuid == existing_dpci.get_PPCI(): - raise DirectPCIError("Device is in use") - - # Assign PPCI to VM - try: - dpci_ref = XendTask.log_progress(0, 100, dom.create_dpci, - dpci_struct) - except XendError, e: - raise DirectPCIError("Failed to assign device") - - # TODO: Retrive virtual pci device infomation. - - return dpci_ref - - create = classmethod(create) - - def get_by_VM(cls, VM_ref): - result = [] - for dpci in XendAPIStore.get_all("DPCI"): - if dpci.get_VM() == VM_ref: - result.append(dpci.get_uuid()) - return result - - get_by_VM = classmethod(get_by_VM) - - def __init__(self, uuid, record): - XendBase.__init__(self, uuid, record) - - self.virtual_domain = -1 - self.virtual_bus = -1 - self.virtual_slot = -1 - self.virtual_func = -1 - - self.VM = record['VM'] - self.PPCI = record['PPCI'] - self.hotplug_slot = int(record['hotplug_slot'], 16) - self.key = record['key'] - if 'options' in record.keys(): - self.options = record['options'] - - def destroy(self): - xendom = XendDomain.instance() - dom = xendom.get_vm_by_uuid(self.get_VM()) - if not dom: - raise InvalidHandleError("VM", self.get_VM()) - XendTask.log_progress(0, 100, dom.destroy_dpci, self.get_uuid()) - - def get_virtual_domain(self): - return self.virtual_domain - - def get_virtual_bus(self): - return self.virtual_bus - - def get_virtual_slot(self): - return self.virtual_slot - - def get_virtual_func(self): - return self.virtual_func - - def get_virtual_name(self): - return "%04x:%02x:%02x.%01x" % (self.virtual_domain, self.virtual_bus, - self.virtual_slot, self.virtual_func) - - def get_VM(self): - return self.VM - - def get_PPCI(self): - return self.PPCI - - def get_hotplug_slot(self): - return "%d" % self.hotplug_slot - - def get_key(self): - return self.key - - def get_options(self): - return self.options diff --git a/tools/python/xen/xend/XendDSCSI.py b/tools/python/xen/xend/XendDSCSI.py deleted file mode 100644 index 794a54f001..0000000000 --- a/tools/python/xen/xend/XendDSCSI.py +++ /dev/null @@ -1,299 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright FUJITSU LIMITED 2008 -# Masaki Kanno -#============================================================================ - -from xen.xend.XendBase import XendBase -from xen.xend.XendPSCSI import XendPSCSI -from xen.xend import XendAPIStore -from xen.xend import sxp -from xen.xend import uuid as genuuid - -import XendDomain, XendNode - -from XendError import * -from XendTask import XendTask -from XendLogging import log - -class XendDSCSI(XendBase): - """Representation of a half-virtualized SCSI device.""" - - def getClass(self): - return "DSCSI" - - def getAttrRO(self): - attrRO = ['VM', - 'PSCSI', - 'HBA', - 'virtual_host', - 'virtual_channel', - 'virtual_target', - 'virtual_lun', - 'virtual_HCTL', - 'runtime_properties'] - return XendBase.getAttrRO() + attrRO - - def getAttrRW(self): - attrRW = [] - return XendBase.getAttrRW() + attrRW - - def getAttrInst(self): - attrInst = ['VM', - 'PSCSI', - 'HBA', - 'virtual_HCTL'] - return XendBase.getAttrInst() + attrInst - - def getMethods(self): - methods = ['destroy'] - return XendBase.getMethods() + methods - - def getFuncs(self): - funcs = ['create'] - return XendBase.getFuncs() + funcs - - getClass = classmethod(getClass) - getAttrRO = classmethod(getAttrRO) - getAttrRW = classmethod(getAttrRW) - getAttrInst = classmethod(getAttrInst) - getMethods = classmethod(getMethods) - getFuncs = classmethod(getFuncs) - - def create(self, dscsi_struct): - - # Check if VM is valid - xendom = XendDomain.instance() - if not xendom.is_valid_vm(dscsi_struct['VM']): - raise InvalidHandleError('VM', dscsi_struct['VM']) - dom = xendom.get_vm_by_uuid(dscsi_struct['VM']) - - # Check if PSCSI is valid - xennode = XendNode.instance() - pscsi_uuid = xennode.get_pscsi_by_uuid(dscsi_struct['PSCSI']) - if not pscsi_uuid: - raise InvalidHandleError('PSCSI', dscsi_struct['PSCSI']) - - # Assign PSCSI to VM - try: - dscsi_ref = XendTask.log_progress(0, 100, \ - dom.create_dscsi, \ - dscsi_struct) - except XendError, e: - log.exception("Error in create_dscsi") - raise - - return dscsi_ref - - create = classmethod(create) - - def get_by_VM(cls, VM_ref): - result = [] - for dscsi in XendAPIStore.get_all("DSCSI"): - if dscsi.get_VM() == VM_ref: - result.append(dscsi.get_uuid()) - return result - - get_by_VM = classmethod(get_by_VM) - - def __init__(self, uuid, record): - XendBase.__init__(self, uuid, record) - v_hctl = self.virtual_HCTL.split(':') - self.virtual_host = int(v_hctl[0]) - self.virtual_channel = int(v_hctl[1]) - self.virtual_target = int(v_hctl[2]) - self.virtual_lun = int(v_hctl[3]) - - def get_VM(self): - return self.VM - - def get_PSCSI(self): - return self.PSCSI - - def get_HBA(self): - return self.HBA - - def get_virtual_host(self): - return self.virtual_host - - def get_virtual_channel(self): - return self.virtual_channel - - def get_virtual_target(self): - return self.virtual_target - - def get_virtual_lun(self): - return self.virtual_lun - - def get_virtual_HCTL(self): - return self.virtual_HCTL - - def get_runtime_properties(self): - xendom = XendDomain.instance() - dominfo = xendom.get_vm_by_uuid(self.VM) - - try: - device_dict = {} - for device_sxp in dominfo.getDeviceSxprs('vscsi'): - target_dev = None - for dev in device_sxp[1][0][1]: - vdev = sxp.child_value(dev, 'v-dev') - if vdev == self.virtual_HCTL: - target_dev = dev - break - if target_dev is None: - continue - - dev_dict = {} - for info in target_dev[1:]: - dev_dict[info[0]] = info[1] - device_dict['dev'] = dev_dict - for info in device_sxp[1][1:]: - device_dict[info[0]] = info[1] - - return device_dict - except Exception, exn: - log.exception(exn) - return {} - - def destroy(self): - xendom = XendDomain.instance() - dom = xendom.get_vm_by_uuid(self.get_VM()) - if not dom: - raise InvalidHandleError("VM", self.get_VM()) - XendTask.log_progress(0, 100, \ - dom.destroy_dscsi, \ - self.get_uuid()) - - -class XendDSCSI_HBA(XendBase): - """Representation of a half-virtualized SCSI HBA.""" - - def getClass(self): - return "DSCSI_HBA" - - def getAttrRO(self): - attrRO = ['VM', - 'PSCSI_HBAs', - 'DSCSIs', - 'virtual_host', - 'assignment_mode'] - return XendBase.getAttrRO() + attrRO - - def getAttrRW(self): - attrRW = [] - return XendBase.getAttrRW() + attrRW - - def getAttrInst(self): - attrInst = ['VM', - 'virtual_host', - 'assignment_mode'] - return XendBase.getAttrInst() + attrInst - - def getMethods(self): - methods = ['destroy'] - return XendBase.getMethods() + methods - - def getFuncs(self): - funcs = ['create'] - return XendBase.getFuncs() + funcs - - getClass = classmethod(getClass) - getAttrRO = classmethod(getAttrRO) - getAttrRW = classmethod(getAttrRW) - getAttrInst = classmethod(getAttrInst) - getMethods = classmethod(getMethods) - getFuncs = classmethod(getFuncs) - - def create(self, dscsi_HBA_struct): - - # Check if VM is valid - xendom = XendDomain.instance() - if not xendom.is_valid_vm(dscsi_HBA_struct['VM']): - raise InvalidHandleError('VM', dscsi_HBA_struct['VM']) - dom = xendom.get_vm_by_uuid(dscsi_HBA_struct['VM']) - - # Check if PSCSI_HBA is valid - xennode = XendNode.instance() - pscsi_HBA_uuid = xennode.get_pscsi_HBA_by_uuid(dscsi_HBA_struct['PSCSI_HBA']) - if not pscsi_HBA_uuid: - raise InvalidHandleError('PSCSI_HBA', dscsi_HBA_struct['PSCSI_HBA']) - - # Assign PSCSI_HBA and PSCSIs to VM - try: - dscsi_HBA_ref = XendTask.log_progress(0, 100, \ - dom.create_dscsi_HBA, \ - dscsi_HBA_struct) - except XendError, e: - log.exception("Error in create_dscsi_HBA") - raise - - return dscsi_HBA_ref - - create = classmethod(create) - - def get_by_VM(cls, VM_ref): - result = [] - for dscsi_HBA in XendAPIStore.get_all("DSCSI_HBA"): - if dscsi_HBA.get_VM() == VM_ref: - result.append(dscsi_HBA.get_uuid()) - return result - - get_by_VM = classmethod(get_by_VM) - - def __init__(self, uuid, record): - XendBase.__init__(self, uuid, record) - self.virtual_host = record['virtual_host'] - self.assignment_mode = record['assignment_mode'] - - def get_VM(self): - return self.VM - - def get_PSCSI_HBAs(self): - PSCSIs = [] - uuid = self.get_uuid() - for dscsi in XendAPIStore.get_all('DSCSI'): - if dscsi.get_VM() == self.VM and dscsi.get_HBA() == uuid: - PSCSIs.append(dscsi.get_PSCSI()) - PSCSI_HBAs = [] - for pscsi_uuid in PSCSIs: - pscsi_HBA_uuid = XendAPIStore.get(pscsi_uuid, 'PSCSI').get_HBA() - if not pscsi_HBA_uuid in PSCSI_HBAs: - PSCSI_HBAs.append(pscsi_HBA_uuid) - return PSCSI_HBAs - - def get_DSCSIs(self): - DSCSIs = [] - uuid = self.get_uuid() - for dscsi in XendAPIStore.get_all('DSCSI'): - if dscsi.get_VM() == self.VM and dscsi.get_HBA() == uuid: - DSCSIs.append(dscsi.get_uuid()) - return DSCSIs - - def get_virtual_host(self): - return self.virtual_host - - def get_assignment_mode(self): - return self.assignment_mode - - def destroy(self): - xendom = XendDomain.instance() - dom = xendom.get_vm_by_uuid(self.get_VM()) - if not dom: - raise InvalidHandleError("VM", self.get_VM()) - XendTask.log_progress(0, 100, \ - dom.destroy_dscsi_HBA, \ - self.get_uuid()) - diff --git a/tools/python/xen/xend/XendDevices.py b/tools/python/xen/xend/XendDevices.py deleted file mode 100644 index bef4d8a11a..0000000000 --- a/tools/python/xen/xend/XendDevices.py +++ /dev/null @@ -1,85 +0,0 @@ -#=========================================================================== -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2006 XenSource Ltd -#============================================================================ - -# -# A collection of DevControllers -# - -from xen.xend.server import blkif, netif, pciif, iopif, irqif, vfbif, vscsiif, netif2, vusbif -from xen.xend.server.BlktapController import BlktapController, Blktap2Controller -from xen.xend.server.ConsoleController import ConsoleController - - -class XendDevices: - """ An ugly halfway point between the module local device name - to class map we used to have in XendDomainInfo and something - slightly more managable. - - This class should contain all the functions that have to do - with managing devices in Xend. Right now it is only a factory - function. - """ - - controllers = { - 'vbd': blkif.BlkifController, - 'vif': netif.NetifController, - 'vif2': netif2.NetifController2, - 'pci': pciif.PciController, - 'ioports': iopif.IOPortsController, - 'irq': irqif.IRQController, - 'tap': BlktapController, - 'tap2': Blktap2Controller, - 'vfb': vfbif.VfbifController, - 'vkbd': vfbif.VkbdifController, - 'console': ConsoleController, - 'vscsi': vscsiif.VSCSIController, - 'vusb': vusbif.VUSBController, - } - - #@classmethod - def valid_devices(cls): - return cls.controllers.keys() - valid_devices = classmethod(valid_devices) - - #@classmethod - def make_controller(cls, name, domain): - """Factory function to make device controllers per domain. - - @param name: device class name in L{VALID_DEVICES} - @type name: String - @param domain: domain this controller is handling devices for. - @type domain: XendDomainInfo - @return: DevController of class 'name' or None - @rtype: subclass of DevController - """ - if name in cls.controllers.keys(): - cls.controllers[name].deviceClass = name - return cls.controllers[name](domain) - return None - - make_controller = classmethod(make_controller) - - def destroy_device_state(cls, domain): - """Destroy the state of (external) devices. This is necessary - to do when a VM's configuration is destroyed. - - @param domain: domain this controller is handling devices for. - @type domain: XendDomainInfo - """ - from xen.xend.XendLogging import log - - destroy_device_state = classmethod(destroy_device_state) diff --git a/tools/python/xen/xend/XendDmesg.py b/tools/python/xen/xend/XendDmesg.py deleted file mode 100644 index f4d0ff6be3..0000000000 --- a/tools/python/xen/xend/XendDmesg.py +++ /dev/null @@ -1,41 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2007 XenSource Inc. -#============================================================================ - -"""Get dmesg output for this node. -""" - -import xen.lowlevel.xc - -class XendDmesg: - def __init__(self): - self.xc = xen.lowlevel.xc.xc() - - def info(self): - return self.xc.readconsolering() - - def clear(self): - return self.xc.readconsolering(True) - -def instance(): - global inst - try: - inst - except: - inst = XendDmesg() - return inst - diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py deleted file mode 100644 index 1d4da8ffbc..0000000000 --- a/tools/python/xen/xend/XendDomain.py +++ /dev/null @@ -1,1958 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2005 Christian Limpach -# Copyright (C) 2005 XenSource Ltd -#============================================================================ - -"""Handler for domain operations. - Nothing here is persistent (across reboots). - Needs to be persistent for one uptime. -""" - -import os -import stat -import shutil -import socket -import tempfile -import threading -import re - -import xen.lowlevel.xc - - -from xen.xend import XendOptions, XendCheckpoint, XendDomainInfo -from xen.xend.PrettyPrint import prettyprint -from xen.xend import XendConfig, image -from xen.xend.XendError import XendError, XendInvalidDomain, VmError -from xen.xend.XendError import VMBadState -from xen.xend.XendLogging import log -from xen.xend.XendAPIConstants import XEN_API_VM_POWER_STATE -from xen.xend.XendConstants import XS_VMROOT -from xen.xend.XendConstants import DOM_STATE_HALTED, DOM_STATE_PAUSED -from xen.xend.XendConstants import DOM_STATE_RUNNING, DOM_STATE_SUSPENDED -from xen.xend.XendConstants import DOM_STATE_SHUTDOWN, DOM_STATE_UNKNOWN -from xen.xend.XendConstants import DOM_STATE_CRASHED, HVM_PARAM_ACPI_S_STATE -from xen.xend.XendConstants import TRIGGER_TYPE, TRIGGER_S3RESUME -from xen.xend.XendDevices import XendDevices -from xen.xend.XendAPIConstants import * - -from xen.xend.xenstore.xstransact import xstransact -from xen.xend.xenstore.xswatch import xswatch -from xen.util import mkdir, rwlock -from xen.xend import uuid - -xc = xen.lowlevel.xc.xc() -xoptions = XendOptions.instance() - -__all__ = [ "XendDomain" ] - -CACHED_CONFIG_FILE = 'config.sxp' -CHECK_POINT_FILE = 'checkpoint.chk' -DOM0_UUID = "00000000-0000-0000-0000-000000000000" -DOM0_NAME = "Domain-0" -DOM0_ID = 0 - -POWER_STATE_NAMES = dict([(x, XEN_API_VM_POWER_STATE[x]) - for x in [DOM_STATE_HALTED, - DOM_STATE_PAUSED, - DOM_STATE_RUNNING, - DOM_STATE_SUSPENDED, - DOM_STATE_SHUTDOWN, - DOM_STATE_CRASHED, - DOM_STATE_UNKNOWN]]) -POWER_STATE_ALL = 'all' - - -class XendDomain: - """Index of all domains. Singleton. - - @ivar domains: map of domains indexed by domid - @type domains: dict of XendDomainInfo - @ivar managed_domains: domains that are not running and managed by Xend - @type managed_domains: dict of XendDomainInfo indexed by uuid - @ivar domains_lock: lock that must be held when manipulating self.domains - @type domains_lock: threaading.RLock - @ivar _allow_new_domains: Flag to set that allows creating of new domains. - @type _allow_new_domains: boolean - """ - - def __init__(self): - self.domains = {} - self.managed_domains = {} - self.domains_lock = threading.RLock() - - self.policy_lock = rwlock.RWLock() - - # xen api instance vars - # TODO: nothing uses this at the moment - self._allow_new_domains = True - - # This must be called only the once, by instance() below. It is separate - # from the constructor because XendDomainInfo calls back into this class - # in order to check the uniqueness of domain names. This means that - # instance() must be able to return a valid instance of this class even - # during this initialisation. - def init(self): - """Singleton initialisation function.""" - - dom_path = self._managed_path() - mkdir.parents(dom_path, stat.S_IRWXU) - - xstransact.Mkdir(XS_VMROOT) - xstransact.SetPermissions(XS_VMROOT, {'dom': DOM0_ID}) - - self.domains_lock.acquire() - try: - try: - dom0info = [d for d in self._running_domains() \ - if d.get('domid') == DOM0_ID][0] - - dom0info['name'] = DOM0_NAME - dom0 = XendDomainInfo.recreate(dom0info, True) - except IndexError: - raise XendError('Unable to find Domain 0') - - self._setDom0CPUCount() - - # This watch registration needs to be before the refresh call, so - # that we're sure that we haven't missed any releases, but inside - # the domains_lock, as we don't want the watch to fire until after - # the refresh call has completed. - xswatch("@introduceDomain", self._on_domains_changed) - xswatch("@releaseDomain", self._on_domains_changed) - - self._init_domains() - finally: - self.domains_lock.release() - - - def _on_domains_changed(self, _): - """ Callback method when xenstore changes. - - Calls refresh which will keep the local cache of domains - in sync. - - @rtype: int - @return: 1 - """ - self.domains_lock.acquire() - try: - self._refresh() - finally: - self.domains_lock.release() - return 1 - - def _init_domains(self): - """Does the initial scan of managed and active domains to - populate self.domains. - - Note: L{XendDomainInfo._checkName} will call back into XendDomain - to make sure domain name is not a duplicate. - - """ - self.domains_lock.acquire() - try: - running = self._running_domains() - managed = self._managed_domains() - - # add all active domains - for dom in running: - if dom['dying'] == 1: - log.warn('Ignoring dying domain %d from now on' % - dom['domid']) - continue - - if dom['domid'] != DOM0_ID: - try: - new_dom = XendDomainInfo.recreate(dom, False) - except Exception: - log.exception("Failed to create reference to running " - "domain id: %d" % dom['domid']) - - image.cleanup_stale_sentinel_fifos() - - # add all managed domains as dormant domains. - for dom in managed: - dom_uuid = dom.get('uuid') - if not dom_uuid: - continue - - dom_name = dom.get('name_label', 'Domain-%s' % dom_uuid) - try: - running_dom = self.domain_lookup_nr(dom_name) - if not running_dom: - # instantiate domain if not started. - new_dom = XendDomainInfo.createDormant(dom) - self._managed_domain_register(new_dom) - else: - self._managed_domain_register(running_dom) - for key in XendConfig.XENAPI_CFG_TYPES.keys(): - if key not in XendConfig.LEGACY_XENSTORE_VM_PARAMS and \ - key in dom: - running_dom.info[key] = dom[key] - # Devices information is restored from xenstore, - # but VDI value in devices information can be not - # restored because there is not VDI value in - # xenstore. So we restore VDI value by using the - # domain config file. - for vbd_ref in running_dom.info['vbd_refs']: - if dom['devices'].has_key(vbd_ref): - r_devtype, r_devinfo = running_dom.info['devices'][vbd_ref] - _, m_devinfo = dom['devices'][vbd_ref] - r_devinfo['VDI'] = m_devinfo.get('VDI', '') - running_dom.info['devices'][vbd_ref] = (r_devtype, r_devinfo) - except Exception: - log.exception("Failed to create reference to managed " - "domain: %s" % dom_name) - - finally: - self.domains_lock.release() - - - # ----------------------------------------------------------------- - # Getting managed domains storage path names - - def _managed_path(self, domuuid = None): - """Returns the path of the directory where managed domain - information is stored. - - @keyword domuuid: If not None, will return the path to the domain - otherwise, will return the path containing - the directories which represent each domain. - @type: None or String. - @rtype: String - @return: Path. - """ - dom_path = xoptions.get_xend_domains_path() - if domuuid: - dom_path = os.path.join(dom_path, domuuid) - return dom_path - - def _managed_config_path(self, domuuid): - """Returns the path to the configuration file of a managed domain. - - @param domname: Domain uuid - @type domname: String - @rtype: String - @return: path to config file. - """ - return os.path.join(self._managed_path(domuuid), CACHED_CONFIG_FILE) - def domain_setpauseflag(self, dom, flag=False): - try: - dominfo = self.domain_lookup_nr(dom) - dominfo.paused_by_admin = flag - except Exception, err: - log.debug("error in in setpauseflag") - def domain_getpauseflag(self, dom): - try: - dominfo = self.domain_lookup_nr(dom) - return dominfo.paused_by_admin - except Exception, err: - log.debug("error in in getpauseflag") - - def _managed_check_point_path(self, domuuid): - """Returns absolute path to check point file for managed domain. - - @param domuuid: Name of managed domain - @type domname: String - @rtype: String - @return: Path - """ - return os.path.join(self._managed_path(domuuid), CHECK_POINT_FILE) - - def _managed_config_remove(self, domuuid): - """Removes a domain configuration from managed list - - @param domuuid: Name of managed domain - @type domname: String - @raise XendError: fails to remove the domain. - """ - config_path = self._managed_path(domuuid) - try: - if os.path.exists(config_path) and os.path.isdir(config_path): - shutil.rmtree(config_path) - except IOError: - log.exception('managed_config_remove failed removing conf') - raise XendError("Unable to remove managed configuration" - " for domain: %s" % domuuid) - - def managed_config_save(self, dominfo): - """Save a domain's configuration to disk - - @param domninfo: Managed domain to save. - @type dominfo: XendDomainInfo - @raise XendError: fails to save configuration. - @rtype: None - """ - if not self.is_domain_managed(dominfo): - return # refuse to save configuration this domain isn't managed - - if dominfo: - domains_dir = self._managed_path() - dom_uuid = dominfo.get_uuid() - domain_config_dir = self._managed_path(dom_uuid) - - def make_or_raise(path): - try: - mkdir.parents(path, stat.S_IRWXU) - except: - log.exception("%s could not be created." % path) - raise XendError("%s could not be created." % path) - - make_or_raise(domains_dir) - make_or_raise(domain_config_dir) - - try: - fd, fn = tempfile.mkstemp() - f = os.fdopen(fd, 'w+b') - try: - prettyprint(dominfo.sxpr(legacy_only = False), f, - width = 78) - finally: - f.close() - - try: - shutil.move(fn, self._managed_config_path(dom_uuid)) - except: - log.exception("Renaming %s to %s", fn, - self._managed_config_path(dom_uuid)) - os.remove(fn) - except: - log.exception("Error occurred saving configuration file " + - "to %s" % domain_config_dir) - raise XendError("Failed to save configuration file to: %s" % - domain_config_dir) - else: - log.warn("Trying to save configuration for invalid domain") - - - def _managed_domains(self): - """ Returns list of domains that are managed. - - Expects to be protected by domains_lock. - - @rtype: list of XendConfig - @return: List of domain configurations that are managed. - """ - dom_path = self._managed_path() - dom_uuids = os.listdir(dom_path) - doms = [] - for dom_uuid in dom_uuids: - try: - cfg_file = self._managed_config_path(dom_uuid) - cfg = XendConfig.XendConfig(filename = cfg_file) - if cfg.get('uuid') != dom_uuid: - # something is wrong with the SXP - log.error("UUID mismatch in stored configuration: %s" % - cfg_file) - continue - doms.append(cfg) - except Exception: - log.exception('Unable to open or parse config.sxp: %s' % \ - cfg_file) - return doms - - def _managed_domain_unregister(self, dom): - try: - if self.is_domain_managed(dom): - self._managed_config_remove(dom.get_uuid()) - del self.managed_domains[dom.get_uuid()] - dom.destroy_xapi_instances() - except ValueError: - log.warn("Domain is not registered: %s" % dom.get_uuid()) - - def _managed_domain_register(self, dom): - self.managed_domains[dom.get_uuid()] = dom - - def is_domain_managed(self, dom = None): - return (dom.get_uuid() in self.managed_domains) - - # End of Managed Domain Access - # -------------------------------------------------------------------- - - def _running_domains(self): - """Get table of domains indexed by id from xc. - - @requires: Expects to be protected by domains_lock. - @rtype: list of dicts - @return: A list of dicts representing the running domains. - """ - try: - return xc.domain_getinfo() - except RuntimeError, e: - log.exception("Unable to get domain information.") - return {} - - def _setDom0CPUCount(self): - """Sets the number of VCPUs dom0 has. Retreived from the - Xend configuration, L{XendOptions}. - - @requires: Expects to be protected by domains_lock. - @rtype: None - """ - dom0 = self.privilegedDomain() - - # get max number of vcpus to use for dom0 from config - target = int(xoptions.get_dom0_vcpus()) - log.debug("number of vcpus to use is %d", target) - - # target == 0 means use all processors - if target > 0: - dom0.setVCpuCount(target) - - - def _refresh(self, refresh_shutdown = True): - """Refresh the domain list. Needs to be called when - either xenstore has changed or when a method requires - up to date information (like uptime, cputime stats). - - Expects to be protected by the domains_lock. - - @rtype: None - """ - - txn = xstransact() - try: - self._refreshTxn(txn, refresh_shutdown) - txn.commit() - except: - txn.abort() - raise - - def _refreshTxn(self, transaction, refresh_shutdown): - running = self._running_domains() - # Add domains that are not already tracked but running in Xen, - # and update domain state for those that are running and tracked. - for dom in running: - domid = dom['domid'] - if domid in self.domains: - self.domains[domid].update(dom, refresh_shutdown, transaction) - elif domid not in self.domains and dom['dying'] != 1: - try: - new_dom = XendDomainInfo.recreate(dom, False) - except VmError: - log.exception("Unable to recreate domain") - try: - xc.domain_pause(domid) - XendDomainInfo.do_FLR(domid, dom['hvm']) - xc.domain_destroy(domid) - except: - log.exception("Hard destruction of domain failed: %d" % - domid) - - # update information for all running domains - # - like cpu_time, status, dying, etc. - # remove domains that are not running from active domain list. - # The list might have changed by now, because the update call may - # cause new domains to be added, if the domain has rebooted. We get - # the list again. - running = self._running_domains() - running_domids = [d['domid'] for d in running if d['dying'] != 1] - for domid, dom in self.domains.items(): - if domid not in running_domids and domid != DOM0_ID: - self._remove_domain(dom, domid) - - - def add_domain(self, info): - """Add a domain to the list of running domains - - @requires: Expects to be protected by the domains_lock. - @param info: XendDomainInfo of a domain to be added. - @type info: XendDomainInfo - """ - log.debug("Adding Domain: %s" % info.getDomid()) - self.domains[info.getDomid()] = info - - # update the managed domains with a new XendDomainInfo object - # if we are keeping track of it. - if info.get_uuid() in self.managed_domains: - self._managed_domain_register(info) - - def remove_domain(self, info, domid = None): - """Remove the domain from the list of running domains, taking the - domains_lock first. - """ - self.domains_lock.acquire() - try: - self._remove_domain(info, domid) - finally: - self.domains_lock.release() - - def _remove_domain(self, info, domid = None): - """Remove the domain from the list of running domains - - @requires: Expects to be protected by the domains_lock. - @param info: XendDomainInfo of a domain to be removed. - @type info: XendDomainInfo - """ - if info: - if domid == None: - domid = info.getDomid() - - if info._stateGet() != DOM_STATE_HALTED: - info.cleanupDomain() - - if domid in self.domains: - del self.domains[domid] - - info.destroy_xapi_instances() - else: - log.warning("Attempted to remove non-existent domain.") - - def restore_(self, config): - """Create a domain as part of the restore process. This is called - only from L{XendCheckpoint}. - - A restore request comes into XendDomain through L{domain_restore} - or L{domain_restore_fd}. That request is - forwarded immediately to XendCheckpoint which, when it is ready, will - call this method. It is necessary to come through here rather than go - directly to L{XendDomainInfo.restore} because we need to - serialise the domain creation process, but cannot lock - domain_restore_fd as a whole, otherwise we will deadlock waiting for - the old domain to die. - - @param config: Configuration of domain to restore - @type config: SXP Object (eg. list of lists) - """ - self.domains_lock.acquire() - try: - dominfo = XendDomainInfo.restore(config) - return dominfo - finally: - self.domains_lock.release() - - - def domain_lookup(self, domid): - """Look up given I{domid} in the list of managed and running - domains. - - @note: Will cause a refresh before lookup up domains, for - a version that does not need to re-read xenstore - use L{domain_lookup_nr}. - - @param domid: Domain ID or Domain Name. - @type domid: int or string - @return: Found domain. - @rtype: XendDomainInfo - @raise XendInvalidDomain: If domain is not found. - """ - self.domains_lock.acquire() - try: - self._refresh(refresh_shutdown = False) - dom = self.domain_lookup_nr(domid) - if not dom: - raise XendInvalidDomain(str(domid)) - return dom - finally: - self.domains_lock.release() - - - def domain_lookup_nr(self, domid): - """Look up given I{domid} in the list of managed and running - domains. - - @param domid: Domain ID or Domain Name. - @type domid: int or string - @return: Found domain. - @rtype: XendDomainInfo or None - """ - self.domains_lock.acquire() - try: - # lookup by name - match = [dom for dom in self.domains.values() \ - if dom.getName() == domid] - if match: - return match[0] - - match = [dom for dom in self.managed_domains.values() \ - if dom.getName() == domid] - if match: - return match[0] - - # lookup by id - try: - if int(domid) in self.domains: - return self.domains[int(domid)] - except ValueError: - pass - - # lookup by uuid for running domains - match = [dom for dom in self.domains.values() \ - if dom.get_uuid() == domid] - if match: - return match[0] - - # lookup by uuid for inactive managed domains - if domid in self.managed_domains: - return self.managed_domains[domid] - - return None - finally: - self.domains_lock.release() - - def privilegedDomain(self): - """ Get the XendDomainInfo of a dom0 - - @rtype: XendDomainInfo - """ - self.domains_lock.acquire() - try: - return self.domains[DOM0_ID] - finally: - self.domains_lock.release() - - def autostart_domains(self): - """ Autostart managed domains that are marked as such. """ - - need_starting = [] - - self.domains_lock.acquire() - try: - for dom_uuid, dom in self.managed_domains.items(): - if dom and dom._stateGet() == DOM_STATE_HALTED: - on_xend_start = dom.info.get('on_xend_start', 'ignore') - auto_power_on = dom.info.get('auto_power_on', False) - should_start = (on_xend_start == 'start') or auto_power_on - if should_start: - need_starting.append(dom_uuid) - finally: - self.domains_lock.release() - - for dom_uuid in need_starting: - self.domain_start(dom_uuid, False) - - def cleanup_domains(self): - """Clean up domains that are marked as autostop. - Should be called when Xend goes down. This is currently - called from L{xen.xend.servers.XMLRPCServer}. - - """ - log.debug('cleanup_domains') - self.domains_lock.acquire() - try: - for dom in self.domains.values(): - if dom.getName() == DOM0_NAME: - continue - - try: - if dom._stateGet() == DOM_STATE_RUNNING: - shutdownAction = dom.info.get('on_xend_stop', 'ignore') - if shutdownAction == 'shutdown': - log.debug('Shutting down domain: %s' % dom.getName()) - dom.shutdown("poweroff") - elif shutdownAction == 'suspend': - self.domain_suspend(dom.getName()) - else: - log.debug('Domain %s continues to run.' % dom.getName()) - except: - log.exception('Domain %s failed to %s.' % \ - (dom.getName(), shutdownAction)) - finally: - self.domains_lock.release() - - - - # ---------------------------------------------------------------- - # Xen API - - - def set_allow_new_domains(self, allow_new_domains): - self._allow_new_domains = allow_new_domains - - def allow_new_domains(self): - return self._allow_new_domains - - def get_domain_refs(self): - result = [] - try: - self.domains_lock.acquire() - result = [d.get_uuid() for d in self.domains.values()] - for d in self.managed_domains.keys(): - if d not in result: - result.append(d) - return result - finally: - self.domains_lock.release() - - def get_all_vms(self): - self.domains_lock.acquire() - try: - result = self.domains.values() - result += [x for x in self.managed_domains.values() if - x not in result] - return result - finally: - self.domains_lock.release() - - def get_vm_by_uuid(self, vm_uuid): - self.domains_lock.acquire() - try: - for dom in self.domains.values(): - if dom.get_uuid() == vm_uuid: - return dom - - if vm_uuid in self.managed_domains: - return self.managed_domains[vm_uuid] - - return None - finally: - self.domains_lock.release() - - def get_vm_with_dev_uuid(self, klass, dev_uuid): - self.domains_lock.acquire() - try: - for dom in self.domains.values() + self.managed_domains.values(): - if dom.has_device(klass, dev_uuid): - return dom - return None - finally: - self.domains_lock.release() - - def get_dev_property_by_uuid(self, klass, dev_uuid, field): - value = None - self.domains_lock.acquire() - - try: - try: - dom = self.get_vm_with_dev_uuid(klass, dev_uuid) - if dom: - value = dom.get_dev_property(klass, dev_uuid, field) - except ValueError, e: - pass - finally: - self.domains_lock.release() - - return value - - def set_dev_property_by_uuid(self, klass, dev_uuid, field, value, - old_val = None): - rc = True - self.domains_lock.acquire() - - try: - try: - dom = self.get_vm_with_dev_uuid(klass, dev_uuid) - if dom: - o_val = dom.get_dev_property(klass, dev_uuid, field) - log.info("o_val=%s, old_val=%s" % (o_val, old_val)) - if old_val and old_val != o_val: - return False - - dom.set_dev_property(klass, dev_uuid, field, value) - self.managed_config_save(dom) - except ValueError, e: - pass - finally: - self.domains_lock.release() - - return rc - - def is_valid_vm(self, vm_ref): - return (self.get_vm_by_uuid(vm_ref) != None) - - def is_valid_dev(self, klass, dev_uuid): - return (self.get_vm_with_dev_uuid(klass, dev_uuid) != None) - - def do_legacy_api_with_uuid(self, fn, vm_uuid, *args, **kwargs): - dom = self.uuid_to_dom(vm_uuid) - fn(dom, *args, **kwargs) - - def uuid_to_dom(self, vm_uuid): - self.domains_lock.acquire() - try: - for domid, dom in self.domains.items(): - if dom.get_uuid() == vm_uuid: - return domid - - if vm_uuid in self.managed_domains: - domid = self.managed_domains[vm_uuid].getDomid() - if domid is None: - return self.managed_domains[vm_uuid].getName() - else: - return domid - - raise XendInvalidDomain(vm_uuid) - finally: - self.domains_lock.release() - - - def create_domain(self, xenapi_vm): - self.domains_lock.acquire() - try: - try: - xeninfo = XendConfig.XendConfig(xapi = xenapi_vm) - dominfo = XendDomainInfo.createDormant(xeninfo) - log.debug("Creating new managed domain: %s: %s" % - (dominfo.getName(), dominfo.get_uuid())) - self._managed_domain_register(dominfo) - self.managed_config_save(dominfo) - return dominfo.get_uuid() - except XendError, e: - raise - except Exception, e: - raise XendError(str(e)) - finally: - self.domains_lock.release() - - def rename_domain(self, dom, new_name): - self.domains_lock.acquire() - try: - old_name = dom.getName() - dom.setName(new_name) - - finally: - self.domains_lock.release() - - - # - # End of Xen API - # ---------------------------------------------------------------- - - # ------------------------------------------------------------ - # Xen Legacy API - - def list(self, state = DOM_STATE_RUNNING): - """Get list of domain objects. - - @param: the state in which the VMs should be -- one of the - DOM_STATE_XYZ constants, or the corresponding name, or 'all'. - @return: domains - @rtype: list of XendDomainInfo - """ - if type(state) == int: - state = POWER_STATE_NAMES[state] - state = state.lower() - resu = False - count = 0 - while True: - resu = self.domains_lock.acquire(0) - if resu or count < 20: - break - count += 1 - try: - if resu: - self._refresh(refresh_shutdown = False) - - # active domains - active_domains = self.domains.values() - active_uuids = [d.get_uuid() for d in active_domains] - - # inactive domains - inactive_domains = [] - for dom_uuid, dom in self.managed_domains.items(): - if dom_uuid not in active_uuids: - inactive_domains.append(dom) - - if state == POWER_STATE_ALL: - return active_domains + inactive_domains - else: - return filter(lambda x: - POWER_STATE_NAMES[x._stateGet()].lower() == state, - active_domains + inactive_domains) - finally: - if resu: - self.domains_lock.release() - - - def list_sorted(self, state = DOM_STATE_RUNNING): - """Get list of domain objects, sorted by name. - - @param: the state in which the VMs should be -- one of the - DOM_STATE_XYZ constants, or the corresponding name, or 'all'. - @return: domain objects - @rtype: list of XendDomainInfo - """ - doms = self.list(state) - doms.sort(lambda x, y: cmp(x.getName(), y.getName())) - return doms - - def list_names(self, state = DOM_STATE_RUNNING): - """Get list of domain names. - - @param: the state in which the VMs should be -- one of the - DOM_STATE_XYZ constants, or the corresponding name, or 'all'. - @return: domain names - @rtype: list of strings. - """ - return [d.getName() for d in self.list_sorted(state)] - - def domain_suspend(self, domname): - """Suspends a domain that is persistently managed by Xend - - @param domname: Domain Name - @type domname: string - @rtype: None - @raise XendError: Failure during checkpointing. - """ - - try: - dominfo = self.domain_lookup_nr(domname) - if not dominfo: - raise XendInvalidDomain(domname) - - if dominfo.getDomid() == DOM0_ID: - raise XendError("Cannot suspend privileged domain %s" % domname) - - if dominfo._stateGet() != DOM_STATE_RUNNING: - raise VMBadState("Domain is not running", - POWER_STATE_NAMES[DOM_STATE_RUNNING], - POWER_STATE_NAMES[dominfo._stateGet()]) - - dom_uuid = dominfo.get_uuid() - - if not os.path.exists(self._managed_config_path(dom_uuid)): - raise XendError("Domain is not managed by Xend lifecycle " + - "support.") - - path = self._managed_check_point_path(dom_uuid) - oflags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC - if hasattr(os, "O_LARGEFILE"): - oflags |= os.O_LARGEFILE - fd = os.open(path, oflags) - try: - # For now we don't support 'live checkpoint' - XendCheckpoint.save(fd, dominfo, False, False, path) - finally: - os.close(fd) - except OSError, ex: - raise XendError("can't write guest state file %s: %s" % - (path, ex[1])) - - def domain_resume(self, domname, start_paused = False): - """Resumes a domain that is persistently managed by Xend. - - @param domname: Domain Name - @type domname: string - @rtype: None - @raise XendError: If failed to restore. - """ - self.domains_lock.acquire() - try: - try: - fd = None - dominfo = self.domain_lookup_nr(domname) - - if not dominfo: - raise XendInvalidDomain(domname) - - if dominfo.getDomid() == DOM0_ID: - raise XendError("Cannot resume privileged domain %s" % domname) - - if dominfo._stateGet() != XEN_API_VM_POWER_STATE_SUSPENDED: - raise XendError("Cannot resume domain that is not suspended.") - - dominfo.setResume(True) - - dom_uuid = dominfo.get_uuid() - chkpath = self._managed_check_point_path(dom_uuid) - if not os.path.exists(chkpath): - raise XendError("Domain was not suspended by Xend") - - # Restore that replaces the existing XendDomainInfo - try: - log.debug('Current DomainInfo state: %d' % dominfo._stateGet()) - oflags = os.O_RDONLY - if hasattr(os, "O_LARGEFILE"): - oflags |= os.O_LARGEFILE - fd = os.open(chkpath, oflags) - XendCheckpoint.restore(self, - fd, - dominfo, - paused = start_paused) - os.unlink(chkpath) - except OSError, ex: - raise XendError("Failed to read stored checkpoint file") - except IOError, ex: - raise XendError("Failed to delete checkpoint file") - except Exception, ex: - log.exception("Exception occurred when resuming") - raise XendError("Error occurred when resuming: %s" % str(ex)) - finally: - if fd is not None: - os.close(fd) - self.domains_lock.release() - - - def domain_create(self, config): - """Create a domain from a configuration. - - @param config: configuration - @type config: SXP Object (list of lists) - @rtype: XendDomainInfo - """ - self.domains_lock.acquire() - try: - self._refresh() - - dominfo = XendDomainInfo.create(config) - return dominfo - finally: - self.domains_lock.release() - - - def domain_create_from_dict(self, config_dict): - """Create a domain from a configuration dictionary. - - @param config_dict: configuration - @rtype: XendDomainInfo - """ - self.domains_lock.acquire() - try: - self._refresh() - - dominfo = XendDomainInfo.create_from_dict(config_dict) - return dominfo - finally: - self.domains_lock.release() - - - def domain_new(self, config): - """Create a domain from a configuration but do not start it. - - @param config: configuration - @type config: SXP Object (list of lists) - @rtype: XendDomainInfo - """ - self.domains_lock.acquire() - try: - try: - domconfig = XendConfig.XendConfig(sxp_obj = config) - dominfo = XendDomainInfo.createDormant(domconfig) - log.debug("Creating new managed domain: %s" % - dominfo.getName()) - self._managed_domain_register(dominfo) - self.managed_config_save(dominfo) - # no return value because it isn't meaningful for client - except XendError, e: - raise - except Exception, e: - raise XendError(str(e)) - finally: - self.domains_lock.release() - - def domain_start(self, domid, start_paused = True): - """Start a managed domain - - @require: Domain must not be running. - @param domid: Domain name or domain ID. - @type domid: string or int - @rtype: None - @raise XendError: If domain is still running - @rtype: None - """ - self.domains_lock.acquire() - try: - self._refresh() - - dominfo = self.domain_lookup_nr(domid) - if not dominfo: - raise XendInvalidDomain(str(domid)) - - if dominfo._stateGet() != DOM_STATE_HALTED: - raise VMBadState("Domain is already running", - POWER_STATE_NAMES[DOM_STATE_HALTED], - POWER_STATE_NAMES[dominfo._stateGet()]) - - dominfo.start(is_managed = True) - finally: - self.domains_lock.release() - - try: - dominfo.waitForDevices() - except Exception, ex: - log.warn("Failed to setup devices for " + str(dominfo) + ": " + str(ex)) - dominfo.destroy() - raise - - if not start_paused: - dominfo.unpause() - - def domain_delete(self, domid): - """Remove a managed domain from database - - @require: Domain must not be running. - @param domid: Domain name or domain ID. - @type domid: string or int - @rtype: None - @raise XendError: If domain is still running - """ - self.domains_lock.acquire() - try: - try: - dominfo = self.domain_lookup_nr(domid) - if not dominfo: - raise XendInvalidDomain(str(domid)) - - if dominfo._stateGet() != XEN_API_VM_POWER_STATE_HALTED: - raise VMBadState("Domain is not halted.", - POWER_STATE_NAMES[DOM_STATE_HALTED], - POWER_STATE_NAMES[dominfo._stateGet()]) - - self._domain_delete_by_info(dominfo) - except Exception, ex: - raise XendError(str(ex)) - finally: - self.domains_lock.release() - - - def domain_delete_by_dominfo(self, dominfo): - """Only for use by XendDomainInfo. - """ - self.domains_lock.acquire() - try: - self._domain_delete_by_info(dominfo) - finally: - self.domains_lock.release() - - - def _domain_delete_by_info(self, dominfo): - """Expects to be protected by domains_lock. - """ - log.info("Domain %s (%s) deleted." % - (dominfo.getName(), dominfo.info.get('uuid'))) - - self._managed_domain_unregister(dominfo) - self._remove_domain(dominfo) - XendDevices.destroy_device_state(dominfo) - - - def domain_configure(self, config): - """Configure an existing domain. - - @param vmconfig: vm configuration - @type vmconfig: SXP Object (list of lists) - @todo: Not implemented - """ - # !!! - raise XendError("Unsupported") - - def domain_restore(self, src, paused=False): - """Restore a domain from file. - - @param src: filename of checkpoint file to restore from - @type src: string - @return: Restored domain - @rtype: XendDomainInfo - @raise XendError: Failure to restore domain - """ - try: - oflags = os.O_RDONLY - if hasattr(os, "O_LARGEFILE"): - oflags |= os.O_LARGEFILE - fd = os.open(src, oflags) - try: - return self.domain_restore_fd(fd, paused=paused) - finally: - os.close(fd) - except OSError, ex: - raise XendError("can't read guest state file %s: %s" % - (src, ex[1])) - - def domain_restore_fd(self, fd, paused=False, relocating=False): - """Restore a domain from the given file descriptor. - - @param fd: file descriptor of the checkpoint file - @type fd: File object - @rtype: XendDomainInfo - @raise XendError: if failed to restore - """ - - try: - self.policy_lock.acquire_reader() - - try: - dominfo = XendCheckpoint.restore(self, fd, paused=paused, relocating=relocating) - if relocating and \ - dominfo.info.has_key("change_home_server"): - chs = (dominfo.info["change_home_server"] == "True") - dominfo.setChangeHomeServer(None) - if chs: - self.domains_lock.acquire() - try: - log.debug("Migrating new managed domain: %s: %s" % - (dominfo.getName(), dominfo.get_uuid())) - self._managed_domain_register(dominfo) - self.managed_config_save(dominfo) - finally: - self.domains_lock.release() - return dominfo - except XendError, e: - log.exception("Restore failed") - raise - except: - # I don't really want to log this exception here, but the error - # handling in the relocation-socket handling code (relocate.py) is - # poor, so we need to log this for debugging. - log.exception("Restore failed") - raise XendError("Restore failed") - finally: - self.policy_lock.release() - - def domain_unpause(self, domid): - """Unpause domain execution. - - @param domid: Domain ID or Name - @type domid: int or string. - @rtype: None - @raise XendError: Failed to unpause - @raise XendInvalidDomain: Domain is not valid - """ - try: - dominfo = self.domain_lookup_nr(domid) - if not dominfo: - raise XendInvalidDomain(str(domid)) - if dominfo.getDomid() == DOM0_ID: - raise XendError("Cannot unpause privileged domain %s" % domid) - if dominfo._stateGet() not in (DOM_STATE_PAUSED, DOM_STATE_RUNNING): - raise VMBadState("Domain '%s' is not started" % domid, - POWER_STATE_NAMES[DOM_STATE_PAUSED], - POWER_STATE_NAMES[dominfo._stateGet()]) - log.info("Domain %s (%d) unpaused.", dominfo.getName(), - int(dominfo.getDomid())) - dominfo.unpause() - except XendInvalidDomain: - log.exception("domain_unpause") - raise - except Exception, ex: - log.exception("domain_unpause") - raise XendError(str(ex)) - - def domain_pause(self, domid, state=False): - """Pause domain execution. - - @param domid: Domain ID or Name - @type domid: int or string. - @keyword state: If True, will return the domain state before pause - @type state: bool - @rtype: int if state is True - @return: Domain state (DOM_STATE_*) - @rtype: None if state is False - @raise XendError: Failed to pause - @raise XendInvalidDomain: Domain is not valid - """ - try: - dominfo = self.domain_lookup_nr(domid) - if not dominfo: - raise XendInvalidDomain(str(domid)) - if dominfo.getDomid() == DOM0_ID: - raise XendError("Cannot pause privileged domain %s" % domid) - ds = dominfo._stateGet() - if ds not in (DOM_STATE_RUNNING, DOM_STATE_PAUSED, DOM_STATE_CRASHED): - raise VMBadState("Domain '%s' is not started" % domid, - POWER_STATE_NAMES[DOM_STATE_RUNNING], - POWER_STATE_NAMES[ds]) - log.info("Domain %s (%d) paused.", dominfo.getName(), - int(dominfo.getDomid())) - if ds == DOM_STATE_RUNNING: - dominfo.pause() - if state: - return ds - except XendInvalidDomain: - log.exception("domain_pause") - raise - except Exception, ex: - log.exception("domain_pause") - raise XendError(str(ex)) - - def domain_dump(self, domid, filename=None, live=False, crash=False, reset=False): - """Dump domain core.""" - - dominfo = self.domain_lookup_nr(domid) - if not dominfo: - raise XendInvalidDomain(str(domid)) - - if dominfo.getDomid() == DOM0_ID: - raise XendError("Cannot dump core for privileged domain %s" % domid) - if dominfo._stateGet() not in (DOM_STATE_PAUSED, DOM_STATE_RUNNING, DOM_STATE_CRASHED): - raise VMBadState("Domain '%s' is not started" % domid, - POWER_STATE_NAMES[DOM_STATE_PAUSED], - POWER_STATE_NAMES[dominfo._stateGet()]) - - dopause = (not live and dominfo._stateGet() == DOM_STATE_RUNNING) - if dopause: - dominfo.pause() - - try: - try: - log.info("Domain core dump requested for domain %s (%d) " - "live=%d crash=%d reset=%d.", - dominfo.getName(), dominfo.getDomid(), live, crash, reset) - dominfo.dumpCore(filename) - if crash: - self.domain_destroy(domid) - elif reset: - self.domain_reset(domid) - except Exception, ex: - raise XendError(str(ex)) - finally: - if dopause and not crash and not reset: - dominfo.unpause() - - def domain_destroy(self, domid): - """Terminate domain immediately. - - @param domid: Domain ID or Name - @type domid: int or string. - @rtype: None - @raise XendError: Failed to destroy - @raise XendInvalidDomain: Domain is not valid - """ - - dominfo = self.domain_lookup_nr(domid) - if dominfo and dominfo.getDomid() == DOM0_ID: - raise XendError("Cannot destroy privileged domain %s" % domid) - - if dominfo: - val = dominfo.destroy() - else: - try: - xc.domain_pause(int(domid)) - dom = self.domains[int(domid)] - XendDomainInfo.do_FLR(int(domid), dom.info.is_hvm()) - val = xc.domain_destroy(int(domid)) - except ValueError: - raise XendInvalidDomain(domid) - except Exception, e: - raise XendError(str(e)) - - return val - - def domain_migrate(self, domid, dst, live=False, port=0, node=-1, ssl=None,\ - chs=False): - """Start domain migration. - - @param domid: Domain ID or Name - @type domid: int or string. - @param dst: Destination IP address - @type dst: string - @keyword live: Live migration - @type live: bool - @keyword port: relocation port on destination - @type port: int - @keyword node: use node number for target - @type node: int - @keyword ssl: use ssl connection - @type ssl: bool - @keyword chs: change home server for managed domain - @type chs: bool - @rtype: None - @raise XendError: Failed to migrate - @raise XendInvalidDomain: Domain is not valid - """ - - dominfo = self.domain_lookup_nr(domid) - if not dominfo: - raise XendInvalidDomain(str(domid)) - - if dominfo.getDomid() == DOM0_ID: - raise XendError("Cannot migrate privileged domain %s" % domid) - if dominfo._stateGet() != DOM_STATE_RUNNING: - raise VMBadState("Domain is not running", - POWER_STATE_NAMES[DOM_STATE_RUNNING], - POWER_STATE_NAMES[dominfo._stateGet()]) - if chs and not self.is_domain_managed(dominfo): - raise XendError("Domain is not a managed domain") - - """ The following call may raise a XendError exception """ - dominfo.testMigrateDevices(True, dst) - - if live: - """ Make sure there's memory free for enabling shadow mode """ - dominfo.checkLiveMigrateMemory() - - if ssl is None: - ssl = xoptions.get_xend_relocation_ssl() - - try: - dominfo.setChangeHomeServer(chs) - if ssl: - self._domain_migrate_by_ssl(dominfo, dst, live, port, node) - else: - self._domain_migrate(dominfo, dst, live, port, node) - except: - dominfo.setChangeHomeServer(None) - raise - - def _domain_migrate_by_ssl(self, dominfo, dst, live, port, node): - from OpenSSL import SSL - from xen.web import connection - if port == 0: - port = xoptions.get_xend_relocation_ssl_port() - try: - ctx = SSL.Context(SSL.SSLv23_METHOD) - sock = SSL.Connection(ctx, - socket.socket(socket.AF_INET, socket.SOCK_STREAM)) - sock.set_connect_state() - sock.connect((dst, port)) - sock.send("sslreceive\n") - sock.recv(80) - except SSL.Error, err: - raise XendError("SSL error: %s" % err) - except socket.error, err: - raise XendError("can't connect: %s" % err) - - p2cread, p2cwrite = os.pipe() - threading.Thread(target=connection.SSLSocketServerConnection.fd2send, - args=(sock, p2cread)).start() - - try: - try: - XendCheckpoint.save(p2cwrite, dominfo, True, live, dst, - node=node,sock=sock) - except Exception, ex: - m_dsterr = None - try: - sock.settimeout(3.0) - dsterr = sock.recv(1024) - sock.settimeout(None) - if dsterr: - # See send_error@relocate.py. If an error occurred - # in a destination side, an error message with the - # following form is returned from the destination - # side. - m_dsterr = \ - re.match(r"^\(err\s\(type\s(.+)\)\s\(value\s'(.+)'\)\)", dsterr) - except: - # Probably socket.timeout exception occurred. - # Ignore the exception because it has nothing to do with - # an exception of XendCheckpoint.save. - pass - - if m_dsterr: - raise XendError("%s (from %s)" % (m_dsterr.group(2), dst)) - raise - finally: - if not live: - try: - sock.shutdown(2) - except: - # Probably the socket is already disconnected by sock.close - # in the destination side. - # Ignore the exception because it has nothing to do with - # an exception of XendCheckpoint.save. - pass - sock.close() - - os.close(p2cread) - os.close(p2cwrite) - - def _domain_migrate(self, dominfo, dst, live, port, node): - if port == 0: - port = xoptions.get_xend_relocation_port() - try: - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - # When connecting to our ssl enabled relocation server using a - # plain socket, send will success but recv will block. Add a - # 30 seconds timeout to raise a socket.timeout exception to - # inform the client. - sock.settimeout(30.0) - sock.connect((dst, port)) - sock.send("receive\n") - sock.recv(80) - sock.settimeout(None) - except socket.error, err: - raise XendError("can't connect: %s" % err) - - try: - try: - XendCheckpoint.save(sock.fileno(), dominfo, True, live, - dst, node=node,sock=sock) - except Exception, ex: - m_dsterr = None - try: - sock.settimeout(3.0) - dsterr = sock.recv(1024) - sock.settimeout(None) - if dsterr: - # See send_error@relocate.py. If an error occurred - # in a destination side, an error message with the - # following form is returned from the destination - # side. - m_dsterr = \ - re.match(r"^\(err\s\(type\s(.+)\)\s\(value\s'(.+)'\)\)", dsterr) - except: - # Probably socket.timeout exception occurred. - # Ignore the exception because it has nothing to do with - # an exception of XendCheckpoint.save. - pass - - if m_dsterr: - raise XendError("%s (from %s)" % (m_dsterr.group(2), dst)) - raise - finally: - if not live: - try: - sock.shutdown(2) - except: - # Probably the socket is already disconnected by sock.close - # in the destination side. - # Ignore the exception because it has nothing to do with - # an exception of XendCheckpoint.save. - pass - sock.close() - - def domain_save(self, domid, dst, checkpoint=False): - """Start saving a domain to file. - - @param domid: Domain ID or Name - @type domid: int or string. - @param dst: Destination filename - @type dst: string - @rtype: None - @raise XendError: Failed to save domain - @raise XendInvalidDomain: Domain is not valid - """ - try: - dominfo = self.domain_lookup_nr(domid) - if not dominfo: - raise XendInvalidDomain(str(domid)) - - if dominfo.getDomid() == DOM0_ID: - raise XendError("Cannot save privileged domain %s" % str(domid)) - if dominfo._stateGet() != DOM_STATE_RUNNING: - raise VMBadState("Domain is not running", - POWER_STATE_NAMES[DOM_STATE_RUNNING], - POWER_STATE_NAMES[dominfo._stateGet()]) - - oflags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC - if hasattr(os, "O_LARGEFILE"): - oflags |= os.O_LARGEFILE - fd = os.open(dst, oflags) - try: - XendCheckpoint.save(fd, dominfo, False, False, dst, - checkpoint=checkpoint) - except Exception, e: - os.close(fd) - raise e - os.close(fd) - except OSError, ex: - raise XendError("can't write guest state file %s: %s" % - (dst, ex[1])) - - def domain_usb_add(self, domid, dev_id): - dominfo = self.domain_lookup_nr(domid) - if not dominfo: - raise XendInvalidDomain(str(domid)) - - usb = dominfo.info['platform'].get('usb') - if not usb: - raise XendError("Can't add usb device to a guest with usb disabled in configure file") - - hvm = dominfo.info.is_hvm() - if not hvm: - raise XendError("Can't add usb device to a non-hvm guest") - - if dominfo._stateGet() != DOM_STATE_HALTED: - dominfo.image.signalDeviceModel("usb-add", - "usb-added", dev_id) - else: - log.debug("error: Domain is not running!") - - - def domain_usb_del(self, domid, dev_id): - dominfo = self.domain_lookup_nr(domid) - if not dominfo: - raise XendInvalidDomain(str(domid)) - - usb = dominfo.info['platform'].get('usb') - if not usb: - raise XendError("Can't add usb device to a guest with usb disabled in configure file") - - hvm = dominfo.info.is_hvm() - if not hvm: - raise XendError("Can't del usb to a non-hvm guest") - - if dominfo._stateGet() != DOM_STATE_HALTED: - dominfo.image.signalDeviceModel("usb-del", - "usb-deleted", dev_id) - else: - log.debug("error: Domain is not running!") - - def domain_pincpu(self, domid, vcpu, cpumap): - """Set which cpus vcpu can use - - @param domid: Domain ID or Name - @type domid: int or string. - @param vcpu: vcpu to pin to - @type vcpu: int - @param cpumap: string repr of usable cpus - @type cpumap: string - @rtype: 0 - """ - dominfo = self.domain_lookup_nr(domid) - if not dominfo: - raise XendInvalidDomain(str(domid)) - - # if vcpu is keyword 'all', apply the cpumap to all vcpus - if str(vcpu).lower() == "all": - vcpus = range(0, int(dominfo.getVCpuCount())) - else: - vcpus = [ int(vcpu) ] - - # set the same cpumask for all vcpus - rc = 0 - cpus = dominfo.getCpus() - cpumap = map(int, cpumap.split(",")) - for v in vcpus: - try: - if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED): - rc = xc.vcpu_setaffinity(dominfo.getDomid(), v, cpumap) - cpus[v] = cpumap - except Exception, ex: - log.exception(ex) - raise XendError("Cannot pin vcpu: %d to cpu: %s - %s" % \ - (v, cpumap, str(ex))) - dominfo.setCpus(cpus) - self.managed_config_save(dominfo) - - return rc - - def domain_cpu_sedf_set(self, domid, period, slice_, latency, extratime, - weight): - """Set Simple EDF scheduler parameters for a domain. - - @param domid: Domain ID or Name - @type domid: int or string. - @rtype: 0 - """ - dominfo = self.domain_lookup_nr(domid) - if not dominfo: - raise XendInvalidDomain(str(domid)) - try: - return xc.sedf_domain_set(dominfo.getDomid(), period, slice_, - latency, extratime, weight) - except Exception, ex: - raise XendError(str(ex)) - - def domain_cpu_sedf_get(self, domid): - """Get Simple EDF scheduler parameters for a domain. - - @param domid: Domain ID or Name - @type domid: int or string. - @rtype: SXP object - @return: The parameters for Simple EDF schedule for a domain. - """ - dominfo = self.domain_lookup_nr(domid) - if not dominfo: - raise XendInvalidDomain(str(domid)) - try: - sedf_info = xc.sedf_domain_get(dominfo.getDomid()) - # return sxpr - return ['sedf', - ['domid', sedf_info['domid']], - ['period', sedf_info['period']], - ['slice', sedf_info['slice']], - ['latency', sedf_info['latency']], - ['extratime', sedf_info['extratime']], - ['weight', sedf_info['weight']]] - - except Exception, ex: - raise XendError(str(ex)) - - def domain_shadow_control(self, domid, op): - """Shadow page control. - - @param domid: Domain ID or Name - @type domid: int or string. - @param op: operation - @type op: int - @rtype: 0 - """ - dominfo = self.domain_lookup(domid) - try: - return xc.shadow_control(dominfo.getDomid(), op) - except Exception, ex: - raise XendError(str(ex)) - - def domain_shadow_mem_get(self, domid): - """Get shadow pagetable memory allocation. - - @param domid: Domain ID or Name - @type domid: int or string. - @rtype: int - @return: shadow memory in MB - """ - dominfo = self.domain_lookup(domid) - try: - return xc.shadow_mem_control(dominfo.getDomid()) - except Exception, ex: - raise XendError(str(ex)) - - def domain_shadow_mem_set(self, domid, mb): - """Set shadow pagetable memory allocation. - - @param domid: Domain ID or Name - @type domid: int or string. - @param mb: shadow memory to set in MB - @type: mb: int - @rtype: int - @return: shadow memory in MB - """ - dominfo = self.domain_lookup(domid) - try: - return xc.shadow_mem_control(dominfo.getDomid(), mb=mb) - except Exception, ex: - raise XendError(str(ex)) - - def domain_sched_credit_get(self, domid): - """Get credit scheduler parameters for a domain. - - @param domid: Domain ID or Name - @type domid: int or string. - @rtype: dict with keys 'weight' and 'cap' - @return: credit scheduler parameters - """ - dominfo = self.domain_lookup_nr(domid) - if not dominfo: - raise XendInvalidDomain(str(domid)) - - if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED): - try: - return xc.sched_credit_domain_get(dominfo.getDomid()) - except Exception, ex: - raise XendError(str(ex)) - else: - return {'weight' : dominfo.getWeight(), - 'cap' : dominfo.getCap()} - - def domain_sched_credit_set(self, domid, weight = None, cap = None): - """Set credit scheduler parameters for a domain. - - @param domid: Domain ID or Name - @type domid: int or string. - @type weight: int - @type cap: int - @rtype: 0 - """ - set_weight = False - set_cap = False - dominfo = self.domain_lookup_nr(domid) - if not dominfo: - raise XendInvalidDomain(str(domid)) - try: - if weight is None: - weight = int(0) - elif weight < 1 or weight > 65535: - raise XendError("Cpu weight out of range, valid values are " - "within range from 1 to 65535") - else: - set_weight = True - - if cap is None: - cap = int(~0) - elif cap < 0 or cap > dominfo.getVCpuCount() * 100: - raise XendError("Cpu cap out of range, valid range is " - "from 0 to %s for specified number of vcpus" % - (dominfo.getVCpuCount() * 100)) - else: - set_cap = True - - assert type(weight) == int - assert type(cap) == int - - rc = 0 - if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED): - rc = xc.sched_credit_domain_set(dominfo.getDomid(), weight, cap) - if rc == 0: - if set_weight: - dominfo.setWeight(weight) - if set_cap: - dominfo.setCap(cap) - self.managed_config_save(dominfo) - return rc - except Exception, ex: - log.exception(ex) - raise XendError(str(ex)) - - def domain_sched_credit2_get(self, domid): - """Get credit2 scheduler parameters for a domain. - - @param domid: Domain ID or Name - @type domid: int or string. - @rtype: dict with keys 'weight' - @return: credit2 scheduler parameters - """ - dominfo = self.domain_lookup_nr(domid) - if not dominfo: - raise XendInvalidDomain(str(domid)) - - if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED): - try: - return xc.sched_credit2_domain_get(dominfo.getDomid()) - except Exception, ex: - raise XendError(str(ex)) - else: - return {'weight' : dominfo.getWeight()} - - def domain_sched_credit2_set(self, domid, weight = None): - """Set credit2 scheduler parameters for a domain. - - @param domid: Domain ID or Name - @type domid: int or string. - @type weight: int - @rtype: 0 - """ - set_weight = False - dominfo = self.domain_lookup_nr(domid) - if not dominfo: - raise XendInvalidDomain(str(domid)) - try: - if weight is None: - weight = int(0) - elif weight < 1 or weight > 65535: - raise XendError("weight is out of range") - else: - set_weight = True - - assert type(weight) == int - - rc = 0 - if dominfo._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED): - rc = xc.sched_credit2_domain_set(dominfo.getDomid(), weight) - if rc == 0: - if set_weight: - dominfo.setWeight(weight) - self.managed_config_save(dominfo) - return rc - except Exception, ex: - log.exception(ex) - raise XendError(str(ex)) - - def domain_maxmem_set(self, domid, mem): - """Set the memory limit for a domain. - - @param domid: Domain ID or Name - @type domid: int or string. - @param mem: memory limit (in MiB) - @type mem: int - @raise XendError: fail to set memory - @rtype: 0 - """ - dominfo = self.domain_lookup_nr(domid) - if not dominfo: - raise XendInvalidDomain(str(domid)) - dominfo.setMemoryMaximum(mem) - - def domain_ioport_range_enable(self, domid, first, last): - """Enable access to a range of IO ports for a domain - - @param first: first IO port - @param last: last IO port - @raise XendError: failed to set range - @rtype: 0 - """ - dominfo = self.domain_lookup_nr(domid) - if not dominfo: - raise XendInvalidDomain(str(domid)) - nr_ports = last - first + 1 - try: - return xc.domain_ioport_permission(dominfo.getDomid(), - first_port = first, - nr_ports = nr_ports, - allow_access = 1) - except Exception, ex: - raise XendError(str(ex)) - - def domain_ioport_range_disable(self, domid, first, last): - """Disable access to a range of IO ports for a domain - - @param first: first IO port - @param last: last IO port - @raise XendError: failed to set range - @rtype: 0 - """ - dominfo = self.domain_lookup_nr(domid) - if not dominfo: - raise XendInvalidDomain(str(domid)) - nr_ports = last - first + 1 - try: - return xc.domain_ioport_permission(dominfo.getDomid(), - first_port = first, - nr_ports = nr_ports, - allow_access = 0) - except Exception, ex: - raise XendError(str(ex)) - - def domain_send_trigger(self, domid, trigger_name, vcpu = 0): - """Send trigger to a domain. - - @param domid: Domain ID or Name - @type domid: int or string. - @param trigger_name: trigger type name - @type trigger_name: string - @param vcpu: VCPU to send trigger (default is 0) - @type vcpu: int - @raise XendError: failed to send trigger - @raise XendInvalidDomain: Domain is not valid - @rtype: 0 - """ - dominfo = self.domain_lookup_nr(domid) - if not dominfo: - raise XendInvalidDomain(str(domid)) - if dominfo._stateGet() not in (DOM_STATE_RUNNING, DOM_STATE_PAUSED): - raise VMBadState("Domain '%s' is not started" % domid, - POWER_STATE_NAMES[DOM_STATE_RUNNING], - POWER_STATE_NAMES[dominfo._stateGet()]) - if trigger_name.lower() in TRIGGER_TYPE.keys(): - trigger = TRIGGER_TYPE[trigger_name.lower()] - else: - raise XendError("Invalid trigger: %s" % trigger_name) - if trigger == TRIGGER_S3RESUME: - xc.hvm_set_param(dominfo.getDomid(), HVM_PARAM_ACPI_S_STATE, 0) - return None - try: - return xc.domain_send_trigger(dominfo.getDomid(), - trigger, - vcpu) - except Exception, ex: - raise XendError(str(ex)) - - def domain_reset(self, domid): - """Terminate domain immediately, and then create domain. - - @param domid: Domain ID or Name - @type domid: int or string. - @rtype: None - @raise XendError: Failed to destroy or create - @raise XendInvalidDomain: Domain is not valid - """ - - dominfo = self.domain_lookup_nr(domid) - if not dominfo: - raise XendInvalidDomain(str(domid)) - if dominfo and dominfo.getDomid() == DOM0_ID: - raise XendError("Cannot reset privileged domain %s" % domid) - if dominfo._stateGet() not in (DOM_STATE_RUNNING, DOM_STATE_PAUSED): - raise VMBadState("Domain '%s' is not started" % domid, - POWER_STATE_NAMES[DOM_STATE_RUNNING], - POWER_STATE_NAMES[dominfo._stateGet()]) - try: - dominfo.resetDomain() - except Exception, ex: - raise XendError(str(ex)) - - -def instance(): - """Singleton constructor. Use this instead of the class constructor. - """ - global inst - try: - inst - except: - inst = XendDomain() - inst.init() - return inst diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py deleted file mode 100644 index 2270ab1dde..0000000000 --- a/tools/python/xen/xend/XendDomainInfo.py +++ /dev/null @@ -1,4429 +0,0 @@ -#=========================================================================== -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2005-2007 XenSource Ltd -#============================================================================ - -"""Representation of a single domain. -Includes support for domain construction, using -open-ended configurations. - -Author: Mike Wray - -""" - -import logging -import time -import threading -import thread -import re -import copy -import os -import stat -import shutil -import traceback -from types import StringTypes -import errno - -import xen.lowlevel.xc -from xen.lowlevel.xc import Error as XCError -from xen.util import asserts, auxbin, mkdir -from xen.util.blkif import parse_uname -import xen.util.xsm.xsm as security -from xen.util import xsconstants -from xen.util import mkdir -from xen.util.pci import serialise_pci_opts, pci_opts_list_to_sxp, \ - append_default_pci_opts, \ - pci_dict_to_bdf_str, pci_dict_to_xc_str, \ - pci_convert_sxp_to_dict, pci_convert_dict_to_sxp, \ - pci_dict_cmp, PCI_DEVFN, PCI_SLOT, PCI_FUNC, parse_hex - -from xen.xend import balloon, sxp, uuid, image, arch -from xen.xend import XendOptions, XendNode, XendConfig - -from xen.xend.XendConfig import scrub_password -from xen.xend.XendBootloader import bootloader, bootloader_tidy -from xen.xend.XendError import XendError, VmError -from xen.xend.XendDevices import XendDevices -from xen.xend.XendTask import XendTask -from xen.xend.xenstore.xstransact import xstransact, complete -from xen.xend.xenstore.xsutil import GetDomainPath, IntroduceDomain, SetTarget, ResumeDomain -from xen.xend.xenstore.xswatch import xswatch -from xen.xend.XendConstants import * -from xen.xend.XendAPIConstants import * -from xen.xend.XendCPUPool import XendCPUPool -from xen.xend.server.DevConstants import xenbusState -from xen.xend.server.BlktapController import TapdiskController, TapdiskException - -from xen.xend.XendVMMetrics import XendVMMetrics - -from xen.xend import XendAPIStore -from xen.xend.XendPPCI import XendPPCI -from xen.xend.XendDPCI import XendDPCI -from xen.xend.XendPSCSI import XendPSCSI -from xen.xend.XendDSCSI import XendDSCSI, XendDSCSI_HBA - -MIGRATE_TIMEOUT = 30.0 -BOOTLOADER_LOOPBACK_DEVICE = '/dev/xvdp' - -xc = xen.lowlevel.xc.xc() -xoptions = XendOptions.instance() - -log = logging.getLogger("xend.XendDomainInfo") -#log.setLevel(logging.TRACE) - - -def create(config): - """Creates and start a VM using the supplied configuration. - - @param config: A configuration object involving lists of tuples. - @type config: list of lists, eg ['vm', ['image', 'xen.gz']] - - @rtype: XendDomainInfo - @return: An up and running XendDomainInfo instance - @raise VmError: Invalid configuration or failure to start. - """ - from xen.xend import XendDomain - domconfig = XendConfig.XendConfig(sxp_obj = config) - othervm = XendDomain.instance().domain_lookup_nr(domconfig["name_label"]) - if othervm is None or othervm.domid is None: - othervm = XendDomain.instance().domain_lookup_nr(domconfig["uuid"]) - if othervm is not None and othervm.domid is not None: - raise VmError("Domain '%s' already exists with ID '%d'" % (domconfig["name_label"], othervm.domid)) - log.debug("XendDomainInfo.create(%s)", scrub_password(config)) - vm = XendDomainInfo(domconfig) - try: - vm.start() - except: - log.exception('Domain construction failed') - vm.destroy() - raise - - return vm - -def create_from_dict(config_dict): - """Creates and start a VM using the supplied configuration. - - @param config_dict: An configuration dictionary. - - @rtype: XendDomainInfo - @return: An up and running XendDomainInfo instance - @raise VmError: Invalid configuration or failure to start. - """ - - log.debug("XendDomainInfo.create_from_dict(%s)", - scrub_password(config_dict)) - vm = XendDomainInfo(XendConfig.XendConfig(xapi = config_dict)) - try: - vm.start() - except: - log.exception('Domain construction failed') - vm.destroy() - raise - return vm - -def recreate(info, priv): - """Create the VM object for an existing domain. The domain must not - be dying, as the paths in the store should already have been removed, - and asking us to recreate them causes problems. - - @param xeninfo: Parsed configuration - @type xeninfo: Dictionary - @param priv: Is a privileged domain (Dom 0) - @type priv: bool - - @rtype: XendDomainInfo - @return: A up and running XendDomainInfo instance - @raise VmError: Invalid configuration. - @raise XendError: Errors with configuration. - """ - - log.debug("XendDomainInfo.recreate(%s)", scrub_password(info)) - - assert not info['dying'] - - xeninfo = XendConfig.XendConfig(dominfo = info) - xeninfo['is_control_domain'] = priv - xeninfo['is_a_template'] = False - xeninfo['auto_power_on'] = False - domid = xeninfo['domid'] - uuid1 = uuid.fromString(xeninfo['uuid']) - needs_reinitialising = False - - dompath = GetDomainPath(domid) - if not dompath: - raise XendError('No domain path in store for existing ' - 'domain %d' % domid) - - log.info("Recreating domain %d, UUID %s. at %s" % - (domid, xeninfo['uuid'], dompath)) - - # need to verify the path and uuid if not Domain-0 - # if the required uuid and vm aren't set, then that means - # we need to recreate the dom with our own values - # - # NOTE: this is probably not desirable, really we should just - # abort or ignore, but there may be cases where xenstore's - # entry disappears (eg. xenstore-rm /) - # - try: - vmpath = xstransact.Read(dompath, "vm") - if not vmpath: - if not priv: - log.warn('/local/domain/%d/vm is missing. recreate is ' - 'confused, trying our best to recover' % domid) - needs_reinitialising = True - raise XendError('reinit') - - uuid2_str = xstransact.Read(vmpath, "uuid") - if not uuid2_str: - log.warn('%s/uuid/ is missing. recreate is confused, ' - 'trying our best to recover' % vmpath) - needs_reinitialising = True - raise XendError('reinit') - - uuid2 = uuid.fromString(uuid2_str) - if uuid1 != uuid2: - log.warn('UUID in /vm does not match the UUID in /dom/%d.' - 'Trying out best to recover' % domid) - needs_reinitialising = True - except XendError: - pass # our best shot at 'goto' in python :) - - vm = XendDomainInfo(xeninfo, domid, dompath, augment = True, priv = priv, - vmpath = vmpath) - - if needs_reinitialising: - vm._recreateDom() - vm._removeVm() - vm._storeVmDetails() - vm._storeDomDetails() - - vm.image = image.create(vm, vm.info) - vm.image.recreate() - - vm._registerWatches() - vm.refreshShutdown(xeninfo) - - # register the domain in the list - from xen.xend import XendDomain - XendDomain.instance().add_domain(vm) - - return vm - - -def restore(config): - """Create a domain and a VM object to do a restore. - - @param config: Domain SXP configuration - @type config: list of lists. (see C{create}) - - @rtype: XendDomainInfo - @return: A up and running XendDomainInfo instance - @raise VmError: Invalid configuration or failure to start. - @raise XendError: Errors with configuration. - """ - - log.debug("XendDomainInfo.restore(%s)", scrub_password(config)) - vm = XendDomainInfo(XendConfig.XendConfig(sxp_obj = config), - resume = True) - try: - vm.resume() - return vm - except: - vm.destroy() - raise - -def createDormant(domconfig): - """Create a dormant/inactive XenDomainInfo without creating VM. - This is for creating instances of persistent domains that are not - yet start. - - @param domconfig: Parsed configuration - @type domconfig: XendConfig object - - @rtype: XendDomainInfo - @return: A up and running XendDomainInfo instance - @raise XendError: Errors with configuration. - """ - - log.debug("XendDomainInfo.createDormant(%s)", scrub_password(domconfig)) - - # domid does not make sense for non-running domains. - domconfig.pop('domid', None) - vm = XendDomainInfo(domconfig) - return vm - -def domain_by_name(name): - """Get domain by name - - @params name: Name of the domain - @type name: string - @return: XendDomainInfo or None - """ - from xen.xend import XendDomain - return XendDomain.instance().domain_lookup_by_name_nr(name) - - -def shutdown_reason(code): - """Get a shutdown reason from a code. - - @param code: shutdown code - @type code: int - @return: shutdown reason - @rtype: string - """ - return DOMAIN_SHUTDOWN_REASONS.get(code, "?") - -def dom_get(dom): - """Get info from xen for an existing domain. - - @param dom: domain id - @type dom: int - @return: info or None - @rtype: dictionary - """ - try: - domlist = xc.domain_getinfo(dom, 1) - if domlist and dom == domlist[0]['domid']: - return domlist[0] - except Exception, err: - # ignore missing domain - log.trace("domain_getinfo(%d) failed, ignoring: %s", dom, str(err)) - return None - -from xen.xend.server.pciif import parse_pci_name, PciDevice,\ - get_assigned_pci_devices, get_all_assigned_pci_devices - - -def do_FLR(domid, is_hvm): - dev_str_list = get_assigned_pci_devices(domid) - - for dev_str in dev_str_list: - try: - dev = PciDevice(parse_pci_name(dev_str)) - except Exception, e: - raise VmError("pci: failed to locate device and "+ - "parse it's resources - "+str(e)) - dev.do_FLR(is_hvm, xoptions.get_pci_dev_assign_strict_check()) - -class XendDomainInfo: - """An object represents a domain. - - @TODO: try to unify dom and domid, they mean the same thing, but - xc refers to it as dom, and everywhere else, including - xenstore it is domid. The best way is to change xc's - python interface. - - @ivar info: Parsed configuration - @type info: dictionary - @ivar domid: Domain ID (if VM has started) - @type domid: int or None - @ivar paused_by_admin: Is this Domain paused by command or API - @type paused_by_admin: bool - @ivar guest_bitsize: the bitsize of guest - @type guest_bitsize: int or None - @ivar alloc_mem: the memory domain allocated when booting - @type alloc_mem: int or None - @ivar vmpath: XenStore path to this VM. - @type vmpath: string - @ivar dompath: XenStore path to this Domain. - @type dompath: string - @ivar image: Reference to the VM Image. - @type image: xen.xend.image.ImageHandler - @ivar store_port: event channel to xenstored - @type store_port: int - @ivar console_port: event channel to xenconsoled - @type console_port: int - @ivar store_mfn: xenstored mfn - @type store_mfn: int - @ivar console_mfn: xenconsoled mfn - @type console_mfn: int - @ivar notes: OS image notes - @type notes: dictionary - @ivar vmWatch: reference to a watch on the xenstored vmpath - @type vmWatch: xen.xend.xenstore.xswatch - @ivar shutdownWatch: reference to watch on the xenstored domain shutdown - @type shutdownWatch: xen.xend.xenstore.xswatch - @ivar shutdownStartTime: UNIX Time when domain started shutting down. - @type shutdownStartTime: float or None - @ivar restart_in_progress: Is a domain restart thread running? - @type restart_in_progress: bool -# @ivar state: Domain state -# @type state: enum(DOM_STATE_HALTED, DOM_STATE_RUNNING, ...) - @ivar state_updated: lock for self.state - @type state_updated: threading.Condition - @ivar refresh_shutdown_lock: lock for polling shutdown state - @type refresh_shutdown_lock: threading.Condition - @ivar _deviceControllers: device controller cache for this domain - @type _deviceControllers: dict 'string' to DevControllers - """ - - def __init__(self, info, domid = None, dompath = None, augment = False, - priv = False, resume = False, vmpath = None): - """Constructor for a domain - - @param info: parsed configuration - @type info: dictionary - @keyword domid: Set initial domain id (if any) - @type domid: int - @keyword dompath: Set initial dompath (if any) - @type dompath: string - @keyword augment: Augment given info with xenstored VM info - @type augment: bool - @keyword priv: Is a privileged domain (Dom 0) - @type priv: bool - @keyword resume: Is this domain being resumed? - @type resume: bool - """ - - self.info = info - if domid == None: - self.domid = self.info.get('domid') - else: - self.domid = domid - self.guest_bitsize = None - self.alloc_mem = None - self.paused_by_admin = False - - maxmem = self.info.get('memory_static_max', 0) - memory = self.info.get('memory_dynamic_max', 0) - - if self.info.is_hvm() and maxmem > memory: - self.pod_enabled = True - else: - self.pod_enabled = False - - #REMOVE: uuid is now generated in XendConfig - #if not self._infoIsSet('uuid'): - # self.info['uuid'] = uuid.toString(uuid.create()) - - # Find a unique /vm// path if not specified. - # This avoids conflict between pre-/post-migrate domains when doing - # localhost relocation. - self.vmpath = vmpath - i = 0 - while self.vmpath == None: - self.vmpath = XS_VMROOT + self.info['uuid'] - if i != 0: - self.vmpath = self.vmpath + '-' + str(i) - try: - if self._readVm("uuid"): - self.vmpath = None - i = i + 1 - except: - pass - - self.dompath = dompath - - self.image = None - self.store_port = None - self.store_mfn = None - self.console_port = None - self.console_mfn = None - - self.native_protocol = None - - self.vmWatch = None - self.shutdownWatch = None - self.shutdownStartTime = None - self._resume = resume - self.restart_in_progress = False - - self.state_updated = threading.Condition() - self.refresh_shutdown_lock = threading.Condition() - self._stateSet(DOM_STATE_HALTED) - - self._deviceControllers = {} - - for state in DOM_STATES_OLD: - self.info[state] = 0 - - if augment: - self._augmentInfo(priv) - - self._checkName(self.info['name_label']) - - self.metrics = XendVMMetrics(uuid.createString(), self) - - - # - # Public functions available through XMLRPC - # - - - def start(self, is_managed = False): - """Attempts to start the VM by do the appropriate - initialisation if it not started. - """ - from xen.xend import XendDomain - - if self._stateGet() in (XEN_API_VM_POWER_STATE_HALTED, XEN_API_VM_POWER_STATE_SUSPENDED, XEN_API_VM_POWER_STATE_CRASHED): - try: - XendTask.log_progress(0, 30, self._constructDomain) - XendTask.log_progress(31, 60, self._initDomain) - - XendTask.log_progress(61, 70, self._storeVmDetails) - XendTask.log_progress(71, 80, self._storeDomDetails) - XendTask.log_progress(81, 90, self._registerWatches) - XendTask.log_progress(91, 100, self.refreshShutdown) - - xendomains = XendDomain.instance() - - # save running configuration if XendDomains believe domain is - # persistent - if is_managed: - xendomains.managed_config_save(self) - except: - log.exception('VM start failed') - self.destroy() - raise - else: - raise XendError('VM already running') - - def resume(self): - """Resumes a domain that has come back from suspension.""" - state = self._stateGet() - if state in (DOM_STATE_SUSPENDED, DOM_STATE_HALTED): - try: - self._constructDomain() - - try: - self._setCPUAffinity() - except: - # usually a CPU we want to set affinity to does not exist - # we just ignore it so that the domain can still be restored - log.warn("Cannot restore CPU affinity") - - self._setSchedParams() - self._storeVmDetails() - self._createChannels() - self._createDevices() - self._storeDomDetails() - self._endRestore() - except: - log.exception('VM resume failed') - self.destroy() - raise - else: - raise XendError('VM is not suspended; it is %s' - % XEN_API_VM_POWER_STATE[state]) - - def shutdown(self, reason): - """Shutdown a domain by signalling this via xenstored.""" - log.debug('XendDomainInfo.shutdown(%s)', reason) - if self._stateGet() in (DOM_STATE_SHUTDOWN, DOM_STATE_HALTED,): - raise XendError('Domain cannot be shutdown') - - if self.domid == 0: - raise XendError('Domain 0 cannot be shutdown') - - if reason not in DOMAIN_SHUTDOWN_REASONS.values(): - raise XendError('Invalid reason: %s' % reason) - self.storeDom("control/shutdown", reason) - - # HVM domain shuts itself down only if it has PV drivers - if self.info.is_hvm(): - hvm_pvdrv = xc.hvm_get_param(self.domid, HVM_PARAM_CALLBACK_IRQ) - hvm_s_state = xc.hvm_get_param(self.domid, HVM_PARAM_ACPI_S_STATE) - if not hvm_pvdrv or hvm_s_state != 0: - code = REVERSE_DOMAIN_SHUTDOWN_REASONS[reason] - log.info("HVM save:remote shutdown dom %d!", self.domid) - xc.domain_shutdown(self.domid, code) - - def pause(self): - """Pause domain - - @raise XendError: Failed pausing a domain - """ - try: - if(self.domid): - # get all blktap2 devices - dev = xstransact.List(self.vmpath + '/device/tap2') - for x in dev: - path = self.getDeviceController('tap2').readBackend(x, 'params') - if path and path.startswith(TapdiskController.TAP_DEV): - TapdiskController.pause(path) - except Exception, ex: - log.warn('Could not pause blktap disk.'); - - try: - xc.domain_pause(self.domid) - self._stateSet(DOM_STATE_PAUSED) - except Exception, ex: - log.exception(ex) - raise XendError("Domain unable to be paused: %s" % str(ex)) - - def unpause(self): - """Unpause domain - - @raise XendError: Failed unpausing a domain - """ - try: - if(self.domid): - dev = xstransact.List(self.vmpath + '/device/tap2') - for x in dev: - path = self.getDeviceController('tap2').readBackend(x, 'params') - if path and path.startswith(TapdiskController.TAP_DEV): - TapdiskController.unpause(path) - - except Exception, ex: - log.warn('Could not unpause blktap disk: %s' % str(ex)); - - try: - xc.domain_unpause(self.domid) - self._stateSet(DOM_STATE_RUNNING) - except Exception, ex: - log.exception(ex) - raise XendError("Domain unable to be unpaused: %s" % str(ex)) - - def send_sysrq(self, key): - """ Send a Sysrq equivalent key via xenstored.""" - if self._stateGet() not in (DOM_STATE_RUNNING, DOM_STATE_PAUSED): - raise XendError("Domain '%s' is not started" % self.info['name_label']) - - asserts.isCharConvertible(key) - self.storeDom("control/sysrq", '%c' % key) - - def pci_device_configure_boot(self): - - if not self.info.is_hvm(): - return - - devid = '0' - first = True - dev_info = self._getDeviceInfo_pci(devid) - if dev_info is None: - return - - # get the virtual slot info from xenstore - dev_uuid = sxp.child_value(dev_info, 'uuid') - pci_conf = self.info['devices'][dev_uuid][1] - pci_devs = pci_conf['devs'] - - # Keep a set of keys that are done rather than - # just itterating through set(map(..., pci_devs)) - # to preserve any order information present. - done = set() - for key in map(lambda x: x['key'], pci_devs): - if key in done: - continue - done |= set([key]) - dev = filter(lambda x: x['key'] == key, pci_devs) - - head_dev = dev.pop() - dev_sxp = pci_convert_dict_to_sxp(head_dev, 'Initialising', - 'Booting') - self.pci_device_configure(dev_sxp, first_dev = first) - first = False - - # That is all for single-function virtual devices - if len(dev) == 0: - continue - - if int(head_dev['vdevfn'], 16) & AUTO_PHP_SLOT: - new_dev_info = self._getDeviceInfo_pci(devid) - if new_dev_info is None: - continue - new_dev_uuid = sxp.child_value(new_dev_info, 'uuid') - new_pci_conf = self.info['devices'][new_dev_uuid][1] - new_pci_devs = new_pci_conf['devs'] - - new_head_dev = filter(lambda x: pci_dict_cmp(x, head_dev), - new_pci_devs)[0] - - if int(new_head_dev['vdevfn'], 16) & AUTO_PHP_SLOT: - continue - - vdevfn = PCI_SLOT(int(new_head_dev['vdevfn'], 16)) - new_dev = [] - for i in dev: - i['vdevfn'] = '0x%02x' % \ - PCI_DEVFN(vdevfn, - PCI_FUNC(int(i['vdevfn'], 16))) - new_dev.append(i) - - dev = new_dev - - for i in dev: - dev_sxp = pci_convert_dict_to_sxp(i, 'Initialising', 'Booting') - self.pci_device_configure(dev_sxp) - - def hvm_pci_device_create(self, dev_config): - log.debug("XendDomainInfo.hvm_pci_device_create: %s" - % scrub_password(dev_config)) - - if not self.info.is_hvm(): - raise VmError("hvm_pci_device_create called on non-HVM guest") - - #all the PCI devs share one conf node - devid = '0' - - new_dev = dev_config['devs'][0] - dev_info = self._getDeviceInfo_pci(devid)#from self.info['devices'] - - #check conflict before trigger hotplug event - if dev_info is not None: - dev_uuid = sxp.child_value(dev_info, 'uuid') - pci_conf = self.info['devices'][dev_uuid][1] - pci_devs = pci_conf['devs'] - for x in pci_devs: - if (int(x['vdevfn'], 16) == int(new_dev['vdevfn'], 16) and - not int(x['vdevfn'], 16) & AUTO_PHP_SLOT): - raise VmError("vdevfn %s already have a device." % - (new_dev['vdevfn'])) - - if (pci_dict_cmp(x, new_dev)): - raise VmError("device is already inserted") - - # Test whether the devices can be assigned. - self.pci_dev_check_attachability_and_do_FLR(new_dev) - - return self.hvm_pci_device_insert_dev(new_dev) - - def iommu_check_pod_mode(self): - """ Disallow PCI device assignment if pod is enabled. """ - if self.pod_enabled: - raise VmError("failed to assign device since pod is enabled") - - def pci_dev_check_assignability_and_do_FLR(self, config): - """ In the case of static device assignment(i.e., the 'pci' string in - guest config file), we check if the device(s) specified in the 'pci' - can be assigned to guest or not; if yes, we do_FLR the device(s). - """ - - self.iommu_check_pod_mode() - pci_dev_ctrl = self.getDeviceController('pci') - return pci_dev_ctrl.dev_check_assignability_and_do_FLR(config) - - def pci_dev_check_attachability_and_do_FLR(self, new_dev): - """ In the case of dynamic device assignment(i.e., xm pci-attach), we - check if the device can be attached to guest or not; if yes, we do_FLR - the device. - """ - - self.iommu_check_pod_mode() - - # Test whether the devices can be assigned - - pci_name = pci_dict_to_bdf_str(new_dev) - _all_assigned_pci_devices = get_all_assigned_pci_devices(self.domid) - if pci_name in _all_assigned_pci_devices: - raise VmError("failed to assign device %s that has" - " already been assigned to other domain." % pci_name) - - # Test whether the device is owned by pciback or pci-stub. - try: - pci_device = PciDevice(new_dev) - except Exception, e: - raise VmError("pci: failed to locate device and "+ - "parse its resources - "+str(e)) - if pci_device.driver!='pciback' and pci_device.driver!='pci-stub': - raise VmError(("pci: PCI Backend and pci-stub don't own device %s")\ - %pci_device.name) - - strict_check = xoptions.get_pci_dev_assign_strict_check() - # Check non-page-aligned MMIO BAR. - if pci_device.has_non_page_aligned_bar and strict_check: - raise VmError("pci: %s: non-page-aligned MMIO BAR found." % \ - pci_device.name) - - # PV guest has less checkings. - if not self.info.is_hvm(): - # try to do FLR for PV guest - pci_device.do_FLR(self.info.is_hvm(), strict_check) - return - - if not strict_check: - return - - # Check if there is intermediate PCIe switch bewteen the device and - # Root Complex. - if pci_device.is_behind_switch_lacking_acs(): - err_msg = 'pci: to avoid potential security issue, %s is not'+\ - ' allowed to be assigned to guest since it is behind'+\ - ' PCIe switch that does not support or enable ACS.' - raise VmError(err_msg % pci_device.name) - - # Check the co-assignment. - # To pci-attach a device D to domN, we should ensure each of D's - # co-assignment devices hasn't been assigned, or has been assigned to - # domN. - coassignment_list = pci_device.find_coassigned_devices() - pci_device.devs_check_driver(coassignment_list) - assigned_pci_device_str_list = self._get_assigned_pci_devices() - for pci_str in coassignment_list: - if not (pci_str in _all_assigned_pci_devices): - continue - if not pci_str in assigned_pci_device_str_list: - raise VmError(("pci: failed to pci-attach %s to domain %s" + \ - " because one of its co-assignment device %s has been" + \ - " assigned to other domain." \ - )% (pci_device.name, self.info['name_label'], pci_str)) - - # try to do FLR for HVM guest - pci_device.do_FLR(self.info.is_hvm(), strict_check) - - def hvm_pci_device_insert(self, dev_config): - log.debug("XendDomainInfo.hvm_pci_device_insert: %s" - % scrub_password(dev_config)) - - if not self.info.is_hvm(): - raise VmError("hvm_pci_device_create called on non-HVM guest") - - new_dev = dev_config['devs'][0] - - return self.hvm_pci_device_insert_dev(new_dev) - - def hvm_pci_device_insert_dev(self, new_dev): - log.debug("XendDomainInfo.hvm_pci_device_insert_dev: %s" - % scrub_password(new_dev)) - - if self.domid is not None: - opts = '' - optslist = [] - pci_defopts = [] - if 'pci_msitranslate' in self.info['platform']: - pci_defopts.append(['msitranslate', - str(self.info['platform']['pci_msitranslate'])]) - if 'pci_power_mgmt' in self.info['platform']: - pci_defopts.append(['power_mgmt', - str(self.info['platform']['pci_power_mgmt'])]) - if new_dev.has_key('opts'): - optslist += new_dev['opts'] - - if optslist or pci_defopts: - opts = ',' + serialise_pci_opts( - append_default_pci_opts(optslist, pci_defopts)) - - bdf_str = "%s@%02x%s" % (pci_dict_to_bdf_str(new_dev), - int(new_dev['vdevfn'], 16), opts) - log.debug("XendDomainInfo.hvm_pci_device_insert_dev: %s" % bdf_str) - bdf = xc.assign_device(self.domid, pci_dict_to_xc_str(new_dev)) - if bdf > 0: - raise VmError("Failed to assign device to IOMMU (%s)" % bdf_str) - log.debug("pci: assign device %s" % bdf_str) - self.image.signalDeviceModel('pci-ins', 'pci-inserted', bdf_str) - - vdevfn = xstransact.Read("/local/domain/0/device-model/%i/parameter" - % self.getDomid()) - try: - vdevfn_int = int(vdevfn, 16) - except ValueError: - raise VmError(("Cannot pass-through PCI function '%s'. " + - "Device model reported an error: %s") % - (bdf_str, vdevfn)) - else: - vdevfn = new_dev['vdevfn'] - - return vdevfn - - - def device_create(self, dev_config): - """Create a new device. - - @param dev_config: device configuration - @type dev_config: SXP object (parsed config) - """ - log.debug("XendDomainInfo.device_create: %s" % scrub_password(dev_config)) - dev_type = sxp.name(dev_config) - - if dev_type == 'vif': - for x in dev_config: - if x != 'vif' and x[0] == 'mac': - if not re.match('^([0-9a-f]{2}:){5}[0-9a-f]{2}$', x[1], re.I): - log.error("Virtual network interface creation error - invalid MAC Address entered: %s", x[1]) - raise VmError("Cannot create a new virtual network interface - MAC address is not valid!"); - - dev_uuid = self.info.device_add(dev_type, cfg_sxp = dev_config) - dev_config_dict = self.info['devices'][dev_uuid][1] - log.debug("XendDomainInfo.device_create: %s" % scrub_password(dev_config_dict)) - - if self.domid is not None: - try: - dev_config_dict['devid'] = devid = \ - self._createDevice(dev_type, dev_config_dict) - if dev_type == 'tap2': - # createDevice may create a blktap1 device if blktap2 is not - # installed or if the blktap driver is not supported in - # blktap1 - dev_type = self.getBlockDeviceClass(devid) - self._waitForDevice(dev_type, devid) - except (VmError, TapdiskException), ex: - del self.info['devices'][dev_uuid] - if dev_type == 'pci': - for dev in dev_config_dict['devs']: - XendAPIStore.deregister(dev['uuid'], 'DPCI') - elif dev_type == 'vscsi': - for dev in dev_config_dict['devs']: - XendAPIStore.deregister(dev['uuid'], 'DSCSI') - elif dev_type == 'tap' or dev_type == 'tap2': - self.info['vbd_refs'].remove(dev_uuid) - else: - self.info['%s_refs' % dev_type].remove(dev_uuid) - raise ex - else: - devid = None - - xen.xend.XendDomain.instance().managed_config_save(self) - return self.getDeviceController(dev_type).sxpr(devid) - - - def pci_device_configure(self, dev_sxp, devid = 0, first_dev = False): - """Configure an existing pci device. - - @param dev_sxp: device configuration - @type dev_sxp: SXP object (parsed config) - @param devid: device id - @type devid: int - @return: Returns True if successfully updated device - @rtype: boolean - """ - log.debug("XendDomainInfo.pci_device_configure: %s" - % scrub_password(dev_sxp)) - - dev_class = sxp.name(dev_sxp) - - if dev_class != 'pci': - return False - - pci_state = sxp.child_value(dev_sxp, 'state') - pci_sub_state = sxp.child_value(dev_sxp, 'sub_state') - existing_dev_info = self._getDeviceInfo_pci(devid) - - if existing_dev_info is None and pci_state != 'Initialising': - raise XendError("Cannot detach when pci platform does not exist") - - pci_dev = sxp.children(dev_sxp, 'dev')[0] - dev_config = pci_convert_sxp_to_dict(dev_sxp) - dev = dev_config['devs'][0] - - stubdomid = self.getStubdomDomid() - # Do HVM specific processing - if self.info.is_hvm(): - from xen.xend import XendDomain - if pci_state == 'Initialising': - if stubdomid is not None : - XendDomain.instance().domain_lookup(stubdomid).pci_device_configure(dev_sxp[:]) - - # HVM PCI device attachment - if pci_sub_state == 'Booting': - vdevfn = self.hvm_pci_device_insert(dev_config) - else: - vdevfn = self.hvm_pci_device_create(dev_config) - # Update vdevfn - dev['vdevfn'] = vdevfn - for n in sxp.children(pci_dev): - if(n[0] == 'vdevfn'): - n[1] = vdevfn - else: - # HVM PCI device detachment - existing_dev_uuid = sxp.child_value(existing_dev_info, 'uuid') - existing_pci_conf = self.info['devices'][existing_dev_uuid][1] - existing_pci_devs = existing_pci_conf['devs'] - new_devs = filter(lambda x: pci_dict_cmp(x, dev), - existing_pci_devs) - if len(new_devs) < 0: - raise VmError("Device %s is not connected" % - pci_dict_to_bdf_str(dev)) - new_dev = new_devs[0] - # Only tell qemu-dm to unplug function 0. - # When unplugging a function, all functions in the - # same vslot must be unplugged, and function 0 must - # be one of the functions present when a vslot is - # hot-plugged. Telling qemu-dm to unplug function 0 - # also tells it to unplug all other functions in the - # same vslot. - if (PCI_FUNC(int(new_dev['vdevfn'], 16)) == 0): - self.hvm_destroyPCIDevice(new_dev) - if stubdomid is not None : - XendDomain.instance().domain_lookup(stubdomid).pci_device_configure(dev_sxp[:]) - # Update vdevfn - dev['vdevfn'] = new_dev['vdevfn'] - for n in sxp.children(pci_dev): - if(n[0] == 'vdevfn'): - n[1] = new_dev['vdevfn'] - else: - # Do PV specific checking - if pci_state == 'Initialising': - # PV PCI device attachment - self.pci_dev_check_attachability_and_do_FLR(dev) - - # If pci platform does not exist, create and exit. - if existing_dev_info is None : - self.device_create(dev_sxp) - return True - - if first_dev is True : - existing_dev_uuid = sxp.child_value(existing_dev_info, 'uuid') - existing_pci_conf = self.info['devices'][existing_dev_uuid][1] - devid = self._createDevice('pci', existing_pci_conf) - self.info['devices'][existing_dev_uuid][1]['devid'] = devid - - if self.domid is not None: - # use DevController.reconfigureDevice to change device config - dev_control = self.getDeviceController(dev_class) - dev_uuid = dev_control.reconfigureDevice(devid, dev_config) - if not self.info.is_hvm() and not self.info.is_stubdom(): - # in PV case, wait until backend state becomes connected. - dev_control.waitForDevice_reconfigure(devid) - num_devs = dev_control.cleanupDevice(devid) - - # update XendConfig with new device info - if dev_uuid: - new_dev_sxp = dev_control.configuration(devid) - self.info.device_update(dev_uuid, new_dev_sxp) - - # If there is no device left, destroy pci and remove config. - if num_devs == 0: - if self.info.is_hvm(): - self.destroyDevice('pci', devid, True) - else: - self.destroyDevice('pci', devid) - del self.info['devices'][dev_uuid] - else: - new_dev_sxp = ['pci'] - for cur_dev in sxp.children(existing_dev_info, 'dev'): - if pci_state == 'Closing': - if int(dev['domain'], 16) == int(sxp.child_value(cur_dev, 'domain'), 16) and \ - int(dev['bus'], 16) == int(sxp.child_value(cur_dev, 'bus'), 16) and \ - int(dev['slot'], 16) == int(sxp.child_value(cur_dev, 'slot'), 16) and \ - int(dev['func'], 16) == int(sxp.child_value(cur_dev, 'func'), 16): - continue - new_dev_sxp.append(cur_dev) - - if pci_state == 'Initialising' and pci_sub_state != 'Booting': - for new_dev in sxp.children(dev_sxp, 'dev'): - new_dev_sxp.append(new_dev) - - dev_uuid = sxp.child_value(existing_dev_info, 'uuid') - self.info.device_update(dev_uuid, new_dev_sxp) - - # If there is no device left, remove config. - if len(sxp.children(new_dev_sxp, 'dev')) == 0: - del self.info['devices'][dev_uuid] - - xen.xend.XendDomain.instance().managed_config_save(self) - - return True - - def vscsi_device_configure(self, dev_sxp): - """Configure an existing vscsi device. - quoted pci funciton - """ - def _is_vscsi_defined(dev_info, p_devs = None, v_devs = None): - if not dev_info: - return False - for dev in sxp.children(dev_info, 'dev'): - if p_devs is not None: - if sxp.child_value(dev, 'p-dev') in p_devs: - return True - if v_devs is not None: - if sxp.child_value(dev, 'v-dev') in v_devs: - return True - return False - - def _vscsi_be(be): - be_xdi = xen.xend.XendDomain.instance().domain_lookup_nr(be) - if be_xdi is not None: - be_domid = be_xdi.getDomid() - if be_domid is not None: - return str(be_domid) - return str(be) - - dev_class = sxp.name(dev_sxp) - if dev_class != 'vscsi': - return False - - dev_config = self.info.vscsi_convert_sxp_to_dict(dev_sxp) - devs = dev_config['devs'] - v_devs = [d['v-dev'] for d in devs] - state = devs[0]['state'] - req_devid = int(devs[0]['devid']) - cur_dev_sxp = self._getDeviceInfo_vscsi(req_devid) - - if state == xenbusState['Initialising']: - # new create - # If request devid does not exist, create and exit. - p_devs = [d['p-dev'] for d in devs] - for dev_type, dev_info in self.info.all_devices_sxpr(): - if dev_type != 'vscsi': - continue - if _is_vscsi_defined(dev_info, p_devs = p_devs): - raise XendError('The physical device "%s" is already defined' % \ - p_devs[0]) - if cur_dev_sxp is None: - self.device_create(dev_sxp) - return True - - if _is_vscsi_defined(cur_dev_sxp, v_devs = v_devs): - raise XendError('The virtual device "%s" is already defined' % \ - v_devs[0]) - - if int(dev_config['feature-host']) != \ - int(sxp.child_value(cur_dev_sxp, 'feature-host')): - raise XendError('The physical device "%s" cannot define ' - 'because mode is different' % devs[0]['p-dev']) - - new_be = dev_config.get('backend', None) - if new_be is not None: - cur_be = sxp.child_value(cur_dev_sxp, 'backend', None) - if cur_be is None: - cur_be = xen.xend.XendDomain.DOM0_ID - new_be_dom = _vscsi_be(new_be) - cur_be_dom = _vscsi_be(cur_be) - if new_be_dom != cur_be_dom: - raise XendError('The physical device "%s" cannot define ' - 'because backend is different' % devs[0]['p-dev']) - - elif state == xenbusState['Closing']: - if not _is_vscsi_defined(cur_dev_sxp, v_devs = v_devs): - raise XendError("Cannot detach vscsi device does not exist") - - if self.domid is not None: - # use DevController.reconfigureDevice to change device config - dev_control = self.getDeviceController(dev_class) - dev_uuid = dev_control.reconfigureDevice(req_devid, dev_config) - dev_control.waitForDevice_reconfigure(req_devid) - num_devs = dev_control.cleanupDevice(req_devid) - - # update XendConfig with new device info - if dev_uuid: - new_dev_sxp = dev_control.configuration(req_devid) - self.info.device_update(dev_uuid, new_dev_sxp) - - # If there is no device left, destroy vscsi and remove config. - if num_devs == 0: - self.destroyDevice('vscsi', req_devid) - del self.info['devices'][dev_uuid] - - else: - new_dev_sxp = ['vscsi'] - cur_mode = sxp.children(cur_dev_sxp, 'feature-host')[0] - new_dev_sxp.append(cur_mode) - try: - cur_be = sxp.children(cur_dev_sxp, 'backend')[0] - new_dev_sxp.append(cur_be) - except IndexError: - pass - - for cur_dev in sxp.children(cur_dev_sxp, 'dev'): - if state == xenbusState['Closing']: - if int(cur_mode[1]) == 1: - continue - if sxp.child_value(cur_dev, 'v-dev') in v_devs: - continue - new_dev_sxp.append(cur_dev) - - if state == xenbusState['Initialising']: - for new_dev in sxp.children(dev_sxp, 'dev'): - new_dev_sxp.append(new_dev) - - dev_uuid = sxp.child_value(cur_dev_sxp, 'uuid') - self.info.device_update(dev_uuid, new_dev_sxp) - - # If there is only 'vscsi' in new_dev_sxp, remove the config. - if len(sxp.children(new_dev_sxp, 'dev')) == 0: - del self.info['devices'][dev_uuid] - - xen.xend.XendDomain.instance().managed_config_save(self) - - return True - - def vusb_device_configure(self, dev_sxp, devid): - """Configure a virtual root port. - """ - dev_class = sxp.name(dev_sxp) - if dev_class != 'vusb': - return False - - dev_config = {} - ports = sxp.child(dev_sxp, 'port') - for port in ports[1:]: - try: - num, bus = port - dev_config['port-%i' % int(num)] = str(bus) - except TypeError: - pass - - dev_control = self.getDeviceController(dev_class) - dev_control.reconfigureDevice(devid, dev_config) - - return True - - def device_configure(self, dev_sxp, devid = None): - """Configure an existing device. - - @param dev_config: device configuration - @type dev_config: SXP object (parsed config) - @param devid: device id - @type devid: int - @return: Returns True if successfully updated device - @rtype: boolean - """ - - # convert device sxp to a dict - dev_class = sxp.name(dev_sxp) - dev_config = {} - - if dev_class == 'pci': - return self.pci_device_configure(dev_sxp) - - if dev_class == 'vscsi': - return self.vscsi_device_configure(dev_sxp) - - if dev_class == 'vusb': - return self.vusb_device_configure(dev_sxp, devid) - - for opt_val in dev_sxp[1:]: - try: - dev_config[opt_val[0]] = opt_val[1] - except IndexError: - pass - - dev_control = self.getDeviceController(dev_class) - if devid is None: - dev = dev_config.get('dev', '') - if not dev: - raise VmError('Block device must have virtual details specified') - if 'ioemu:' in dev: - (_, dev) = dev.split(':', 1) - try: - (dev, _) = dev.split(':', 1) # Remove ":disk" or ":cdrom" - except ValueError: - pass - devid = dev_control.convertToDeviceNumber(dev) - dev_info = self._getDeviceInfo_vbd(devid) - if dev_info is None: - raise VmError("Device %s not connected" % devid) - dev_uuid = sxp.child_value(dev_info, 'uuid') - - if self.domid is not None: - # use DevController.reconfigureDevice to change device config - dev_control.reconfigureDevice(devid, dev_config) - else: - (_, new_b, new_f) = dev_control.getDeviceDetails(dev_config) - if (new_f['device-type'] == 'cdrom' and - sxp.child_value(dev_info, 'dev').endswith(':cdrom') and - new_b['mode'] == 'r' and - sxp.child_value(dev_info, 'mode') == 'r'): - pass - else: - raise VmError('Refusing to reconfigure device %s:%d to %s' % - (dev_class, devid, dev_config)) - - # update XendConfig with new device info - self.info.device_update(dev_uuid, dev_sxp) - xen.xend.XendDomain.instance().managed_config_save(self) - - return True - - def waitForDevices(self): - """Wait for this domain's configured devices to connect. - - @raise VmError: if any device fails to initialise. - """ - for devclass in XendDevices.valid_devices(): - self.getDeviceController(devclass).waitForDevices() - - def hvm_destroyPCIDevice(self, pci_dev): - log.debug("hvm_destroyPCIDevice: %s", pci_dev) - - if not self.info.is_hvm(): - raise VmError("hvm_destroyPCIDevice called on non-HVM guest") - - # Check the co-assignment. - # To pci-detach a device D from domN, we should ensure: for each DD in the - # list of D's co-assignment devices, DD is not assigned (to domN). - # - from xen.xend.server.pciif import PciDevice - try: - pci_device = PciDevice(pci_dev) - except Exception, e: - raise VmError("pci: failed to locate device and "+ - "parse its resources - "+str(e)) - coassignment_list = pci_device.find_coassigned_devices() - coassignment_list.remove(pci_device.name) - assigned_pci_device_str_list = self._get_assigned_pci_devices() - for pci_str in coassignment_list: - if xoptions.get_pci_dev_assign_strict_check() and \ - pci_str in assigned_pci_device_str_list: - raise VmError(("pci: failed to pci-detach %s from domain %s" + \ - " because one of its co-assignment device %s is still " + \ - " assigned to the domain." \ - )% (pci_device.name, self.info['name_label'], pci_str)) - - - bdf_str = pci_dict_to_bdf_str(pci_dev) - log.info("hvm_destroyPCIDevice:%s:%s!", pci_dev, bdf_str) - if self.domid is not None: - self.image.signalDeviceModel('pci-rem', 'pci-removed', bdf_str) - - return 0 - - def destroyDevice(self, deviceClass, devid, force = False, rm_cfg = False): - log.debug("XendDomainInfo.destroyDevice: deviceClass = %s, device = %s", - deviceClass, devid) - - if rm_cfg: - # Convert devid to device number. A device number is - # needed to remove its configuration. - dev = self.getDeviceController(deviceClass).convertToDeviceNumber(devid) - - # Save current sxprs. A device number and a backend - # path are needed to remove its configuration but sxprs - # do not have those after calling destroyDevice. - sxprs = self.getDeviceSxprs(deviceClass) - - rc = None - if self.domid is not None: - - #new blktap implementation may need a sysfs write after everything is torn down. - if deviceClass == 'tap2': - dev = self.getDeviceController(deviceClass).convertToDeviceNumber(devid) - path = self.getDeviceController(deviceClass).readBackend(dev, 'params') - frontpath = self.getDeviceController(deviceClass).frontendPath(dev) - backpath = xstransact.Read(frontpath, "backend") - thread.start_new_thread(self.getDeviceController(deviceClass).finishDeviceCleanup, (backpath, path)) - - rc = self.getDeviceController(deviceClass).destroyDevice(devid, force) - if not force and rm_cfg: - # The backend path, other than the device itself, - # has to be passed because its accompanied frontend - # path may be void until its removal is actually - # issued. It is probable because destroyDevice is - # issued first. - for dev_num, dev_info in sxprs: - dev_num = int(dev_num) - if dev_num == dev: - for x in dev_info: - if x[0] == 'backend': - backend = x[1] - break - break - self._waitForDevice_destroy(deviceClass, devid, backend) - - if rm_cfg and deviceClass != "vif2": - if deviceClass == 'vif': - if self.domid is not None: - mac = '' - for dev_num, dev_info in sxprs: - dev_num = int(dev_num) - if dev_num == dev: - for x in dev_info: - if x[0] == 'mac': - mac = x[1] - break - break - dev_info = self._getDeviceInfo_vif(mac) - else: - _, dev_info = sxprs[dev] - else: # 'vbd' or 'tap' or 'tap2' - dev_info = self._getDeviceInfo_vbd(dev) - # To remove the UUID of the device from refs, - # deviceClass must be always 'vbd'. - deviceClass = 'vbd' - if dev_info is None: - raise XendError("Device %s is not defined" % devid) - - dev_uuid = sxp.child_value(dev_info, 'uuid') - del self.info['devices'][dev_uuid] - self.info['%s_refs' % deviceClass].remove(dev_uuid) - xen.xend.XendDomain.instance().managed_config_save(self) - - return rc - - def getDeviceSxprs(self, deviceClass): - if deviceClass == 'pci': - dev_info = self._getDeviceInfo_pci('0')#from self.info['devices'] - if dev_info is None: - return [] - dev_uuid = sxp.child_value(dev_info, 'uuid') - pci_devs = self.info['devices'][dev_uuid][1]['devs'] - return pci_devs - if self._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED, DOM_STATE_CRASHED): - return self.getDeviceController(deviceClass).sxprs() - else: - sxprs = [] - dev_num = 0 - for dev_type, dev_info in self.info.all_devices_sxpr(): - if (deviceClass == 'vbd' and dev_type not in ['vbd', 'tap', 'tap2']) or \ - (deviceClass != 'vbd' and dev_type != deviceClass): - continue - - if deviceClass == 'vscsi': - vscsi_devs = ['devs', []] - for vscsi_dev in sxp.children(dev_info, 'dev'): - vscsi_dev.append(['frontstate', None]) - vscsi_devs[1].append(vscsi_dev) - dev_num = int(sxp.child_value(vscsi_dev, 'devid')) - vscsi_mode = sxp.children(dev_info, 'feature-host')[0] - sxprs.append([dev_num, [vscsi_devs, vscsi_mode]]) - elif deviceClass == 'vbd': - dev = sxp.child_value(dev_info, 'dev') - if 'ioemu:' in dev: - (_, dev) = dev.split(':', 1) - try: - (dev_name, _) = dev.split(':', 1) # Remove ":disk" or ":cdrom" - except ValueError: - dev_name = dev - dev_num = self.getDeviceController('vbd').convertToDeviceNumber(dev_name) - sxprs.append([dev_num, dev_info]) - else: - sxprs.append([dev_num, dev_info]) - dev_num += 1 - return sxprs - - def getBlockDeviceClass(self, devid): - # if the domain is running we can get the device class from xenstore. - # This is more accurate, as blktap1 devices show up as blktap2 devices - # in the config. - if self._stateGet() in (DOM_STATE_RUNNING, DOM_STATE_PAUSED, DOM_STATE_CRASHED): - # All block devices have a vbd frontend, so we know the frontend path - dev = self.getDeviceController('vbd').convertToDeviceNumber(devid) - frontendPath = "%s/device/vbd/%s" % (self.dompath, dev) - for devclass in XendDevices.valid_devices(): - for dev in xstransact.List("%s/device/%s" % (self.vmpath, devclass)): - devFrontendPath = xstransact.Read("%s/device/%s/%s/frontend" % (self.vmpath, devclass, dev)) - if frontendPath == devFrontendPath: - return devclass - - else: # the domain is not active so we must get the device class - # from the config - # To get a device number from the devid, - # we temporarily use the device controller of VBD. - dev = self.getDeviceController('vbd').convertToDeviceNumber(devid) - dev_info = self._getDeviceInfo_vbd(dev) - if dev_info: - return dev_info[0] - - def _getDeviceInfo_vif(self, mac): - for dev_type, dev_info in self.info.all_devices_sxpr(): - if dev_type != 'vif': - continue - if mac == sxp.child_value(dev_info, 'mac'): - return dev_info - - def _getDeviceInfo_vbd(self, devid): - for dev_type, dev_info in self.info.all_devices_sxpr(): - if dev_type != 'vbd' and dev_type != 'tap' and dev_type != 'tap2': - continue - dev = sxp.child_value(dev_info, 'dev') - dev = dev.split(':')[0] - dev = self.getDeviceController(dev_type).convertToDeviceNumber(dev) - if devid == dev: - return dev_info - - def _getDeviceInfo_pci(self, devid): - for dev_type, dev_info in self.info.all_devices_sxpr(): - if dev_type != 'pci': - continue - return dev_info - return None - - def _getDeviceInfo_vscsi(self, devid): - devid = int(devid) - for dev_type, dev_info in self.info.all_devices_sxpr(): - if dev_type != 'vscsi': - continue - devs = sxp.children(dev_info, 'dev') - if devid == int(sxp.child_value(devs[0], 'devid')): - return dev_info - return None - - def _getDeviceInfo_vusb(self, devid): - for dev_type, dev_info in self.info.all_devices_sxpr(): - if dev_type != 'vusb': - continue - return dev_info - return None - - def _get_assigned_pci_devices(self, devid = 0): - if self.domid is not None: - return get_assigned_pci_devices(self.domid) - - dev_info = self._getDeviceInfo_pci(devid) - if dev_info is None: - return [] - dev_uuid = sxp.child_value(dev_info, 'uuid') - pci_conf = self.info['devices'][dev_uuid][1] - return map(pci_dict_to_bdf_str, pci_conf['devs']) - - def setMemoryTarget(self, target): - """Set the memory target of this domain. - @param target: In MiB. - """ - log.debug("Setting memory target of domain %s (%s) to %d MiB.", - self.info['name_label'], str(self.domid), target) - - MiB = 1024 * 1024 - memory_cur = self.get_memory_dynamic_max() / MiB - - if self.domid == 0: - dom0_min_mem = xoptions.get_dom0_min_mem() - if target < memory_cur and dom0_min_mem > target: - raise XendError("memory_dynamic_max too small") - - self._safe_set_memory('memory_dynamic_min', target * MiB) - self._safe_set_memory('memory_dynamic_max', target * MiB) - - if self.domid >= 0: - if target > memory_cur: - balloon.free((target - memory_cur) * 1024, self) - self.storeVm("memory", target) - self.storeDom("memory/target", target << 10) - xc.domain_set_target_mem(self.domid, - (target * 1024)) - xen.xend.XendDomain.instance().managed_config_save(self) - - def setMemoryMaximum(self, limit): - """Set the maximum memory limit of this domain - @param limit: In MiB. - """ - log.debug("Setting memory maximum of domain %s (%s) to %d MiB.", - self.info['name_label'], str(self.domid), limit) - - maxmem_cur = self.get_memory_static_max() - MiB = 1024 * 1024 - self._safe_set_memory('memory_static_max', limit * MiB) - - if self.domid >= 0: - maxmem = int(limit) * 1024 - try: - return xc.domain_setmaxmem(self.domid, maxmem) - except Exception, ex: - self._safe_set_memory('memory_static_max', maxmem_cur) - raise XendError(str(ex)) - xen.xend.XendDomain.instance().managed_config_save(self) - - - def getVCPUInfo(self): - try: - # We include the domain name and ID, to help xm. - sxpr = ['domain', - ['domid', self.domid], - ['name', self.info['name_label']], - ['vcpu_count', self.info['VCPUs_max']]] - - for i in range(0, self.info['VCPUs_max']): - if self.domid is not None: - info = xc.vcpu_getinfo(self.domid, i) - - sxpr.append(['vcpu', - ['number', i], - ['online', info['online']], - ['blocked', info['blocked']], - ['running', info['running']], - ['cpu_time', info['cpu_time'] / 1e9], - ['cpu', info['cpu']], - ['cpumap', info['cpumap']]]) - else: - sxpr.append(['vcpu', - ['number', i], - ['online', 0], - ['blocked', 0], - ['running', 0], - ['cpu_time', 0.0], - ['cpu', -1], - ['cpumap', self.info['cpus'][i] and \ - self.info['cpus'][i] or range(64)]]) - - return sxpr - - except XCError, exn: - # Domain already died. - if exn.args[0] == errno.ESRCH: - return sxpr - raise XendError(str(exn)) - - - def getDomInfo(self): - return dom_get(self.domid) - - # - # internal functions ... TODO: re-categorised - # - - def _augmentInfo(self, priv): - """Augment self.info, as given to us through L{recreate}, with - values taken from the store. This recovers those values known - to xend but not to the hypervisor. - """ - augment_entries = XendConfig.LEGACY_XENSTORE_VM_PARAMS[:] - if priv: - augment_entries.remove('memory') - augment_entries.remove('maxmem') - augment_entries.remove('vcpus') - augment_entries.remove('vcpu_avail') - - vm_config = self._readVMDetails([(k, XendConfig.LEGACY_CFG_TYPES[k]) - for k in augment_entries]) - - # make returned lists into a dictionary - vm_config = dict(zip(augment_entries, vm_config)) - - for arg in augment_entries: - val = vm_config[arg] - if val != None: - if arg in XendConfig.LEGACY_CFG_TO_XENAPI_CFG: - xapiarg = XendConfig.LEGACY_CFG_TO_XENAPI_CFG[arg] - self.info[xapiarg] = val - elif arg == "memory": - self.info["static_memory_min"] = val - elif arg == "maxmem": - self.info["static_memory_max"] = val - else: - self.info[arg] = val - - # read CPU Affinity - self.info['cpus'] = [] - vcpus_info = self.getVCPUInfo() - for vcpu_info in sxp.children(vcpus_info, 'vcpu'): - self.info['cpus'].append(sxp.child_value(vcpu_info, 'cpumap')) - - # For dom0, we ignore any stored value for the vcpus fields, and - # read the current value from Xen instead. This allows boot-time - # settings to take precedence over any entries in the store. - if priv: - xeninfo = dom_get(self.domid) - self.info['VCPUs_max'] = xeninfo['online_vcpus'] - self.info['vcpu_avail'] = (1 << xeninfo['online_vcpus']) - 1 - - # read image value - image_sxp = self._readVm('image') - if image_sxp: - self.info.update_with_image_sxp(sxp.from_string(image_sxp)) - - # read devices - devices = [] - for devclass in XendDevices.valid_devices(): - devconfig = self.getDeviceController(devclass).configurations() - if devconfig: - devices.extend(devconfig) - - if not self.info['devices'] and devices is not None: - for device in devices: - self.info.device_add(device[0], cfg_sxp = device) - - self._update_consoles() - - def _update_consoles(self, transaction = None): - if self.domid == None or self.domid == 0: - return - - # Update VT100 port if it exists - if transaction is None: - self.console_port = self.readDom('console/port') - else: - self.console_port = self.readDomTxn(transaction, 'console/port') - if self.console_port is not None: - serial_consoles = self.info.console_get_all('vt100') - if not serial_consoles: - cfg = self.info.console_add('vt100', self.console_port) - self._createDevice('console', cfg) - else: - console_uuid = serial_consoles[0].get('uuid') - self.info.console_update(console_uuid, 'location', - self.console_port) - # Notify xenpv device model that console info is ready - if not self.info.is_hvm() and self.info.has_rfb(): - console_ctrl = self.getDeviceController('console') - # The value is unchanged. Just for xenstore watcher - console_ctrl.writeBackend(0, 'uuid', console_uuid) - - - # Update VNC port if it exists and write to xenstore - if transaction is None: - vnc_port = self.readDom('console/vnc-port') - else: - vnc_port = self.readDomTxn(transaction, 'console/vnc-port') - if vnc_port is not None: - for dev_uuid, (dev_type, dev_info) in self.info['devices'].items(): - if dev_type == 'vfb': - old_location = dev_info.get('location') - listen_host = dev_info.get('vnclisten', \ - XendOptions.instance().get_vnclisten_address()) - new_location = '%s:%s' % (listen_host, str(vnc_port)) - if old_location == new_location: - break - - dev_info['location'] = new_location - self.info.device_update(dev_uuid, cfg_xenapi = dev_info) - vfb_ctrl = self.getDeviceController('vfb') - vfb_ctrl.reconfigureDevice(0, dev_info) - break - - # - # Function to update xenstore /vm/* - # - - def _readVm(self, *args): - return xstransact.Read(self.vmpath, *args) - - def _writeVm(self, *args): - return xstransact.Write(self.vmpath, *args) - - def _removeVm(self, *args): - return xstransact.Remove(self.vmpath, *args) - - def _gatherVm(self, *args): - return xstransact.Gather(self.vmpath, *args) - - def _listRecursiveVm(self, *args): - return xstransact.ListRecursive(self.vmpath, *args) - - def storeVm(self, *args): - return xstransact.Store(self.vmpath, *args) - - def permissionsVm(self, *args): - return xstransact.SetPermissions(self.vmpath, *args) - - # - # Function to update xenstore /dom/* - # - - def readDom(self, *args): - return xstransact.Read(self.dompath, *args) - - def gatherDom(self, *args): - return xstransact.Gather(self.dompath, *args) - - def _writeDom(self, *args): - return xstransact.Write(self.dompath, *args) - - def _removeDom(self, *args): - return xstransact.Remove(self.dompath, *args) - - def storeDom(self, *args): - return xstransact.Store(self.dompath, *args) - - - def readDomTxn(self, transaction, *args): - paths = map(lambda x: self.dompath + "/" + x, args) - return transaction.read(*paths) - - def gatherDomTxn(self, transaction, *args): - paths = map(lambda x: self.dompath + "/" + x, args) - return transaction.gather(*paths) - - def _writeDomTxn(self, transaction, *args): - paths = map(lambda x: self.dompath + "/" + x, args) - return transaction.write(*paths) - - def _removeDomTxn(self, transaction, *args): - paths = map(lambda x: self.dompath + "/" + x, args) - return transaction.remove(*paths) - - def storeDomTxn(self, transaction, *args): - paths = map(lambda x: self.dompath + "/" + x, args) - return transaction.store(*paths) - - - def _recreateDom(self): - complete(self.dompath, lambda t: self._recreateDomFunc(t)) - - def _recreateDomFunc(self, t): - t.remove() - t.mkdir() - t.set_permissions({'dom' : self.domid, 'read' : True}) - t.write('vm', self.vmpath) - # NB. Solaris guests use guest/ and hvmpv/ xenstore directories - # XCP Windows paravirtualized guests use data/ - for i in [ 'device', 'control', 'error', 'memory', 'guest', \ - 'hvmpv', 'data' ]: - t.mkdir(i) - t.set_permissions(i, {'dom' : self.domid}) - - def _storeDomDetails(self): - to_store = { - 'domid': str(self.domid), - 'vm': self.vmpath, - 'name': self.info['name_label'], - 'console/limit': str(xoptions.get_console_limit() * 1024), - 'memory/target': str(self.info['memory_dynamic_max'] / 1024), - 'description': str(self.info['description']), - } - - def f(n, v): - if v is not None: - if type(v) == bool: - to_store[n] = v and "1" or "0" - else: - to_store[n] = str(v) - - # Figure out if we need to tell xenconsoled to ignore this guest's - # console - device model will handle console if it is running - constype = "ioemu" - if 'device_model' not in self.info['platform']: - constype = "xenconsoled" - - f('console/port', self.console_port) - f('console/ring-ref', self.console_mfn) - f('console/type', constype) - f('store/port', self.store_port) - f('store/ring-ref', self.store_mfn) - - f('control/platform-feature-xs_reset_watches', True) - if arch.type == "x86": - f('control/platform-feature-multiprocessor-suspend', True) - - # elfnotes - for n, v in self.info.get_notes().iteritems(): - n = n.lower().replace('_', '-') - if n == 'features': - for v in v.split('|'): - v = v.replace('_', '-') - if v.startswith('!'): - f('image/%s/%s' % (n, v[1:]), False) - else: - f('image/%s/%s' % (n, v), True) - else: - f('image/%s' % n, v) - - if self.info.has_key('security_label'): - f('security_label', self.info['security_label']) - - to_store.update(self._vcpuDomDetails()) - - log.debug("Storing domain details: %s", scrub_password(to_store)) - - self._writeDom(to_store) - - def _vcpuDomDetails(self): - def availability(n): - if self.info['vcpu_avail'] & (1 << n): - return 'online' - else: - return 'offline' - - result = {} - for v in range(0, self.info['VCPUs_max']): - result["cpu/%d/availability" % v] = availability(v) - return result - - # - # xenstore watches - # - - def _registerWatches(self): - """Register a watch on this VM's entries in the store, and the - domain's control/shutdown node, so that when they are changed - externally, we keep up to date. This should only be called by {@link - #create}, {@link #recreate}, or {@link #restore}, once the domain's - details have been written, but before the new instance is returned.""" - self.vmWatch = xswatch(self.vmpath, self._storeChanged) - self.shutdownWatch = xswatch(self.dompath + '/control/shutdown', - self._handleShutdownWatch) - - def _storeChanged(self, _): - log.trace("XendDomainInfo.storeChanged"); - - changed = False - - # Check whether values in the configuration have - # changed in Xenstore. - - cfg_vm = ['name', 'on_poweroff', 'on_reboot', 'on_crash', - 'rtc/timeoffset'] - - vm_details = self._readVMDetails([(k,XendConfig.LEGACY_CFG_TYPES[k]) - for k in cfg_vm]) - - # convert two lists into a python dictionary - vm_details = dict(zip(cfg_vm, vm_details)) - - for arg, val in vm_details.items(): - if arg in XendConfig.LEGACY_CFG_TO_XENAPI_CFG: - xapiarg = XendConfig.LEGACY_CFG_TO_XENAPI_CFG[arg] - if val != None and val != self.info[xapiarg]: - self.info[xapiarg] = val - changed = True - elif arg == "memory": - if val != None and val != self.info["static_memory_min"]: - self.info["static_memory_min"] = val - changed = True - elif arg == "maxmem": - if val != None and val != self.info["static_memory_max"]: - self.info["static_memory_max"] = val - changed = True - - # Check whether image definition has been updated - image_sxp = self._readVm('image') - if image_sxp and image_sxp != sxp.to_string(self.info.image_sxpr()): - self.info.update_with_image_sxp(sxp.from_string(image_sxp)) - changed = True - - # Update the rtc_timeoffset to be preserved across reboot. - # NB. No need to update xenstore domain section. - val = int(vm_details.get("rtc/timeoffset", 0)) - self.info["platform"]["rtc_timeoffset"] = val - - if changed: - # Update the domain section of the store, as this contains some - # parameters derived from the VM configuration. - self.refresh_shutdown_lock.acquire() - try: - state = self._stateGet() - if state not in (DOM_STATE_SHUTDOWN, DOM_STATE_HALTED,): - self._storeDomDetails() - finally: - self.refresh_shutdown_lock.release() - - return 1 - - def _handleShutdownWatch(self, _): - log.debug('XendDomainInfo.handleShutdownWatch') - - reason = self.readDom('control/shutdown') - - if reason and reason != 'suspend': - sst = self.readDom('xend/shutdown_start_time') - now = time.time() - if sst: - self.shutdownStartTime = float(sst) - timeout = float(sst) + SHUTDOWN_TIMEOUT - now - else: - self.shutdownStartTime = now - self.storeDom('xend/shutdown_start_time', now) - timeout = SHUTDOWN_TIMEOUT - - log.trace( - "Scheduling refreshShutdown on domain %d in %ds.", - self.domid, timeout) - threading.Timer(timeout, self.refreshShutdown).start() - - return True - - - # - # Public Attributes for the VM - # - - - def getDomid(self): - return self.domid - - def getStubdomDomid(self): - dom_list = xstransact.List('/local/domain') - for d in dom_list: - target = xstransact.Read('/local/domain/' + d + '/target') - if target is not None and int(target) == self.domid: - return int(d) - return None - - def setName(self, name, to_store = True): - self._checkName(name) - self.info['name_label'] = name - if to_store: - self.storeVm("name", name) - - def getName(self): - return self.info['name_label'] - - def getDomainPath(self): - return self.dompath - - def getShutdownReason(self): - return self.readDom('control/shutdown') - - def getStorePort(self): - """For use only by image.py and XendCheckpoint.py.""" - return self.store_port - - def getConsolePort(self): - """For use only by image.py and XendCheckpoint.py""" - return self.console_port - - def getFeatures(self): - """For use only by image.py.""" - return self.info['features'] - - def getVCpuCount(self): - return self.info['VCPUs_max'] - - def getVCpuAvail(self): - return self.info['vcpu_avail'] - - def setVCpuCount(self, vcpus): - def vcpus_valid(n): - if vcpus <= 0: - raise XendError('Zero or less VCPUs is invalid') - if self.domid >= 0 and vcpus > self.info['VCPUs_max']: - raise XendError('Cannot set vcpus greater than max vcpus on running domain') - vcpus_valid(vcpus) - - self.info['vcpu_avail'] = (1 << vcpus) - 1 - if self.domid >= 0: - self.storeVm('vcpu_avail', self.info['vcpu_avail']) - self._writeDom(self._vcpuDomDetails()) - self.info['VCPUs_live'] = vcpus - else: - if self.info['VCPUs_max'] > vcpus: - # decreasing - del self.info['cpus'][vcpus:] - elif self.info['VCPUs_max'] < vcpus: - # increasing - for c in range(self.info['VCPUs_max'], vcpus): - self.info['cpus'].append(list()) - self.info['VCPUs_max'] = vcpus - xen.xend.XendDomain.instance().managed_config_save(self) - log.info("Set VCPU count on domain %s to %d", self.info['name_label'], - vcpus) - - def getMemoryTarget(self): - """Get this domain's target memory size, in KB.""" - return self.info['memory_dynamic_max'] / 1024 - - def getMemoryMaximum(self): - """Get this domain's maximum memory size, in KB.""" - # remember, info now stores memory in bytes - return self.info['memory_static_max'] / 1024 - - def getResume(self): - return str(self._resume) - - def setResume(self, isresume): - self._resume = isresume - - def getCpus(self): - return self.info['cpus'] - - def setCpus(self, cpumap): - self.info['cpus'] = cpumap - - def getCap(self): - return self.info['vcpus_params']['cap'] - - def setCap(self, cpu_cap): - self.info['vcpus_params']['cap'] = cpu_cap - - def getWeight(self): - return self.info['vcpus_params']['weight'] - - def setWeight(self, cpu_weight): - self.info['vcpus_params']['weight'] = cpu_weight - - def getRestartCount(self): - return self._readVm('xend/restart_count') - - def refreshShutdown(self, xeninfo = None): - """ Checks the domain for whether a shutdown is required. - - Called from XendDomainInfo and also image.py for HVM images. - """ - - # If set at the end of this method, a restart is required, with the - # given reason. This restart has to be done out of the scope of - # refresh_shutdown_lock. - restart_reason = None - - self.refresh_shutdown_lock.acquire() - try: - if xeninfo is None: - xeninfo = dom_get(self.domid) - if xeninfo is None: - # The domain no longer exists. This will occur if we have - # scheduled a timer to check for shutdown timeouts and the - # shutdown succeeded. It will also occur if someone - # destroys a domain beneath us. We clean up the domain, - # just in case, but we can't clean up the VM, because that - # VM may have migrated to a different domain on this - # machine. - self.cleanupDomain() - self._stateSet(DOM_STATE_HALTED) - return - - if xeninfo['dying']: - # Dying means that a domain has been destroyed, but has not - # yet been cleaned up by Xen. This state could persist - # indefinitely if, for example, another domain has some of its - # pages mapped. We might like to diagnose this problem in the - # future, but for now all we do is make sure that it's not us - # holding the pages, by calling cleanupDomain. We can't - # clean up the VM, as above. - self.cleanupDomain() - self._stateSet(DOM_STATE_SHUTDOWN) - return - - elif xeninfo['crashed']: - if self.readDom('xend/shutdown_completed'): - # We've seen this shutdown already, but we are preserving - # the domain for debugging. Leave it alone. - return - - log.warn('Domain has crashed: name=%s id=%d.', - self.info['name_label'], self.domid) - self._writeVm(LAST_SHUTDOWN_REASON, 'crash') - - restart_reason = 'crash' - self._stateSet(DOM_STATE_HALTED) - - elif xeninfo['shutdown']: - self._stateSet(DOM_STATE_SHUTDOWN) - if self.readDom('xend/shutdown_completed'): - # We've seen this shutdown already, but we are preserving - # the domain for debugging. Leave it alone. - return - - else: - reason = shutdown_reason(xeninfo['shutdown_reason']) - - log.info('Domain has shutdown: name=%s id=%d reason=%s.', - self.info['name_label'], self.domid, reason) - self._writeVm(LAST_SHUTDOWN_REASON, reason) - - self._clearRestart() - - if reason == 'suspend': - self._stateSet(DOM_STATE_SUSPENDED) - # Don't destroy the domain. XendCheckpoint will do - # this once it has finished. However, stop watching - # the VM path now, otherwise we will end up with one - # watch for the old domain, and one for the new. - self._unwatchVm() - elif reason in ('poweroff', 'reboot'): - restart_reason = reason - else: - self.destroy() - - elif self.dompath is None: - # We have yet to manage to call introduceDomain on this - # domain. This can happen if a restore is in progress, or has - # failed. Ignore this domain. - pass - else: - # Domain is alive. If we are shutting it down, log a message - # if it seems unresponsive. - if xeninfo['paused']: - self._stateSet(DOM_STATE_PAUSED) - else: - self._stateSet(DOM_STATE_RUNNING) - - if self.shutdownStartTime: - timeout = (SHUTDOWN_TIMEOUT - time.time() + - self.shutdownStartTime) - if (timeout < 0 and not self.readDom('xend/unresponsive')): - log.info( - "Domain shutdown timeout expired: name=%s id=%s", - self.info['name_label'], self.domid) - self.storeDom('xend/unresponsive', 'True') - finally: - self.refresh_shutdown_lock.release() - - if restart_reason and not self.restart_in_progress: - self.restart_in_progress = True - threading.Thread(target = self._maybeRestart, - args = (restart_reason,)).start() - - - # - # Restart functions - handling whether we come back up on shutdown. - # - - def _clearRestart(self): - self._removeDom("xend/shutdown_start_time") - - def _maybeDumpCore(self, reason): - if reason == 'crash': - if xoptions.get_enable_dump() or self.get_on_crash() \ - in ['coredump_and_destroy', 'coredump_and_restart']: - try: - self.dumpCore() - except XendError: - # This error has been logged -- there's nothing more - # we can do in this context. - pass - - def _maybeRestart(self, reason): - # Before taking configured action, dump core if configured to do so. - # - self._maybeDumpCore(reason) - - # Dispatch to the correct method based upon the configured on_{reason} - # behaviour. - actions = {"destroy" : self.destroy, - "restart" : self._restart, - "preserve" : self._preserve, - "rename-restart" : self._renameRestart, - "coredump-destroy" : self.destroy, - "coredump-restart" : self._restart} - - action_conf = { - 'poweroff': 'actions_after_shutdown', - 'reboot': 'actions_after_reboot', - 'crash': 'actions_after_crash', - } - - action_target = self.info.get(action_conf.get(reason)) - func = actions.get(action_target, None) - if func and callable(func): - func() - else: - self.destroy() # default to destroy - - def _renameRestart(self): - self._restart(True) - - def _restart(self, rename = False): - """Restart the domain after it has exited. - - @param rename True if the old domain is to be renamed and preserved, - False if it is to be destroyed. - """ - from xen.xend import XendDomain - - if self._readVm(RESTART_IN_PROGRESS): - log.error('Xend failed during restart of domain %s. ' - 'Refusing to restart to avoid loops.', - str(self.domid)) - self.destroy() - return - - old_domid = self.domid - self._writeVm(RESTART_IN_PROGRESS, 'True') - - elapse = time.time() - self.info['start_time'] - if elapse < MINIMUM_RESTART_TIME: - log.error('VM %s restarting too fast (Elapsed time: %f seconds). ' - 'Refusing to restart to avoid loops.', - self.info['name_label'], elapse) - self.destroy() - return - - prev_vm_xend = self._listRecursiveVm('xend') - new_dom_info = self.info - try: - if rename: - new_dom_info = self._preserveForRestart() - else: - self._unwatchVm() - self.destroy() - - # new_dom's VM will be the same as this domain's VM, except where - # the rename flag has instructed us to call preserveForRestart. - # In that case, it is important that we remove the - # RESTART_IN_PROGRESS node from the new domain, not the old one, - # once the new one is available. - - new_dom = None - try: - new_dom = XendDomain.instance().domain_create_from_dict( - new_dom_info) - for x in prev_vm_xend[0][1]: - new_dom._writeVm('xend/%s' % x[0], x[1]) - new_dom.waitForDevices() - new_dom.unpause() - rst_cnt = new_dom._readVm('xend/restart_count') - rst_cnt = int(rst_cnt) + 1 - new_dom._writeVm('xend/restart_count', str(rst_cnt)) - new_dom._removeVm(RESTART_IN_PROGRESS) - except: - if new_dom: - new_dom._removeVm(RESTART_IN_PROGRESS) - new_dom.destroy() - else: - self._removeVm(RESTART_IN_PROGRESS) - raise - except: - log.exception('Failed to restart domain %s.', str(old_domid)) - - def _preserveForRestart(self): - """Preserve a domain that has been shut down, by giving it a new UUID, - cloning the VM details, and giving it a new name. This allows us to - keep this domain for debugging, but restart a new one in its place - preserving the restart semantics (name and UUID preserved). - """ - - new_uuid = uuid.createString() - new_name = 'Domain-%s' % new_uuid - log.info("Renaming dead domain %s (%d, %s) to %s (%s).", - self.info['name_label'], self.domid, self.info['uuid'], - new_name, new_uuid) - self._unwatchVm() - self._releaseDevices() - # Remove existing vm node in xenstore - self._removeVm() - new_dom_info = self.info.copy() - new_dom_info['name_label'] = self.info['name_label'] - new_dom_info['uuid'] = self.info['uuid'] - self.info['name_label'] = new_name - self.info['uuid'] = new_uuid - self.vmpath = XS_VMROOT + new_uuid - # Write out new vm node to xenstore - self._storeVmDetails() - self._preserve() - return new_dom_info - - - def _preserve(self): - log.info("Preserving dead domain %s (%d).", self.info['name_label'], - self.domid) - self._unwatchVm() - self.storeDom('xend/shutdown_completed', 'True') - self._stateSet(DOM_STATE_HALTED) - - # - # Debugging .. - # - - def dumpCore(self, corefile = None): - """Create a core dump for this domain. - - @raise: XendError if core dumping failed. - """ - - if not corefile: - # To prohibit directory traversal - based_name = os.path.basename(self.info['name_label']) - - coredir = "/var/xen/dump/%s" % (based_name) - if not os.path.exists(coredir): - try: - mkdir.parents(coredir, stat.S_IRWXU) - except Exception, ex: - log.error("Cannot create directory: %s" % str(ex)) - - if not os.path.isdir(coredir): - # Use former directory to dump core - coredir = '/var/xen/dump' - - this_time = time.strftime("%Y-%m%d-%H%M.%S", time.localtime()) - corefile = "%s/%s-%s.%s.core" % (coredir, this_time, - self.info['name_label'], self.domid) - - if os.path.isdir(corefile): - raise XendError("Cannot dump core in a directory: %s" % - corefile) - - try: - try: - self._writeVm(DUMPCORE_IN_PROGRESS, 'True') - xc.domain_dumpcore(self.domid, corefile) - except RuntimeError, ex: - corefile_incomp = corefile+'-incomplete' - try: - os.rename(corefile, corefile_incomp) - except: - pass - - log.error("core dump failed: id = %s name = %s: %s", - self.domid, self.info['name_label'], str(ex)) - raise XendError("Failed to dump core: %s" % str(ex)) - finally: - self._removeVm(DUMPCORE_IN_PROGRESS) - - # - # Device creation/deletion functions - # - - def _createDevice(self, deviceClass, devConfig): - return self.getDeviceController(deviceClass).createDevice(devConfig) - - def _waitForDevice(self, deviceClass, devid): - return self.getDeviceController(deviceClass).waitForDevice(devid) - - def _waitForDeviceUUID(self, dev_uuid): - deviceClass, config = self.info['devices'].get(dev_uuid) - self._waitForDevice(deviceClass, config['devid']) - - def _waitForDevice_destroy(self, deviceClass, devid, backpath): - return self.getDeviceController(deviceClass).waitForDevice_destroy( - devid, backpath) - - def _reconfigureDevice(self, deviceClass, devid, devconfig): - return self.getDeviceController(deviceClass).reconfigureDevice( - devid, devconfig) - - def _createDevices(self): - """Create the devices for a vm. - - @raise: VmError for invalid devices - """ - if self.image: - self.image.prepareEnvironment() - - vscsi_uuidlist = {} - vscsi_devidlist = [] - ordered_refs = self.info.ordered_device_refs() - for dev_uuid in ordered_refs: - devclass, config = self.info['devices'][dev_uuid] - if devclass in XendDevices.valid_devices() and devclass != 'vscsi': - log.info("createDevice: %s : %s" % (devclass, scrub_password(config))) - dev_uuid = config.get('uuid') - - if devclass == 'pci': - self.pci_dev_check_assignability_and_do_FLR(config) - - if devclass != 'pci' or not self.info.is_hvm() : - devid = self._createDevice(devclass, config) - - # store devid in XendConfig for caching reasons - if dev_uuid in self.info['devices']: - self.info['devices'][dev_uuid][1]['devid'] = devid - - elif devclass == 'vscsi': - vscsi_config = config.get('devs', [])[0] - devid = vscsi_config.get('devid', '') - dev_uuid = config.get('uuid') - vscsi_uuidlist[devid] = dev_uuid - vscsi_devidlist.append(devid) - - #It is necessary to sorted it for /dev/sdxx in guest. - if len(vscsi_uuidlist) > 0: - vscsi_devidlist.sort() - for vscsiid in vscsi_devidlist: - dev_uuid = vscsi_uuidlist[vscsiid] - devclass, config = self.info['devices'][dev_uuid] - log.info("createDevice: %s : %s" % (devclass, scrub_password(config))) - dev_uuid = config.get('uuid') - devid = self._createDevice(devclass, config) - # store devid in XendConfig for caching reasons - if dev_uuid in self.info['devices']: - self.info['devices'][dev_uuid][1]['devid'] = devid - - - if self.image: - self.image.createDeviceModel() - - #if have pass-through devs, need the virtual pci slots info from qemu - self.pci_device_configure_boot() - - def _releaseDevices(self, suspend = False): - """Release all domain's devices. Nothrow guarantee.""" - if self.image: - try: - log.debug("Destroying device model") - self.image.destroyDeviceModel() - except Exception, e: - log.exception("Device model destroy failed %s" % str(e)) - else: - log.debug("No device model") - - log.debug("Releasing devices") - t = xstransact("%s/device" % self.vmpath) - try: - for devclass in XendDevices.valid_devices(): - for dev in t.list(devclass): - try: - log.debug("Removing %s", dev); - self.destroyDevice(devclass, dev, False); - except: - # Log and swallow any exceptions in removal -- - # there's nothing more we can do. - log.exception("Device release failed: %s; %s; %s", - self.info['name_label'], - devclass, dev) - finally: - t.abort() - - def getDeviceController(self, name): - """Get the device controller for this domain, and if it - doesn't exist, create it. - - @param name: device class name - @type name: string - @rtype: subclass of DevController - """ - if name not in self._deviceControllers: - devController = XendDevices.make_controller(name, self) - if not devController: - raise XendError("Unknown device type: %s" % name) - self._deviceControllers[name] = devController - - return self._deviceControllers[name] - - # - # Migration functions (public) - # - - def testMigrateDevices(self, network, dst): - """ Notify all device about intention of migration - @raise: XendError for a device that cannot be migrated - """ - for (n, c) in self.info.all_devices_sxpr(): - rc = self.migrateDevice(n, c, network, dst, DEV_MIGRATE_TEST, self.getName()) - if rc != 0: - raise XendError("Device of type '%s' refuses migration." % n) - - def migrateDevices(self, network, dst, step, domName=''): - """Notify the devices about migration - """ - ctr = 0 - try: - for (dev_type, dev_conf) in self.info.all_devices_sxpr(): - self.migrateDevice(dev_type, dev_conf, network, dst, - step, domName) - ctr = ctr + 1 - except: - for dev_type, dev_conf in self.info.all_devices_sxpr(): - if ctr == 0: - step = step - 1 - ctr = ctr - 1 - self._recoverMigrateDevice(dev_type, dev_conf, network, - dst, step, domName) - raise - - def migrateDevice(self, deviceClass, deviceConfig, network, dst, - step, domName=''): - return self.getDeviceController(deviceClass).migrate(deviceConfig, - network, dst, step, domName) - - def _recoverMigrateDevice(self, deviceClass, deviceConfig, network, - dst, step, domName=''): - return self.getDeviceController(deviceClass).recover_migrate( - deviceConfig, network, dst, step, domName) - - def setChangeHomeServer(self, chs): - if chs is not None: - self.info['change_home_server'] = bool(chs) - else: - if self.info.has_key('change_home_server'): - del self.info['change_home_server'] - - - ## private: - - def _constructDomain(self): - """Construct the domain. - - @raise: VmError on error - """ - - log.debug('XendDomainInfo.constructDomain') - - self.shutdownStartTime = None - self.restart_in_progress = False - - hap = 0 - hvm = self.info.is_hvm() - if hvm: - hap = self.info.is_hap() - info = xc.xeninfo() - if 'hvm' not in info['xen_caps']: - raise VmError("HVM guest support is unavailable: is VT/AMD-V " - "supported by your CPU and enabled in your " - "BIOS?") - - # Hack to pre-reserve some memory for initial domain creation. - # There is an implicit memory overhead for any domain creation. This - # overhead is greater for some types of domain than others. For - # example, an x86 HVM domain will have a default shadow-pagetable - # allocation of 4MB. We free up 16MB here to be on the safe side. - balloon.free(16*1024, self) # 16MB should be plenty - - ssidref = 0 - if security.on() == xsconstants.XS_POLICY_USE: - ssidref = security.calc_dom_ssidref_from_info(self.info) - if security.has_authorization(ssidref) == False: - raise VmError("VM is not authorized to run.") - - s3_integrity = 0 - if self.info.has_key('s3_integrity'): - s3_integrity = self.info['s3_integrity'] - - oos = self.info['platform'].get('oos', 1) - oos_off = 1 - int(oos) - - # look-up pool id to use - pool_name = self.info['pool_name'] - if len(pool_name) == 0: - pool_name = "Pool-0" - - pool = XendCPUPool.lookup_pool(pool_name) - - if pool is None: - raise VmError("unknown pool %s" % pool_name) - pool_id = pool.query_pool_id() - if pool_id is None: - raise VmError("pool %s not activated" % pool_name) - - flags = (int(hvm) << 0) | (int(hap) << 1) | (int(s3_integrity) << 2) | (int(oos_off) << 3) - - try: - self.domid = xc.domain_create( - domid = 0, - ssidref = ssidref, - handle = uuid.fromString(self.info['uuid']), - flags = flags, - #cpupool = pool_id, - target = self.info.target()) - except Exception, e: - # may get here if due to ACM the operation is not permitted - if security.on() == xsconstants.XS_POLICY_ACM: - raise VmError('Domain in conflict set with running domain?') - log.exception(e) - - if not self.domid or self.domid < 0: - failmsg = 'Creating domain failed: name=%s' % self.info['name_label'] - if self.domid: - failmsg += ', error=%i' % int(self.domid) - raise VmError(failmsg) - - try: - xc.cpupool_movedomain(pool_id, self.domid) - except Exception, e: - raise VmError('Moving domain to target pool failed') - - self.dompath = GetDomainPath(self.domid) - - self._recreateDom() - - # Set TSC mode of domain - tsc_mode = self.info["platform"].get("tsc_mode") - if arch.type == "x86" and tsc_mode is not None: - xc.domain_set_tsc_info(self.domid, int(tsc_mode)) - - # Set timer configuration of domain - timer_mode = self.info["platform"].get("timer_mode") - if hvm and timer_mode is not None: - xc.hvm_set_param(self.domid, HVM_PARAM_TIMER_MODE, - long(timer_mode)) - - if arch.type == "x86" and hvm: - # Set Viridian interface configuration of domain - viridian = self.info["platform"].get("viridian") - if viridian is not None: - xc.hvm_set_param(self.domid, HVM_PARAM_VIRIDIAN, long(viridian)) - # Set nestedhvm of domain - nestedhvm = self.info["platform"].get("nestedhvm") - if nestedhvm is not None: - xc.hvm_set_param(self.domid, HVM_PARAM_NESTEDHVM, long(nestedhvm)) - - # If nomigrate is set, disable migration - nomigrate = self.info["platform"].get("nomigrate") - if nomigrate is not None and long(nomigrate) != 0: - xc.domain_disable_migrate(self.domid) - - # Optionally enable virtual HPET - hpet = self.info["platform"].get("hpet") - if hvm and hpet is not None: - xc.hvm_set_param(self.domid, HVM_PARAM_HPET_ENABLED, - long(hpet)) - - # Optionally enable periodic vpt aligning - vpt_align = self.info["platform"].get("vpt_align") - if hvm and vpt_align is not None: - xc.hvm_set_param(self.domid, HVM_PARAM_VPT_ALIGN, - long(vpt_align)) - - # Set maximum number of vcpus in domain - xc.domain_max_vcpus(self.domid, int(self.info['VCPUs_max'])) - - # Check for cpu_{cap|weight} validity for credit scheduler - if XendNode.instance().xenschedinfo() == 'credit': - cap = self.getCap() - weight = self.getWeight() - - assert type(weight) == int - assert type(cap) == int - - if weight < 1 or weight > 65535: - raise VmError("Cpu weight out of range, valid values are within range from 1 to 65535") - - if cap < 0 or cap > self.getVCpuCount() * 100: - raise VmError("Cpu cap out of range, valid range is from 0 to %s for specified number of vcpus" % - (self.getVCpuCount() * 100)) - - # Test whether the devices can be assigned with VT-d - self.info.update_platform_pci() - pci = self.info["platform"].get("pci") - pci_str = '' - if pci and len(pci) > 0: - pci = map(lambda x: x[0:4], pci) # strip options - pci_str = str(pci) - - # This test is done for both pv and hvm guest. - for p in pci: - pci_name = '%04x:%02x:%02x.%x' % \ - (parse_hex(p[0]), parse_hex(p[1]), parse_hex(p[2]), parse_hex(p[3])) - try: - pci_device = PciDevice(parse_pci_name(pci_name)) - except Exception, e: - raise VmError("pci: failed to locate device and "+ - "parse its resources - "+str(e)) - if pci_device.driver!='pciback' and pci_device.driver!='pci-stub': - raise VmError(("pci: PCI Backend and pci-stub don't own device %s")\ - %pci_device.name) - if pci_name in get_all_assigned_pci_devices(): - raise VmError("failed to assign device %s that has" - " already been assigned to other domain." % pci_name) - - if hvm and pci_str != '': - bdf = xc.test_assign_device(0, pci_str) - if bdf != 0: - if bdf == -1: - raise VmError("failed to assign device: maybe the platform" - " doesn't support VT-d, or VT-d isn't enabled" - " properly?") - bus = (bdf >> 16) & 0xff - devfn = (bdf >> 8) & 0xff - dev = (devfn >> 3) & 0x1f - func = devfn & 0x7 - raise VmError("failed to assign device %02x:%02x.%x: maybe it has" - " already been assigned to other domain, or maybe" - " it doesn't exist." % (bus, dev, func)) - - # register the domain in the list - from xen.xend import XendDomain - XendDomain.instance().add_domain(self) - - def _introduceDomain(self): - assert self.domid is not None - assert self.store_mfn is not None - assert self.store_port is not None - - try: - IntroduceDomain(self.domid, self.store_mfn, self.store_port) - except RuntimeError, exn: - raise XendError(str(exn)) - - def _setTarget(self, target): - assert self.domid is not None - - try: - SetTarget(self.domid, target) - self.storeDom('target', target) - except RuntimeError, exn: - raise XendError(str(exn)) - - - def _setCPUAffinity(self): - """ Repin domain vcpus if a restricted cpus list is provided. - Returns the choosen node number. - """ - - def has_cpus(): - if self.info['cpus'] is not None: - for c in self.info['cpus']: - if c: - return True - return False - - def has_cpumap(): - if self.info.has_key('vcpus_params'): - for k, v in self.info['vcpus_params'].items(): - if k.startswith('cpumap'): - return True - return False - - index = 0 - if has_cpumap(): - for v in range(0, self.info['VCPUs_max']): - if self.info['vcpus_params'].has_key('cpumap%i' % v): - cpumask = map(int, self.info['vcpus_params']['cpumap%i' % v].split(',')) - xc.vcpu_setaffinity(self.domid, v, cpumask) - elif has_cpus(): - for v in range(0, self.info['VCPUs_max']): - if self.info['cpus'][v]: - xc.vcpu_setaffinity(self.domid, v, self.info['cpus'][v]) - else: - def find_relaxed_node(node_list): - import sys - nr_nodes = info['max_node_index'] + 1 - if node_list is None: - node_list = range(0, nr_nodes) - nodeload = [0] - nodeload = nodeload * nr_nodes - from xen.xend import XendDomain - doms = XendDomain.instance().list('all') - for dom in filter (lambda d: d.domid != self.domid, doms): - cpuinfo = dom.getVCPUInfo() - for vcpu in sxp.children(cpuinfo, 'vcpu'): - if sxp.child_value(vcpu, 'online') == 0: continue - cpumap = list(sxp.child_value(vcpu,'cpumap')) - for i in range(0, nr_nodes): - node_cpumask = node_to_cpu[i] - for j in node_cpumask: - if j in cpumap: - nodeload[i] += 1 - break - for i in range(0, nr_nodes): - if len(node_to_cpu[i]) == 0: - nodeload[i] += 8 - else: - nodeload[i] = int(nodeload[i] * 16 / len(node_to_cpu[i])) - if i not in node_list: - nodeload[i] += 8 - return map(lambda x: x[0], sorted(enumerate(nodeload), key=lambda x:x[1])) - - info = xc.numainfo() - if info['max_node_index'] > 0 and XendCPUPool.number_of_pools() < 2: - node_memory_list = info['node_memfree'] - node_to_cpu = [] - for i in range(0, info['max_node_index'] + 1): - node_to_cpu.append([]) - for cpu, node in enumerate(xc.topologyinfo()['cpu_to_node']): - node_to_cpu[node].append(cpu) - needmem = self.image.getRequiredAvailableMemory(self.info['memory_dynamic_max']) / 1024 - candidate_node_list = [] - for i in range(0, info['max_node_index'] + 1): - if node_memory_list[i] >= needmem and len(node_to_cpu[i]) > 0: - candidate_node_list.append(i) - best_node = find_relaxed_node(candidate_node_list)[0] - cpumask = node_to_cpu[best_node] - best_nodes = find_relaxed_node(filter(lambda x: x != best_node, range(0,info['max_node_index']+1))) - for node_idx in best_nodes: - if len(cpumask) >= self.info['VCPUs_max']: - break - cpumask = cpumask + node_to_cpu[node_idx] - log.debug("allocating additional NUMA node %d", node_idx) - for v in range(0, self.info['VCPUs_max']): - xc.vcpu_setaffinity(self.domid, v, cpumask) - return index - - def _freeDMAmemory(self, node): - - # If we are PV and have PCI devices the guest will - # turn on a SWIOTLB. The SWIOTLB _MUST_ be located in the DMA32 - # zone (under 4GB). To do so, we need to balloon down Dom0 to where - # there is enough (64MB) memory under the 4GB mark. This balloon-ing - # might take more memory out than just 64MB thought :-( - if not self.info.is_pv_and_has_pci(): - return - - retries = 2000 - ask_for_mem = 0 - need_mem = 0 - try: - while (retries > 0): - physinfo = xc.physinfo() - free_mem = physinfo['free_memory'] - max_node_id = physinfo['max_node_id'] - node_to_dma32_mem = physinfo['node_to_dma32_mem'] - if (node > max_node_id): - return - # Extra 2MB above 64GB seems to do the trick. - need_mem = 64 * 1024 + 2048 - node_to_dma32_mem[node] - # our starting point. We ask just for the difference to - # be have an extra 64MB under 4GB. - ask_for_mem = max(need_mem, ask_for_mem); - if (need_mem > 0): - log.debug('_freeDMAmemory (%d) Need %dKiB DMA memory. ' - 'Asking for %dKiB', retries, need_mem, - ask_for_mem) - - balloon.free(ask_for_mem, self) - ask_for_mem = ask_for_mem + 2048 - else: - # OK. We got enough DMA memory. - break - retries = retries - 1 - except: - # This is best-try after all. - need_mem = max(1, need_mem) - pass - - if (need_mem > 0): - log.warn('We tried our best to balloon down DMA memory to ' - 'accomodate your PV guest. We need %dKiB extra memory.', - need_mem) - - def _setSchedParams(self): - if XendNode.instance().xenschedinfo() == 'credit': - from xen.xend import XendDomain - XendDomain.instance().domain_sched_credit_set(self.getDomid(), - self.getWeight(), - self.getCap()) - elif XendNode.instance().xenschedinfo() == 'credit2': - from xen.xend import XendDomain - XendDomain.instance().domain_sched_credit2_set(self.getDomid(), - self.getWeight()) - - def _initDomain(self): - log.debug('XendDomainInfo.initDomain: %s %s', - self.domid, - self.info['vcpus_params']['weight']) - - self._configureBootloader() - - try: - self.image = image.create(self, self.info) - - # repin domain vcpus if a restricted cpus list is provided - # this is done prior to memory allocation to aide in memory - # distribution for NUMA systems. - node = self._setCPUAffinity() - - # Set scheduling parameters. - self._setSchedParams() - - # Use architecture- and image-specific calculations to determine - # the various headrooms necessary, given the raw configured - # values. maxmem, memory, and shadow are all in KiB. - # but memory_static_max etc are all stored in bytes now. - memory = self.image.getRequiredAvailableMemory( - self.info['memory_dynamic_max'] / 1024) - maxmem = self.image.getRequiredAvailableMemory( - self.info['memory_static_max'] / 1024) - shadow = self.image.getRequiredShadowMemory( - self.info['shadow_memory'] * 1024, - self.info['memory_static_max'] / 1024) - - log.debug("_initDomain:shadow_memory=0x%x, memory_static_max=0x%x, memory_static_min=0x%x.", self.info['shadow_memory'], self.info['memory_static_max'], self.info['memory_static_min'],) - # Round shadow up to a multiple of a MiB, as shadow_mem_control - # takes MiB and we must not round down and end up under-providing. - shadow = ((shadow + 1023) / 1024) * 1024 - - # set memory limit - xc.domain_setmaxmem(self.domid, maxmem) - - vtd_mem = 0 - info = xc.physinfo() - if 'hvm_directio' in info['virt_caps']: - # Reserve 1 page per MiB of RAM for separate VT-d page table. - vtd_mem = 4 * (self.info['memory_static_max'] / 1024 / 1024) - # Round vtd_mem up to a multiple of a MiB. - vtd_mem = ((vtd_mem + 1023) / 1024) * 1024 - - self.guest_bitsize = self.image.getBitSize() - # Make sure there's enough RAM available for the domain - balloon.free(memory + shadow + vtd_mem, self) - - # Set up the shadow memory - shadow_cur = xc.shadow_mem_control(self.domid, shadow / 1024) - self.info['shadow_memory'] = shadow_cur - - # machine address size - if self.info.has_key('machine_address_size'): - log.debug("_initDomain: setting maximum machine address size %d" % self.info['machine_address_size']) - xc.domain_set_machine_address_size(self.domid, self.info['machine_address_size']) - - if self.info.has_key('suppress_spurious_page_faults') and self.info['suppress_spurious_page_faults']: - log.debug("_initDomain: suppressing spurious page faults") - xc.domain_suppress_spurious_page_faults(self.domid) - - self._createChannels() - - channel_details = self.image.createImage() - - self.store_mfn = channel_details['store_mfn'] - if 'console_mfn' in channel_details: - self.console_mfn = channel_details['console_mfn'] - if 'notes' in channel_details: - self.info.set_notes(channel_details['notes']) - if 'native_protocol' in channel_details: - self.native_protocol = channel_details['native_protocol']; - - self._introduceDomain() - if self.info.target(): - self._setTarget(self.info.target()) - - self._freeDMAmemory(node) - - self._createDevices() - - self.image.cleanupTmpImages() - - self.info['start_time'] = time.time() - - self._stateSet(DOM_STATE_RUNNING) - except VmError, exn: - log.exception("XendDomainInfo.initDomain: exception occurred") - if self.image: - self.image.cleanupTmpImages() - raise exn - except RuntimeError, exn: - log.exception("XendDomainInfo.initDomain: exception occurred") - if self.image: - self.image.cleanupTmpImages() - raise VmError(str(exn)) - - - def cleanupDomain(self): - """Cleanup domain resources; release devices. Idempotent. Nothrow - guarantee.""" - - self.refresh_shutdown_lock.acquire() - try: - self.unwatchShutdown() - self._releaseDevices() - bootloader_tidy(self) - - if self.image: - self.image = None - - try: - self._removeDom() - except: - log.exception("Removing domain path failed.") - - self._stateSet(DOM_STATE_HALTED) - self.domid = None # Do not push into _stateSet()! - finally: - self.refresh_shutdown_lock.release() - - - def unwatchShutdown(self): - """Remove the watch on the domain's control/shutdown node, if any. - Idempotent. Nothrow guarantee. Expects to be protected by the - refresh_shutdown_lock.""" - - try: - try: - if self.shutdownWatch: - self.shutdownWatch.unwatch() - finally: - self.shutdownWatch = None - except: - log.exception("Unwatching control/shutdown failed.") - - def waitForShutdown(self): - self.state_updated.acquire() - try: - while self._stateGet() in (DOM_STATE_RUNNING,DOM_STATE_PAUSED): - self.state_updated.wait(timeout=1.0) - finally: - self.state_updated.release() - - def waitForSuspend(self): - """Wait for the guest to respond to a suspend request by - shutting down. If the guest hasn't re-written control/shutdown - after a certain amount of time, it's obviously not listening and - won't suspend, so we give up. HVM guests with no PV drivers - should already be shutdown. - """ - state = "suspend" - nr_tries = 60 - - self.state_updated.acquire() - try: - while self._stateGet() in (DOM_STATE_RUNNING,DOM_STATE_PAUSED): - self.state_updated.wait(1.0) - if state == "suspend": - if nr_tries == 0: - msg = ('Timeout waiting for domain %s to suspend' - % self.domid) - self._writeDom('control/shutdown', '') - raise XendError(msg) - state = self.readDom('control/shutdown') - nr_tries -= 1 - finally: - self.state_updated.release() - - # - # TODO: recategorise - called from XendCheckpoint - # - - def completeRestore(self, store_mfn, console_mfn): - - log.debug("XendDomainInfo.completeRestore") - - self.store_mfn = store_mfn - self.console_mfn = console_mfn - - self._introduceDomain() - self.image = image.create(self, self.info) - if self.image: - self.image.createDeviceModel(True) - self._storeDomDetails() - self._registerWatches() - self.refreshShutdown() - - log.debug("XendDomainInfo.completeRestore done") - - - def _endRestore(self): - self.setResume(False) - - # - # VM Destroy - # - - def _prepare_phantom_paths(self): - # get associated devices to destroy - # build list of phantom devices to be removed after normal devices - plist = [] - if self.domid is not None: - t = xstransact("%s/device/vbd" % GetDomainPath(self.domid)) - try: - for dev in t.list(): - backend_phantom_vbd = xstransact.Read("%s/device/vbd/%s/phantom_vbd" \ - % (self.dompath, dev)) - if backend_phantom_vbd is not None: - frontend_phantom_vbd = xstransact.Read("%s/frontend" \ - % backend_phantom_vbd) - plist.append(backend_phantom_vbd) - plist.append(frontend_phantom_vbd) - finally: - t.abort() - return plist - - def _cleanup_phantom_devs(self, plist): - # remove phantom devices - if not plist == []: - time.sleep(2) - for paths in plist: - if paths.find('backend') != -1: - # Modify online status /before/ updating state (latter is watched by - # drivers, so this ordering avoids a race). - xstransact.Write(paths, 'online', "0") - xstransact.Write(paths, 'state', str(xenbusState['Closing'])) - # force - xstransact.Remove(paths) - - def destroy(self): - """Cleanup VM and destroy domain. Nothrow guarantee.""" - - if self.domid is None: - return - from xen.xend import XendDomain - log.debug("XendDomainInfo.destroy: domid=%s", str(self.domid)) - - paths = self._prepare_phantom_paths() - - if self.dompath is not None: - try: - xc.domain_destroy_hook(self.domid) - xc.domain_pause(self.domid) - do_FLR(self.domid, self.info.is_hvm()) - xc.domain_destroy(self.domid) - for state in DOM_STATES_OLD: - self.info[state] = 0 - self._stateSet(DOM_STATE_HALTED) - except: - log.exception("XendDomainInfo.destroy: domain destruction failed.") - - XendDomain.instance().remove_domain(self) - self.cleanupDomain() - - if self.info.is_hvm() or self.guest_bitsize != 32: - if self.alloc_mem: - import MemoryPool - log.debug("%s KiB need to add to Memory pool" %self.alloc_mem) - MemoryPool.instance().increase_memory(self.alloc_mem) - - self._cleanup_phantom_devs(paths) - self._cleanupVm() - - if ("transient" in self.info["other_config"] and \ - bool(self.info["other_config"]["transient"])) or \ - ("change_home_server" in self.info and \ - bool(self.info["change_home_server"])): - XendDomain.instance().domain_delete_by_dominfo(self) - - - def resetDomain(self): - log.debug("XendDomainInfo.resetDomain(%s)", str(self.domid)) - - old_domid = self.domid - prev_vm_xend = self._listRecursiveVm('xend') - new_dom_info = self.info - try: - self._unwatchVm() - self.destroy() - - new_dom = None - try: - from xen.xend import XendDomain - new_dom_info['domid'] = None - new_dom = XendDomain.instance().domain_create_from_dict( - new_dom_info) - for x in prev_vm_xend[0][1]: - new_dom._writeVm('xend/%s' % x[0], x[1]) - new_dom.waitForDevices() - new_dom.unpause() - except: - if new_dom: - new_dom.destroy() - raise - except: - log.exception('Failed to reset domain %s.', str(old_domid)) - - - def resumeDomain(self): - log.debug("XendDomainInfo.resumeDomain(%s)", str(self.domid)) - - # resume a suspended domain (e.g. after live checkpoint, or after - # a later error during save or migate); checks that the domain - # is currently suspended first so safe to call from anywhere - - xeninfo = dom_get(self.domid) - if xeninfo is None: - return - if not xeninfo['shutdown']: - return - reason = shutdown_reason(xeninfo['shutdown_reason']) - if reason != 'suspend': - return - - try: - # could also fetch a parsed note from xenstore - fast = self.info.get_notes().get('SUSPEND_CANCEL') and 1 or 0 - if not fast: - self._releaseDevices() - self.testDeviceComplete() - self.testvifsComplete() - log.debug("XendDomainInfo.resumeDomain: devices released") - - self._resetChannels() - - self._removeDom('control/shutdown') - self._removeDom('device-misc/vif/nextDeviceID') - - self._createChannels() - self._introduceDomain() - self._storeDomDetails() - - self._createDevices() - log.debug("XendDomainInfo.resumeDomain: devices created") - - xc.domain_resume(self.domid, fast) - ResumeDomain(self.domid) - except: - log.exception("XendDomainInfo.resume: xc.domain_resume failed on domain %s." % (str(self.domid))) - self.image.resumeDeviceModel() - log.debug("XendDomainInfo.resumeDomain: completed") - - - # - # Channels for xenstore and console - # - - def _createChannels(self): - """Create the channels to the domain. - """ - self.store_port = self._createChannel() - self.console_port = self._createChannel() - - - def _createChannel(self): - """Create an event channel to the domain. - """ - try: - if self.domid != None: - return xc.evtchn_alloc_unbound(domid = self.domid, - remote_dom = 0) - except: - log.exception("Exception in alloc_unbound(%s)", str(self.domid)) - raise - - def _resetChannels(self): - """Reset all event channels in the domain. - """ - try: - if self.domid != None: - return xc.evtchn_reset(dom = self.domid) - except: - log.exception("Exception in evtcnh_reset(%s)", str(self.domid)) - raise - - - # - # Bootloader configuration - # - - def _configureBootloader(self): - """Run the bootloader if we're configured to do so.""" - - blexec = self.info['PV_bootloader'] - bootloader_args = self.info['PV_bootloader_args'] - kernel = self.info['PV_kernel'] - ramdisk = self.info['PV_ramdisk'] - args = self.info['PV_args'] - boot = self.info['HVM_boot_policy'] - - if boot: - # HVM booting. - pass - elif not blexec and kernel: - # Boot from dom0. Nothing left to do -- the kernel and ramdisk - # will be picked up by image.py. - pass - else: - # Boot using bootloader - if not blexec or blexec == 'pygrub': - blexec = auxbin.pathTo('pygrub') - - blcfg = None - disks = [x for x in self.info['vbd_refs'] - if self.info['devices'][x][1]['bootable']] - - if not disks: - msg = "Had a bootloader specified, but no disks are bootable" - log.error(msg) - raise VmError(msg) - - devinfo = self.info['devices'][disks[0]] - devtype = devinfo[0] - disk = devinfo[1]['uname'] - - (fn, types) = parse_uname(disk) - def _shouldMount(types): - if types[0] in ('file', 'phy'): - return False - if types[0] in ('tap', 'tap2'): - if types[1] in ('aio', 'sync'): - return False - else: - return True - return os.access('/etc/xen/scripts/block-%s' % types[0], os.X_OK) - - mounted = _shouldMount(types) - mounted_vbd_uuid = 0 - if mounted: - # This is a file, not a device. pygrub can cope with a - # file if it's raw, but if it's QCOW or other such formats - # used through blktap, then we need to mount it first. - - log.info("Mounting %s on %s." % - (fn, BOOTLOADER_LOOPBACK_DEVICE)) - - vbd = { - 'mode': 'RO', - 'device': BOOTLOADER_LOOPBACK_DEVICE, - } - - from xen.xend import XendDomain - dom0 = XendDomain.instance().privilegedDomain() - mounted_vbd_uuid = dom0.create_vbd(vbd, disk); - dom0._waitForDeviceUUID(mounted_vbd_uuid) - fn = BOOTLOADER_LOOPBACK_DEVICE - - try: - blcfg = bootloader(blexec, fn, self, False, - bootloader_args, kernel, ramdisk, args) - finally: - if mounted: - log.info("Unmounting %s from %s." % - (fn, BOOTLOADER_LOOPBACK_DEVICE)) - _, vbd_info = dom0.info['devices'][mounted_vbd_uuid] - dom0.destroyDevice(dom0.getBlockDeviceClass(vbd_info['devid']), - BOOTLOADER_LOOPBACK_DEVICE, force = True) - - if blcfg is None: - msg = "Had a bootloader specified, but can't find disk" - log.error(msg) - raise VmError(msg) - - self.info.update_with_image_sxp(blcfg, True) - - - # - # VM Functions - # - - def _readVMDetails(self, params): - """Read the specified parameters from the store. - """ - try: - return self._gatherVm(*params) - except ValueError: - # One of the int/float entries in params has a corresponding store - # entry that is invalid. We recover, because older versions of - # Xend may have put the entry there (memory/target, for example), - # but this is in general a bad situation to have reached. - log.exception( - "Store corrupted at %s! Domain %d's configuration may be " - "affected.", self.vmpath, self.domid) - return [] - - def _cleanupVm(self): - """Cleanup VM resources. Idempotent. Nothrow guarantee.""" - - self._unwatchVm() - - try: - self._removeVm() - except: - log.exception("Removing VM path failed.") - - - def checkLiveMigrateMemory(self): - """ Make sure there's enough memory to migrate this domain """ - overhead_kb = 0 - if arch.type == "x86": - # 1MB per vcpu plus 4Kib/Mib of RAM. This is higher than - # the minimum that Xen would allocate if no value were given. - overhead_kb = self.info['VCPUs_max'] * 1024 + \ - (self.info['memory_static_max'] / 1024 / 1024) * 4 - overhead_kb = ((overhead_kb + 1023) / 1024) * 1024 - # The domain might already have some shadow memory - overhead_kb -= xc.shadow_mem_control(self.domid) * 1024 - if overhead_kb > 0: - balloon.free(overhead_kb, self) - - def _unwatchVm(self): - """Remove the watch on the VM path, if any. Idempotent. Nothrow - guarantee.""" - try: - try: - if self.vmWatch: - self.vmWatch.unwatch() - finally: - self.vmWatch = None - except: - log.exception("Unwatching VM path failed.") - - def testDeviceComplete(self): - """ For Block IO migration safety we must ensure that - the device has shutdown correctly, i.e. all blocks are - flushed to disk - """ - start = time.time() - while True: - test = 0 - diff = time.time() - start - vbds = self.getDeviceController('vbd').deviceIDs() - taps = self.getDeviceController('tap').deviceIDs() - tap2s = self.getDeviceController('tap2').deviceIDs() - for i in vbds + taps + tap2s: - test = 1 - log.info("Dev %s still active, looping...", i) - time.sleep(0.1) - - if test == 0: - break - if diff >= MIGRATE_TIMEOUT: - log.info("Dev still active but hit max loop timeout") - break - - def testvifsComplete(self): - """ In case vifs are released and then created for the same - domain, we need to wait the device shut down. - """ - start = time.time() - while True: - test = 0 - diff = time.time() - start - for i in self.getDeviceController('vif').deviceIDs(): - test = 1 - log.info("Dev %s still active, looping...", i) - time.sleep(0.1) - - if test == 0: - break - if diff >= MIGRATE_TIMEOUT: - log.info("Dev still active but hit max loop timeout") - break - - def _storeVmDetails(self): - to_store = {} - - for key in XendConfig.LEGACY_XENSTORE_VM_PARAMS: - info_key = XendConfig.LEGACY_CFG_TO_XENAPI_CFG.get(key, key) - if self._infoIsSet(info_key): - to_store[key] = str(self.info[info_key]) - - if self._infoIsSet("static_memory_min"): - to_store["memory"] = str(self.info["static_memory_min"]) - if self._infoIsSet("static_memory_max"): - to_store["maxmem"] = str(self.info["static_memory_max"]) - - image_sxpr = self.info.image_sxpr() - if image_sxpr: - to_store['image'] = sxp.to_string(image_sxpr) - - if not self._readVm('xend/restart_count'): - to_store['xend/restart_count'] = str(0) - - log.debug("Storing VM details: %s", scrub_password(to_store)) - - self._writeVm(to_store) - self._setVmPermissions() - - def _setVmPermissions(self): - """Allow the guest domain to read its UUID. We don't allow it to - access any other entry, for security.""" - xstransact.SetPermissions('%s/uuid' % self.vmpath, - { 'dom' : self.domid, - 'read' : True, - 'write' : False }) - - # - # Utility functions - # - - def __getattr__(self, name): - if name == "state": - log.warn("Somebody tried to read XendDomainInfo.state... should us _stateGet()!!!") - log.warn("".join(traceback.format_stack())) - return self._stateGet() - else: - raise AttributeError(name) - - def __setattr__(self, name, value): - if name == "state": - log.warn("Somebody tried to set XendDomainInfo.state... should us _stateGet()!!!") - log.warn("".join(traceback.format_stack())) - self._stateSet(value) - else: - self.__dict__[name] = value - - def _stateSet(self, state): - self.state_updated.acquire() - try: - # TODO Not sure this is correct... - # _stateGet is live now. Why not fire event - # even when it hasn't changed? - if self._stateGet() != state: - self.state_updated.notifyAll() - import XendAPI - XendAPI.event_dispatch('mod', 'VM', self.info['uuid'], - 'power_state') - finally: - self.state_updated.release() - - def _stateGet(self): - # Lets try and reconsitute the state from xc - # first lets try and get the domain info - # from xc - this will tell us if the domain - # exists - info = dom_get(self.getDomid()) - if info is None or info['shutdown']: - # We are either HALTED or SUSPENDED - # check saved image exists - from xen.xend import XendDomain - managed_config_path = \ - XendDomain.instance()._managed_check_point_path( \ - self.get_uuid()) - if os.path.exists(managed_config_path): - return XEN_API_VM_POWER_STATE_SUSPENDED - else: - return XEN_API_VM_POWER_STATE_HALTED - elif info['crashed']: - # Crashed - return XEN_API_VM_POWER_STATE_CRASHED - else: - # We are either RUNNING or PAUSED - if info['paused']: - return XEN_API_VM_POWER_STATE_PAUSED - else: - return XEN_API_VM_POWER_STATE_RUNNING - - def _infoIsSet(self, name): - return name in self.info and self.info[name] is not None - - def _checkName(self, name): - """Check if a vm name is valid. Valid names contain alphabetic - characters, digits, or characters in '_-.:+'. - The same name cannot be used for more than one vm at the same time. - - @param name: name - @raise: VmError if invalid - """ - from xen.xend import XendDomain - - if name is None or name == '': - raise VmError('Missing VM Name') - - if not re.search(r'^[A-Za-z0-9_\-\.\:\+]+$', name): - raise VmError('Invalid VM Name') - - dom = XendDomain.instance().domain_lookup_nr(name) - if dom and dom.info['uuid'] != self.info['uuid']: - raise VmError("VM name '%s' already exists%s" % - (name, - dom.domid is not None and - (" as domain %s" % str(dom.domid)) or "")) - - - def update(self, info = None, refresh = True, transaction = None): - """Update with info from xc.domain_getinfo(). - """ - log.trace("XendDomainInfo.update(%s) on domain %s", info, - str(self.domid)) - - if not info: - info = dom_get(self.domid) - if not info: - return - - if info["maxmem_kb"] < 0: - info["maxmem_kb"] = XendNode.instance() \ - .physinfo_dict()['total_memory'] * 1024 - - # make sure state is reset for info - # TODO: we should eventually get rid of old_dom_states - - self.info.update_config(info) - self._update_consoles(transaction) - - if refresh: - self.refreshShutdown(info) - - log.trace("XendDomainInfo.update done on domain %s: %s", - str(self.domid), self.info) - - def sxpr(self, ignore_store = False, legacy_only = True): - result = self.info.to_sxp(domain = self, - ignore_devices = ignore_store, - legacy_only = legacy_only) - - return result - - # Xen API - # ---------------------------------------------------------------- - - def get_uuid(self): - dom_uuid = self.info.get('uuid') - if not dom_uuid: # if it doesn't exist, make one up - dom_uuid = uuid.createString() - self.info['uuid'] = dom_uuid - return dom_uuid - - def get_memory_static_max(self): - return self.info.get('memory_static_max', 0) - def get_memory_static_min(self): - return self.info.get('memory_static_min', 0) - def get_memory_dynamic_max(self): - return self.info.get('memory_dynamic_max', 0) - def get_memory_dynamic_min(self): - return self.info.get('memory_dynamic_min', 0) - - # only update memory-related config values if they maintain sanity - def _safe_set_memory(self, key, newval): - oldval = self.info.get(key, 0) - try: - self.info[key] = newval - self.info._memory_sanity_check() - except Exception, ex: - self.info[key] = oldval - raise - - def set_memory_static_max(self, val): - self._safe_set_memory('memory_static_max', val) - def set_memory_static_min(self, val): - self._safe_set_memory('memory_static_min', val) - def set_memory_dynamic_max(self, val): - self._safe_set_memory('memory_dynamic_max', val) - def set_memory_dynamic_min(self, val): - self._safe_set_memory('memory_dynamic_min', val) - - def get_vcpus_params(self): - if self.getDomid() is None: - return self.info['vcpus_params'] - - retval = xc.sched_credit_domain_get(self.getDomid()) - return retval - def get_cpu_pool(self): - if self.getDomid() is None: - return None - xeninfo = dom_get(self.domid) - return xeninfo['cpupool'] - def get_power_state(self): - return XEN_API_VM_POWER_STATE[self._stateGet()] - def get_platform(self): - return self.info.get('platform', {}) - def get_pci_bus(self): - return self.info.get('pci_bus', '') - def get_tools_version(self): - return self.info.get('tools_version', {}) - def get_metrics(self): - return self.metrics.get_uuid(); - - - def get_security_label(self, xspol=None): - import xen.util.xsm.xsm as security - label = security.get_security_label(self, xspol) - return label - - def set_security_label(self, seclab, old_seclab, xspol=None, - xspol_old=None): - """ - Set the security label of a domain from its old to - a new value. - @param seclab New security label formatted in the form - :: - @param old_seclab The current security label that the - VM must have. - @param xspol An optional policy under which this - update should be done. If not given, - then the current active policy is used. - @param xspol_old The old policy; only to be passed during - the updating of a policy - @return Returns return code, a string with errors from - the hypervisor's operation, old label of the - domain - """ - rc = 0 - errors = "" - old_label = "" - new_ssidref = 0 - domid = self.getDomid() - res_labels = None - is_policy_update = (xspol_old != None) - - from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance - - state = self._stateGet() - # Relabel only HALTED or RUNNING or PAUSED domains - if domid != 0 and \ - state not in \ - [ DOM_STATE_HALTED, DOM_STATE_RUNNING, DOM_STATE_PAUSED, \ - DOM_STATE_SUSPENDED ]: - log.warn("Relabeling domain not possible in state '%s'" % - DOM_STATES[state]) - return (-xsconstants.XSERR_VM_WRONG_STATE, "", "", 0) - - # Remove security label. Works only for halted or suspended domains - if not seclab or seclab == "": - if state not in [ DOM_STATE_HALTED, DOM_STATE_SUSPENDED ]: - return (-xsconstants.XSERR_VM_WRONG_STATE, "", "", 0) - - if self.info.has_key('security_label'): - old_label = self.info['security_label'] - # Check label against expected one. - if old_label != old_seclab: - return (-xsconstants.XSERR_BAD_LABEL, "", "", 0) - del self.info['security_label'] - xen.xend.XendDomain.instance().managed_config_save(self) - return (xsconstants.XSERR_SUCCESS, "", "", 0) - - tmp = seclab.split(":") - if len(tmp) != 3: - return (-xsconstants.XSERR_BAD_LABEL_FORMAT, "", "", 0) - typ, policy, label = tmp - - poladmin = XSPolicyAdminInstance() - if not xspol: - xspol = poladmin.get_policy_by_name(policy) - - try: - xen.xend.XendDomain.instance().policy_lock.acquire_writer() - - if state in [ DOM_STATE_RUNNING, DOM_STATE_PAUSED ]: - #if domain is running or paused try to relabel in hypervisor - if not xspol: - return (-xsconstants.XSERR_POLICY_NOT_LOADED, "", "", 0) - - if typ != xspol.get_type_name() or \ - policy != xspol.get_name(): - return (-xsconstants.XSERR_BAD_LABEL, "", "", 0) - - if typ == xsconstants.ACM_POLICY_ID: - new_ssidref = xspol.vmlabel_to_ssidref(label) - if new_ssidref == xsconstants.INVALID_SSIDREF: - return (-xsconstants.XSERR_BAD_LABEL, "", "", 0) - - # Check that all used resources are accessible under the - # new label - if not is_policy_update and \ - not security.resources_compatible_with_vmlabel(xspol, - self, label): - return (-xsconstants.XSERR_BAD_LABEL, "", "", 0) - - #Check label against expected one. Can only do this - # if the policy hasn't changed underneath in the meantime - if xspol_old == None: - old_label = self.get_security_label() - if old_label != old_seclab: - log.info("old_label != old_seclab: %s != %s" % - (old_label, old_seclab)) - return (-xsconstants.XSERR_BAD_LABEL, "", "", 0) - - # relabel domain in the hypervisor - rc, errors = security.relabel_domains([[domid, new_ssidref]]) - log.info("rc from relabeling in HV: %d" % rc) - else: - return (-xsconstants.XSERR_POLICY_TYPE_UNSUPPORTED, "", "", 0) - - if rc == 0: - # HALTED, RUNNING or PAUSED - if domid == 0: - if xspol: - self.info['security_label'] = seclab - ssidref = poladmin.set_domain0_bootlabel(xspol, label) - else: - return (-xsconstants.XSERR_POLICY_NOT_LOADED, "", "", 0) - else: - if self.info.has_key('security_label'): - old_label = self.info['security_label'] - # Check label against expected one, unless wildcard - if old_label != old_seclab: - return (-xsconstants.XSERR_BAD_LABEL, "", "", 0) - - self.info['security_label'] = seclab - - try: - xen.xend.XendDomain.instance().managed_config_save(self) - except: - pass - return (rc, errors, old_label, new_ssidref) - finally: - xen.xend.XendDomain.instance().policy_lock.release() - - def get_on_shutdown(self): - after_shutdown = self.info.get('actions_after_shutdown') - if not after_shutdown or after_shutdown not in XEN_API_ON_NORMAL_EXIT: - return XEN_API_ON_NORMAL_EXIT[-1] - return after_shutdown - - def get_on_reboot(self): - after_reboot = self.info.get('actions_after_reboot') - if not after_reboot or after_reboot not in XEN_API_ON_NORMAL_EXIT: - return XEN_API_ON_NORMAL_EXIT[-1] - return after_reboot - - def get_on_suspend(self): - # TODO: not supported - after_suspend = self.info.get('actions_after_suspend') - if not after_suspend or after_suspend not in XEN_API_ON_NORMAL_EXIT: - return XEN_API_ON_NORMAL_EXIT[-1] - return after_suspend - - def get_on_crash(self): - after_crash = self.info.get('actions_after_crash') - if not after_crash or after_crash not in \ - XEN_API_ON_CRASH_BEHAVIOUR + restart_modes: - return XEN_API_ON_CRASH_BEHAVIOUR[0] - return XEN_API_ON_CRASH_BEHAVIOUR_FILTER[after_crash] - - def get_dev_config_by_uuid(self, dev_class, dev_uuid): - """ Get's a device configuration either from XendConfig or - from the DevController. - - @param dev_class: device class, either, 'vbd' or 'vif' - @param dev_uuid: device UUID - - @rtype: dictionary - """ - dev_type, dev_config = self.info['devices'].get(dev_uuid, (None, None)) - - # shortcut if the domain isn't started because - # the devcontrollers will have no better information - # than XendConfig. - if self._stateGet() in (XEN_API_VM_POWER_STATE_HALTED, - XEN_API_VM_POWER_STATE_SUSPENDED): - if dev_config: - return copy.deepcopy(dev_config) - return None - - # instead of using dev_class, we use the dev_type - # that is from XendConfig. - controller = self.getDeviceController(dev_type) - if not controller: - return None - - all_configs = controller.getAllDeviceConfigurations() - if not all_configs: - return None - - updated_dev_config = copy.deepcopy(dev_config) - for _devid, _devcfg in all_configs.items(): - if _devcfg.get('uuid') == dev_uuid: - updated_dev_config.update(_devcfg) - updated_dev_config['id'] = _devid - return updated_dev_config - - return updated_dev_config - - def get_dev_xenapi_config(self, dev_class, dev_uuid): - config = self.get_dev_config_by_uuid(dev_class, dev_uuid) - if not config: - return {} - - config['VM'] = self.get_uuid() - - if dev_class == 'vif': - if not config.has_key('name'): - config['name'] = config.get('vifname', '') - if not config.has_key('MAC'): - config['MAC'] = config.get('mac', '') - if not config.has_key('type'): - config['type'] = 'paravirtualised' - if not config.has_key('device'): - devid = config.get('id') - if devid != None: - config['device'] = 'eth%s' % devid - else: - config['device'] = '' - - if not config.has_key('network'): - try: - bridge = config.get('bridge', None) - if bridge is None: - from xen.util import Brctl - if_to_br = dict([(i,b) - for (b,ifs) in Brctl.get_state().items() - for i in ifs]) - vifname = "vif%s.%s" % (self.getDomid(), - config.get('id')) - bridge = if_to_br.get(vifname, None) - config['network'] = \ - XendNode.instance().bridge_to_network( - config.get('bridge')).get_uuid() - except Exception: - log.exception('bridge_to_network') - # Ignore this for now -- it may happen if the device - # has been specified using the legacy methods, but at - # some point we're going to have to figure out how to - # handle that properly. - - config['MTU'] = 1500 # TODO - - if self._stateGet() not in (XEN_API_VM_POWER_STATE_HALTED,): - xennode = XendNode.instance() - rx_bps, tx_bps = xennode.get_vif_util(self.domid, devid) - config['io_read_kbs'] = rx_bps/1024 - config['io_write_kbs'] = tx_bps/1024 - rx, tx = xennode.get_vif_stat(self.domid, devid) - config['io_total_read_kbs'] = rx/1024 - config['io_total_write_kbs'] = tx/1024 - else: - config['io_read_kbs'] = 0.0 - config['io_write_kbs'] = 0.0 - config['io_total_read_kbs'] = 0.0 - config['io_total_write_kbs'] = 0.0 - - config['security_label'] = config.get('security_label', '') - - if dev_class == 'vbd': - - if self._stateGet() not in (XEN_API_VM_POWER_STATE_HALTED,): - controller = self.getDeviceController(dev_class) - devid, _1, _2 = controller.getDeviceDetails(config) - xennode = XendNode.instance() - rd_blkps, wr_blkps = xennode.get_vbd_util(self.domid, devid) - config['io_read_kbs'] = rd_blkps - config['io_write_kbs'] = wr_blkps - else: - config['io_read_kbs'] = 0.0 - config['io_write_kbs'] = 0.0 - - config['VDI'] = config.get('VDI', '') - config['device'] = config.get('dev', '') - if config['device'].startswith('ioemu:'): - _, vbd_device = config['device'].split(':', 1) - config['device'] = vbd_device - if ':' in config['device']: - vbd_name, vbd_type = config['device'].split(':', 1) - config['device'] = vbd_name - if vbd_type == 'cdrom': - config['type'] = XEN_API_VBD_TYPE[0] - else: - config['type'] = XEN_API_VBD_TYPE[1] - - config['driver'] = 'paravirtualised' # TODO - config['image'] = config.get('uname', '') - - if config.get('mode', 'r') == 'r': - config['mode'] = 'RO' - else: - config['mode'] = 'RW' - - return config - - def get_dev_property(self, dev_class, dev_uuid, field): - config = self.get_dev_xenapi_config(dev_class, dev_uuid) - try: - return config[field] - except KeyError: - raise XendError('Invalid property for device: %s' % field) - - def set_dev_property(self, dev_class, dev_uuid, field, value): - self.info['devices'][dev_uuid][1][field] = value - - def get_vcpus_util(self): - vcpu_util = {} - xennode = XendNode.instance() - if 'VCPUs_max' in self.info and self.domid != None: - for i in range(0, self.info['VCPUs_max']): - util = xennode.get_vcpu_util(self.domid, i) - vcpu_util[str(i)] = util - - return vcpu_util - - def get_consoles(self): - return self.info.get('console_refs', []) - - def get_vifs(self): - return self.info.get('vif_refs', []) - - def get_vbds(self): - return self.info.get('vbd_refs', []) - - def get_dpcis(self): - return XendDPCI.get_by_VM(self.info.get('uuid')) - - def get_dscsis(self): - return XendDSCSI.get_by_VM(self.info.get('uuid')) - - def get_dscsi_HBAs(self): - return XendDSCSI_HBA.get_by_VM(self.info.get('uuid')) - - def create_vbd(self, xenapi_vbd, vdi_image_path): - """Create a VBD using a VDI from XendStorageRepository. - - @param xenapi_vbd: vbd struct from the Xen API - @param vdi_image_path: VDI UUID - @rtype: string - @return: uuid of the device - """ - xenapi_vbd['image'] = vdi_image_path - if vdi_image_path.startswith('tap'): - dev_uuid = self.info.device_add('tap2', cfg_xenapi = xenapi_vbd) - else: - dev_uuid = self.info.device_add('vbd', cfg_xenapi = xenapi_vbd) - - if not dev_uuid: - raise XendError('Failed to create device') - - if self._stateGet() in (XEN_API_VM_POWER_STATE_RUNNING, - XEN_API_VM_POWER_STATE_PAUSED): - _, config = self.info['devices'][dev_uuid] - - if vdi_image_path.startswith('tap'): - dev_control = self.getDeviceController('tap2') - else: - dev_control = self.getDeviceController('vbd') - - try: - devid = dev_control.createDevice(config) - dev_type = self.getBlockDeviceClass(devid) - self._waitForDevice(dev_type, devid) - self.info.device_update(dev_uuid, - cfg_xenapi = {'devid': devid}) - except Exception, exn: - log.exception(exn) - del self.info['devices'][dev_uuid] - self.info['vbd_refs'].remove(dev_uuid) - raise - - return dev_uuid - - def create_phantom_vbd_with_vdi(self, xenapi_vbd, vdi_image_path): - """Create a VBD using a VDI from XendStorageRepository. - - @param xenapi_vbd: vbd struct from the Xen API - @param vdi_image_path: VDI UUID - @rtype: string - @return: uuid of the device - """ - xenapi_vbd['image'] = vdi_image_path - dev_uuid = self.info.phantom_device_add('tap', cfg_xenapi = xenapi_vbd) - if not dev_uuid: - raise XendError('Failed to create device') - - if self._stateGet() == XEN_API_VM_POWER_STATE_RUNNING: - _, config = self.info['devices'][dev_uuid] - config['devid'] = self.getDeviceController('tap').createDevice(config) - - return config['devid'] - - def create_vif(self, xenapi_vif): - """Create VIF device from the passed struct in Xen API format. - - @param xenapi_vif: Xen API VIF Struct. - @rtype: string - @return: UUID - """ - dev_uuid = self.info.device_add('vif', cfg_xenapi = xenapi_vif) - if not dev_uuid: - raise XendError('Failed to create device') - - if self._stateGet() in (XEN_API_VM_POWER_STATE_RUNNING, - XEN_API_VM_POWER_STATE_PAUSED): - - _, config = self.info['devices'][dev_uuid] - dev_control = self.getDeviceController('vif') - - try: - devid = dev_control.createDevice(config) - dev_control.waitForDevice(devid) - self.info.device_update(dev_uuid, - cfg_xenapi = {'devid': devid}) - except Exception, exn: - log.exception(exn) - del self.info['devices'][dev_uuid] - self.info['vif_refs'].remove(dev_uuid) - raise - - return dev_uuid - - def create_console(self, xenapi_console): - """ Create a console device from a Xen API struct. - - @return: uuid of device - @rtype: string - """ - if self._stateGet() not in (DOM_STATE_HALTED,): - raise VmError("Can only add console to a halted domain.") - - dev_uuid = self.info.device_add('console', cfg_xenapi = xenapi_console) - if not dev_uuid: - raise XendError('Failed to create device') - - return dev_uuid - - def set_console_other_config(self, console_uuid, other_config): - self.info.console_update(console_uuid, 'other_config', other_config) - - def create_dpci(self, xenapi_pci): - """Create pci device from the passed struct in Xen API format. - - @param xenapi_pci: DPCI struct from Xen API - @rtype: bool - #@rtype: string - @return: True if successfully created device - #@return: UUID - """ - - dpci_uuid = uuid.createString() - - dpci_opts = [] - opts_dict = xenapi_pci.get('options') - for k in opts_dict.keys(): - dpci_opts.append([k, opts_dict[k]]) - opts_sxp = pci_opts_list_to_sxp(dpci_opts) - - # Convert xenapi to sxp - ppci = XendAPIStore.get(xenapi_pci.get('PPCI'), 'PPCI') - - dev_sxp = ['dev', - ['domain', '0x%02x' % ppci.get_domain()], - ['bus', '0x%02x' % ppci.get_bus()], - ['slot', '0x%02x' % ppci.get_slot()], - ['func', '0x%1x' % ppci.get_func()], - ['vdevfn', '0x%02x' % xenapi_pci.get('hotplug_slot')], - ['key', xenapi_pci['key']], - ['uuid', dpci_uuid]] - dev_sxp = sxp.merge(dev_sxp, opts_sxp) - - target_pci_sxp = ['pci', dev_sxp, ['state', 'Initialising'] ] - - if self._stateGet() != XEN_API_VM_POWER_STATE_RUNNING: - - old_pci_sxp = self._getDeviceInfo_pci(0) - - if old_pci_sxp is None: - dev_uuid = self.info.device_add('pci', cfg_sxp = target_pci_sxp) - if not dev_uuid: - raise XendError('Failed to create device') - - else: - new_pci_sxp = ['pci'] - for existing_dev in sxp.children(old_pci_sxp, 'dev'): - new_pci_sxp.append(existing_dev) - new_pci_sxp.append(sxp.child0(target_pci_sxp, 'dev')) - - dev_uuid = sxp.child_value(old_pci_sxp, 'uuid') - self.info.device_update(dev_uuid, new_pci_sxp) - - xen.xend.XendDomain.instance().managed_config_save(self) - - else: - try: - self.device_configure(target_pci_sxp) - - except Exception, exn: - raise XendError('Failed to create device') - - return dpci_uuid - - def create_dscsi(self, xenapi_dscsi): - """Create scsi device from the passed struct in Xen API format. - - @param xenapi_dscsi: DSCSI struct from Xen API - @rtype: string - @return: UUID - """ - - dscsi_uuid = uuid.createString() - - # Convert xenapi to sxp - pscsi = XendAPIStore.get(xenapi_dscsi.get('PSCSI'), 'PSCSI') - devid = int(xenapi_dscsi.get('virtual_HCTL').split(':')[0]) - target_vscsi_sxp = \ - ['vscsi', - ['dev', - ['devid', devid], - ['p-devname', pscsi.get_dev_name()], - ['p-dev', pscsi.get_physical_HCTL()], - ['v-dev', xenapi_dscsi.get('virtual_HCTL')], - ['state', xenbusState['Initialising']], - ['uuid', dscsi_uuid] - ], - ['feature-host', 0] - ] - - if self._stateGet() != XEN_API_VM_POWER_STATE_RUNNING: - - cur_vscsi_sxp = self._getDeviceInfo_vscsi(devid) - - if cur_vscsi_sxp is None: - dev_uuid = self.info.device_add('vscsi', cfg_sxp = target_vscsi_sxp) - if not dev_uuid: - raise XendError('Failed to create device') - - else: - new_vscsi_sxp = ['vscsi', ['feature-host', 0]] - for existing_dev in sxp.children(cur_vscsi_sxp, 'dev'): - new_vscsi_sxp.append(existing_dev) - new_vscsi_sxp.append(sxp.child0(target_vscsi_sxp, 'dev')) - - dev_uuid = sxp.child_value(cur_vscsi_sxp, 'uuid') - self.info.device_update(dev_uuid, new_vscsi_sxp) - - xen.xend.XendDomain.instance().managed_config_save(self) - - else: - try: - self.device_configure(target_vscsi_sxp) - except Exception, exn: - log.exception('create_dscsi: %s', exn) - raise XendError('Failed to create device') - - return dscsi_uuid - - def create_dscsi_HBA(self, xenapi_dscsi): - """Create scsi devices from the passed struct in Xen API format. - - @param xenapi_dscsi: DSCSI_HBA struct from Xen API - @rtype: string - @return: UUID - """ - - dscsi_HBA_uuid = uuid.createString() - - # Convert xenapi to sxp - feature_host = xenapi_dscsi.get('assignment_mode', 'HOST') == 'HOST' and 1 or 0 - target_vscsi_sxp = \ - ['vscsi', - ['feature-host', feature_host], - ['uuid', dscsi_HBA_uuid], - ] - pscsi_HBA = XendAPIStore.get(xenapi_dscsi.get('PSCSI_HBA'), 'PSCSI_HBA') - devid = pscsi_HBA.get_physical_host() - for pscsi_uuid in pscsi_HBA.get_PSCSIs(): - pscsi = XendAPIStore.get(pscsi_uuid, 'PSCSI') - pscsi_HCTL = pscsi.get_physical_HCTL() - dscsi_uuid = uuid.createString() - dev = \ - ['dev', - ['devid', devid], - ['p-devname', pscsi.get_dev_name()], - ['p-dev', pscsi_HCTL], - ['v-dev', pscsi_HCTL], - ['state', xenbusState['Initialising']], - ['uuid', dscsi_uuid] - ] - target_vscsi_sxp.append(dev) - - if self._stateGet() != XEN_API_VM_POWER_STATE_RUNNING: - if not self.info.device_add('vscsi', cfg_sxp = target_vscsi_sxp): - raise XendError('Failed to create device') - xen.xend.XendDomain.instance().managed_config_save(self) - else: - try: - self.device_configure(target_vscsi_sxp) - except Exception, exn: - log.exception('create_dscsi_HBA: %s', exn) - raise XendError('Failed to create device') - - return dscsi_HBA_uuid - - - def change_vdi_of_vbd(self, xenapi_vbd, vdi_image_path): - """Change current VDI with the new VDI. - - @param xenapi_vbd: vbd struct from the Xen API - @param vdi_image_path: path of VDI - """ - dev_uuid = xenapi_vbd['uuid'] - if dev_uuid not in self.info['devices']: - raise XendError('Device does not exist') - - # Convert xenapi to sxp - if vdi_image_path.startswith('tap'): - dev_class = 'tap' - else: - dev_class = 'vbd' - dev_sxp = [ - dev_class, - ['uuid', dev_uuid], - ['uname', vdi_image_path], - ['dev', '%s:cdrom' % xenapi_vbd['device']], - ['mode', 'r'], - ['VDI', xenapi_vbd['VDI']] - ] - - if self._stateGet() in (XEN_API_VM_POWER_STATE_RUNNING, - XEN_API_VM_POWER_STATE_PAUSED): - self.device_configure(dev_sxp) - else: - self.info.device_update(dev_uuid, dev_sxp) - - - def destroy_device_by_uuid(self, dev_type, dev_uuid): - if dev_uuid not in self.info['devices']: - raise XendError('Device does not exist') - - try: - if self._stateGet() in (XEN_API_VM_POWER_STATE_RUNNING, - XEN_API_VM_POWER_STATE_PAUSED): - _, config = self.info['devices'][dev_uuid] - devid = config.get('devid') - if devid != None: - self.getDeviceController(dev_type).destroyDevice(devid, force = False) - else: - raise XendError('Unable to get devid for device: %s:%s' % - (dev_type, dev_uuid)) - finally: - del self.info['devices'][dev_uuid] - self.info['%s_refs' % dev_type].remove(dev_uuid) - - def destroy_vbd(self, dev_uuid): - self.destroy_device_by_uuid('vbd', dev_uuid) - - def destroy_vif(self, dev_uuid): - self.destroy_device_by_uuid('vif', dev_uuid) - - def destroy_dpci(self, dev_uuid): - - dpci = XendAPIStore.get(dev_uuid, 'DPCI') - ppci = XendAPIStore.get(dpci.get_PPCI(), 'PPCI') - - old_pci_sxp = self._getDeviceInfo_pci(0) - dev_uuid = sxp.child_value(old_pci_sxp, 'uuid') - target_dev = None - new_pci_sxp = ['pci'] - for dev in sxp.children(old_pci_sxp, 'dev'): - pci_dev = {} - pci_dev['domain'] = sxp.child_value(dev, 'domain') - pci_dev['bus'] = sxp.child_value(dev, 'bus') - pci_dev['slot'] = sxp.child_value(dev, 'slot') - pci_dev['func'] = sxp.child_value(dev, 'func') - if ppci.get_name() == pci_dict_to_bdf_str(pci_dev): - target_dev = dev - else: - new_pci_sxp.append(dev) - - if target_dev is None: - raise XendError('Failed to destroy device') - - target_pci_sxp = ['pci', target_dev, ['state', 'Closing']] - - if self._stateGet() != XEN_API_VM_POWER_STATE_RUNNING: - - self.info.device_update(dev_uuid, new_pci_sxp) - if len(sxp.children(new_pci_sxp, 'dev')) == 0: - del self.info['devices'][dev_uuid] - xen.xend.XendDomain.instance().managed_config_save(self) - - else: - try: - self.device_configure(target_pci_sxp) - - except Exception, exn: - raise XendError('Failed to destroy device') - - def destroy_dscsi(self, dev_uuid): - dscsi = XendAPIStore.get(dev_uuid, 'DSCSI') - devid = dscsi.get_virtual_host() - vHCTL = dscsi.get_virtual_HCTL() - cur_vscsi_sxp = self._getDeviceInfo_vscsi(devid) - dev_uuid = sxp.child_value(cur_vscsi_sxp, 'uuid') - - target_dev = None - new_vscsi_sxp = ['vscsi', ['feature-host', 0]] - for dev in sxp.children(cur_vscsi_sxp, 'dev'): - if vHCTL == sxp.child_value(dev, 'v-dev'): - target_dev = dev - else: - new_vscsi_sxp.append(dev) - - if target_dev is None: - raise XendError('Failed to destroy device') - - target_dev.append(['state', xenbusState['Closing']]) - target_vscsi_sxp = ['vscsi', target_dev, ['feature-host', 0]] - - if self._stateGet() != XEN_API_VM_POWER_STATE_RUNNING: - - self.info.device_update(dev_uuid, new_vscsi_sxp) - if len(sxp.children(new_vscsi_sxp, 'dev')) == 0: - del self.info['devices'][dev_uuid] - xen.xend.XendDomain.instance().managed_config_save(self) - - else: - try: - self.device_configure(target_vscsi_sxp) - except Exception, exn: - log.exception('destroy_dscsi: %s', exn) - raise XendError('Failed to destroy device') - - def destroy_dscsi_HBA(self, dev_uuid): - dscsi_HBA = XendAPIStore.get(dev_uuid, 'DSCSI_HBA') - devid = dscsi_HBA.get_virtual_host() - cur_vscsi_sxp = self._getDeviceInfo_vscsi(devid) - feature_host = sxp.child_value(cur_vscsi_sxp, 'feature-host') - - if self._stateGet() != XEN_API_VM_POWER_STATE_RUNNING: - new_vscsi_sxp = ['vscsi', ['feature-host', feature_host]] - self.info.device_update(dev_uuid, new_vscsi_sxp) - del self.info['devices'][dev_uuid] - xen.xend.XendDomain.instance().managed_config_save(self) - else: - # If feature_host is 1, all devices are destroyed by just - # one reconfiguration. - # If feature_host is 0, we should reconfigure all devices - # one-by-one to destroy all devices. - # See reconfigureDevice@VSCSIController. - for dev in sxp.children(cur_vscsi_sxp, 'dev'): - target_vscsi_sxp = [ - 'vscsi', - dev + [['state', xenbusState['Closing']]], - ['feature-host', feature_host] - ] - try: - self.device_configure(target_vscsi_sxp) - except Exception, exn: - log.exception('destroy_dscsi_HBA: %s', exn) - raise XendError('Failed to destroy device') - if feature_host: - break - - def destroy_xapi_instances(self): - """Destroy Xen-API instances stored in XendAPIStore. - """ - # Xen-API classes based on XendBase have their instances stored - # in XendAPIStore. Cleanup these instances here, if they are supposed - # to be destroyed when the parent domain is dead. - # - # Most of the virtual devices (vif, vbd, vfb, etc) are not based on - # XendBase and there's no need to remove them from XendAPIStore. - - from xen.xend import XendDomain - if XendDomain.instance().is_valid_vm(self.info.get('uuid')): - # domain still exists. - return - - # Destroy the VMMetrics instance. - if XendAPIStore.get(self.metrics.get_uuid(), self.metrics.getClass()) \ - is not None: - self.metrics.destroy() - - # Destroy DPCI instances. - for dpci_uuid in XendDPCI.get_by_VM(self.info.get('uuid')): - XendAPIStore.deregister(dpci_uuid, "DPCI") - - # Destroy DSCSI instances. - for dscsi_uuid in XendDSCSI.get_by_VM(self.info.get('uuid')): - XendAPIStore.deregister(dscsi_uuid, "DSCSI") - - # Destroy DSCSI_HBA instances. - for dscsi_HBA_uuid in XendDSCSI_HBA.get_by_VM(self.info.get('uuid')): - XendAPIStore.deregister(dscsi_HBA_uuid, "DSCSI_HBA") - - def has_device(self, dev_class, dev_uuid): - return (dev_uuid in self.info['%s_refs' % dev_class.lower()]) - - def __str__(self): - return '' % \ - (str(self.domid), self.info['name_label'], - str(self.info['memory_dynamic_max']), DOM_STATES[self._stateGet()]) - - __repr__ = __str__ - diff --git a/tools/python/xen/xend/XendError.py b/tools/python/xen/xend/XendError.py deleted file mode 100644 index d7ec42daf3..0000000000 --- a/tools/python/xen/xend/XendError.py +++ /dev/null @@ -1,252 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (c) 2006, 2007 XenSource Inc. -#============================================================================ - -from xmlrpclib import Fault - -import types -import XendClient - -class XendInvalidDomain(Fault): - def __init__(self, value): - Fault.__init__(self, XendClient.ERROR_INVALID_DOMAIN, value) - -class XendError(Fault): - - def __init__(self, value): - Fault.__init__(self, XendClient.ERROR_GENERIC, value) - self.value = value - - def __str__(self): - return self.value - -class VMBadState(XendError): - def __init__(self, value, expected, actual): - XendError.__init__(self, value) - self.expected = expected - self.actual = actual - -class NetworkAlreadyConnected(XendError): - def __init__(self, pif_uuid): - XendError.__init__(self, 'Network already connected') - self.pif_uuid = pif_uuid - -class PIFIsPhysical(XendError): - def __init__(self): - XendError.__init__(self, 'PIF is physical') - -class VmError(XendError): - """Vm construction error.""" - pass - -class HVMRequired(VmError): - def __init__(self): - XendError.__init__(self, - 'HVM guest support is unavailable: is VT/AMD-V ' - 'supported by your CPU and enabled in your BIOS?') - -class XendAPIError(XendError): - """Extend this class for all error thrown by - autoplugged classes""" - def __init__(self): - XendError.__init__(self, 'XendAPI Error: You should never see this' - ' message; this class need to be overidden') - - def get_api_error(self): - return ['INTERNAL_ERROR', 'You should never see this message; ' - 'this method needs to be overidden'] - -class CreateUnspecifiedAttributeError(XendAPIError): - def __init__(self, attr_name, class_name): - XendAPIError.__init__(self) - self.attr_name = attr_name - self.class_name = class_name - - def get_api_error(self): - return ['CREATE_UNSPECIFIED_ATTRIBUTE', self.attr_name, - self.class_name] - - def __str__(self): - return "CREATE_UNSPECIFIED_ATTRIBUTE: %s, %s" % (self.attr_name, - self.class_name) - -class UnmanagedNetworkError(XendAPIError): - def __init__(self, attr_name): - XendAPIError.__init__(self) - self.attr_name = attr_name - - def get_api_error(self): - return ['UNMANAGED_NETWORK_ERROR', self.attr_name] - - def __str__(self): - return "UNMANAGED_NETWORK_ERROR: %s" % self.attr_name - -class UniqueNameError(XendAPIError): - def __init__(self, name, class_name): - XendAPIError.__init__(self) - self.name = name - self.class_name = class_name - - def get_api_error(self): - return ['UNIQUE_NAME_ERROR', self.name, self.class_name] - - def __str__(self): - return 'UNIQUE_NAME_ERROR: %s, %s' % (self.name, self.class_name) - -class InvalidDeviceError(XendAPIError): - def __init__(self, dev): - XendAPIError.__init__(self) - self.dev = dev - - def get_api_error(self): - return ['INVALID_DEVICE_ERROR', self.dev] - - def __str__(self): - return 'INVALID_DEVICE_ERROR: %s' % self.dev - -class DeviceExistsError(XendAPIError): - def __init__(self, dev): - XendAPIError.__init__(self) - self.dev = dev - - def get_api_error(self): - return ['DEVICE_EXISTS_ERROR', self.dev] - - def __str__(self): - return 'DEVICE_EXISTS_ERROR: %s' % self.dev - -class InvalidHandleError(XendAPIError): - def __init__(self, klass, handle): - XendAPIError.__init__(self) - self.klass = klass - self.handle = handle - - def get_api_error(self): - return ['HANDLE_INVALID', self.klass, self.handle] - - def __str__(self): - return 'HANDLE_INVALID: %s %s' % (self.klass, self.handle) - -class ImplementationError(XendAPIError): - def __init__(self, klass, func): - XendAPIError.__init__(self) - self.klass = klass - self.func = func - - def get_api_error(self): - return ['IMPLEMENTATION_ERROR', self.klass, self.func] - - def __str__(self): - return 'IMPLEMENTATION_ERROR: %s %s' % (self.klass, self.func) - -class VLANTagInvalid(XendAPIError): - def __init__(self, vlan): - XendAPIError.__init__(self) - self.vlan = vlan - - def get_api_error(self): - return ['VLAN_TAG_INVALID', self.vlan] - - def __str__(self): - return 'VLAN_TAG_INVALID: %s' % self.vlan - -class NetworkError(XendAPIError): - def __init__(self, error, network): - XendAPIError.__init__(self) - self.network = network - self.error = error - - def get_api_error(self): - return ['NETWORK_ERROR', self.error, self.network] - - def __str__(self): - return 'NETWORK_ERROR: %s %s' % (self.error, self.network) - -class DirectPCIError(XendAPIError): - def __init__(self, error): - XendAPIError.__init__(self) - self.error = error - - def get_api_error(self): - return ['DIRECT_PCI_ERROR', self.error] - - def __str__(self): - return 'DIRECT_PCI_ERROR: %s' % self.error - -class PoolError(XendAPIError): - def __init__(self, error, spec=None): - XendAPIError.__init__(self) - self.spec = [] - if spec: - if isinstance(spec, types.ListType): - self.spec = spec - else: - self.spec = [spec] - self.error = error - - def get_api_error(self): - return [self.error] + self.spec - - def __str__(self): - if self.spec: - return '%s: %s' % (self.error, self.spec) - else: - return '%s' % self.error - -class VDIError(XendAPIError): - def __init__(self, error, vdi): - XendAPIError.__init__(self) - self.vdi = vdi - self.error = error - - def get_api_error(self): - return ['VDI_ERROR', self.error, self.vdi] - - def __str__(self): - return 'VDI_ERROR: %s %s' % (self.error, self.vdi) - -from xen.util.xsconstants import xserr2string - -class SecurityError(XendAPIError): - def __init__(self, error, message=None): - XendAPIError.__init__(self) - self.error = error - if not message: - self.message = xserr2string(-error) - else: - self.message = message - - def get_api_error(self): - return ['SECURITY_ERROR', self.error, self.message] - - def __str__(self): - return 'SECURITY_ERROR: %s:%s' % (self.error, self.message) - -XEND_ERROR_AUTHENTICATION_FAILED = ('ELUSER', 'Authentication Failed') -XEND_ERROR_SESSION_INVALID = ('EPERMDENIED', 'Session Invalid') -XEND_ERROR_DOMAIN_INVALID = ('EINVALIDDOMAIN', 'Domain Invalid') -XEND_ERROR_HOST_INVALID = ('EINVALIDHOST', 'Host Invalid') -XEND_ERROR_HOST_RUNNING = ('EHOSTRUNNING', 'Host is still Running') -XEND_ERROR_HOST_CPU_INVALID = ('EHOSTCPUINVALID', 'Host CPU Invalid') -XEND_ERROR_UNSUPPORTED = ('EUNSUPPORTED', 'Method Unsupported') -XEND_ERROR_VM_INVALID = ('EVMINVALID', 'VM Invalid') -XEND_ERROR_VBD_INVALID = ('EVBDINVALID', 'VBD Invalid') -XEND_ERROR_VIF_INVALID = ('EVIFINVALID', 'VIF Invalid') -XEND_ERROR_VDI_INVALID = ('EVDIINVALID', 'VDI Invalid') -XEND_ERROR_SR_INVALID = ('ESRINVALID', 'SR Invalid') -XEND_ERROR_XSPOLICY_INVALID = ('EXSPOLICYINVALID', 'XS Invalid') -XEND_ERROR_TODO = ('ETODO', 'Lazy Programmer Error') diff --git a/tools/python/xen/xend/XendLocalStorageRepo.py b/tools/python/xen/xend/XendLocalStorageRepo.py deleted file mode 100644 index 31b86f667b..0000000000 --- a/tools/python/xen/xend/XendLocalStorageRepo.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/python -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2007 XenSource Ltd. -#============================================================================ -# -# A pseudo-StorageRepository to provide a representation for the images -# that can be specified by xm. -# - -import commands -import logging -import os -import stat -import threading -import re -import sys -import struct - -from xen.util import mkdir -import uuid -from XendError import XendError -from XendVDI import * -from XendTask import XendTask -from XendStorageRepository import XendStorageRepository -from XendStateStore import XendStateStore -from XendOptions import instance as xendoptions - -MB = 1024 * 1024 - -log = logging.getLogger("xend.XendLocalStorageRepo") - -class XendLocalStorageRepo(XendStorageRepository): - """A backwards compatibility storage repository so that - traditional file:/dir/file.img and phy:/dev/hdxx images can - still be represented in terms of the Xen API. - """ - - def __init__(self, sr_uuid, sr_type = 'local', - name_label = 'Local', - name_description = 'Traditional Local Storage Repo'): - """ - @ivar images: mapping of all the images. - @type images: dictionary by image uuid. - @ivar lock: lock to provide thread safety. - """ - - XendStorageRepository.__init__(self, sr_uuid, sr_type, - name_label, name_description) - - self.state = XendStateStore(xendoptions().get_xend_state_path() - + '/local_sr') - - stored_images = self.state.load_state('vdi') - if stored_images: - for image_uuid, image in stored_images.items(): - self.images[image_uuid] = XendLocalVDI(image) - - def create_vdi(self, vdi_struct): - """ Creates a fake VDI image for a traditional image string. - - The image uri is stored in the attribute 'uri' - """ - vdi_struct['uuid'] = uuid.createString() - vdi_struct['SR'] = self.uuid - new_image = XendLocalVDI(vdi_struct) - self.images[new_image.uuid] = new_image - self.save_state() - return new_image.uuid - - def save_state(self): - vdi_records = dict([(k, v.get_record(transient = False)) - for k, v in self.images.items()]) - self.state.save_state('vdi', vdi_records) - - def destroy_vdi(self, vdi_uuid): - if vdi_uuid in self.images: - del self.images[vdi_uuid] - - self.save_state() - diff --git a/tools/python/xen/xend/XendLogging.py b/tools/python/xen/xend/XendLogging.py deleted file mode 100644 index d95133b2c8..0000000000 --- a/tools/python/xen/xend/XendLogging.py +++ /dev/null @@ -1,149 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2005, 2006 XenSource Ltd. -#============================================================================ - -import inspect -import os -import os.path -import sys -import stat -import tempfile -import types -import logging -import logging.handlers - -from xen.util import mkdir -from xen.xend.server import params -from xen.util import oshelp - - -__all__ = [ 'log', 'init', 'getLogFilename' ] - - -if 'TRACE' not in logging.__dict__: - logging.TRACE = logging.DEBUG - 1 - logging.addLevelName(logging.TRACE,'TRACE') - def trace(self, *args, **kwargs): - self.log(logging.TRACE, *args, **kwargs) - logging.Logger.trace = trace - - def findCaller(self): - """ - Override logging.Logger.findCaller so that the above trace function - does not appear as the source of log messages. The signature of this - function changed between Python 2.3 and 2.4. - """ - frames = inspect.stack() - thisfile = os.path.normcase(frames[0][1]) - for frame in frames: - filename = os.path.normcase(frame[1]) - if filename != thisfile and filename != logging._srcfile: - major, minor, micro, _, _ = sys.version_info - if (major, minor, micro) >= (2, 4, 2): - return filename, frame[2], frame[3] - else: - return filename, frame[2] - logging.Logger.findCaller = findCaller - - # Work around a bug in Python's inspect module: findsource is supposed to - # raise IOError if it fails, with other functions in that module coping - # with that, but some people are seeing IndexError raised from there. - # This is Python bug 1628987. http://python.org/sf/1628987. - if hasattr(inspect, 'findsource'): - real_findsource = getattr(inspect, 'findsource') - def findsource(*args, **kwargs): - try: - return real_findsource(*args, **kwargs) - except IndexError, exn: - raise IOError(exn) - inspect.findsource = findsource - - -log = logging.getLogger("xend") - - -MAX_BYTES = 1 << 20 # 1MB -BACKUP_COUNT = 5 - -STDERR_FORMAT = "[%(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s" -LOGFILE_FORMAT = "[%(asctime)s %(process)d] %(levelname)s (%(module)s:%(lineno)d) %(message)s" -DATE_FORMAT = "%Y-%m-%d %H:%M:%S" - - -logfilename = None - -class XendRotatingFileHandler(logging.handlers.RotatingFileHandler): - - def __init__(self, fname, mode, maxBytes, backupCount): - logging.handlers.RotatingFileHandler.__init__(self, fname, mode, maxBytes, backupCount) - self.setCloseOnExec() - - def doRollover(self): - logging.handlers.RotatingFileHandler.doRollover(self) - self.setCloseOnExec() - - # NB yes accessing 'self.stream' violates OO encapsulation somewhat, - # but python logging API gives no other way to access the file handle - # and the entire python logging stack is already full of OO encapsulation - # violations. The other alternative is copy-and-paste duplicating the - # entire FileHandler, StreamHandler & RotatingFileHandler classes which - # is even worse - def setCloseOnExec(self): - oshelp.fcntl_setfd_cloexec(self.stream, True) - - -def init(filename, level): - """Initialise logging. Logs to the given filename, and logs to stderr if - XEND_DEBUG is set. - """ - - global logfilename - - def openFileHandler(fname): - mkdir.parents(os.path.dirname(fname), stat.S_IRWXU) - return XendRotatingFileHandler(fname, mode = 'a', - maxBytes = MAX_BYTES, - backupCount = BACKUP_COUNT) - - # Rather unintuitively, getLevelName will get the number corresponding to - # a level name, as well as getting the name corresponding to a level - # number. setLevel seems to take the number only though, so convert if we - # are given a string. - if isinstance(level, types.StringType): - level = logging.getLevelName(level) - - log.setLevel(level) - - try: - fileHandler = openFileHandler(filename) - logfilename = filename - except IOError: - logfilename = tempfile.mkstemp("-xend.log")[1] - fileHandler = openFileHandler(logfilename) - - fileHandler.setFormatter(logging.Formatter(LOGFILE_FORMAT, DATE_FORMAT)) - log.addHandler(fileHandler) - - if params.XEND_DEBUG: - stderrHandler = logging.StreamHandler() - stderrHandler.setFormatter(logging.Formatter(STDERR_FORMAT, - DATE_FORMAT)) - log.addHandler(stderrHandler) - - -def getLogFilename(): - return logfilename diff --git a/tools/python/xen/xend/XendMonitor.py b/tools/python/xen/xend/XendMonitor.py deleted file mode 100644 index 83fcb182d3..0000000000 --- a/tools/python/xen/xend/XendMonitor.py +++ /dev/null @@ -1,340 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2007 XenSource Ltd. -#============================================================================ - -from xen.lowlevel.xc import xc -import time -import threading -import os -import re - -"""Monitoring thread to keep track of Xend statistics. """ - -VBD_SYSFS_PATH = '/sys/devices/xen-backend/' -VBD_WR_PATH = VBD_SYSFS_PATH + '%s/statistics/wr_sect' -VBD_RD_PATH = VBD_SYSFS_PATH + '%s/statistics/rd_sect' -VBD_DOMAIN_RE = r'vbd-(?P\d+)-(?P\d+)$' - -NET_PROCFS_PATH = '/proc/net/dev' -PROC_NET_DEV_RE = r'(?P\d+)\s+' \ - r'(?P\d+)\s+' \ - r'(?P\d+)\s+' \ - r'(?P\d+)\s+' \ - r'(?P\d+)\s+' \ - r'(?P\d+)\s+' \ - r'(?P\d+)\s+' \ - r'(?P\d+)\s+' \ - r'(?P\d+)\s+' \ - r'(?P\d+)\s+' \ - r'(?P\d+)\s+' \ - r'(?P\d+)\s+' \ - r'(?P\d+)\s+' \ - r'(?P\d+)\s+' \ - r'(?P\d+)\s+' \ - r'(?P\d+)\s*$' - - -VIF_DOMAIN_RE = re.compile(r'vif(?P\d+)\.(?P\d+):\s*' + - PROC_NET_DEV_RE) -PIF_RE = re.compile(r'^\s*(?Ppeth\d+):\s*' + PROC_NET_DEV_RE) - -# Interval to poll xc, sysfs and proc -POLL_INTERVAL = 2.0 -SECTOR_SIZE = 512 -class XendMonitor(threading.Thread): - """Monitors VCPU, VBD, VIF and PIF statistics for Xen API. - - Polls sysfs and procfs for statistics on VBDs and VIFs respectively. - - @ivar domain_vcpus_util: Utilisation for VCPUs indexed by domain - @type domain_vcpus_util: {domid: {vcpuid: float, vcpuid: float}} - @ivar domain_vifs_util: Bytes per second for VIFs indexed by domain - @type domain_vifs_util: {domid: {vifid: (rx_bps, tx_bps)}} - @ivar domain_vifs_stat: Total amount of bytes used for VIFs indexed by domain - @type domain_vifs_stat: {domid: {vbdid: (rx, tx)}} - @ivar domain_vbds_util: Blocks per second for VBDs index by domain. - @type domain_vbds_util: {domid: {vbdid: (rd_reqps, wr_reqps)}} - - """ - def __init__(self): - threading.Thread.__init__(self) - self.setDaemon(True) - self.xc = xc() - - self.lock = threading.Lock() - - # tracks the last polled statistics - self._domain_vcpus = {} - self._domain_vifs = {} - self._domain_vbds = {} - self.pifs = {} - - # instantaneous statistics - self._domain_vcpus_util = {} - self._domain_vifs_util = {} - self._domain_vifs_stat = {} - self._domain_vbds_util = {} - self.pifs_util = {} - - def get_domain_vcpus_util(self): - self.lock.acquire() - try: - return self._domain_vcpus_util - finally: - self.lock.release() - - def get_domain_vbds_util(self): - self.lock.acquire() - try: - return self._domain_vbds_util - finally: - self.lock.release() - - def get_domain_vifs_util(self): - self.lock.acquire() - try: - return self._domain_vifs_util - finally: - self.lock.release() - - def get_domain_vifs_stat(self): - self.lock.acquire() - try: - return self._domain_vifs_stat - finally: - self.lock.release() - - def get_pifs_util(self): - self.lock.acquire() - try: - return self.pifs_util - finally: - self.lock.release() - - def _get_vif_stats(self): - stats = {} - - if not os.path.exists(NET_PROCFS_PATH): - return stats - - usage_at = time.time() - for line in open(NET_PROCFS_PATH): - is_vif = re.search(VIF_DOMAIN_RE, line.strip()) - if not is_vif: - continue - - domid = int(is_vif.group('domid')) - vifid = int(is_vif.group('iface')) - rx_bytes = int(is_vif.group('rx_bytes')) - tx_bytes = int(is_vif.group('tx_bytes')) - if not domid in stats: - stats[domid] = {} - - stats[domid][vifid] = (usage_at, rx_bytes, tx_bytes) - - return stats - - def _get_pif_stats(self): - stats = {} - - if not os.path.exists(NET_PROCFS_PATH): - return stats - - usage_at = time.time() - for line in open(NET_PROCFS_PATH): - is_pif = re.search(PIF_RE, line.strip()) - if not is_pif: - continue - - pifname = is_pif.group('iface') - rx_bytes = int(is_pif.group('rx_bytes')) - tx_bytes = int(is_pif.group('tx_bytes')) - stats[pifname] = (usage_at, rx_bytes, tx_bytes) - - return stats - - def _get_vbd_stats(self): - stats = {} - - if not os.path.exists(VBD_SYSFS_PATH): - return stats - - for vbd_path in os.listdir(VBD_SYSFS_PATH): - is_vbd = re.search(VBD_DOMAIN_RE, vbd_path) - if not is_vbd: - continue - - domid = int(is_vbd.group('domid')) - vbdid = int(is_vbd.group('devid')) - rd_stat_path = VBD_RD_PATH % vbd_path - wr_stat_path = VBD_WR_PATH % vbd_path - - if not os.path.exists(rd_stat_path) or \ - not os.path.exists(wr_stat_path): - continue - - - try: - usage_at = time.time() - rd_stat = int(open(rd_stat_path).readline().strip()) - wr_stat = int(open(wr_stat_path).readline().strip()) - rd_stat *= SECTOR_SIZE - wr_stat *= SECTOR_SIZE - if domid not in stats: - stats[domid] = {} - - stats[domid][vbdid] = (usage_at, rd_stat, wr_stat) - - except (IOError, ValueError): - continue - - return stats - - def _get_cpu_stats(self): - stats = {} - for domain in self.xc.domain_getinfo(): - domid = domain['domid'] - vcpu_count = domain['online_vcpus'] - stats[domid] = {} - for i in range(vcpu_count): - vcpu_info = self.xc.vcpu_getinfo(domid, i) - usage = vcpu_info['cpu_time'] - usage_at = time.time() - stats[domid][i] = (usage_at, usage) - - return stats - - - def run(self): - - # loop every second for stats - while True: - self.lock.acquire() - try: - active_domids = [] - # Calculate utilisation for VCPUs - - for domid, cputimes in self._get_cpu_stats().items(): - active_domids.append(domid) - if domid not in self._domain_vcpus: - # if not initialised, save current stats - # and skip utilisation calculation - self._domain_vcpus[domid] = cputimes - self._domain_vcpus_util[domid] = {} - continue - - for vcpu, (usage_at, usage) in cputimes.items(): - if vcpu not in self._domain_vcpus[domid]: - continue - - prv_usage_at, prv_usage = \ - self._domain_vcpus[domid][vcpu] - interval_s = (usage_at - prv_usage_at) * 1000000000 - if interval_s > 0: - util = (usage - prv_usage) / interval_s - self._domain_vcpus_util[domid][vcpu] = util - - self._domain_vcpus[domid] = cputimes - - # Calculate utilisation for VBDs - - for domid, vbds in self._get_vbd_stats().items(): - if domid not in self._domain_vbds: - self._domain_vbds[domid] = vbds - self._domain_vbds_util[domid] = {} - continue - - for devid, (usage_at, rd, wr) in vbds.items(): - if devid not in self._domain_vbds[domid]: - continue - - prv_at, prv_rd, prv_wr = \ - self._domain_vbds[domid][devid] - interval = usage_at - prv_at - rd_util = (rd - prv_rd)/interval - wr_util = (wr - prv_wr)/interval - self._domain_vbds_util[domid][devid] = \ - (rd_util, wr_util) - - self._domain_vbds[domid] = vbds - - - # Calculate utilisation for VIFs - - for domid, vifs in self._get_vif_stats().items(): - - if domid not in self._domain_vifs: - self._domain_vifs[domid] = vifs - self._domain_vifs_util[domid] = {} - self._domain_vifs_stat[domid] = {} - continue - - for devid, (usage_at, rx, tx) in vifs.items(): - if devid not in self._domain_vifs[domid]: - continue - - prv_at, prv_rx, prv_tx = \ - self._domain_vifs[domid][devid] - interval = usage_at - prv_at - rx_util = (rx - prv_rx)/interval - tx_util = (tx - prv_tx)/interval - - # note these are flipped around because - # we are measuring the host interface, - # not the guest interface - self._domain_vifs_util[domid][devid] = \ - (tx_util, rx_util) - self._domain_vifs_stat[domid][devid] = \ - (float(tx), float(rx)) - - self._domain_vifs[domid] = vifs - - # Calculate utilisation for PIFs - - for pifname, stats in self._get_pif_stats().items(): - if pifname not in self.pifs: - self.pifs[pifname] = stats - continue - - usage_at, rx, tx = stats - prv_at, prv_rx, prv_tx = self.pifs[pifname] - interval = usage_at - prv_at - rx_util = (rx - prv_rx)/interval - tx_util = (tx - prv_tx)/interval - - self.pifs_util[pifname] = (rx_util, tx_util) - self.pifs[pifname] = stats - - for domid in self._domain_vcpus_util.keys(): - if domid not in active_domids: - del self._domain_vcpus_util[domid] - del self._domain_vcpus[domid] - for domid in self._domain_vifs_util.keys(): - if domid not in active_domids: - del self._domain_vifs_util[domid] - del self._domain_vifs[domid] - del self._domain_vifs_stat[domid] - for domid in self._domain_vbds_util.keys(): - if domid not in active_domids: - del self._domain_vbds_util[domid] - del self._domain_vbds[domid] - - finally: - self.lock.release() - - # Sleep a while before next poll - time.sleep(POLL_INTERVAL) - diff --git a/tools/python/xen/xend/XendNetwork.py b/tools/python/xen/xend/XendNetwork.py deleted file mode 100644 index 489d5d5ae9..0000000000 --- a/tools/python/xen/xend/XendNetwork.py +++ /dev/null @@ -1,238 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (c) 2006 Xensource Inc. -#============================================================================ - -import os -import commands -import re -import struct -import socket - -import XendDomain -import XendNode -from XendLogging import log -from xen.xend import uuid as genuuid -from xen.xend.XendBase import XendBase -from xen.xend.XendError import * -from xen.util import Brctl -from xen.xend import XendAPIStore - -IP_ROUTE_RE = r'^default via ([\d\.]+) dev (\w+)' - -def bridge_exists(name): - return name in Brctl.get_state().keys() - -class XendNetwork(XendBase): - """We're going to assert that the name_label of this - network is just the name of the bridge""" - - def getClass(self): - return "network" - - def getAttrRW(self): - attrRW = ['name_label', - 'name_description', - 'other_config', - 'default_gateway', - 'default_netmask'] - return XendBase.getAttrRW() + attrRW - - def getAttrRO(self): - attrRO = ['VIFs', - 'PIFs', - 'managed'] - return XendBase.getAttrRO() + attrRO - - def getAttrInst(self): - return XendBase.getAttrInst() + self.getAttrRW() - - def getMethods(self): - methods = ['add_to_other_config', - 'remove_from_other_config', - 'destroy'] - return XendBase.getMethods() + methods - - def getFuncs(self): - funcs = ['create', 'get_by_name_label'] - return XendBase.getFuncs() + funcs - - getClass = classmethod(getClass) - getAttrRO = classmethod(getAttrRO) - getAttrRW = classmethod(getAttrRW) - getAttrInst = classmethod(getAttrInst) - getMethods = classmethod(getMethods) - getFuncs = classmethod(getFuncs) - - def create_phy(self, name): - """ - Called when a new bridge is found on xend start - """ - # Create new uuids - uuid = genuuid.createString() - - # Create instance - record = { - 'name_label': name, - 'name_description': '', - 'other_config': {}, - 'default_gateway': '', - 'default_netmask': '', - 'managed': False, - } - network = XendNetwork(record, uuid) - - return uuid - - def recreate(self, record, uuid): - """ - Called on xend start / restart, or machine - restart, when read from saved config. - Needs to check network exists, create it otherwise - """ - - # Create instance (do this first, to check record) - network = XendNetwork(record, uuid) - - # Create network if it doesn't already exist - if not bridge_exists(network.name_label): - if network.managed: - Brctl.bridge_create(network.name_label) - else: - log.info("Not recreating missing unmanaged network %s" % network.name_label) - - return uuid - - def create(self, record): - """ - Called from API, to create a new network - """ - # Create new uuids - uuid = genuuid.createString() - - # Create instance (do this first, to check record) - network = XendNetwork(record, uuid) - - # Check network doesn't already exist - name_label = network.name_label - if bridge_exists(name_label): - del network - raise UniqueNameError(name_label, "network") - - # Create the bridge - Brctl.bridge_create(network.name_label) - - XendNode.instance().save_networks() - - return uuid - - def get_by_name_label(cls, name): - return [inst.get_uuid() - for inst in XendAPIStore.get_all(cls.getClass()) - if inst.get_name_label() == name] - - create_phy = classmethod(create_phy) - recreate = classmethod(recreate) - create = classmethod(create) - get_by_name_label = classmethod(get_by_name_label) - - def __init__(self, record, uuid): - # This is a read-only attr, so we need to - # set it here, as super class won't try to - if record.has_key("managed"): - self.managed = record["managed"] - else: - self.managed = True - XendBase.__init__(self, uuid, record) - - # - # XenAPI Mehtods - # - - def destroy(self): - # check no VIFs or PIFs attached - if len(self.get_VIFs()) > 0: - raise NetworkError("Cannot destroy network with VIFs attached", - self.get_name_label()) - - if len(self.get_PIFs()) > 0: - raise NetworkError("Cannot destroy network with PIFs attached", - self.get_name_label()) - - XendBase.destroy(self) - Brctl.bridge_del(self.get_name_label()) - XendNode.instance().save_networks() - - def get_name_label(self): - return self.name_label - - def get_name_description(self): - return self.name_description - - def set_name_label(self, new_name): - pass - - def set_name_description(self, new_desc): - self.name_description = new_desc - XendNode.instance().save_networks() - - def get_managed(self): - return self.managed - - def get_VIFs(self): - result = [] - vms = XendDomain.instance().get_all_vms() - for vm in vms: - vifs = vm.get_vifs() - for vif in vifs: - vif_cfg = vm.get_dev_xenapi_config('vif', vif) - if vif_cfg.get('network') == self.get_uuid(): - result.append(vif) - return result - - def get_PIFs(self): - pifs = XendAPIStore.get_all("PIF") - return [pif.get_uuid() for pif in pifs - if pif.get_network() == self.get_uuid()] - - def get_other_config(self): - return self.other_config - - def set_other_config(self, value): - self.other_config = value - XendNode.instance().save_networks() - - def add_to_other_config(self, key, value): - self.other_config[key] = value - XendNode.instance().save_networks() - - def remove_from_other_config(self, key): - if key in self.other_config: - del self.other_config[key] - XendNode.instance().save_networks() - - def get_default_gateway(self): - return self.default_gateway - - def set_default_gateway(self, gateway): - self.default_gateway = gateway - XendNode.instance().save_networks() - - def get_default_netmask(self): - return self.default_netmask - - def set_default_netmask(self, netmask): - self.default_netmask = netmask - XendNode.instance().save_networks() diff --git a/tools/python/xen/xend/XendNode.py b/tools/python/xen/xend/XendNode.py deleted file mode 100644 index a26383bca0..0000000000 --- a/tools/python/xen/xend/XendNode.py +++ /dev/null @@ -1,1173 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (c) 2006, 2007 Xensource Inc. -#============================================================================ - -import os -import socket -import time -import xen.lowlevel.xc - -from xen.util import Brctl -from xen.util import pci as PciUtil -from xen.util import vscsi_util -from xen.util import vusb_util -from xen.xend import XendAPIStore -from xen.xend import osdep -from xen.xend.XendConstants import * - -import uuid, arch -from XendPBD import XendPBD -from XendError import * -from XendOptions import instance as xendoptions -from XendQCoWStorageRepo import XendQCoWStorageRepo -from XendLocalStorageRepo import XendLocalStorageRepo -from XendLogging import log -from XendPIF import * -from XendPIFMetrics import XendPIFMetrics -from XendNetwork import * -from XendStateStore import XendStateStore -from XendMonitor import XendMonitor -from XendPPCI import XendPPCI -from XendPSCSI import XendPSCSI, XendPSCSI_HBA -from xen.xend.XendCPUPool import XendCPUPool - -class XendNode: - """XendNode - Represents a Domain 0 Host.""" - - def __init__(self): - """Initalises the state of all host specific objects such as - - * host - * host_CPU - * host_metrics - * PIF - * PIF_metrics - * network - * Storage Repository - * PPCI - * PSCSI - """ - - self.xc = xen.lowlevel.xc.xc() - self.state_store = XendStateStore(xendoptions().get_xend_state_path()) - self.monitor = XendMonitor() - self.monitor.start() - - # load host state from XML file - saved_host = self.state_store.load_state('host') - if saved_host and len(saved_host.keys()) == 1: - self.uuid = saved_host.keys()[0] - host = saved_host[self.uuid] - self.name = host.get('name_label', socket.gethostname()) - self.desc = host.get('name_description', '') - self.host_metrics_uuid = host.get('metrics_uuid', - uuid.createString()) - try: - self.other_config = eval(host['other_config']) - except: - self.other_config = {} - self.cpus = {} - else: - self.uuid = uuid.createString() - self.name = socket.gethostname() - self.desc = '' - self.other_config = {} - self.cpus = {} - self.host_metrics_uuid = uuid.createString() - - # put some arbitrary params in other_config as this - # is directly exposed via XenAPI - self.other_config["xen_pagesize"] = self.xeninfo_dict()["xen_pagesize"] - self.other_config["platform_params"] = self.xeninfo_dict()["platform_params"] - self.other_config["xen_commandline"] = self.xeninfo_dict()["xen_commandline"] - - # load CPU UUIDs - saved_cpus = self.state_store.load_state('cpu') - for cpu_uuid, cpu in saved_cpus.items(): - self.cpus[cpu_uuid] = cpu - - cpuinfo = osdep.get_cpuinfo() - physinfo = self.physinfo_dict() - cpu_count = physinfo['nr_cpus'] - cpu_features = physinfo['hw_caps'] - virt_caps = physinfo['virt_caps'] - - # If the number of CPUs don't match, we should just reinitialise - # the CPU UUIDs. - if cpu_count != len(self.cpus): - self.cpus = {} - for i in range(cpu_count): - u = uuid.createString() - self.cpus[u] = {'uuid': u, 'number': i } - - for u in self.cpus.keys(): - number = self.cpus[u]['number'] - # We can run off the end of the cpuinfo list if domain0 does not - # have #vcpus == #pcpus. In that case we just replicate one that's - # in the hash table. - if not cpuinfo.has_key(number): - number = cpuinfo.keys()[0] - if arch.type == "x86": - self.cpus[u].update( - { 'host' : self.uuid, - 'features' : cpu_features, - 'virt_caps': virt_caps, - 'speed' : int(float(cpuinfo[number]['cpu MHz'])), - 'vendor' : cpuinfo[number]['vendor_id'], - 'modelname': cpuinfo[number]['model name'], - 'stepping' : cpuinfo[number]['stepping'], - 'flags' : cpuinfo[number]['flags'], - }) - else: - self.cpus[u].update( - { 'host' : self.uuid, - 'features' : cpu_features, - }) - - self.srs = {} - - self._init_networks() - self._init_PIFs() - - self._init_SRs() - self._init_PBDs() - - self._init_PPCIs() - - self._init_PSCSIs() - - self._init_cpu_pools() - - - def _init_networks(self): - # Initialise networks - # First configure ones off disk - saved_networks = self.state_store.load_state('network') - if saved_networks: - for net_uuid, network in saved_networks.items(): - try: - XendNetwork.recreate(network, net_uuid) - except CreateUnspecifiedAttributeError: - log.warn("Error recreating network %s", net_uuid) - - # Next discover any existing bridges and check - # they are not already configured - - # 'tmpbridge' is a temporary bridge created by network-bridge script. - # Wait a couple of seconds for it to be renamed. - for i in xrange(20): - bridges = Brctl.get_state().keys() - if 'tmpbridge' in bridges: - time.sleep(0.1) - else: - break - - configured_bridges = [XendAPIStore.get( - network_uuid, "network") - .get_name_label() - for network_uuid in XendNetwork.get_all()] - unconfigured_bridges = [bridge - for bridge in bridges - if bridge not in configured_bridges] - for unconfigured_bridge in unconfigured_bridges: - if unconfigured_bridge != 'tmpbridge': - XendNetwork.create_phy(unconfigured_bridge) - - def _init_PIFs(self): - # Initialise PIFs - # First configure ones off disk - saved_pifs = self.state_store.load_state('pif') - if saved_pifs: - for pif_uuid, pif in saved_pifs.items(): - try: - XendPIF.recreate(pif, pif_uuid) - except CreateUnspecifiedAttributeError: - log.warn("Error recreating PIF %s", pif_uuid) - - # Next discover any existing PIFs and check - # they are not already configured - configured_pifs = [XendAPIStore.get( - pif_uuid, "PIF") - .get_interface_name() - for pif_uuid in XendPIF.get_all()] - unconfigured_pifs = [(name, mtu, mac) - for name, mtu, mac in linux_get_phy_ifaces() - if name not in configured_pifs] - - # Get a mapping from interface to bridge - if_to_br = dict([(i,b) - for (b,ifs) in Brctl.get_state().items() - for i in ifs]) - - for name, mtu, mac in unconfigured_pifs: - # Check PIF is on bridge - # if not, ignore - bridge_name = if_to_br.get(name, None) - if bridge_name is not None: - # Translate bridge name to network uuid - for network_uuid in XendNetwork.get_all(): - network = XendAPIStore.get( - network_uuid, 'network') - if network.get_name_label() == bridge_name: - XendPIF.create_phy(network_uuid, name, - mac, mtu) - break - else: - log.debug("Cannot find network for bridge %s " - "when configuring PIF %s", - (bridge_name, name)) - - def _init_SRs(self): - # initialise storage - saved_srs = self.state_store.load_state('sr') - if saved_srs: - for sr_uuid, sr_cfg in saved_srs.items(): - if sr_cfg['type'] == 'qcow_file': - self.srs[sr_uuid] = XendQCoWStorageRepo(sr_uuid) - elif sr_cfg['type'] == 'local': - self.srs[sr_uuid] = XendLocalStorageRepo(sr_uuid) - - # Create missing SRs if they don't exist - if not self.get_sr_by_type('local'): - image_sr_uuid = uuid.createString() - self.srs[image_sr_uuid] = XendLocalStorageRepo(image_sr_uuid) - - if not self.get_sr_by_type('qcow_file'): - qcow_sr_uuid = uuid.createString() - self.srs[qcow_sr_uuid] = XendQCoWStorageRepo(qcow_sr_uuid) - - def _init_PBDs(self): - saved_pbds = self.state_store.load_state('pbd') - if saved_pbds: - for pbd_uuid, pbd_cfg in saved_pbds.items(): - try: - XendPBD.recreate(pbd_uuid, pbd_cfg) - except CreateUnspecifiedAttributeError: - log.warn("Error recreating PBD %s", pbd_uuid) - - def _init_PPCIs(self): - saved_ppcis = self.state_store.load_state('ppci') - saved_ppci_table = {} - if saved_ppcis: - for ppci_uuid, ppci_record in saved_ppcis.items(): - try: - saved_ppci_table[ppci_record['name']] = ppci_uuid - except KeyError: - pass - - for pci_dev in PciUtil.get_all_pci_devices(): - ppci_record = { - 'domain': pci_dev.domain, - 'bus': pci_dev.bus, - 'slot': pci_dev.slot, - 'func': pci_dev.func, - 'vendor_id': pci_dev.vendor, - 'vendor_name': pci_dev.vendorname, - 'device_id': pci_dev.device, - 'device_name': pci_dev.devicename, - 'revision_id': pci_dev.revision, - 'class_code': pci_dev.classcode, - 'class_name': pci_dev.classname, - 'subsystem_vendor_id': pci_dev.subvendor, - 'subsystem_vendor_name': pci_dev.subvendorname, - 'subsystem_id': pci_dev.subdevice, - 'subsystem_name': pci_dev.subdevicename, - 'driver': pci_dev.driver - } - # If saved uuid exists, use it. Otherwise create one. - ppci_uuid = saved_ppci_table.get(pci_dev.name, uuid.createString()) - XendPPCI(ppci_uuid, ppci_record) - - def _init_PSCSIs(self): - # Initialise PSCSIs and PSCSI_HBAs - saved_pscsis = self.state_store.load_state('pscsi') - saved_pscsi_table = {} - if saved_pscsis: - for pscsi_uuid, pscsi_record in saved_pscsis.items(): - try: - saved_pscsi_table[pscsi_record['scsi_id']] = pscsi_uuid - except KeyError: - pass - - saved_pscsi_HBAs = self.state_store.load_state('pscsi_HBA') - saved_pscsi_HBA_table = {} - if saved_pscsi_HBAs: - for pscsi_HBA_uuid, pscsi_HBA_record in saved_pscsi_HBAs.items(): - try: - physical_host = int(pscsi_HBA_record['physical_host']) - saved_pscsi_HBA_table[physical_host] = pscsi_HBA_uuid - except (KeyError, ValueError): - pass - - pscsi_table = {} - pscsi_HBA_table = {} - - pscsi_records = [] - for pscsi_mask in xendoptions().get_pscsi_device_mask(): - pscsi_records += vscsi_util.get_all_scsi_devices(pscsi_mask) - log.debug("pscsi record count: %s" % len(pscsi_records)) - - for pscsi_record in pscsi_records: - scsi_id = pscsi_record['scsi_id'] - if scsi_id: - saved_HBA_uuid = None - - pscsi_uuid = saved_pscsi_table.get(scsi_id, None) - if pscsi_uuid is None: - pscsi_uuid = uuid.createString() - saved_pscsi_table[scsi_id] = pscsi_uuid - else: - try: - saved_HBA_uuid = saved_pscsis[pscsi_uuid].get('HBA', None) - except KeyError: - log.warn("Multi-path SCSI devices are not supported for XenAPI") - return - - physical_host = int(pscsi_record['physical_HCTL'].split(':')[0]) - if pscsi_HBA_table.has_key(physical_host): - pscsi_HBA_uuid = pscsi_HBA_table[physical_host] - elif saved_pscsi_HBA_table.has_key(physical_host): - pscsi_HBA_uuid = saved_pscsi_HBA_table[physical_host] - pscsi_HBA_table[physical_host] = pscsi_HBA_uuid - else: - pscsi_HBA_uuid = uuid.createString() - pscsi_HBA_table[physical_host] = pscsi_HBA_uuid - - if saved_HBA_uuid is not None and \ - saved_HBA_uuid != pscsi_HBA_uuid: - log.debug('The PSCSI(%s) host number was changed', scsi_id) - pscsi_record['HBA'] = pscsi_HBA_uuid - pscsi_table[pscsi_uuid] = pscsi_record - - for pscsi_uuid, pscsi_record in pscsi_table.items(): - XendPSCSI(pscsi_uuid, pscsi_record) - - for physical_host, pscsi_HBA_uuid in pscsi_HBA_table.items(): - XendPSCSI_HBA(pscsi_HBA_uuid, {'physical_host': physical_host}) - - def _init_cpu_pools(self): - # Initialise cpu_pools - saved_cpu_pools = self.state_store.load_state(XendCPUPool.getClass()) - if saved_cpu_pools: - for cpu_pool_uuid, cpu_pool in saved_cpu_pools.items(): - try: - XendCPUPool.recreate(cpu_pool, cpu_pool_uuid) - except CreateUnspecifiedAttributeError: - log.warn("Error recreating %s %s", - (XendCPUPool.getClass(), cpu_pool_uuid)) - XendCPUPool.recreate_active_pools() - - - def add_network(self, interface): - # TODO - log.debug("add_network(): Not implemented.") - - - def remove_network(self, interface): - # TODO - log.debug("remove_network(): Not implemented.") - - - def add_PPCI(self, pci_name): - # Update lspci info - PciUtil.create_lspci_info() - - # Initialise the PPCI - saved_ppcis = self.state_store.load_state('ppci') - saved_ppci_table = {} - if saved_ppcis: - for ppci_uuid, ppci_record in saved_ppcis.items(): - try: - saved_ppci_table[ppci_record['name']] = ppci_uuid - except KeyError: - pass - - pci_dev = PciUtil.PciDevice(PciUtil.parse_pci_name(pci_name)) - ppci_record = { - 'domain': pci_dev.domain, - 'bus': pci_dev.bus, - 'slot': pci_dev.slot, - 'func': pci_dev.func, - 'vendor_id': pci_dev.vendor, - 'vendor_name': pci_dev.vendorname, - 'device_id': pci_dev.device, - 'device_name': pci_dev.devicename, - 'revision_id': pci_dev.revision, - 'class_code': pci_dev.classcode, - 'class_name': pci_dev.classname, - 'subsystem_vendor_id': pci_dev.subvendor, - 'subsystem_vendor_name': pci_dev.subvendorname, - 'subsystem_id': pci_dev.subdevice, - 'subsystem_name': pci_dev.subdevicename, - 'driver': pci_dev.driver - } - # If saved uuid exists, use it. Otherwise create one. - ppci_uuid = saved_ppci_table.get(pci_dev.name, uuid.createString()) - XendPPCI(ppci_uuid, ppci_record) - - self.save_PPCIs() - - - def remove_PPCI(self, pci_name): - # Update lspci info - PciUtil.create_lspci_info() - - # Remove the PPCI - (domain, bus, slot, func) = PciUtil.parse_pci_name(pci_name) - ppci_ref = XendPPCI.get_by_sbdf(domain, bus, slot, func) - XendAPIStore.get(ppci_ref, "PPCI").destroy() - - self.save_PPCIs() - - - def add_PSCSI(self, add_HCTL): - saved_pscsis = self.state_store.load_state('pscsi') - saved_pscsi_table = {} - if saved_pscsis: - for saved_uuid, saved_record in saved_pscsis.items(): - try: - saved_pscsi_table[saved_record['scsi_id']] = saved_uuid - except KeyError: - pass - - saved_pscsi_HBAs = self.state_store.load_state('pscsi_HBA') - saved_pscsi_HBA_table = {} - if saved_pscsi_HBAs: - for saved_HBA_uuid, saved_HBA_record in saved_pscsi_HBAs.items(): - try: - physical_host = int(saved_HBA_record['physical_host']) - saved_pscsi_HBA_table[physical_host] = saved_HBA_uuid - except (KeyError, ValueError): - pass - - # Initialise the PSCSI and the PSCSI_HBA - pscsi_record = vscsi_util.get_scsi_device(add_HCTL) - if pscsi_record and pscsi_record['scsi_id']: - pscsi_uuid = saved_pscsi_table.get(pscsi_record['scsi_id'], None) - if pscsi_uuid is None: - physical_host = int(add_HCTL.split(':')[0]) - pscsi_HBA_uuid = saved_pscsi_HBA_table.get(physical_host, None) - if pscsi_HBA_uuid is None: - pscsi_HBA_uuid = uuid.createString() - XendPSCSI_HBA(pscsi_HBA_uuid, {'physical_host': physical_host}) - pscsi_record['HBA'] = pscsi_HBA_uuid - - pscsi_uuid = uuid.createString() - XendPSCSI(pscsi_uuid, pscsi_record) - self.save_PSCSIs() - self.save_PSCSI_HBAs() - - - def remove_PSCSI(self, rem_HCTL): - saved_pscsis = self.state_store.load_state('pscsi') - if not saved_pscsis: - return - - # Remove the PSCSI - for pscsi_record in saved_pscsis.values(): - if rem_HCTL == pscsi_record['physical_HCTL']: - pscsi_ref = XendPSCSI.get_by_HCTL(rem_HCTL) - XendAPIStore.get(pscsi_ref, "PSCSI").destroy() - self.save_PSCSIs() - - physical_host = int(rem_HCTL.split(':')[0]) - pscsi_HBA_ref = XendPSCSI_HBA.get_by_physical_host(physical_host) - if pscsi_HBA_ref: - if not XendAPIStore.get(pscsi_HBA_ref, 'PSCSI_HBA').get_PSCSIs(): - XendAPIStore.get(pscsi_HBA_ref, 'PSCSI_HBA').destroy() - self.save_PSCSI_HBAs() - - return - - def add_usbdev(self, busid): - # if the adding usb device should be owned by usbback - # and is probed by other usb drivers, seize it! - bus, intf = busid.split(':') - buses = vusb_util.get_assigned_buses() - if str(bus) in buses: - if not vusb_util.usb_intf_is_binded(busid): - log.debug("add_usb(): %s is binded to other driver" % busid) - vusb_util.unbind_usb_device(bus) - vusb_util.bind_usb_device(bus) - return - - def remove_usbdev(self, busid): - log.debug("remove_usbdev(): Not implemented.") - -## def network_destroy(self, net_uuid): - ## del self.networks[net_uuid] - ## self.save_networks() - - - def get_PIF_refs(self): - log.debug(XendPIF.get_all()) - return XendPIF.get_all() - -## def _PIF_create(self, name, mtu, vlan, mac, network, persist = True, -## pif_uuid = None, metrics_uuid = None): -## for pif in self.pifs.values(): -## if pif.network == network: -## raise NetworkAlreadyConnected(pif.uuid) - -## if pif_uuid is None: -## pif_uuid = uuid.createString() -## if metrics_uuid is None: -## metrics_uuid = uuid.createString() - -## metrics = XendPIFMetrics(metrics_uuid) -## pif = XendPIF(pif_uuid, metrics, name, mtu, vlan, mac, network, self) -## metrics.set_PIF(pif) - -## self.pif_metrics[metrics_uuid] = metrics -## self.pifs[pif_uuid] = pif - -## if persist: -## self.save_PIFs() -## self.refreshBridges() -## return pif_uuid - -## def PIF_destroy(self, pif_uuid): -## pif = self.pifs[pif_uuid] - -## if pif.vlan == -1: -## raise PIFIsPhysical() - -## del self.pifs[pif_uuid] -## self.save_PIFs() - - - def get_PPCI_refs(self): - return XendPPCI.get_all() - - def get_ppci_by_uuid(self, ppci_uuid): - if ppci_uuid in self.get_PPCI_refs(): - return ppci_uuid - return None - - - def get_PSCSI_refs(self): - return XendPSCSI.get_all() - - def get_pscsi_by_uuid(self, pscsi_uuid): - if pscsi_uuid in self.get_PSCSI_refs(): - return pscsi_uuid - return None - - def get_PSCSI_HBA_refs(self): - return XendPSCSI_HBA.get_all() - - def get_pscsi_HBA_by_uuid(self, pscsi_HBA_uuid): - if pscsi_HBA_uuid in self.get_PSCSI_HBA_refs(): - return pscsi_HBA_uuid - return None - - - def save(self): - # save state - host_record = {self.uuid: {'name_label':self.name, - 'name_description':self.desc, - 'metrics_uuid': self.host_metrics_uuid, - 'other_config': self.other_config}} - self.state_store.save_state('host',host_record) - self.state_store.save_state('cpu', self.cpus) - self.save_PIFs() - self.save_networks() - self.save_PBDs() - self.save_SRs() - self.save_PPCIs() - self.save_PSCSIs() - self.save_PSCSI_HBAs() - self.save_cpu_pools() - - def save_PIFs(self): - pif_records = dict([(pif_uuid, XendAPIStore.get( - pif_uuid, "PIF").get_record()) - for pif_uuid in XendPIF.get_all()]) - self.state_store.save_state('pif', pif_records) - - def save_networks(self): - net_records = dict([(network_uuid, XendAPIStore.get( - network_uuid, "network").get_record()) - for network_uuid in XendNetwork.get_all()]) - self.state_store.save_state('network', net_records) - - def save_PBDs(self): - pbd_records = dict([(pbd_uuid, XendAPIStore.get( - pbd_uuid, "PBD").get_record()) - for pbd_uuid in XendPBD.get_all()]) - self.state_store.save_state('pbd', pbd_records) - - def save_SRs(self): - sr_records = dict([(k, v.get_record(transient = False)) - for k, v in self.srs.items()]) - self.state_store.save_state('sr', sr_records) - - def save_PPCIs(self): - ppci_records = dict([(ppci_uuid, XendAPIStore.get( - ppci_uuid, "PPCI").get_record()) - for ppci_uuid in XendPPCI.get_all()]) - self.state_store.save_state('ppci', ppci_records) - - def save_PSCSIs(self): - pscsi_records = dict([(pscsi_uuid, XendAPIStore.get( - pscsi_uuid, "PSCSI").get_record()) - for pscsi_uuid in XendPSCSI.get_all()]) - self.state_store.save_state('pscsi', pscsi_records) - - def save_PSCSI_HBAs(self): - pscsi_HBA_records = dict([(pscsi_HBA_uuid, XendAPIStore.get( - pscsi_HBA_uuid, "PSCSI_HBA").get_record()) - for pscsi_HBA_uuid in XendPSCSI_HBA.get_all()]) - self.state_store.save_state('pscsi_HBA', pscsi_HBA_records) - - def save_cpu_pools(self): - cpu_pool_records = dict([(cpu_pool_uuid, XendAPIStore.get( - cpu_pool_uuid, XendCPUPool.getClass()).get_record()) - for cpu_pool_uuid in XendCPUPool.get_all_managed()]) - self.state_store.save_state(XendCPUPool.getClass(), cpu_pool_records) - - def shutdown(self): - return 0 - - def reboot(self): - return 0 - - def notify(self, _): - return 0 - - # - # Ref validation - # - - def is_valid_host(self, host_ref): - return (host_ref == self.uuid) - - def is_valid_cpu(self, cpu_ref): - return (cpu_ref in self.cpus) - - def is_valid_sr(self, sr_ref): - return (sr_ref in self.srs) - - def is_valid_vdi(self, vdi_ref): - for sr in self.srs.values(): - if sr.is_valid_vdi(vdi_ref): - return True - return False - - # - # Storage Repositories - # - - def get_sr(self, sr_uuid): - return self.srs.get(sr_uuid) - - def get_sr_by_type(self, sr_type): - return [sr.uuid for sr in self.srs.values() if sr.type == sr_type] - - def get_sr_by_name(self, name): - return [sr.uuid for sr in self.srs.values() if sr.name_label == name] - - def get_all_sr_uuid(self): - return self.srs.keys() - - def get_vdi_by_uuid(self, vdi_uuid): - for sr in self.srs.values(): - if sr.is_valid_vdi(vdi_uuid): - return sr.get_vdi_by_uuid(vdi_uuid) - return None - - def get_vdi_by_name_label(self, name): - for sr in self.srs.values(): - vdi = sr.get_vdi_by_name_label(name) - if vdi: - return vdi - return None - - def get_sr_containing_vdi(self, vdi_uuid): - for sr in self.srs.values(): - if sr.is_valid_vdi(vdi_uuid): - return sr - return None - - - # - # Host Functions - # - - def xen_version(self): - info = self.xc.xeninfo() - - info = {'Xen': '%(xen_major)d.%(xen_minor)d' % info} - - # Add xend_config_format - info.update(self.xendinfo_dict()) - - # Add version info about machine - info.update(self.nodeinfo_dict()) - - # Add specific xen version info - xeninfo_dict = self.xeninfo_dict() - - info.update({ - "xen_major": xeninfo_dict["xen_major"], - "xen_minor": xeninfo_dict["xen_minor"], - "xen_extra": xeninfo_dict["xen_extra"], - "cc_compiler": xeninfo_dict["cc_compiler"], - "cc_compile_by": xeninfo_dict["cc_compile_by"], - "cc_compile_domain": xeninfo_dict["cc_compile_domain"], - "cc_compile_date": xeninfo_dict["cc_compile_date"], - "xen_changeset": xeninfo_dict["xen_changeset"], - "xen_commandline": xeninfo_dict["xen_commandline"] - }) - - return info - - def get_name(self): - return self.name - - def set_name(self, new_name): - self.name = new_name - - def get_description(self): - return self.desc - - def set_description(self, new_desc): - self.desc = new_desc - - def get_uuid(self): - return self.uuid - - def get_capabilities(self): - return self.xc.xeninfo()['xen_caps'].split(" ") - - # - # Host CPU Functions - # - - def get_host_cpu_by_uuid(self, host_cpu_uuid): - if host_cpu_uuid in self.cpus: - return host_cpu_uuid - raise XendError('Invalid CPU UUID') - - def get_host_cpu_refs(self): - return self.cpus.keys() - - def get_host_cpu_uuid(self, host_cpu_ref): - if host_cpu_ref in self.cpus: - return host_cpu_ref - else: - raise XendError('Invalid CPU Reference') - - def get_host_cpu_field(self, ref, field): - try: - return self.cpus[ref][field] - except KeyError: - raise XendError('Invalid CPU Reference') - - def get_host_cpu_load(self, host_cpu_ref): - host_cpu = self.cpus.get(host_cpu_ref) - if not host_cpu: - return 0.0 - - vcpu = int(host_cpu['number']) - cpu_loads = self.monitor.get_domain_vcpus_util() - if 0 in cpu_loads and vcpu in cpu_loads[0]: - return cpu_loads[0][vcpu] - - return 0.0 - - def get_vcpus_policy(self): - sched_id = self.xc.sched_id_get() - if sched_id == xen.lowlevel.xc.XEN_SCHEDULER_SEDF: - return 'sedf' - elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT: - return 'credit' - elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT2: - return 'credit2' - else: - return 'unknown' - - def get_cpu_configuration(self): - phys_info = self.physinfo_dict() - - cpu_info = { - "nr_nodes": phys_info["nr_nodes"], - "nr_cpus": phys_info["nr_cpus"], - "cores_per_socket": phys_info["cores_per_socket"], - "threads_per_core": phys_info["threads_per_core"] - } - - return cpu_info - - # - # Network Functions - # - - def bridge_to_network(self, bridge): - """ - Determine which network a particular bridge is attached to. - - @param bridge The name of the bridge. If empty, the default bridge - will be used instead (the first one in the list returned by brctl - show); this is the behaviour of the vif-bridge script. - @return The XendNetwork instance to which this bridge is attached. - @raise Exception if the interface is not connected to a network. - """ - if not bridge: - rc, bridge = commands.getstatusoutput( - 'brctl show | cut -d "\n" -f 2 | cut -f 1') - if rc != 0 or not bridge: - raise Exception( - 'Could not find default bridge, and none was specified') - - for network_uuid in XendNetwork.get_all(): - network = XendAPIStore.get(network_uuid, "network") - if network.get_name_label() == bridge: - return network - else: - raise Exception('Cannot find network for bridge %s' % bridge) - - # - # Debug keys. - # - - def send_debug_keys(self, keys): - return self.xc.send_debug_keys(keys) - - # - # Getting host information. - # - - def info(self, show_numa = 1): - return (self.nodeinfo() + self.physinfo(show_numa) + self.xeninfo() + - self.xendinfo()) - - def nodeinfo(self): - (sys, host, rel, ver, mch) = os.uname() - return [['system', sys], - ['host', host], - ['release', rel], - ['version', ver], - ['machine', mch]] - - def list_to_rangepairs(self,cmap): - cmap.sort() - pairs = [] - x = y = 0 - for i in range(0,len(cmap)): - try: - if ((cmap[y+1] - cmap[i]) > 1): - pairs.append((cmap[x],cmap[y])) - x = y = i+1 - else: - y = y + 1 - # if we go off the end, then just add x to y - except IndexError: - pairs.append((cmap[x],cmap[y])) - - return pairs - - def format_pairs(self,pairs): - if not pairs: - return "no cpus" - out = "" - for f,s in pairs: - if (f==s): - out += '%d'%f - else: - out += '%d-%d'%(f,s) - out += ',' - # trim trailing ',' - return out[:-1] - - def list_to_strrange(self,list): - return self.format_pairs(self.list_to_rangepairs(list)) - - def format_cpu_to_core_socket_node(self, tinfo): - max_cpu_index=tinfo['max_cpu_index'] - str='\ncpu: core socket node\n' - for i in range(0, max_cpu_index+1): - try: - str+='%3d:%8d %8d %8d\n' % (i, - tinfo['cpu_to_core'][i], - tinfo['cpu_to_socket'][i], - tinfo['cpu_to_node'][i]) - except: - pass - return str[:-1]; - - def format_numa_info(self, ninfo): - try: - max_node_index=ninfo['max_node_index'] - str='\nnode: TotalMemory FreeMemory dma32Memory NodeDist:' - for i in range(0, max_node_index+1): - str+='%4d ' % i - str+='\n' - for i in range(0, max_node_index+1): - str+='%4d: %8dMB %8dMB %8dMB :' % (i, - ninfo['node_memsize'][i], - ninfo['node_memfree'][i], - ninfo['node_to_dma32_mem'][i]) - for j in range(0, nr_nodes): - try: - str+='%4d ' % ninfo['node_to_node_dist'][i][j] - except: - str+='- ' - str+='\n' - except: - str='none\n' - return str[:-1]; - - def physinfo(self, show_numa): - info = self.xc.physinfo() - tinfo = self.xc.topologyinfo() - ninfo = self.xc.numainfo() - - info['cpu_mhz'] = info['cpu_khz'] / 1000 - - # physinfo is in KiB, need it in MiB - info['total_memory'] = info['total_memory'] / 1024 - info['free_memory'] = info['free_memory'] / 1024 - info['free_cpus'] = len(XendCPUPool.unbound_cpus()) - - ITEM_ORDER = ['nr_cpus', - 'nr_nodes', - 'cores_per_socket', - 'threads_per_core', - 'cpu_mhz', - 'hw_caps', - 'virt_caps', - 'total_memory', - 'free_memory', - 'free_cpus', - ] - - if show_numa != 0: - info['cpu_topology'] = \ - self.format_cpu_to_core_socket_node(tinfo) - - info['numa_info'] = \ - self.format_numa_info(ninfo) - - ITEM_ORDER += [ 'cpu_topology', 'numa_info' ] - - return [[k, info[k]] for k in ITEM_ORDER] - - def pciinfo(self): - from xen.xend.server.pciif import get_all_assigned_pci_devices - assigned_devs = get_all_assigned_pci_devices() - - # Each element of dev_list is a PciDevice - dev_list = PciUtil.find_all_assignable_devices() - if dev_list is None: - return None - - # Each element of devs_list is a list of PciDevice - devs_list = PciUtil.check_FLR_capability(dev_list) - - devs_list = PciUtil.check_mmio_bar(devs_list) - - # Check if the devices have been assigned to guests. - final_devs_list = [] - for dev_list in devs_list: - available = True - for d in dev_list: - if d.name in assigned_devs: - available = False - break - if available: - final_devs_list = final_devs_list + [dev_list] - - pci_sxp_list = [] - for dev_list in final_devs_list: - for d in dev_list: - pci_sxp = ['dev', ['domain', '0x%04x' % d.domain], - ['bus', '0x%02x' % d.bus], - ['slot', '0x%02x' % d.slot], - ['func', '0x%x' % d.func]] - pci_sxp_list.append(pci_sxp) - - return pci_sxp_list - - - def xenschedinfo(self): - sched_id = self.xc.sched_id_get() - if sched_id == xen.lowlevel.xc.XEN_SCHEDULER_SEDF: - return 'sedf' - elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT: - return 'credit' - elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT2: - return 'credit2' - else: - return 'unknown' - - def xeninfo(self): - info = self.xc.xeninfo() - info['xen_scheduler'] = self.xenschedinfo() - - ITEM_ORDER = ['xen_major', - 'xen_minor', - 'xen_extra', - 'xen_caps', - 'xen_scheduler', - 'xen_pagesize', - 'platform_params', - 'xen_changeset', - 'xen_commandline', - 'cc_compiler', - 'cc_compile_by', - 'cc_compile_domain', - 'cc_compile_date', - ] - - return [[k, info[k]] for k in ITEM_ORDER] - - def xendinfo(self): - return [['xend_config_format', 4]] - - # - # utilisation tracking - # - - def get_vcpu_util(self, domid, vcpuid): - cpu_loads = self.monitor.get_domain_vcpus_util() - if domid in cpu_loads: - return cpu_loads[domid].get(vcpuid, 0.0) - return 0.0 - - def get_vif_util(self, domid, vifid): - vif_loads = self.monitor.get_domain_vifs_util() - if domid in vif_loads: - return vif_loads[domid].get(vifid, (0.0, 0.0)) - return (0.0, 0.0) - - def get_vif_stat(self, domid, vifid): - vif_loads = self.monitor.get_domain_vifs_stat() - if domid in vif_loads: - return vif_loads[domid].get(vifid, (0.0, 0.0)) - return (0.0, 0.0) - - def get_vbd_util(self, domid, vbdid): - vbd_loads = self.monitor.get_domain_vbds_util() - if domid in vbd_loads: - return vbd_loads[domid].get(vbdid, (0.0, 0.0)) - return (0.0, 0.0) - - # dictionary version of *info() functions to get rid of - # SXPisms. - def nodeinfo_dict(self): - return dict(self.nodeinfo()) - def xendinfo_dict(self): - return dict(self.xendinfo()) - def xeninfo_dict(self): - return dict(self.xeninfo()) - def physinfo_dict(self): - return dict(self.physinfo(1)) - def info_dict(self): - return dict(self.info()) - - # tmem - def tmem_list(self, cli_id, use_long): - pool_id = -1 - subop = TMEMC_LIST - arg1 = 32768 - arg2 = use_long - arg3 = 0 - buf = '' - return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf) - - def tmem_thaw(self, cli_id): - pool_id = -1 - subop = TMEMC_THAW - arg1 = 0 - arg2 = 0 - arg3 = 0 - buf = '' - return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf) - - def tmem_freeze(self, cli_id): - pool_id = -1 - subop = TMEMC_FREEZE - arg1 = 0 - arg2 = 0 - arg3 = 0 - buf = '' - return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf) - - def tmem_flush(self, cli_id, pages): - pool_id = -1 - subop = TMEMC_FLUSH - arg1 = pages - arg2 = 0 - arg3 = 0 - buf = '' - return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf) - - def tmem_destroy(self, cli_id): - pool_id = -1 - subop = TMEMC_DESTROY - arg1 = 0 - arg2 = 0 - arg3 = 0 - buf = '' - return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf) - - def tmem_set_weight(self, cli_id, arg1): - pool_id = -1 - subop = TMEMC_SET_WEIGHT - arg2 = 0 - arg3 = 0 - buf = '' - return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf) - - def tmem_set_cap(self, cli_id, arg1): - pool_id = -1 - subop = TMEMC_SET_CAP - arg2 = 0 - arg3 = 0 - buf = '' - return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf) - - def tmem_set_compress(self, cli_id, arg1): - pool_id = -1 - subop = TMEMC_SET_COMPRESS - arg2 = 0 - arg3 = 0 - buf = '' - return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf) - - def tmem_query_freeable_mb(self): - pool_id = -1 - cli_id = -1 - subop = TMEMC_QUERY_FREEABLE_MB - arg1 = 0 - arg2 = 0 - arg3 = 0 - buf = '' - return self.xc.tmem_control(pool_id, subop, cli_id, arg1, arg2, arg3, buf) - - def tmem_shared_auth(self, cli_id, uuid_str, auth): - return self.xc.tmem_auth(cli_id, uuid_str, auth) - -def instance(): - global inst - try: - inst - except: - inst = XendNode() - inst.save() - return inst diff --git a/tools/python/xen/xend/XendOptions.py b/tools/python/xen/xend/XendOptions.py deleted file mode 100644 index cc6f38ed2c..0000000000 --- a/tools/python/xen/xend/XendOptions.py +++ /dev/null @@ -1,567 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2005 XenSource Ltd -#============================================================================ - -"""Xend root class. -Creates the servers and handles configuration. - -Other classes get config variables by importing this module, -using instance() to get a XendOptions instance, and then -the config functions (e.g. get_xend_port()) to get -configured values. -""" - -import os -import os.path -import string -import sys - -from xen.xend import sxp, osdep, XendLogging -from xen.xend.XendError import XendError -from xen.util import auxbin - -if os.uname()[0] == 'SunOS': - from xen.lowlevel import scf - -class XendOptions: - """Configuration options.""" - - """Where network control scripts live.""" - network_script_dir = auxbin.scripts_dir() - - """Where block control scripts live.""" - block_script_dir = auxbin.scripts_dir() - - """Default path to the log file. """ - logfile_default = "/var/log/xen/xend.log" - - """Default level of information to be logged.""" - loglevel_default = 'DEBUG' - - """Default Xen-API server configuration. """ - xen_api_server_default = [['unix']] - - """Default for the flag indicating whether xend should run an http server - (deprecated).""" - xend_http_server_default = 'no' - - xend_tcp_xmlrpc_server_default = 'no' - - xend_tcp_xmlrpc_server_address_default = 'localhost' - - xend_tcp_xmlrpc_server_port_default = 8006 - - xend_unix_xmlrpc_server_default = 'yes' - - """Default interface address xend listens at. """ - xend_address_default = '' - - """Default for the flag indicating whether xend should run a relocation server.""" - xend_relocation_server_default = 'no' - - """Default for the flag indicating whether xend should run a ssl relocation server.""" - xend_relocation_ssl_server_default = 'no' - - """Default for the flag indicating whether xend should run a udev event server.""" - xend_udev_event_server_default = 'no' - - """Default interface address the xend relocation server listens at. """ - xend_relocation_address_default = '' - - """Default port xend serves HTTP at. """ - xend_port_default = 8000 - - """Default port xend serves relocation at. """ - xend_relocation_port_default = 8002 - - """Default port xend serves ssl relocation at. """ - xend_relocation_ssl_port_default = 8003 - - xend_relocation_hosts_allow_default = '' - - """Default for the flag indicating whether xend should run a unix-domain - server (deprecated).""" - xend_unix_server_default = 'no' - - """Default external migration tool """ - external_migration_tool_default = '' - - """Default path the unix-domain server listens at.""" - xend_unix_path_default = '/var/lib/xend/xend-socket' - - dom0_min_mem_default = 0 - - reserved_memory_default = 0 - - dom0_vcpus_default = 0 - - vncpasswd_default = None - - """Default interface to listen for VNC connections on""" - xend_vnc_listen_default = '127.0.0.1' - - """Use of TLS mode in QEMU VNC server""" - xend_vnc_tls = 0 - - """x509 certificate directory for QEMU VNC server""" - xend_vnc_x509_cert_dir = auxbin.xen_configdir() + "/vnc" - - """Verify incoming client x509 certs""" - xend_vnc_x509_verify = 0 - - """Default session storage path.""" - xend_domains_path_default = '/var/lib/xend/domains' - - """Default xend management state storage.""" - xend_state_path_default = '/var/lib/xend/state' - - """Default xend QCoW storage repository location.""" - xend_storage_path_default = '/var/lib/xend/storage' - - """Default xend security state storage path.""" - xend_security_path_default = '/var/lib/xend/security' - - """Default script to configure a backend network interface""" - vif_script = osdep.vif_script - - """Default Xen Security Module""" - xsm_module_default = 'dummy' - - """Default rotation count of qemu-dm log file.""" - qemu_dm_logrotate_count = 10 - - """Default timeout for device creation.""" - device_create_timeout_default = 100 - - """Default timeout for device destruction.""" - device_destroy_timeout_default = 100 - - """By default, we use the strict check for HVM guest. (For PV guest, we - use loose check automatically if necessary.""" - pci_dev_assign_strict_check_default = True - - def __init__(self): - self.configure() - - def _logError(self, fmt, *args): - """Logging function to log to stderr. We use this for XendOptions log - messages because they may be logged before the logger has been - configured. Other components can safely use the logger. - """ - print >>sys.stderr, "xend [ERROR]", fmt % args - - """Default mask for pscsi device scan.""" - xend_pscsi_device_mask = ['*'] - - - def configure(self): - self.set_config() - XendLogging.init(self.get_config_string("logfile", - self.logfile_default), - self.get_config_string("loglevel", - self.loglevel_default)) - - def set_config(self): - raise NotImplementedError() - - def get_config_bool(self, name, val=None): - raise NotImplementedError() - - def get_config_int(self, name, val=None): - raise NotImplementedError() - - def get_config_string(self, name, val=None): - raise NotImplementedError() - - def get_xen_api_server(self): - raise NotImplementedError() - - def get_xend_http_server(self): - """Get the flag indicating whether xend should run an http server. - """ - return self.get_config_bool("xend-http-server", self.xend_http_server_default) - - def get_xend_tcp_xmlrpc_server(self): - return self.get_config_bool("xend-tcp-xmlrpc-server", - self.xend_tcp_xmlrpc_server_default) - - def get_xend_tcp_xmlrpc_server_port(self): - return self.get_config_int("xend-tcp-xmlrpc-server-port", - self.xend_tcp_xmlrpc_server_port_default) - - def get_xend_tcp_xmlrpc_server_address(self): - return self.get_config_string("xend-tcp-xmlrpc-server-address", - self.xend_tcp_xmlrpc_server_address_default) - - def get_xend_tcp_xmlrpc_server_ssl_key_file(self): - name = 'xend-tcp-xmlrpc-server-ssl-key-file' - file = self.get_config_string(name) - if file and os.path.dirname(file) == "": - file = auxbin.xen_configdir() + '/' + file; - if file and not os.path.exists(file): - raise XendError("invalid xend config %s: directory '%s' does not exist" % (name, file)) - return file - - def get_xend_tcp_xmlrpc_server_ssl_cert_file(self): - name = 'xend-tcp-xmlrpc-server-ssl-cert-file' - file = self.get_config_string(name) - if file and os.path.dirname(file) == "": - file = auxbin.xen_configdir() + '/' + file; - if file and not os.path.exists(file): - raise XendError("invalid xend config %s: directory '%s' does not exist" % (name, file)) - return file - - def get_xend_unix_xmlrpc_server(self): - return self.get_config_bool("xend-unix-xmlrpc-server", - self.xend_unix_xmlrpc_server_default) - - def get_xend_relocation_server(self): - """Get the flag indicating whether xend should run a relocation server. - """ - return self.get_config_bool("xend-relocation-server", - self.xend_relocation_server_default) - - def get_xend_relocation_ssl_server(self): - """Get the flag indicating whether xend should run a ssl relocation server. - """ - return self.get_config_bool("xend-relocation-ssl-server", - self.xend_relocation_ssl_server_default) - - def get_xend_relocation_server_ssl_key_file(self): - name = 'xend-relocation-server-ssl-key-file' - file = self.get_config_string(name) - if os.path.dirname(file) == "": - file = auxbin.xen_configdir() + '/' + file; - if not os.path.exists(file): - raise XendError("invalid xend config %s: directory '%s' does not exist" % (name, file)) - return file - - def get_xend_relocation_server_ssl_cert_file(self): - name = 'xend-relocation-server-ssl-cert-file' - file = self.get_config_string(name) - if os.path.dirname(file) == "": - file = auxbin.xen_configdir() + '/' + file; - if not os.path.exists(file): - raise XendError("invalid xend config %s: directory '%s' does not exist" % (name, file)) - return file - - def get_xend_udev_event_server(self): - return self.get_config_bool("xend-udev-event-server", - self.xend_udev_event_server_default) - - def get_xend_port(self): - """Get the port xend listens at for its HTTP interface. - """ - return self.get_config_int('xend-port', self.xend_port_default) - - def get_xend_relocation_port(self): - """Get the port xend listens at for connection to its relocation server. - """ - return self.get_config_int('xend-relocation-port', - self.xend_relocation_port_default) - - def get_xend_relocation_ssl_port(self): - """Get the port xend listens at for ssl connection to its relocation - server. - """ - return self.get_config_int('xend-relocation-ssl-port', - self.xend_relocation_ssl_port_default) - - def get_xend_relocation_ssl(self): - """Whether to use ssl when relocating. - """ - return self.get_config_bool('xend-relocation-ssl', 'no') - - def get_xend_relocation_hosts_allow(self): - return self.get_config_string("xend-relocation-hosts-allow", - self.xend_relocation_hosts_allow_default) - - def get_xend_address(self): - """Get the address xend listens at for its HTTP port. - This defaults to the empty string which allows all hosts to connect. - If this is set to 'localhost' only the localhost will be able to connect - to the HTTP port. - """ - return self.get_config_string('xend-address', self.xend_address_default) - - def get_xend_relocation_address(self): - """Get the address xend listens at for its relocation server port. - This defaults to the empty string which allows all hosts to connect. - If this is set to 'localhost' only the localhost will be able to connect - to the relocation port. - """ - return self.get_config_string('xend-relocation-address', self.xend_relocation_address_default) - - def get_xend_unix_server(self): - """Get the flag indicating whether xend should run a unix-domain server. - """ - return self.get_config_bool("xend-unix-server", self.xend_unix_server_default) - - def get_xend_unix_path(self): - """Get the path the xend unix-domain server listens at. - """ - return self.get_config_string("xend-unix-path", self.xend_unix_path_default) - - def get_xend_domains_path(self): - """ Get the path for persistent domain configuration storage - """ - return self.get_config_string("xend-domains-path", self.xend_domains_path_default) - - def get_xend_state_path(self): - """ Get the path for persistent domain configuration storage - """ - return self.get_config_string("xend-state-path", self.xend_state_path_default) - - def get_xend_storage_path(self): - """ Get the path for persistent domain configuration storage - """ - return self.get_config_string("xend-storage-path", self.xend_storage_path_default) - - def get_xend_security_path(self): - """ Get the path for security state - """ - return self.get_config_string("xend-security-path", self.xend_security_path_default) - - def get_network_script(self): - """@return the script used to alter the network configuration when - Xend starts and stops, or None if no such script is specified.""" - - s = self.get_config_string('network-script') - - if s: - result = s.split(" ") - result[0] = os.path.join(self.network_script_dir, result[0]) - return result - else: - return None - - def get_external_migration_tool(self): - """@return the name of the tool to handle virtual device migration.""" - return self.get_config_string('external-migration-tool', self.external_migration_tool_default) - - def get_enable_dump(self): - return self.get_config_bool('enable-dump', 'no') - - def get_vif_script(self): - return self.get_config_string('vif-script', self.vif_script) - - def get_dom0_min_mem(self): - return self.get_config_int('dom0-min-mem', self.dom0_min_mem_default) - - def get_enable_dom0_ballooning(self): - enable_dom0_ballooning_default = 'yes' - if self.get_dom0_min_mem() == 0: - enable_dom0_ballooning_default = 'no' - return self.get_config_bool('enable-dom0-ballooning', - enable_dom0_ballooning_default) - - def get_reserved_memory(self): - if not self.get_enable_dom0_ballooning(): - return 0 #no ballooning of dom0 will close this item - else: - return self.get_config_int('total_available_memory', self.reserved_memory_default) - - - def get_dom0_vcpus(self): - return self.get_config_int('dom0-cpus', self.dom0_vcpus_default) - - def get_console_limit(self): - return self.get_config_int('console-limit', 1024) - - def get_vnclisten_address(self): - return self.get_config_string('vnc-listen', self.xend_vnc_listen_default) - - def get_vncpasswd_default(self): - return self.get_config_string('vncpasswd', - self.vncpasswd_default) - - def get_keymap(self): - return self.get_config_string('keymap', None) - - def get_resource_label_change_script(self): - s = self.get_config_string('resource-label-change-script') - if s: - result = s.split(" ") - result[0] = os.path.join(auxbin.scripts_dir(), result[0]) - return result - else: - return None - - - def get_vnc_tls(self): - return self.get_config_string('vnc-tls', self.xend_vnc_tls) - - def get_vnc_x509_cert_dir(self): - name = 'vnc-x509-cert-dir' - vncdir = self.get_config_string(name, self.xend_vnc_x509_cert_dir) - if os.path.dirname(vncdir) == "": - vncdir = auxbin.xen_configdir() + '/' + vncdir - if not os.path.exists(vncdir): - raise XendError("invalid xend config %s: directory '%s' does not exist" % (name, vncdir)) - return vncdir - - def get_vnc_x509_verify(self): - return self.get_config_string('vnc-x509-verify', self.xend_vnc_x509_verify) - - def get_qemu_dm_logrotate_count(self): - return self.get_config_int("qemu-dm-logrotate-count", - self.qemu_dm_logrotate_count) - - def get_device_create_timeout(self): - return self.get_config_int("device-create-timeout", - self.device_create_timeout_default) - - def get_device_destroy_timeout(self): - return self.get_config_int("device-destroy-timeout", - self.device_destroy_timeout_default) - - def get_pci_dev_assign_strict_check(self): - return self.get_config_bool("pci-passthrough-strict-check", - self.pci_dev_assign_strict_check_default) - - def get_pscsi_device_mask(self): - return self.get_config_value("pscsi-device-mask", - self.xend_pscsi_device_mask) - -class XendOptionsFile(XendOptions): - - """Default path to the config file.""" - config_default = auxbin.xen_configdir() + "/xend-config.sxp" - - """Environment variable used to override config_default.""" - config_var = "XEND_CONFIG" - - def set_config(self): - """If the config file exists, read it. If not, ignore it. - - The config file is a sequence of sxp forms. - """ - self.config_path = os.getenv(self.config_var, self.config_default) - if os.path.exists(self.config_path): - try: - fin = file(self.config_path, 'rb') - try: - config = sxp.parse(fin) - finally: - fin.close() - if config is None: - config = ['xend-config'] - else: - config.insert(0, 'xend-config') - self.config = config - except Exception, ex: - self._logError('Reading config file %s: %s', - self.config_path, str(ex)) - raise - else: - self._logError('Config file does not exist: %s', - self.config_path) - self.config = ['xend-config'] - - def get_config_value(self, name, val=None): - """Get the value of an atomic configuration element. - - @param name: element name - @param val: default value (optional, defaults to None) - @return: value - """ - return sxp.child_value(self.config, name, val=val) - - def get_config_bool(self, name, val=None): - v = string.lower(str(self.get_config_value(name, val))) - if v in ['yes', 'y', '1', 'on', 'true', 't']: - return True - if v in ['no', 'n', '0', 'off', 'false', 'f']: - return False - raise XendError("invalid xend config %s: expected bool: %s" % (name, v)) - - def get_config_int(self, name, val=None): - v = self.get_config_value(name, val) - try: - return int(v) - except Exception: - raise XendError("invalid xend config %s: expected int: %s" % (name, v)) - - def get_config_string(self, name, val=None): - return self.get_config_value(name, val) - - def get_xen_api_server(self): - """Get the Xen-API server configuration. - """ - return self.get_config_value('xen-api-server', - self.xen_api_server_default) - - def get_xsm_module_name(self): - """Get the Xen Security Module name. - """ - return self.get_config_string('xsm_module_name', self.xsm_module_default) - -if os.uname()[0] == 'SunOS': - class XendOptionsSMF(XendOptions): - - def set_config(self): - pass - - def get_config_bool(self, name, val=None): - try: - return scf.get_bool(name) - except scf.error, e: - if e[0] == scf.SCF_ERROR_NOT_FOUND: - if val in ['yes', 'y', '1', 'on', 'true', 't']: - return True - if val in ['no', 'n', '0', 'off', 'false', 'f']: - return False - return val - else: - raise XendError("option %s: %s:%s" % (name, e[1], e[2])) - - def get_config_int(self, name, val=None): - try: - return scf.get_int(name) - except scf.error, e: - if e[0] == scf.SCF_ERROR_NOT_FOUND: - return val - else: - raise XendError("option %s: %s:%s" % (name, e[1], e[2])) - - def get_config_string(self, name, val=None): - try: - return scf.get_string(name) - except scf.error, e: - if e[0] == scf.SCF_ERROR_NOT_FOUND: - return val - else: - raise XendError("option %s: %s:%s" % (name, e[1], e[2])) - - def get_xen_api_server(self): - # When the new server is a supported configuration, we should - # expand this. - return [["unix"]] - -def instance(): - """Get an instance of XendOptions. - Use this instead of the constructor. - """ - global inst - try: - inst - except: - if os.uname()[0] == 'SunOS': - inst = XendOptionsSMF() - else: - inst = XendOptionsFile() - return inst diff --git a/tools/python/xen/xend/XendPBD.py b/tools/python/xen/xend/XendPBD.py deleted file mode 100644 index 2187cd7850..0000000000 --- a/tools/python/xen/xend/XendPBD.py +++ /dev/null @@ -1,99 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (c) 2007 Xensource Inc. -#============================================================================ - - -import uuid -from XendLogging import log -from xen.xend.XendBase import XendBase -from xen.xend import XendAPIStore -from xen.xend import uuid as genuuid - -class XendPBD(XendBase): - """Physical block devices.""" - - def getClass(self): - return "PBD" - - def getAttrRO(self): - attrRO = ['host', - 'SR', - 'device_config', - 'currently_attached'] - return XendBase.getAttrRO() + attrRO - - def getAttrRW(self): - attrRW = [] - return XendBase.getAttrRW() + attrRW - - def getAttrInst(self): - return ['host', - 'SR', - 'device_config'] - - def getMethods(self): - methods = ['destroy'] - return XendBase.getMethods() + methods - - def getFuncs(self): - funcs = ['create', - 'get_by_SR'] - return XendBase.getFuncs() + funcs - - getClass = classmethod(getClass) - getAttrRO = classmethod(getAttrRO) - getAttrRW = classmethod(getAttrRW) - getAttrInst = classmethod(getAttrInst) - getMethods = classmethod(getMethods) - getFuncs = classmethod(getFuncs) - - def recreate(uuid, record): - pbd = XendPBD(record, uuid) - return uuid - - def create(cls, record): - uuid = genuuid.createString() - pbd = XendPBD(record, uuid) - return uuid - - create = classmethod(create) - - def __init__(self, record, uuid): - XendBase.__init__(self, uuid, record) - self.currently_attached = True - - def get_host(self): - return self.host - - def get_SR(self): - return self.SR - - def get_device_config(self): - return self.device_config - - def get_currently_attached(self): - return self.currently_attached - - def destroy(self): - pass - - def get_by_SR(cls, sr_ref): - pbds = XendAPIStore.get_all("PBD") - return [pbd.get_uuid() - for pbd in pbds - if pbd.get_SR() == sr_ref] - - get_by_SR = classmethod(get_by_SR) diff --git a/tools/python/xen/xend/XendPIF.py b/tools/python/xen/xend/XendPIF.py deleted file mode 100644 index d6e073e6f3..0000000000 --- a/tools/python/xen/xend/XendPIF.py +++ /dev/null @@ -1,390 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (c) 2006 Xensource Inc. -#============================================================================ - -import commands -import logging -import os -import re -from xen.xend import uuid as genuuid -from xen.xend import XendAPIStore -from xen.xend.XendBase import XendBase -from xen.xend.XendPIFMetrics import XendPIFMetrics -from xen.xend.XendError import * -from xen.xend import Vifctl -from xen.util import auxbin - -log = logging.getLogger("xend.XendPIF") -log.setLevel(logging.TRACE) - -MAC_RE = re.compile(':'.join(['[0-9a-f]{2}'] * 6)) -IP_IFACE_RE = re.compile(r'^\d+: (\w+):.*mtu (\d+) .* link/\w+ ([0-9a-f:]+)') - - -Vifctl.network('start') - -def linux_phy_to_virt(pif_name): - return 'eth' + re.sub(r'^[a-z]+', '', pif_name) - -def linux_get_phy_ifaces(): - """Returns a list of physical interfaces. - - Identifies PIFs as those that have a interface name starting with - 'peth'. - - See /etc/xen/scripts/network-bridge for how the devices are renamed. - - @rtype: array of 3-element tuple (name, mtu, mac) - """ - - ip_cmd = 'ip -o link show' - rc, output = commands.getstatusoutput(ip_cmd) - ifaces = {} - phy_ifaces = [] - if rc == 0: - # parse all interfaces into (name, mtu, mac) - for line in output.split('\n'): - has_if = re.search(IP_IFACE_RE, line) - if has_if: - ifaces[has_if.group(1)] = has_if.groups() - - # resolve pifs' mac addresses - for name, mtu, mac in ifaces.values(): - if name.startswith('peth'): - bridged_ifname = linux_phy_to_virt(name) - bridged_if = ifaces.get(bridged_ifname) - bridged_mac = '' - if bridged_if: - bridged_mac = bridged_if[2] - phy_ifaces.append((name, int(mtu), bridged_mac)) - - return phy_ifaces - -def linux_set_mac(iface, mac): - if not re.search(MAC_RE, mac): - return False - - ip_mac_cmd = 'ip link set %s addr %s' % \ - (linux_phy_to_virt(iface), mac) - rc, output = commands.getstatusoutput(ip_mac_cmd) - if rc == 0: - return True - - return False - -def linux_set_mtu(iface, mtu): - try: - ip_mtu_cmd = 'ip link set %s mtu %d' % \ - (linux_phy_to_virt(iface), int(mtu)) - rc, output = commands.getstatusoutput(ip_mtu_cmd) - if rc == 0: - return True - return False - except ValueError: - return False - -def linux_get_mtu(device): - return _linux_get_pif_param(device, 'mtu') - -def linux_get_mac(device): - return _linux_get_pif_param(device, 'link/ether') - -def _linux_get_pif_param(device, param_name): - ip_get_dev_data = 'ip link show %s' % device - rc, output = commands.getstatusoutput(ip_get_dev_data) - if rc == 0: - params = output.split(' ') - for i in xrange(len(params)): - if params[i] == param_name: - return params[i+1] - return '' - -def _create_VLAN(dev, vlan): - rc, _ = commands.getstatusoutput('vconfig add %s %d' % - (dev, vlan)) - if rc != 0: - return False - - rc, _ = commands.getstatusoutput('ifconfig %s.%d up' % - (dev, vlan)) - return rc == 0 - -def _destroy_VLAN(dev, vlan): - rc, _ = commands.getstatusoutput('ifconfig %s.%d down' % - (dev, vlan)) - if rc != 0: - return False - - rc, _ = commands.getstatusoutput('vconfig rem %s.%d' % - (dev, vlan)) - return rc == 0 - -class XendPIF(XendBase): - """Representation of a Physical Network Interface.""" - - def getClass(self): - return "PIF" - - def getAttrRO(self): - attrRO = ['network', - 'host', - 'metrics', - 'device', - 'VLAN'] - return XendBase.getAttrRO() + attrRO - - def getAttrRW(self): - attrRW = ['MAC', - 'MTU'] - return XendBase.getAttrRW() + attrRW - - def getAttrInst(self): - attrInst = ['network', - 'device', - 'MAC', - 'MTU', - 'VLAN'] - return attrInst - - def getMethods(self): - methods = ['plug', - 'unplug', - 'destroy'] - return XendBase.getMethods() + methods - - def getFuncs(self): - funcs = ['create_VLAN'] - return XendBase.getFuncs() + funcs - - getClass = classmethod(getClass) - getAttrRO = classmethod(getAttrRO) - getAttrRW = classmethod(getAttrRW) - getAttrInst = classmethod(getAttrInst) - getMethods = classmethod(getMethods) - getFuncs = classmethod(getFuncs) - - def create_phy(self, network_uuid, device, - MAC, MTU): - """ - Called when a new physical PIF is found - Could be a VLAN... - """ - # Create new uuids - pif_uuid = genuuid.createString() - metrics_uuid = genuuid.createString() - - # Create instances - metrics = XendPIFMetrics(metrics_uuid, pif_uuid) - - # Is this a VLAN? - VLANdot = device.split(".") - VLANcolon = device.split(":") - - if len(VLANdot) > 1: - VLAN = VLANdot[1] - device = VLANdot[0] - elif len(VLANcolon) > 1: - VLAN = VLANcolon[1] - device = VLANcolon[0] - else: - VLAN = -1 - - record = { - 'network': network_uuid, - 'device': device, - 'MAC': MAC, - 'MTU': MTU, - 'VLAN': VLAN - } - pif = XendPIF(record, pif_uuid, metrics_uuid) - - return pif_uuid - - def recreate(self, record, uuid): - """Called on xend start / restart""" - pif_uuid = uuid - metrics_uuid = record['metrics'] - - # Create instances - metrics = XendPIFMetrics(metrics_uuid, pif_uuid) - pif = XendPIF(record, pif_uuid, metrics_uuid) - - # If physical PIF, check exists - # If VLAN, create if not exist - ifs = [dev for dev, _1, _2 in linux_get_phy_ifaces()] - if pif.get_VLAN() == -1: - if pif.get_device() not in ifs: - XendBase.destroy(pif) - metrics.destroy() - return None - else: - if pif.get_interface_name() not in ifs: - _create_VLAN(pif.get_device(), pif.get_VLAN()) - pif.plug() - - return pif_uuid - - def create_VLAN(self, device, network_uuid, host_ref, vlan): - """Exposed via API - create a new VLAN from existing VIF""" - - ifs = [name for name, _, _ in linux_get_phy_ifaces()] - - vlan = int(vlan) - - # Check VLAN tag is valid - if vlan < 0 or vlan >= 4096: - raise VLANTagInvalid(vlan) - - # Check device exists - if device not in ifs: - raise InvalidDeviceError(device) - - # Check VLAN doesn't already exist - if "%s.%d" % (device, vlan) in ifs: - raise DeviceExistsError("%s.%d" % (device, vlan)) - - # Check network ref is valid - from XendNetwork import XendNetwork - if network_uuid not in XendNetwork.get_all(): - raise InvalidHandleError("Network", network_uuid) - - # Check host_ref is this host - import XendNode - if host_ref != XendNode.instance().get_uuid(): - raise InvalidHandleError("Host", host_ref) - - # Create the VLAN - _create_VLAN(device, vlan) - - # Create new uuids - pif_uuid = genuuid.createString() - metrics_uuid = genuuid.createString() - - # Create the record - record = { - "device": device, - "MAC": linux_get_mac('%s.%d' % (device, vlan)), - "MTU": linux_get_mtu('%s.%d' % (device, vlan)), - "network": network_uuid, - "VLAN": vlan - } - - # Create instances - metrics = XendPIFMetrics(metrics_uuid, pif_uuid) - pif = XendPIF(record, pif_uuid, metrics_uuid) - - # Not sure if they should be created plugged or not... - pif.plug() - - XendNode.instance().save_PIFs() - return pif_uuid - - create_phy = classmethod(create_phy) - recreate = classmethod(recreate) - create_VLAN = classmethod(create_VLAN) - - def __init__(self, record, uuid, metrics_uuid): - XendBase.__init__(self, uuid, record) - self.metrics = metrics_uuid - - def plug(self): - """Plug the PIF into the network""" - network = XendAPIStore.get(self.network, - "network") - bridge_name = network.get_name_label() - - from xen.util import Brctl - Brctl.vif_bridge_add({ - "bridge": bridge_name, - "vif": self.get_interface_name() - }) - - def unplug(self): - """Unplug the PIF from the network""" - network = XendAPIStore.get(self.network, - "network") - bridge_name = network.get_name_label() - - from xen.util import Brctl - Brctl.vif_bridge_rem({ - "bridge": bridge_name, - "vif": self.get_interface_name() - }) - - def destroy(self): - # Figure out if this is a physical device - if self.get_interface_name() == \ - self.get_device(): - raise PIFIsPhysical() - - self.unplug() - - if _destroy_VLAN(self.get_device(), self.get_VLAN()): - XendBase.destroy(self) - import XendNode - XendNode.instance().save_PIFs() - else: - raise NetworkError("Unable to delete VLAN", self.get_uuid()) - - def get_interface_name(self): - if self.get_VLAN() == -1: - return self.get_device() - else: - return "%s.%d" % (self.get_device(), self.get_VLAN()) - - def get_device(self): - """ - This is the base interface. - For phy if (VLAN == -1) this is same as - if name. - For VLANs, this it the bit before the period - """ - return self.device - - def get_network(self): - return self.network - - def get_host(self): - from xen.xend import XendNode - return XendNode.instance().get_uuid() - - def get_metrics(self): - return self.metrics - - def get_MAC(self): - return self.MAC - - def set_MAC(self, new_mac): - success = linux_set_mac(self.device, new_mac) - if success: - self.MAC = new_mac - import XendNode - XendNode.instance().save_PIFs() - return success - - def get_MTU(self): - return self.MTU - - def set_MTU(self, new_mtu): - success = linux_set_mtu(self.device, new_mtu) - if success: - self.MTU = new_mtu - import XendNode - XendNode.instance().save_PIFs() - return success - - def get_VLAN(self): - return self.VLAN diff --git a/tools/python/xen/xend/XendPIFMetrics.py b/tools/python/xen/xend/XendPIFMetrics.py deleted file mode 100644 index aca808384c..0000000000 --- a/tools/python/xen/xend/XendPIFMetrics.py +++ /dev/null @@ -1,59 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (c) 2006-2007 Xensource Inc. -#============================================================================ - -from XendBase import XendBase - -class XendPIFMetrics(XendBase): - """PIF Metrics.""" - - def getClass(self): - return "PIF_metrics" - - def getAttrRO(self): - attrRO = ['io_read_kbs', - 'io_write_kbs', - 'last_updated', - 'pif'] - return XendBase.getAttrRO() + attrRO - - getClass = classmethod(getClass) - getAttrRO = classmethod(getAttrRO) - - def __init__(self, uuid, pif_uuid): - XendBase.__init__(self, uuid, {}) - self.pif_uuid = pif_uuid - - def get_pif(self): - return self.pif_uuid - - def get_io_read_kbs(self): - return self._get_stat(0) - - def get_io_write_kbs(self): - return self._get_stat(1) - - def _get_stat(self, n): - from xen.xend.XendNode import instance as xennode - #pifname = self.pif.device - #pifs_util = xennode().monitor.get_pifs_util() - #if pifname in pifs_util: - # return pifs_util[pifname][n] - return 0.0 - - def get_last_updated(self): - import xen.xend.XendAPI as XendAPI - return XendAPI.now() diff --git a/tools/python/xen/xend/XendPPCI.py b/tools/python/xen/xend/XendPPCI.py deleted file mode 100644 index e6248b714a..0000000000 --- a/tools/python/xen/xend/XendPPCI.py +++ /dev/null @@ -1,160 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (c) 2008 NEC Corporation -# Yosuke Iwamatsu -#============================================================================ - -from xen.xend.XendBase import XendBase -from xen.xend.XendBase import XendAPIStore -from xen.xend import uuid as genuuid - -from xen.util.pci import parse_hex - -class XendPPCI(XendBase): - """Representation of a physical PCI device.""" - - def getClass(self): - return "PPCI" - - def getAttrRO(self): - attrRO = ['host', - 'domain', - 'bus', - 'slot', - 'func', - 'name', - 'vendor_id', - 'vendor_name', - 'device_id', - 'device_name', - 'revision_id', - 'class_code', - 'class_name', - 'subsystem_vendor_id', - 'subsystem_vendor_name', - 'subsystem_id', - 'subsystem_name', - 'driver'] - return XendBase.getAttrRO() + attrRO - - def getAttrRW(self): - attrRW = [] - return XendBase.getAttrRW() + attrRW - - def getAttrInst(self): - attrInst = [] - return XendBase.getAttrInst() + attrInst - - def getMethods(self): - methods = [] - return XendBase.getMethods() + methods - - def getFuncs(self): - funcs = [] - return XendBase.getFuncs() + funcs - - getClass = classmethod(getClass) - getAttrRO = classmethod(getAttrRO) - getAttrRW = classmethod(getAttrRW) - getAttrInst = classmethod(getAttrInst) - getMethods = classmethod(getMethods) - getFuncs = classmethod(getFuncs) - - def get_by_sbdf(self, domain, bus, slot, func): - for ppci in XendAPIStore.get_all("PPCI"): - if ppci.get_domain() == parse_hex(domain) and \ - ppci.get_bus() == parse_hex(bus) and \ - ppci.get_slot() == parse_hex(slot) and \ - ppci.get_func() == parse_hex(func): - return ppci.get_uuid() - return None - - get_by_sbdf = classmethod(get_by_sbdf) - - def __init__(self, uuid, record): - self.domain = record['domain'] - self.bus = record['bus'] - self.slot = record['slot'] - self.func = record['func'] - self.vendor_id = record['vendor_id'] - self.vendor_name = record['vendor_name'] - self.device_id = record['device_id'] - self.device_name = record['device_name'] - self.revision_id = record['revision_id'] - self.class_code = record['class_code'] - self.class_name = record['class_name'] - self.subsystem_vendor_id = record['subsystem_vendor_id'] - self.subsystem_vendor_name = record['subsystem_vendor_name'] - self.subsystem_id = record['subsystem_id'] - self.subsystem_name = record['subsystem_name'] - self.driver = record['driver'] - XendBase.__init__(self, uuid, record) - - def get_host(self): - from xen.xend import XendNode - return XendNode.instance().get_uuid() - - def get_domain(self): - return self.domain - - def get_bus(self): - return self.bus - - def get_slot(self): - return self.slot - - def get_func(self): - return self.func - - def get_name(self): - return "%04x:%02x:%02x.%01x" % (self.domain, self.bus, self.slot, - self.func) - - def get_vendor_id(self): - return self.vendor_id - - def get_vendor_name(self): - return self.vendor_name - - def get_device_id(self): - return self.device_id - - def get_device_name(self): - return self.device_name - - def get_class_code(self): - return self.class_code - - def get_class_name(self): - return self.class_name - - def get_revision_id(self): - return self.revision_id - - def get_subsystem_vendor_id(self): - return self.subsystem_vendor_id - - def get_subsystem_vendor_name(self): - return self.subsystem_vendor_name - - def get_subsystem_id(self): - return self.subsystem_id - - def get_subsystem_name(self): - return self.subsystem_name - - def get_driver(self): - return self.driver - diff --git a/tools/python/xen/xend/XendPSCSI.py b/tools/python/xen/xend/XendPSCSI.py deleted file mode 100644 index e50aa5bec9..0000000000 --- a/tools/python/xen/xend/XendPSCSI.py +++ /dev/null @@ -1,211 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright FUJITSU LIMITED 2008 -# Masaki Kanno -#============================================================================ - -from xen.xend.XendBase import XendBase -from xen.xend.XendBase import XendAPIStore -from xen.xend import uuid as genuuid - -class XendPSCSI(XendBase): - """Representation of a physical SCSI device.""" - - def getClass(self): - return "PSCSI" - - def getAttrRO(self): - attrRO = ['host', - 'physical_host', - 'physical_channel', - 'physical_target', - 'physical_lun', - 'physical_HCTL', - 'HBA', - 'vendor_name', - 'model', - 'type_id', - 'type', - 'dev_name', - 'sg_name', - 'revision', - 'scsi_id', - 'scsi_level'] - return XendBase.getAttrRO() + attrRO - - def getAttrRW(self): - attrRW = [] - return XendBase.getAttrRW() + attrRW - - def getAttrInst(self): - attrInst = [] - return XendBase.getAttrInst() + attrInst - - def getMethods(self): - methods = [] - return XendBase.getMethods() + methods - - def getFuncs(self): - funcs = [] - return XendBase.getFuncs() + funcs - - getClass = classmethod(getClass) - getAttrRO = classmethod(getAttrRO) - getAttrRW = classmethod(getAttrRW) - getAttrInst = classmethod(getAttrInst) - getMethods = classmethod(getMethods) - getFuncs = classmethod(getFuncs) - - def get_by_HCTL(self, physical_HCTL): - for pscsi in XendAPIStore.get_all("PSCSI"): - if pscsi.get_physical_HCTL() == physical_HCTL: - return pscsi.get_uuid() - return None - - get_by_HCTL = classmethod(get_by_HCTL) - - def __init__(self, uuid, record): - self.physical_HCTL = record['physical_HCTL'] - self.physical_HBA = record['HBA'] - self.vendor_name = record['vendor_name'] - self.model = record['model'] - self.type_id = record['type_id'] - self.type = record['type'] - self.dev_name = record['dev_name'] - self.sg_name = record['sg_name'] - self.revision = record['revision'] - self.scsi_id = record['scsi_id'] - self.scsi_level = record['scsi_level'] - - p_hctl = self.physical_HCTL.split(':') - self.physical_host = int(p_hctl[0]) - self.physical_channel = int(p_hctl[1]) - self.physical_target = int(p_hctl[2]) - self.physical_lun = int(p_hctl[3]) - - XendBase.__init__(self, uuid, record) - - def get_host(self): - from xen.xend import XendNode - return XendNode.instance().get_uuid() - - def get_physical_host(self): - return self.physical_host - - def get_physical_channel(self): - return self.physical_channel - - def get_physical_target(self): - return self.physical_target - - def get_physical_lun(self): - return self.physical_lun - - def get_physical_HCTL(self): - return self.physical_HCTL - - def get_HBA(self): - return self.physical_HBA - - def get_vendor_name(self): - return self.vendor_name - - def get_model(self): - return self.model - - def get_type_id(self): - return self.type_id - - def get_type(self): - return self.type - - def get_dev_name(self): - return self.dev_name - - def get_sg_name(self): - return self.sg_name - - def get_revision(self): - return self.revision - - def get_scsi_id(self): - return self.scsi_id - - def get_scsi_level(self): - return self.scsi_level - - -class XendPSCSI_HBA(XendBase): - """Representation of a physical SCSI HBA.""" - - def getClass(self): - return "PSCSI_HBA" - - def getAttrRO(self): - attrRO = ['host', - 'physical_host', - 'PSCSIs'] - return XendBase.getAttrRO() + attrRO - - def getAttrRW(self): - attrRW = [] - return XendBase.getAttrRW() + attrRW - - def getAttrInst(self): - attrInst = [] - return XendBase.getAttrInst() + attrInst - - def getMethods(self): - methods = [] - return XendBase.getMethods() + methods - - def getFuncs(self): - funcs = [] - return XendBase.getFuncs() + funcs - - getClass = classmethod(getClass) - getAttrRO = classmethod(getAttrRO) - getAttrRW = classmethod(getAttrRW) - getAttrInst = classmethod(getAttrInst) - getMethods = classmethod(getMethods) - getFuncs = classmethod(getFuncs) - - def get_by_physical_host(self, physical_host): - for pscsi_HBA in XendAPIStore.get_all('PSCSI_HBA'): - if pscsi_HBA.get_physical_host() == physical_host: - return pscsi_HBA.get_uuid() - return None - - get_by_physical_host = classmethod(get_by_physical_host) - - def __init__(self, uuid, record): - self.physical_host = record['physical_host'] - XendBase.__init__(self, uuid, record) - - def get_host(self): - from xen.xend import XendNode - return XendNode.instance().get_uuid() - - def get_physical_host(self): - return self.physical_host - - def get_PSCSIs(self): - PSCSIs = [] - uuid = self.get_uuid() - for pscsi in XendAPIStore.get_all('PSCSI'): - if pscsi.get_HBA() == uuid: - PSCSIs.append(pscsi.get_uuid()) - return PSCSIs - diff --git a/tools/python/xen/xend/XendProtocol.py b/tools/python/xen/xend/XendProtocol.py deleted file mode 100644 index 34af4a4b2b..0000000000 --- a/tools/python/xen/xend/XendProtocol.py +++ /dev/null @@ -1,225 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2005 XenSource Ltd. -#============================================================================ - -import socket -import httplib -import time -import types - -from encode import * -from xen.xend import sxp - -from xen.xend import XendOptions - -DEBUG = 0 - -HTTP_OK = 200 -HTTP_CREATED = 201 -HTTP_ACCEPTED = 202 -HTTP_NO_CONTENT = 204 - - -xoptions = XendOptions.instance() - - -class XendError(RuntimeError): - """Error class for 'expected errors' when talking to xend. - """ - pass - -class XendRequest: - """A request to xend. - """ - - def __init__(self, url, method, args): - """Create a request. Sets up the headers, argument data, and the - url. - - @param url: the url to request - @param method: request method, GET or POST - @param args: dict containing request args, if any - """ - if url.proto != 'http': - raise ValueError('Invalid protocol: ' + url.proto) - (hdr, data) = encode_data(args) - if args and method == 'GET': - url.query = data - data = None - if method == "POST" and url.path.endswith('/'): - url.path = url.path[:-1] - - self.headers = hdr - self.data = data - self.url = url - self.method = method - -class XendClientProtocol: - """Abstract class for xend clients. - """ - def xendRequest(self, url, method, args=None): - """Make a request to xend. - Implement in a subclass. - - @param url: xend request url - @param method: http method: POST or GET - @param args: request arguments (dict) - """ - raise NotImplementedError() - - def xendGet(self, url, args=None): - """Make a xend request using HTTP GET. - Requests using GET are usually 'safe' and may be repeated without - nasty side-effects. - - @param url: xend request url - @param data: request arguments (dict) - """ - return self.xendRequest(url, "GET", args) - - def xendPost(self, url, args): - """Make a xend request using HTTP POST. - Requests using POST potentially cause side-effects, and should - not be repeated unless you really want to repeat the side - effect. - - @param url: xend request url - @param args: request arguments (dict) - """ - return self.xendRequest(url, "POST", args) - - def handleStatus(self, _, status, message): - """Handle the status returned from the request. - """ - status = int(status) - if status in [ HTTP_NO_CONTENT ]: - return None - if status not in [ HTTP_OK, HTTP_CREATED, HTTP_ACCEPTED ]: - return self.handleException(XendError(message)) - return 'ok' - - def handleResponse(self, data): - """Handle the data returned in response to the request. - """ - if data is None: return None - typ = self.getHeader('Content-Type') - if typ != sxp.mime_type: - return data - try: - pin = sxp.Parser() - pin.input(data); - pin.input_eof() - val = pin.get_val() - except sxp.ParseError, err: - return self.handleException(err) - if isinstance(val, types.ListType) and sxp.name(val) == 'xend.err': - err = XendError(val[1]) - return self.handleException(err) - return val - - def handleException(self, err): - """Handle an exception during the request. - May be overridden in a subclass. - """ - raise err - - def getHeader(self, key): - """Get a header from the response. - Case is ignored in the key. - - @param key: header key - @return: header - """ - raise NotImplementedError() - -class HttpXendClientProtocol(XendClientProtocol): - """A synchronous xend client. This will make a request, wait for - the reply and return the result. - """ - - resp = None - request = None - - def makeConnection(self, url): - return httplib.HTTPConnection(url.location()) - - def makeRequest(self, url, method, args): - return XendRequest(url, method, args) - - def xendRequest(self, url, method, args=None): - """Make a request to xend. - - @param url: xend request url - @param method: http method: POST or GET - @param args: request arguments (dict) - """ - retries = 0 - while retries < 2: - self.request = self.makeRequest(url, method, args) - conn = self.makeConnection(url) - try: - if DEBUG: conn.set_debuglevel(1) - conn.request(method, url.fullpath(), self.request.data, - self.request.headers) - try: - resp = conn.getresponse() - self.resp = resp - val = self.handleStatus(resp.version, resp.status, - resp.reason) - if val is None: - data = None - else: - data = resp.read() - val = self.handleResponse(data) - return val - except httplib.BadStatusLine: - retries += 1 - time.sleep(5) - finally: - conn.close() - - raise XendError("Received invalid response from Xend, twice.") - - - def getHeader(self, key): - return self.resp.getheader(key) - - -class UnixConnection(httplib.HTTPConnection): - """Subclass of Python library HTTPConnection that uses a unix-domain socket. - """ - - def __init__(self, path): - httplib.HTTPConnection.__init__(self, 'localhost') - self.path = path - - def connect(self): - sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - sock.connect(self.path) - self.sock = sock - -class UnixXendClientProtocol(HttpXendClientProtocol): - """A synchronous xend client using a unix-domain socket. - """ - - def __init__(self, path=None): - if path is None: - path = xoptions.get_xend_unix_path() - self.path = path - - def makeConnection(self, _): - return UnixConnection(self.path) diff --git a/tools/python/xen/xend/XendQCoWStorageRepo.py b/tools/python/xen/xend/XendQCoWStorageRepo.py deleted file mode 100644 index 726df0bca3..0000000000 --- a/tools/python/xen/xend/XendQCoWStorageRepo.py +++ /dev/null @@ -1,340 +0,0 @@ -#!/usr/bin/python -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2006,2007 XenSource Ltd. -#============================================================================ -# -# The default QCOW Xen API Storage Repository -# - -import commands -import logging -import os -import stat -import threading -import re -import sys -import struct - -from xen.util import mkdir -import uuid -from XendPBD import XendPBD -from XendError import XendError -from XendVDI import * -from XendTask import XendTask -from XendStorageRepository import XendStorageRepository -from XendOptions import instance as xendoptions - -XEND_STORAGE_NO_MAXIMUM = sys.maxint -XEND_STORAGE_QCOW_FILENAME = "%s.qcow" -XEND_STORAGE_VDICFG_FILENAME = "%s.vdi.xml" -QCOW_CREATE_COMMAND = "/usr/sbin/qcow-create -r %d %s" - -MB = 1024 * 1024 - -log = logging.getLogger("xend.XendQCowStorageRepo") - - -def qcow_virtual_size(qcow_file): - """Read the first 32 bytes of the QCoW header to determine its size. - - See: http://www.gnome.org/~markmc/qcow-image-format.html. - """ - try: - qcow_header = open(qcow_file, 'rb').read(32) - parts = struct.unpack('>IIQIIQ', qcow_header) - return parts[-1] - except IOError: - return -1 - -class XendQCoWStorageRepo(XendStorageRepository): - """A simple file backed QCOW Storage Repository. - - This class exposes the interface to create VDI's via the - Xen API. The backend is a file-backed QCOW format that is stored - in XEND_STORAGE_DIR or any that is specified in the constructor. - - The actual images are created in the format .img and .qcow. - """ - - def __init__(self, sr_uuid, - sr_type = "qcow_file", - name_label = "QCoW", - name_description = "Xend QCoW Storage Repository", - storage_max = XEND_STORAGE_NO_MAXIMUM): - """ - @keyword storage_max: Maximum disk space to use in bytes. - @type storage_max: int - - @ivar storage_free: storage space free for this repository - @ivar images: mapping of all the images. - @type images: dictionary by image uuid. - @ivar lock: lock to provide thread safety. - """ - - XendStorageRepository.__init__(self, sr_uuid, sr_type, name_label, - name_description, storage_max) - self.storage_free = 0 - self.location = xendoptions().get_xend_storage_path() - self._refresh() - - def get_record(self, transient = True): - retval = {'uuid': self.uuid, - 'name_label': self.name_label, - 'name_description': self.name_description, - 'virtual_allocation': self.virtual_allocation, - 'physical_utilisation': self.physical_utilisation, - 'physical_size': self.physical_size, - 'type': self.type, - 'content_type': self.content_type, - 'VDIs': self.images.keys(), - 'PBDs': XendPBD.get_by_SR(self.uuid)} - - if self.physical_size == XEND_STORAGE_NO_MAXIMUM: - stfs = os.statvfs(self.location) - retval['physical_size'] = stfs.f_blocks * stfs.f_frsize - - return retval - - def _refresh(self): - """Internal function that refreshes the state of the disk and - updates the list of images available. - """ - self.lock.acquire() - try: - mkdir.parents(self.location, stat.S_IRWXU) - - # scan the directory and populate self.images - virtual_alloc = 0 - physical_used = 0 - seen_images = [] - for filename in os.listdir(self.location): - if filename[-5:] == XEND_STORAGE_QCOW_FILENAME[-5:]: - image_uuid = filename[:-5] - seen_images.append(image_uuid) - - qcow_file = XEND_STORAGE_QCOW_FILENAME % image_uuid - cfg_file = XEND_STORAGE_VDICFG_FILENAME % image_uuid - qcow_path = os.path.join(self.location, qcow_file) - cfg_path = os.path.join(self.location, cfg_file) - - phys_size = os.stat(qcow_path).st_size - virt_size = qcow_virtual_size(qcow_path) - - # add this image if we haven't seen it before - if image_uuid not in self.images: - vdi = XendQCoWVDI(image_uuid, self.uuid, - qcow_path, cfg_path, - virt_size, phys_size) - - if cfg_path and os.path.exists(cfg_path): - try: - vdi.load_config(cfg_path) - except: - log.error('Corrupt VDI configuration file %s' % - cfg_path) - - self.images[image_uuid] = vdi - - physical_used += phys_size - virtual_alloc += virt_size - - # remove images that aren't valid - for image_uuid in self.images.keys(): - if image_uuid not in seen_images: - try: - os.unlink(self.images[image_uuid].qcow_path) - except OSError: - pass - del self.images[image_uuid] - - self.virtual_allocation = virtual_alloc - self.physical_utilisation = physical_used - - # update free storage if we have to track that - if self.physical_size == XEND_STORAGE_NO_MAXIMUM: - self.storage_free = self._get_free_space() - else: - self.storage_free = self.physical_size - self.virtual_allocation - - finally: - self.lock.release() - - def _get_free_space(self): - """Returns the amount of free space in bytes available in the storage - partition. Note that this may not be used if the storage repository - is initialised with a maximum size in storage_max. - - @rtype: int - """ - stfs = os.statvfs(self.location) - return stfs.f_bavail * stfs.f_frsize - - def _has_space_available_for(self, size_bytes): - """Returns whether there is enough space for an image in the - partition which the storage_dir resides on. - - @rtype: bool - """ - if self.physical_size != XEND_STORAGE_NO_MAXIMUM: - return self.storage_free > size_bytes - - bytes_free = self._get_free_space() - if size_bytes < bytes_free: - return True - return False - - def _create_image_files(self, desired_size_bytes): - """Create an image and return its assigned UUID. - - @param desired_size_bytes: Desired image size in bytes - @type desired_size_bytes: int - @rtype: string - @return: uuid - - @raises XendError: If an error occurs. - """ - self.lock.acquire() - try: - if not self._has_space_available_for(desired_size_bytes): - raise XendError("Not enough space (need %d)" % - desired_size_bytes) - - image_uuid = uuid.createString() - qcow_path = os.path.join(self.location, - XEND_STORAGE_QCOW_FILENAME % image_uuid) - - if qcow_path and os.path.exists(qcow_path): - raise XendError("Image with same UUID alreaady exists:" % - image_uuid) - - cmd = QCOW_CREATE_COMMAND % (desired_size_bytes/MB, qcow_path) - rc, output = commands.getstatusoutput(cmd) - - if rc != 0: - # cleanup the image file - os.unlink(qcow_path) - raise XendError("Failed to create QCOW Image: %s" % output) - - self._refresh() - return image_uuid - finally: - self.lock.release() - - def destroy_vdi(self, image_uuid): - """Destroy an image that is managed by this storage repository. - - @param image_uuid: Image UUID - @type image_uuid: String - @rtype: String - """ - self.lock.acquire() - try: - if image_uuid in self.images: - # TODO: check if it is being used? - qcow_path = self.images[image_uuid].qcow_path - cfg_path = self.images[image_uuid].cfg_path - try: - os.unlink(qcow_path) - if cfg_path and os.path.exists(cfg_path): - os.unlink(cfg_path) - except OSError: - log.exception("Failed to destroy image") - del self.images[image_uuid] - self._refresh() - return True - finally: - self.lock.release() - - return False - - def free_space_bytes(self): - """Returns the amount of available space in KB. - @rtype: int - """ - self.lock.acquire() - try: - return self.storage_free - finally: - self.lock.release() - - def total_space_bytes(self): - """Returns the total usable space of the storage repo in KB. - @rtype: int - """ - self.lock.acquire() - try: - if self.physical_size == XEND_STORAGE_NO_MAXIMUM: - stfs = os.statvfs(self.location) - return stfs.f_blocks * stfs.f_frsize - else: - return self.physical_size - finally: - self.lock.release() - - def used_space_bytes(self): - """Returns the total amount of space used by this storage repository. - @rtype: int - """ - self.lock.acquire() - try: - return self.physical_utilisation - finally: - self.lock.release() - - def virtual_allocation(self): - """Returns the total virtual space allocated within the storage repo. - @rtype: int - """ - self.lock.acquire() - try: - return self.virtual_allocation - finally: - self.lock.release() - - - def create_vdi(self, vdi_struct): - image_uuid = None - try: - size_bytes = int(vdi_struct.get('virtual_size', 0)) - - image_uuid = self._create_image_files(size_bytes) - - image = self.images[image_uuid] - image_cfg = { - 'virtual_size': size_bytes, - 'type': vdi_struct.get('type', 'system'), - 'name_label': vdi_struct.get('name_label', ''), - 'name_description': vdi_struct.get('name_description', ''), - 'sharable': bool(vdi_struct.get('sharable', False)), - 'read_only': bool(vdi_struct.get('read_only', False)), - } - - # load in configuration from vdi_struct - image.load_config_dict(image_cfg) - - # save configuration to file - cfg_filename = XEND_STORAGE_VDICFG_FILENAME % image_uuid - cfg_path = os.path.join(self.location, cfg_filename) - image.save_config(cfg_path) - - except Exception, e: - # cleanup before raising exception - if image_uuid: - self.destroy_vdi(image_uuid) - - raise - - return image_uuid diff --git a/tools/python/xen/xend/XendSXPDev.py b/tools/python/xen/xend/XendSXPDev.py deleted file mode 100644 index f145701ea8..0000000000 --- a/tools/python/xen/xend/XendSXPDev.py +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env python -# -# Helper functions for dealing with the sxp representation of devices - -import types - -def dev_dict_to_sxp(dev): - def f((key, val)): - if isinstance(val, types.ListType): - return map(lambda x: [key, x], val) - return [[key, val]] - dev_sxp = ['dev'] + reduce(lambda x, y: x + y, map(f, dev.items())) - return dev_sxp diff --git a/tools/python/xen/xend/XendStateStore.py b/tools/python/xen/xend/XendStateStore.py deleted file mode 100644 index a66181d1d4..0000000000 --- a/tools/python/xen/xend/XendStateStore.py +++ /dev/null @@ -1,234 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (c) 2006 Xensource Inc. -#============================================================================ - -import os - -from xen.xend import uuid -from xen.xend.XendLogging import log -from xml.dom import minidom -from xml.dom import Node - -class XendStateStore: - """Manages persistent storage of Xend's internal state, mainly - relating to API objects. - - It stores objects atomically in the file system as flat XML files - categorised by their 'class'. - - For example: - - /var/lib/xend/state/cpu.xml will contain the host cpu state - /var/lib/xend/state/sr.xml will contain the storage repository state. - - For the application, it will load the state via this class: - - load_state('cpu') will return a marshalled dictionary object - containing the cpu state. - - save_state('cpu', dict) will save the state contained in the dictionary - object about the 'cpu'. - - The state is stored where each top level element has a UUID in its - attributes. eg: - - host['49c01812-3c28-1ad4-a59d-2a3f81b13ec2'] = { - 'name': 'norwich', - 'desc': 'Test Xen Host', - 'cpu': {'6fc2d1ed-7eb0-4c9d-8006-3657d5483ae0': , - '669df3b8-62be-4e61-800b-bbe8ee63a760': } - } - - will turn into: - - - - norwich - Test Xen Host - - - - - - - - Note that it only dumps one level, so the references to CPU are - stored in a separate file. - - """ - - def __init__(self, base = "/var/lib/xend/state"): - self.base = base - if not os.path.exists(self.base): - os.makedirs(self.base) - - def _xml_file(self, cls): - """Return the absolute filename of the XML state storage file. - - @param cls: name of the class. - @type cls: string - @rtype: string - @return absolute filename of XML file to write/read from. - """ - return os.path.join(self.base, '%s.xml' % cls) - - def load_state(self, cls): - """Load the saved state of a class from persistent XML storage. - - References loaded from the XML will just point to an empty - dictionary which the caller will need to replace manually. - - @param cls: name of the class to load. - @type cls: string - @rtype: dict - """ - - xml_path = self._xml_file(cls) - if not os.path.exists(xml_path): - return {} - - if os.path.getsize(xml_path) == 0: - return {} - - dom = minidom.parse(xml_path) - root = dom.documentElement - state = {} - - for child in root.childNodes: - if child.nodeType != Node.ELEMENT_NODE: - continue # skip non element nodes - - uuid = child.getAttribute('uuid').encode('utf8') - cls_dict = {} - for val_elem in child.childNodes: - if val_elem.nodeType != Node.ELEMENT_NODE: - continue # skip non element nodes - - val_name = val_elem.tagName - val_type = val_elem.getAttribute('type').encode('utf8') - val_uuid = val_elem.getAttribute('uuid').encode('utf8') - val_elem.normalize() - val_text = '' - if val_elem.firstChild: - val_text = val_elem.firstChild.nodeValue.strip() - - if val_type == 'list': - cls_dict[val_name] = [] - for item in val_elem.childNodes: - if item.nodeType != Node.ELEMENT_NODE: - continue # skip non element nodes - cls_dict[val_name].append(item.getAttribute('uuid')) - elif val_type == 'dict': - cls_dict[val_name] = {} - for item in val_elem.childNodes: - if item.nodeType != Node.ELEMENT_NODE: - continue # skip non element nodes - k = item.getAttribute('key').encode('utf8') - v = item.getAttribute('value').encode('utf8') - cls_dict[val_name][k] = v - elif val_type == 'string': - cls_dict[val_name] = val_text.encode('utf8') - elif val_type == 'float': - cls_dict[val_name] = float(val_text) - elif val_type == 'int': - cls_dict[val_name] = int(val_text) - elif val_type == 'bool': - cls_dict[val_name] = bool(int(val_text)) - state[uuid] = cls_dict - - dom.unlink() - return state - - def save_state(self, cls, state): - """Save a Xen API record struct into an XML persistent storage - for future loading when Xend restarts. - - If we encounter a dictionary or a list, we only store the - keys because they are going to be UUID references to another - object. - - @param cls: Class name (singular) of the record - @type cls: string - @param state: a Xen API struct of the state of the class. - @type state: dict - @rtype: None - """ - xml_path = self._xml_file(cls) - - doc = minidom.getDOMImplementation().createDocument(None, - cls + 's', - None) - root = doc.documentElement - - # Marshall a dictionary into our custom XML file format. - for uuid, info in state.items(): - node = doc.createElement(cls) - root.appendChild(node) - node.setAttribute('uuid', uuid) - - for key, val in info.items(): - store_val = val - store_type = None - - # deal with basic types - if type(val) in (str, unicode): - store_val = val - store_type = 'string' - elif type(val) == int: - store_val = str(val) - store_type = 'int' - elif type(val) == float: - store_val = str(val) - store_type = 'float' - elif type(val) == bool: - store_val = str(int(val)) - store_type = 'bool' - - if store_type is not None: - val_node = doc.createElement(key) - val_node.setAttribute('type', store_type) - node.appendChild(val_node) - # attach the value - val_text = doc.createTextNode(store_val) - val_node.appendChild(val_text) - continue - - # deal with dicts and lists - if type(val) == dict: - val_node = doc.createElement(key) - val_node.setAttribute('type', 'dict') - for val_item in val.keys(): - tmp = doc.createElement("item") - if key in ['other_config', 'device_config']: - tmp.setAttribute('key', str(val_item)) - tmp.setAttribute('value', str(val[val_item])) - else: - tmp.setAttribute('uuid', val_uuid) - val_node.appendChild(tmp) - node.appendChild(val_node) - elif type(val) in (list, tuple): - val_node = doc.createElement(key) - val_node.setAttribute('type', 'list') - for val_uuid in val: - tmp = doc.createElement("item") - tmp.setAttribute('uuid', val_uuid) - val_node.appendChild(tmp) - node.appendChild(val_node) - - open(xml_path, 'w').write(doc.toprettyxml()) - doc.unlink() - diff --git a/tools/python/xen/xend/XendStorageRepository.py b/tools/python/xen/xend/XendStorageRepository.py deleted file mode 100644 index 6ac94d38c8..0000000000 --- a/tools/python/xen/xend/XendStorageRepository.py +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/python -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2006, 2007 XenSource Ltd. -#============================================================================ -# -# Abstract class for XendStorageRepositories -# - -import threading -import sys - -from XendError import XendError -from XendVDI import * -from XendPBD import XendPBD - -XEND_STORAGE_NO_MAXIMUM = sys.maxint - -class XendStorageRepository: - """ Base class for Storage Repos. """ - - def __init__(self, uuid, - sr_type = "unknown", - name_label = 'Unknown', - name_description = 'Not Implemented', - storage_max = XEND_STORAGE_NO_MAXIMUM): - """ - @keyword storage_max: Maximum disk space to use in bytes. - @type storage_max: int - - @ivar storage_free: storage space free for this repository - @ivar images: mapping of all the images. - @type images: dictionary by image uuid. - @ivar lock: lock to provide thread safety. - """ - - # XenAPI Parameters - self.uuid = uuid - self.type = sr_type - self.name_label = name_label - self.name_description = name_description - self.images = {} - - self.physical_size = storage_max - self.physical_utilisation = 0 - self.virtual_allocation = 0 - self.content_type = '' - - self.lock = threading.RLock() - - def get_record(self, transient = True): - retval = {'uuid': self.uuid, - 'name_label': self.name_label, - 'name_description': self.name_description, - 'virtual_allocation': self.virtual_allocation, - 'physical_utilisation': self.physical_utilisation, - 'physical_size': self.physical_size, - 'type': self.type, - 'content_type': self.content_type, - 'VDIs': self.images.keys()} - if not transient: - retval ['PBDs'] = XendPBD.get_by_SR(self.uuid) - return retval - - - def is_valid_vdi(self, vdi_uuid): - return (vdi_uuid in self.images) - - def get_vdi_by_uuid(self, image_uuid): - self.lock.acquire() - try: - return self.images.get(image_uuid) - finally: - self.lock.release() - - def get_vdi_by_name_label(self, label): - self.lock.acquire() - try: - for image_uuid, image in self.images.items(): - if image.name_label == label: - return image_uuid - return None - finally: - self.lock.release() - - def get_vdis(self): - return self.images.keys() - - def create_vdi(self, vdi_struct): - raise NotImplementedError() - - def destroy_vdi(self, vdi_struct): - raise NotImplementedError() - - def list_images(self): - """ List all the available images by UUID. - - @rtype: list of strings. - @return: list of UUIDs - """ - self.lock.acquire() - try: - return self.images.keys() - finally: - self.lock.release() - diff --git a/tools/python/xen/xend/XendTask.py b/tools/python/xen/xend/XendTask.py deleted file mode 100644 index 5045a06d75..0000000000 --- a/tools/python/xen/xend/XendTask.py +++ /dev/null @@ -1,224 +0,0 @@ -#=========================================================================== -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2007 XenSource Ltd -#============================================================================ - -from xen.xend.XendAPIConstants import XEN_API_TASK_STATUS_TYPE -from xen.xend.XendLogging import log -import thread -import threading - -class XendTask(threading.Thread): - """Represents a Asynchronous Task used by Xen API. - - Basically proxies the callable object in a thread and returns the - results via self.{type,result,error_info}. - - @cvar task_progress: Thread local storage for progress tracking. - It is a dict indexed by thread_id. Note that the - thread_id may be reused when the previous - thread with the thread_id ends. - - @cvar task_progress_lock: lock on thread access to task_progress - - """ - - # progress stack: - # thread_id : [(start_task, end_task), - # (start_sub_task, end_sub_task)..] - # example : (0, 100), (50, 100) (50, 100) ... - # That would mean that the task is 75% complete. - # as it is 50% of the last 50% of the task. - - task_progress = {} - task_progress_lock = threading.Lock() - - def __init__(self, uuid, func, args, func_name, return_type, label, desc, - session): - """ - @param uuid: UUID of the task - @type uuid: string - @param func: Method to call (from XendAPI) - @type func: callable object - @param args: arguments to pass to function - @type args: list or tuple - @param label: name label of the task. - @type label: string - @param desc: name description of the task. - @type desc: string - @param func_name: function name, eg ('VM.start') - @type desc: string - """ - - threading.Thread.__init__(self) - self.status_lock = threading.Lock() - self.status = XEN_API_TASK_STATUS_TYPE[0] - - self.progress = 0 - self.type = return_type - self.uuid = uuid - - self.result = None - self.error_info = [] - - self.name_label = label or func.__name__ - self.name_description = desc - self.thread_id = 0 - - self.func_name = func_name - self.func = func - self.args = args - - self.session = session - - def set_status(self, new_status): - self.status_lock.acquire() - try: - self.status = new_status - finally: - self.status_lock.release() - - def get_status(self): - self.status_lock.acquire() - try: - return self.status - finally: - self.status_lock.release() - - def run(self): - """Runs the method and stores the result for later access. - - Is invoked by threading.Thread.start(). - """ - - self.thread_id = thread.get_ident() - self.task_progress_lock.acquire() - try: - self.task_progress[self.thread_id] = {} - self.progress = 0 - finally: - self.task_progress_lock.release() - - try: - result = self.func(*self.args) - if result['Status'] == 'Success': - self.result = result['Value'] - self.set_status(XEN_API_TASK_STATUS_TYPE[1]) - else: - self.error_info = result['ErrorDescription'] - self.set_status(XEN_API_TASK_STATUS_TYPE[2]) - except Exception, e: - log.exception('Error running Async Task') - self.error_info = ['INTERNAL ERROR', str(e)] - self.set_status(XEN_API_TASK_STATUS_TYPE[2]) - - self.task_progress_lock.acquire() - try: - del self.task_progress[self.thread_id] - self.progress = 100 - finally: - self.task_progress_lock.release() - - def get_record(self): - """Returns a Xen API compatible record.""" - return { - 'uuid': self.uuid, - 'name_label': self.name_label, - 'name_description': self.name_description, - 'status': self.status, - 'progress': self.get_progress(), - 'type': self.type, - 'result': self.result, - 'error_info': self.error_info, - 'allowed_operations': {}, - 'session': self.session, - } - - def get_progress(self): - """ Checks the thread local progress storage. """ - if self.status != XEN_API_TASK_STATUS_TYPE[0]: - return 100 - - self.task_progress_lock.acquire() - try: - # Pop each progress range in the stack and map it on to - # the next progress range until we find out cumulative - # progress based on the (start, end) range of each level - start = 0 - prog_stack = self.task_progress.get(self.thread_id, [])[:] - if len(prog_stack) > 0: - start, stop = prog_stack.pop() - while prog_stack: - new_start, new_stop = prog_stack.pop() - start = new_start + ((new_stop - new_start)/100.0 * start) - - # only update progress if it increases, this will prevent - # progress from going backwards when tasks are popped off - # the stack - if start > self.progress: - self.progress = int(start) - finally: - self.task_progress_lock.release() - - return self.progress - - - def log_progress(cls, progress_min, progress_max, - func, *args, **kwds): - """ Callable function wrapper that logs the progress of the - function to thread local storage for task progress calculation. - - This is a class method so other parts of Xend will update - the task progress by calling: - - XendTask.push_progress(progress_min, progress_max, - func, *args, **kwds) - - The results of the progress is stored in thread local storage - and the result of the func(*args, **kwds) is returned back - to the caller. - - """ - thread_id = thread.get_ident() - retval = None - - # Log the start of the method - cls.task_progress_lock.acquire() - try: - if type(cls.task_progress.get(thread_id)) != list: - cls.task_progress[thread_id] = [] - - cls.task_progress[thread_id].append((progress_min, - progress_max)) - finally: - cls.task_progress_lock.release() - - # Execute the method - retval = func(*args, **kwds) - - # Log the end of the method by popping the progress range - # off the stack. - cls.task_progress_lock.acquire() - try: - cls.task_progress[thread_id].pop() - finally: - cls.task_progress_lock.release() - - return retval - - log_progress = classmethod(log_progress) - - - diff --git a/tools/python/xen/xend/XendTaskManager.py b/tools/python/xen/xend/XendTaskManager.py deleted file mode 100644 index 6282078a44..0000000000 --- a/tools/python/xen/xend/XendTaskManager.py +++ /dev/null @@ -1,110 +0,0 @@ -#=========================================================================== -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2007 XenSource Ltd -#============================================================================ - -""" -Task Manager for Xen API asynchronous tasks. - -Stores all tasks in a simple dictionary in module's own local storage to -avoid the 'instance()' methods. - -Tasks are indexed by UUID. - -""" - -from xen.xend.XendTask import XendTask -from xen.xend import uuid -import threading - -tasks = {} -tasks_lock = threading.Lock() - -def create_task(func, args, func_name, return_type, label, session): - """Creates a new Task and registers it with the XendTaskManager. - - @param func: callable object XMLRPC method - @type func: callable object - @param args: tuple or list of arguments - @type args: tuple or list - @param func_name: XMLRPC method name, so we can estimate the progress - @type func_name: string - - @return: Task UUID - @rtype: string. - """ - task_uuid = uuid.createString() - try: - tasks_lock.acquire() - task = XendTask(task_uuid, func, args, func_name, return_type, label, - '', session) - tasks[task_uuid] = task - finally: - tasks_lock.release() - - task.start() - - return task_uuid - -def destroy_task(task_uuid): - """Destroys a task. - - @param task_uuid: Task UUID - @type task_uuid: string. - """ - try: - tasks_lock.acquire() - if task_uuid in tasks: - del tasks[task_uuid] - finally: - tasks_lock.release() - -def get_all_tasks(): - """ Returns all the UUID of tracked tasks, completed or pending. - - @returns: list of UUIDs - @rtype: list of strings - """ - try: - tasks_lock.acquire() - return tasks.keys() - finally: - tasks_lock.release() - -def get_task(task_uuid): - """ Retrieves a task by UUID. - - @rtype: XendTask or None - @return: Task denoted by UUID. - """ - try: - tasks_lock.acquire() - return tasks.get(task_uuid) - finally: - tasks_lock.release() - -def get_tasks_by_name(task_name): - """ Retrieves a task by UUID. - - @rtype: XendTask or None - @return: Task denoted by UUID. - """ - try: - tasks_lock.acquire() - return [t.uuid for t in tasks if t.name_label == name] - finally: - tasks_lock.release() - - diff --git a/tools/python/xen/xend/XendVDI.py b/tools/python/xen/xend/XendVDI.py deleted file mode 100644 index f8abea615f..0000000000 --- a/tools/python/xen/xend/XendVDI.py +++ /dev/null @@ -1,214 +0,0 @@ -#!/usr/bin/python -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2006 XenSource Ltd. -#============================================================================ -# -# Representation of a Xen API VDI -# - -import os - -from xen.util.xmlrpclib2 import stringify -from xmlrpclib import dumps, loads -from xen.util import xsconstants -import xen.util.xsm.xsm as security -from xen.xend.XendError import SecurityError - -KB = 1024 -MB = 1024 * 1024 - -class AutoSaveObject(object): - - def __init__(self): - self.cfg_path = None - self.auto_save = True - object - - def save_config(self, cfg_file = None): - raise NotImplementedError() - - def __setattr__(self, name, value): - """A very simple way of making sure all attribute changes are - flushed to disk. - """ - object.__setattr__(self, name, value) - if name != 'auto_save' and getattr(self, 'auto_save', False): - self.save_config() - -class XendVDI(AutoSaveObject): - """Generic Xen API compatible VDI representation. - - @cvar SAVED_CFG: list of configuration attributes to save. - @cvar SAVED_CFG_INT: list of configurations that should be ints. - """ - - SAVED_CFG = ['name_label', - 'name_description', - 'virtual_size', - 'physical_utilisation', - 'sharable', - 'read_only', - 'type'] - - SAVED_CFG_INT = ['sector_size', 'virtual_size', 'physical_utilisation'] - - def __init__(self, uuid, sr_uuid): - self.uuid = uuid - self.sr_uuid = sr_uuid - self.name_label = "" - self.name_description = "" - self.virtual_size = 0 - self.physical_utilisation = 0 - self.sharable = False - self.read_only = False - self.type = "system" - self.other_config = {} - - def getVBDs(self): - from xen.xend import XendDomain - vbd_refs = [d.get_vbds() for d in XendDomain.instance().list('all')] - vbd_refs = reduce(lambda x, y: x + y, vbd_refs) - vbds = [] - for vbd_ref in vbd_refs: - vdi = XendDomain.instance().get_dev_property_by_uuid('vbd', vbd_ref, 'VDI') - if vdi == self.uuid: - vbds.append(vbd_ref) - return vbds - - def load_config_dict(self, cfg): - """Loads configuration into the object from a dict. - - @param cfg: configuration dict - @type cfg: dict - """ - self.auto_save = False - for key in self.SAVED_CFG: - if key in cfg: - if key in self.SAVED_CFG_INT: - setattr(self, key, int(cfg[key])) - else: - setattr(self, key, cfg[key]) - self.auto_save = True - - def load_config(self, cfg_path): - """Loads configuration from an XMLRPC parameter format. - - @param cfg_path: configuration file path - @type cfg_path: type - @rtype: bool - @return: Successful or not. - """ - try: - cfg, _ = loads(open(cfg_path).read()) - cfg = cfg[0] - self.load_config_dict(cfg) - self.cfg_path = cfg_path - except IOError, e: - return False - - return True - - def save_config(self, cfg_path = None): - """Saves configuration at give path in XMLRPC parameter format. - - If cfg_path is not give, it defaults to the where the VDI - configuration as loaded if it load_config was called. - - @keyword cfg_path: optional configuration file path - @rtype: bool - @return: Successful or not. - """ - try: - if not cfg_path and not self.cfg_path: - return False - - if not cfg_path: - cfg_path = self.cfg_path - - cfg = {} - for key in self.SAVED_CFG: - try: - cfg[key] = getattr(self, key) - except AttributeError: - pass - open(cfg_path, 'w').write(dumps((stringify(cfg),), - allow_none = True)) - except IOError, e: - return False - - return True - - def get_record(self, transient = True): - return {'uuid': self.uuid, - 'name_label': self.name_label, - 'name_description': self.name_description, - 'virtual_size': self.virtual_size, - 'physical_utilisation': self.physical_utilisation, - 'sharable': self.sharable, - 'read_only': self.read_only, - 'type': self.type, - 'SR': self.sr_uuid, - 'other_config': self.other_config, - 'VBDs': self.getVBDs()} - - def get_location(self): - raise NotImplementedError() - - def set_security_label(self, sec_lab, old_lab): - image = self.get_location() - rc = security.set_resource_label_xapi(image, sec_lab, old_lab) - if rc != xsconstants.XSERR_SUCCESS: - raise SecurityError(rc) - return rc - - def get_security_label(self): - image = self.get_location() - return security.get_resource_label_xapi(image) - - -class XendQCoWVDI(XendVDI): - def __init__(self, uuid, sr_uuid, qcow_path, cfg_path, vsize, psize): - XendVDI.__init__(self, uuid, sr_uuid) - self.auto_save = False - self.qcow_path = qcow_path - self.cfg_path = cfg_path - self.physical_utilisation = psize - self.virtual_size = vsize - self.auto_save = True - self.other_config['location'] = 'tap:qcow:%s' % self.qcow_path - - def get_location(self): - return self.other_config['location'] - -class XendLocalVDI(XendVDI): - def __init__(self, vdi_struct): - vdi_uuid = vdi_struct['uuid'] - sr_uuid = vdi_struct['SR'] - XendVDI.__init__(self, vdi_uuid, sr_uuid) - - self.auto_save = False - self.cfg_path = None - self.name_label = vdi_struct.get('name_label','') - self.name_description = vdi_struct.get('name_description', '') - self.physical_utilisation = 0 - self.virtual_size = 0 - self.type = vdi_struct.get('type', '') - self.sharable = vdi_struct.get('sharable', False) - self.read_only = vdi_struct.get('read_only', False) - self.other_config = vdi_struct.get('other_config', {}) - - def get_location(self): - return self.other_config['location'] diff --git a/tools/python/xen/xend/XendVMMetrics.py b/tools/python/xen/xend/XendVMMetrics.py deleted file mode 100644 index 9577060fc6..0000000000 --- a/tools/python/xen/xend/XendVMMetrics.py +++ /dev/null @@ -1,146 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (c) 2006-2007 Xensource Inc. -# Copyright (c) 2007 Tom Wilkie -#============================================================================ - -from xen.xend.XendLogging import log -from xen.xend.XendBase import XendBase -import xen.lowlevel.xc - -xc = xen.lowlevel.xc.xc() - -class XendVMMetrics(XendBase): - """VM Metrics.""" - - def getClass(self): - return "VM_metrics" - - def getAttrRO(self): - attrRO = ['memory_actual', - 'VCPUs_number', - 'VCPUs_utilisation', - 'VCPUs_CPU', - 'VCPUs_flags', - 'VCPUs_params', - 'state', - 'start_time', - 'last_updated'] - return XendBase.getAttrRO() + attrRO - - getClass = classmethod(getClass) - getAttrRO = classmethod(getAttrRO) - - def __init__(self, uuid, xend_domain_instance): - XendBase.__init__(self, uuid, {}) - self.xend_domain_instance = xend_domain_instance - - def get_memory_actual(self): - domInfo = self.xend_domain_instance.getDomInfo() - if domInfo: - return domInfo["mem_kb"] * 1024 - else: - return 0 - - def get_VCPUs_number(self): - domInfo = self.xend_domain_instance.getDomInfo() - if domInfo: - return domInfo["online_vcpus"] - else: - return 0 - - def get_VCPUs_utilisation(self): - return self.xend_domain_instance.get_vcpus_util() - - def get_VCPUs_CPU(self): - domid = self.xend_domain_instance.getDomid() - if domid is not None: - vcpus_cpu = {} - vcpus_max = self.xend_domain_instance.info['VCPUs_max'] - for i in range(0, vcpus_max): - info = xc.vcpu_getinfo(domid, i) - vcpus_cpu[i] = info['cpu'] - return vcpus_cpu - else: - return {} - - def get_VCPUs_flags(self): - domid = self.xend_domain_instance.getDomid() - if domid is not None: - vcpus_flags = {} - vcpus_max = self.xend_domain_instance.info['VCPUs_max'] - for i in range(0, vcpus_max): - info = xc.vcpu_getinfo(domid, i) - flags = [] - def set_flag(flag): - if info[flag] == 1: - flags.append(flag) - set_flag('blocked') - set_flag('online') - set_flag('running') - vcpus_flags[i] = flags - return vcpus_flags - else: - return {} - - def get_state(self): - try: - domid = self.xend_domain_instance.getDomid() - domlist = xc.domain_getinfo(domid, 1) - if domlist and domid == domlist[0]['domid']: - dominfo = domlist[0] - - states = [] - def addState(key): - if dominfo[key] == 1: - states.append(key) - - addState("running") - addState("blocked") - addState("paused") - addState("dying") - addState("crashed") - addState("shutdown") - return states - except Exception, err: - # ignore missing domain - log.trace("domain_getinfo(%d) failed, ignoring: %s", domid, str(err)) - return [] - - def get_VCPUs_params(self): - domid = self.xend_domain_instance.getDomid() - if domid is not None: - params_live = {} - vcpus_max = self.xend_domain_instance.info['VCPUs_max'] - for i in range(0, vcpus_max): - info = xc.vcpu_getinfo(domid, i) - params_live['cpumap%i' % i] = \ - ",".join(map(str, info['cpumap'])) - - # FIXME: credit2?? - params_live.update(xc.sched_credit_domain_get(domid)) - - return params_live - else: - return {} - - def get_start_time(self): - import xen.xend.XendAPI as XendAPI - return XendAPI.datetime( - self.xend_domain_instance.info.get("start_time", 0)) - - def get_last_updated(self): - import xen.xend.XendAPI as XendAPI - return XendAPI.now() diff --git a/tools/python/xen/xend/XendVnet.py b/tools/python/xen/xend/XendVnet.py deleted file mode 100644 index 8f5b6d7dc2..0000000000 --- a/tools/python/xen/xend/XendVnet.py +++ /dev/null @@ -1,181 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2005 XenSource Ltd -#============================================================================ - -"""Handler for vnet operations. -""" - -from xen.util import Brctl -from xen.xend import sxp -from xen.xend.XendError import XendError -from xen.xend.XendLogging import log -from xen.xend.xenstore.xstransact import xstransact - - -def vnet_cmd(cmd): - out = None - try: - try: - out = file("/proc/vnet/policy", "wb") - sxp.show(cmd, out) - except IOError, ex: - raise XendError(str(ex)) - finally: - if out: out.close() - -class XendVnetInfo: - - vifctl_ops = {'up': 'vif.add', 'down': 'vif.del'} - - def __init__(self, dbpath, config=None): - if config: - self.id = str(sxp.child_value(config, 'id')) - self.dbid = self.id.replace(':', '-') - self.dbpath = dbpath + '/' + self.dbid - self.config = config - else: - self.dbpath = dbpath - self.importFromDB() - - self.bridge = sxp.child_value(self.config, 'bridge') - if not self.bridge: - self.bridge = "vnet%s" % self.id - self.vnetif = sxp.child_value(self.config, 'vnetif') - if not self.vnetif: - self.vnetif = "vnif%s" % self.id - - - def exportToDB(self, save=False, sync=False): - to_store = { - 'id' : self.id, - 'dbid' : self.dbid, - 'config' : sxp.to_string(self.config) - } - xstransact.Write(self.dbpath, to_store) - - - def importFromDB(self): - (self.id, self.dbid, c) = xstransact.Gather(self.dbpath, - ('id', str), - ('dbid', str), - ('config', str)) - self.config = sxp.from_string(c) - - - def sxpr(self): - return self.config - - def configure(self): - log.info("Configuring vnet %s", self.id) - val = vnet_cmd(['vnet.add'] + sxp.children(self.config)) - Brctl.bridge_create(self.bridge) - Brctl.vif_bridge_add({'bridge': self.bridge, 'vif': self.vnetif}) - return val - - def delete(self): - log.info("Deleting vnet %s", self.id) - Brctl.vif_bridge_rem({'bridge': self.bridge, 'vif': self.vnetif}) - Brctl.bridge_del(self.bridge) - val = vnet_cmd(['vnet.del', self.id]) - xstransact.Remove(self.dbpath) - return val - - def vifctl(self, op, vif, vmac): - try: - fn = self.vifctl_ops[op] - return vnet_cmd([fn, ['vnet', self.id], ['vif', vif], ['vmac', vmac]]) - except XendError: - log.warning("vifctl failed: op=%s vif=%s mac=%s", op, vif, vmac) - -class XendVnet: - """Index of all vnets. Singleton. - """ - - dbpath = "/vnet" - - def __init__(self): - # Table of vnet info indexed by vnet id. - self.vnet = {} - listing = xstransact.List(self.dbpath) - for entry in listing: - try: - info = XendVnetInfo(self.dbpath + '/' + entry) - self.vnet[info.id] = info - info.configure() - except XendError, ex: - log.warning("Failed to configure vnet %s: %s", str(info.id), str(ex)) - except Exception, ex: - log.exception("Vnet error") - xstransact.Remove(self.dbpath + '/' + entry) - - def vnet_of_bridge(self, bridge): - """Get the vnet for a bridge (if any). - - @param bridge: bridge name - @return vnet or None - """ - for v in self.vnet.values(): - if v.bridge == bridge: - return v - else: - return None - - def vnet_ls(self): - """List all vnet ids. - """ - return self.vnet.keys() - - def vnets(self): - """List all vnets. - """ - return self.vnet.values() - - def vnet_get(self, id): - """Get a vnet. - - @param id vnet id - """ - id = str(id) - return self.vnet.get(id) - - def vnet_create(self, config): - """Create a vnet. - - @param config: config - """ - info = XendVnetInfo(self.dbpath, config=config) - self.vnet[info.id] = info - info.exportToDB() - info.configure() - - def vnet_delete(self, id): - """Delete a vnet. - - @param id: vnet id - """ - info = self.vnet_get(id) - if info: - del self.vnet[id] - info.delete() - -def instance(): - global inst - try: - inst - except: - inst = XendVnet() - return inst diff --git a/tools/python/xen/xend/XendXSPolicy.py b/tools/python/xen/xend/XendXSPolicy.py deleted file mode 100644 index dd508d9b9e..0000000000 --- a/tools/python/xen/xend/XendXSPolicy.py +++ /dev/null @@ -1,305 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (c) 2007 IBM Corporation -# Copyright (c) 2006 Xensource -#============================================================================ - -import base64 -import logging -from xen.xend import XendDomain -from xen.xend.XendBase import XendBase -from xen.xend.XendError import * -from xen.xend.XendAPIConstants import * -from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance -from xen.util import xsconstants -import xen.util.xsm.xsm as security - -log = logging.getLogger("xend.XendXSPolicy") -log.setLevel(logging.TRACE) - - -class XendXSPolicy(XendBase): - """ Administration class for an XSPolicy. """ - - def getClass(self): - return "XSPolicy" - - def getMethods(self): - methods = ['activate_xspolicy'] - return XendBase.getMethods() + methods - - def getFuncs(self): - funcs = [ 'get_xstype', - 'set_xspolicy', - 'reset_xspolicy', - 'get_xspolicy', - 'rm_xsbootpolicy', - 'get_resource_label', - 'set_resource_label', - 'get_labeled_resources', - 'can_run', - 'getenforce', - 'setenforce'] - return XendBase.getFuncs() + funcs - - getClass = classmethod(getClass) - getMethods = classmethod(getMethods) - getFuncs = classmethod(getFuncs) - - def __init__(self, xspol, record, uuid): - """ xspol = actual XSPolicy object """ - self.xspol = xspol - XendBase.__init__(self, uuid, record) - - def get_record(self): - xspol_record = { - 'uuid' : self.get_uuid(), - 'flags' : XSPolicyAdminInstance().get_policy_flags(self.xspol), - 'repr' : self.xspol.toxml(), - 'type' : self.xspol.get_type(), - } - return xspol_record - - def get_xstype(self): - return XSPolicyAdminInstance().isXSEnabled() - - def set_xspolicy(self, xstype, policy, flags, overwrite): - ref = "" - xstype = int(xstype) - flags = int(flags) - - polstate = { 'xs_ref': "", 'repr' : "", 'type' : 0, - 'flags' : 0 , 'version': 0 , 'errors' : "", 'xserr' : 0 } - if xstype == xsconstants.XS_POLICY_ACM: - poladmin = XSPolicyAdminInstance() - try: - (xspol, rc, errors) = poladmin.add_acmpolicy_to_system( - policy, flags, - overwrite) - if rc != 0: - polstate.update( { 'xserr' : rc, - 'errors': base64.b64encode(errors) } ) - else: - ref = xspol.get_ref() - polstate = { - 'xs_ref' : ref, - 'flags' : poladmin.get_policy_flags(xspol), - 'type' : xstype, - 'repr' : "", - 'version': xspol.get_version(), - 'errors' : base64.b64encode(errors), - 'xserr' : rc, - } - except Exception, e: - raise - elif xstype == xsconstants.XS_POLICY_FLASK: - rc, errors = security.set_policy(xstype, policy); - if rc != 0: - polstate.update( { 'xserr' : -xsconstants.XSERR_POLICY_LOAD_FAILED, - 'errors': errors } ) - else: - polstate.update( { 'xserr' : xsconstants.XSERR_SUCCESS, - 'errors': errors } ) - else: - raise SecurityError(-xsconstants.XSERR_POLICY_TYPE_UNSUPPORTED) - return polstate - - - def reset_xspolicy(self, xstype): - xstype = int(xstype) - polstate = { 'xs_ref': "", 'repr' : "", 'type' : 0, - 'flags' : 0 , 'version': 0 , 'errors' : "", 'xserr' : 0 } - if xstype == xsconstants.XS_POLICY_ACM: - poladmin = XSPolicyAdminInstance() - try: - (xspol, rc, errors) = poladmin.reset_acmpolicy() - if rc != 0: - polstate.update( { 'xserr' : rc, - 'errors': base64.b64encode(errors) } ) - else: - ref = xspol.get_ref() - polstate = { - 'xs_ref' : ref, - 'flags' : poladmin.get_policy_flags(xspol), - 'type' : xstype, - 'repr' : "", - 'version': xspol.get_version(), - 'errors' : base64.b64encode(errors), - 'xserr' : rc, - } - except Exception, e: - raise - else: - raise SecurityError(-xsconstants.XSERR_POLICY_TYPE_UNSUPPORTED) - return polstate - - - def activate_xspolicy(self, flags): - flags = int(flags) - rc = -xsconstants.XSERR_GENERAL_FAILURE - poladmin = XSPolicyAdminInstance() - try: - rc = poladmin.activate_xspolicy(self.xspol, flags) - except Exception, e: - log.info("Activate_policy: %s" % str(e)) - if rc != flags: - raise SecurityError(rc) - return flags - - def get_xspolicy(self): - polstate = { 'xs_ref' : "", - 'repr' : "", - 'type' : 0, - 'flags' : 0, - 'version': "", - 'errors' : "", - 'xserr' : 0 } - poladmin = XSPolicyAdminInstance() - refs = poladmin.get_policies_refs() - # Will return one or no policy - if refs and len(refs) > 0: - ref = refs[0] - xspol = XSPolicyAdminInstance().policy_from_ref(ref) - if xspol: - polstate = { - 'xs_ref' : ref, - 'repr' : xspol.toxml(), - 'type' : xspol.get_type(), - 'flags' : poladmin.get_policy_flags(xspol), - 'version': xspol.get_version(), - 'errors' : "", - 'xserr' : 0, - } - return polstate - - def rm_xsbootpolicy(self): - rc = XSPolicyAdminInstance().rm_bootpolicy() - if rc != xsconstants.XSERR_SUCCESS: - raise SecurityError(rc) - - def get_labeled_resources(self): - return security.get_labeled_resources_xapi() - - def set_resource_label(self, resource, sec_lab, old_lab): - rc = security.set_resource_label_xapi(resource, sec_lab, old_lab) - if rc != xsconstants.XSERR_SUCCESS: - raise SecurityError(rc) - - def get_resource_label(self, resource): - res = security.get_resource_label_xapi(resource) - return res - - def can_run(self, sec_label): - irc = security.validate_label_xapi(sec_label, 'dom') - if irc != xsconstants.XSERR_SUCCESS: - raise SecurityError(irc) - return security.check_can_run(sec_label) - - def getenforce(self): - return security.getenforce() - - def setenforce(self, mode): - return security.setenforce(mode) - - get_xstype = classmethod(get_xstype) - get_xspolicy = classmethod(get_xspolicy) - set_xspolicy = classmethod(set_xspolicy) - reset_xspolicy = classmethod(reset_xspolicy) - rm_xsbootpolicy = classmethod(rm_xsbootpolicy) - set_resource_label = classmethod(set_resource_label) - get_resource_label = classmethod(get_resource_label) - get_labeled_resources = classmethod(get_labeled_resources) - can_run = classmethod(can_run) - getenforce = classmethod(getenforce) - setenforce = classmethod(setenforce) - - -class XendACMPolicy(XendXSPolicy): - """ Administration class of an ACMPolicy """ - - def getClass(self): - return "ACMPolicy" - - def getAttrRO(self): - attrRO = [ 'xml', - 'map', - 'binary', - 'header' ] - return XendXSPolicy.getAttrRO() + attrRO - - def getFuncs(self): - funcs = [ 'get_enforced_binary', 'get_VM_ssidref' ] - return XendBase.getFuncs() + funcs - - getClass = classmethod(getClass) - getAttrRO = classmethod(getAttrRO) - getFuncs = classmethod(getFuncs) - - def __init__(self, acmpol, record, uuid): - """ acmpol = actual ACMPolicy object """ - self.acmpol = acmpol - XendXSPolicy.__init__(self, acmpol, record, uuid) - - def get_record(self): - polstate = { - 'uuid' : self.get_uuid(), - 'flags' : XSPolicyAdminInstance().get_policy_flags(self.acmpol), - 'repr' : self.acmpol.toxml(), - 'type' : self.acmpol.get_type(), - } - return polstate - - def get_header(self): - header = { - 'policyname' : "", 'policyurl' : "", 'reference' : "", - 'date' : "", 'namespaceurl' : "", 'version' : "", - } - try: - header = self.acmpol.get_header_fields_map() - except: - pass - return header - - def get_xml(self): - return self.acmpol.toxml() - - def get_map(self): - return self.acmpol.get_map() - - def get_binary(self): - polbin = self.acmpol.get_bin() - return base64.b64encode(polbin) - - def get_VM_ssidref(self, vm_ref): - dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - if not dom: - raise InvalidHandleError("VM", vm_ref) - if dom._stateGet() not in [ XEN_API_VM_POWER_STATE_RUNNING, \ - XEN_API_VM_POWER_STATE_PAUSED ]: - raise VMBadState("Domain is not running or paused.") - ssid = security.get_ssid(dom.getDomid()) - if not ssid: - raise SecurityError(-xsconstants.XSERR_GENERAL_FAILURE) - return ssid[3] - - def get_enforced_binary(self): - polbin = XSPolicyAdminInstance(). \ - get_enforced_binary(xsconstants.XS_POLICY_ACM) - if polbin: - return base64.b64encode(polbin) - return None - - get_enforced_binary = classmethod(get_enforced_binary) - get_VM_ssidref = classmethod(get_VM_ssidref) diff --git a/tools/python/xen/xend/XendXSPolicyAdmin.py b/tools/python/xen/xend/XendXSPolicyAdmin.py deleted file mode 100644 index 8df8d0d728..0000000000 --- a/tools/python/xen/xend/XendXSPolicyAdmin.py +++ /dev/null @@ -1,386 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2006,2007 International Business Machines Corp. -# Author: Stefan Berger -#============================================================================ -import os -import shutil - -from xml.dom import minidom, Node - -from xen.xend.XendLogging import log -from xen.xend import uuid -from xen.util import xsconstants, bootloader -import xen.util.xsm.acm.acm as security -from xen.util.xspolicy import XSPolicy -from xen.util.acmpolicy import ACMPolicy, initialize -from xen.xend.XendError import SecurityError - - -class XSPolicyAdmin: - """ The class that handles the managed policies in the system. - Handles adding and removing managed policies. All managed - policies are handled using a reference (UUID) which is - assigned to the policy by this class. - """ - - def __init__(self, maxpolicies): - """ Create a management class for managing the system's - policies. - - @param maxpolicies: The max. number of policies allowed - on the system (currently '1') - """ - self.maxpolicies = maxpolicies - self.policies = {} - self.xsobjs = {} - bootloader.init() - - if security.on() == xsconstants.XS_POLICY_ACM: - self.__acm_init() - - def __acm_init(self): - act_pol_name = self.get_hv_loaded_policy_name() - initialize() - - ref = uuid.createString() - try: - self.xsobjs[ref] = ACMPolicy(name=act_pol_name, ref=ref) - self.policies[ref] = (act_pol_name, xsconstants.ACM_POLICY_ID) - self.xsobjs[ref].validate_enforced_policy_hash() - except Exception, e: - log.error("Could not find XML representation of policy '%s': " - "%s" % (act_pol_name,e)) - rc, errors, acmpol_def = ACMPolicy.force_default_policy(ref) - if rc == xsconstants.XSERR_SUCCESS: - self.xsobjs[ref] = acmpol_def - self.policies[ref] = (acmpol_def.get_name(), - xsconstants.ACM_POLICY_ID) - log.info("Switched to DEFAULT policy.") - - log.debug("XSPolicyAdmin: Known policies: %s" % self.policies) - - - def isXSEnabled(self): - """ Check whether 'security' is enabled on this system. - """ - rc = 0 - if security.on() == xsconstants.XS_POLICY_ACM: - rc |= xsconstants.XS_POLICY_ACM - else: - rc |= xsconstants.XS_POLICY_FLASK - return rc - - def add_acmpolicy_to_system(self, xmltext, flags, overwrite): - """ Add an ACM policy's xml representation to the system. The - policy will automatically be compiled - flags: - XS_INST_BOOT : make policy the one to boot the system with - by default; if there's a policy already installed, - refuse to install this policy unless its one with - the same name - XS_INST_LOAD : load the policy immediately; if this does not work - refuse to install this policy - overwrite: - If any policy is installed and this is False, refuse to install - this policy - If flags is True, then any existing policy will be removed from - the system and the new one will be installed - """ - from xen.xend import XendDomain - domains = XendDomain.instance() - try: - domains.domains_lock.acquire() - return self.__add_acmpolicy_to_system(xmltext, flags, overwrite) - finally: - domains.domains_lock.release() - - def __add_acmpolicy_to_system(self, xmltext, flags, overwrite): - errors = "" - if security.on() != xsconstants.XS_POLICY_ACM: - raise SecurityError(-xsconstants.XSERR_POLICY_TYPE_UNSUPPORTED) - loadedpol = self.get_loaded_policy() - if loadedpol: - # This is meant as an update to a currently loaded policy - if flags & xsconstants.XS_INST_LOAD == 0: - raise SecurityError(-xsconstants.XSERR_POLICY_LOADED) - - # Remember old flags, so they can be restored if update fails - old_flags = self.get_policy_flags(loadedpol) - - # Remove policy from bootloader in case of new name of policy - self.rm_bootpolicy() - - rc, errors = loadedpol.update(xmltext) - if rc == 0: - irc = self.activate_xspolicy(loadedpol, flags) - # policy is loaded; if setting the boot flag fails it's ok. - else: - old_flags = old_flags & xsconstants.XS_INST_BOOT - log.info("OLD FLAGS TO RESTORE: %s" % str(old_flags)) - if old_flags != 0: - self.activate_xspolicy(loadedpol, xsconstants.XS_INST_BOOT) - - return (loadedpol, rc, errors) - - try: - dom = minidom.parseString(xmltext.encode("utf-8")) - except: - raise SecurityError(-xsconstants.XSERR_BAD_XML) - - ref = uuid.createString() - - acmpol = ACMPolicy(dom=dom, ref=ref) - - #First some basic tests that do not modify anything: - - if flags & xsconstants.XS_INST_BOOT and not overwrite: - filename = acmpol.get_filename(".bin","",dotted=True) - if bootloader.get_default_policy != None and \ - not bootloader.loads_default_policy(filename): - raise SecurityError(-xsconstants.XSERR_BOOTPOLICY_INSTALLED) - - if not overwrite and len(self.policies) >= self.maxpolicies: - raise SecurityError(-xsconstants.XSERR_BOOTPOLICY_INSTALLED) - - if overwrite: - #This should only give one key since only one policy is - #allowed. - keys = self.policies.keys() - for k in keys: - self.rm_bootpolicy() - rc = self.rm_policy_from_system(k, force=overwrite) - if rc != xsconstants.XSERR_SUCCESS: - raise SecurityError(rc) - - rc = acmpol.compile() - if rc != 0: - raise SecurityError(rc) - - if flags & xsconstants.XS_INST_LOAD: - rc = acmpol.loadintohv() - if rc != 0: - raise SecurityError(rc) - - if flags & xsconstants.XS_INST_BOOT: - rc = self.make_boot_policy(acmpol) - if rc != 0: - # If it cannot be installed due to unsupported - # bootloader, let it be ok. - pass - - if dom: - new_entry = { ref : tuple([acmpol.get_name(), - xsconstants.ACM_POLICY_ID]) } - self.policies.update(new_entry) - self.xsobjs[ref] = acmpol - return (acmpol, xsconstants.XSERR_SUCCESS, errors) - - - def reset_acmpolicy(self): - """ - Attempt to reset the system's policy by udating it with - the DEFAULT policy. - """ - from xen.xend import XendDomain - domains = XendDomain.instance() - try: - domains.domains_lock.acquire() - xml = ACMPolicy.get_reset_policy_xml() - flags = xsconstants.XS_INST_BOOT | xsconstants.XS_INST_LOAD - return self.__add_acmpolicy_to_system(xml, flags, True) - finally: - domains.domains_lock.release() - - - def make_boot_policy(self, acmpol): - if acmpol.is_default_policy(): - return xsconstants.XSERR_SUCCESS - rc = acmpol.copy_policy_file(".bin","/boot") - if rc != xsconstants.XSERR_SUCCESS: - return rc - - try: - filename = acmpol.get_filename(".bin","",dotted=True) - if bootloader.set_default_boot_policy(filename) != True: - return xsconstants.XSERR_BOOTPOLICY_INSTALL_ERROR - except: - return xsconstants.XSERR_FILE_ERROR - return xsconstants.XSERR_SUCCESS - - def activate_xspolicy(self, xspol, flags): - from xen.xend import XendDomain - domains = XendDomain.instance() - try: - domains.domains_lock.acquire() - return self.__activate_xspolicy(xspol, flags) - finally: - domains.domains_lock.release() - - def __activate_xspolicy(self, xspol, flags): - rc = xsconstants.XSERR_SUCCESS - if flags & xsconstants.XS_INST_LOAD: - rc = xspol.loadintohv() - if rc == xsconstants.XSERR_SUCCESS and \ - flags & xsconstants.XS_INST_BOOT: - rc = self.make_boot_policy(xspol) - if rc == xsconstants.XSERR_SUCCESS: - rc = flags - return rc - - def rm_policy_from_system(self, ref, force=False): - if self.policies.has_key(ref): - acmpol = self.xsobjs[ref] - rc = acmpol.destroy() - if rc == xsconstants.XSERR_SUCCESS or force: - del self.policies[ref] - del self.xsobjs[ref] - rc = xsconstants.XSERR_SUCCESS - return rc - - def rm_bootpolicy(self): - """ Remove any (ACM) boot policy from the grub configuration file - """ - rc = 0 - title = bootloader.get_default_title() - if title != None: - polnames = [] - for (k, v) in self.xsobjs.items(): - polnames.append(v.get_filename(".bin","",dotted=True)) - bootloader.rm_policy_from_boottitle(title, polnames) - else: - rc = -xsconstants.XSERR_NO_DEFAULT_BOOT_TITLE - return rc - - def get_policy_flags(self, acmpol): - """ Get the currently active flags of a policy, i.e., whether the - system is using this policy as its boot policy for the default - boot title. - """ - flags = 0 - - filename = acmpol.get_filename(".bin","", dotted=True) - if bootloader.loads_default_policy(filename) or \ - acmpol.is_default_policy(): - flags |= xsconstants.XS_INST_BOOT - - if acmpol.isloaded(): - flags |= xsconstants.XS_INST_LOAD - return flags - - def get_policies(self): - """ Get all managed policies. """ - return self.xsobjs.values() - - def get_policies_refs(self): - """ Get all managed policies' references. """ - return self.xsobjs.keys() - - def has_ref(self, ref): - """ Check whether there is a policy with the given reference """ - return self.xsobjs.has_key(ref) - - def policy_from_ref(self, ref): - """ Get the policy's object given its reference """ - if ref in self.xsobjs.keys(): - return self.xsobjs[ref] - return None - - def ref_from_polname(self, polname): - """ Get the reference of the policy given its name """ - ref = None - for (k, v) in self.xsobjs.items(): - if v.get_name() == polname: - ref = k - break - return ref - - def lock_policy(self, ref): - """ get exclusive access to a policy """ - self.xsobjs[ref].grab_lock() - - def unlock_policy(self, ref): - """ release exclusive access to a policy """ - self.xsobjs[ref].unlock() - - def get_loaded_policy(self): - for pol in self.xsobjs.values(): - if pol.isloaded(): - return pol - return None - - def get_hv_loaded_policy_name(self): - return security.get_active_policy_name() - - def get_policy_by_name(self, name): - for pol in self.xsobjs.values(): - if pol.get_name() == name: - return pol - return None - - def get_domain0_bootlabel(self): - """ Get the domain0 bootlabel from the default boot title """ - title = "" - def_title = bootloader.get_default_title() - line = bootloader.get_kernel_val(def_title, "ssidref") - if line: - parms = line.split(":",1) - if len(parms) > 1: - title = parms[1] - return title - - def set_domain0_bootlabel(self, xspol, label): - """ Set the domain-0 bootlabel under the given policy. If the - current policy is the default policy, it will remove it. """ - rm_entry = (xspol.get_name() == "DEFAULT") - return xspol.set_vm_bootlabel(label, rm_entry) - - def rm_domain0_bootlabel(self): - """ Remove the domain-0 bootlabel from the default boot title """ - def_title = bootloader.get_default_title() - return bootloader.set_kernel_attval(def_title, "ssidref", None) - - def ssidref_to_vmlabel(self, ssidref): - """ Given an ssidref, return the vmlabel under the current policy """ - vmlabel = "" - pol = self.get_loaded_policy() - if pol: - vmlabel = pol.policy_get_domain_label_by_ssidref_formatted(ssidref) - return vmlabel - - def get_stes_of_vmlabel(self, vmlabel_xapi): - """ Get the list of STEs given a VM label in XenAPI format """ - stes = [] - loadedpol = self.get_loaded_policy() - if loadedpol: - tmp = vmlabel_xapi.split(":") - if len(tmp) != 3: - return [] - stes = loadedpol.policy_get_stes_of_vmlabel(tmp[2]) - return stes - - def get_enforced_binary(self, xstype): - res = None - if xstype == xsconstants.XS_POLICY_ACM: - res = ACMPolicy.get_enforced_binary() - return res - -poladmin = None - -def XSPolicyAdminInstance(maxpolicies=1): - global poladmin - if poladmin == None: - poladmin = XSPolicyAdmin(maxpolicies) - return poladmin diff --git a/tools/python/xen/xend/__init__.py b/tools/python/xen/xend/__init__.py deleted file mode 100644 index 8d1c8b69c3..0000000000 --- a/tools/python/xen/xend/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tools/python/xen/xend/arch.py b/tools/python/xen/xend/arch.py deleted file mode 100644 index 2af55e8e21..0000000000 --- a/tools/python/xen/xend/arch.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# Copyright (C) IBM Corp. 2006 -# -# Authors: Hollis Blanchard - -import os - -_types = { - "i386": "x86", - "i486": "x86", - "i586": "x86", - "i686": "x86", - "x86_64": "x86", - "amd64": "x86", - "i86pc": "x86", -} -type = _types.get(os.uname()[4], "unknown") diff --git a/tools/python/xen/xend/balloon.py b/tools/python/xen/xend/balloon.py deleted file mode 100644 index 89965d71b9..0000000000 --- a/tools/python/xen/xend/balloon.py +++ /dev/null @@ -1,244 +0,0 @@ -#=========================================================================== -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2005 XenSource Ltd -#============================================================================ - - -import time - -import xen.lowlevel.xc - -import XendDomain -import XendOptions -import MemoryPool -from XendLogging import log -from XendError import VmError -import osdep -from xen.xend.XendConstants import * - -RETRY_LIMIT = 20 -RETRY_LIMIT_INCR = 5 -## -# The time to sleep between retries grows linearly, using this value (in -# seconds). When the system is lightly loaded, memory should be scrubbed and -# returned to the system very quickly, whereas when it is loaded, the system -# needs idle time to get the scrubbing done. This linear growth accommodates -# such requirements. -SLEEP_TIME_GROWTH = 0.1 - -# A mapping between easy-to-remember labels and the more verbose -# label actually shown in the PROC_XEN_BALLOON file. -#labels = { 'current' : 'Current allocation', -# 'target' : 'Requested target', -# 'low-balloon' : 'Low-mem balloon', -# 'high-balloon' : 'High-mem balloon', -# 'limit' : 'Xen hard limit' } - -def _get_proc_balloon(label): - """Returns the value for the named label. Returns None if the label was - not found or the value was non-numeric.""" - - return osdep.lookup_balloon_stat(label) - -def get_dom0_current_alloc(): - """Returns the current memory allocation (in KiB) of dom0.""" - - kb = _get_proc_balloon('current') - if kb == None: - raise VmError('Failed to query current memory allocation of dom0.') - return kb - -def get_dom0_target_alloc(): - """Returns the target memory allocation (in KiB) of dom0.""" - - kb = _get_proc_balloon('target') - if kb == None: - raise VmError('Failed to query target memory allocation of dom0.') - return kb - -def free(need_mem, dominfo): - """Balloon out memory from the privileged domain so that there is the - specified required amount (in KiB) free. - """ - - # We check whether there is enough free memory, and if not, instruct dom0 - # to balloon out to free some up. Memory freed by a destroyed domain may - # not appear in the free_memory field immediately, because it needs to be - # scrubbed before it can be released to the free list, which is done - # asynchronously by Xen; ballooning is asynchronous also. Such memory - # does, however, need to be accounted for when calculating how much dom0 - # needs to balloon. No matter where we expect the free memory to come - # from, we need to wait for it to become available. - # - # We are not allowed to balloon below dom0_min_mem, or if dom0_ballooning - # is False, we cannot balloon at all. Memory can still become available - # through a rebooting domain, however. - # - # Eventually, we time out (presumably because there really isn't enough - # free memory). - # - # We don't want to set the memory target (triggering a watch) when that - # has already been done, but we do want to respond to changing memory - # usage, so we recheck the required alloc each time around the loop, but - # track the last used value so that we don't trigger too many watches. - - xoptions = XendOptions.instance() - dom0 = XendDomain.instance().privilegedDomain() - xc = xen.lowlevel.xc.xc() - memory_pool = MemoryPool.instance() - try: - dom0_min_mem = xoptions.get_dom0_min_mem() * 1024 - dom0_ballooning = xoptions.get_enable_dom0_ballooning() - guest_size = 0 - hvm = dominfo.info.is_hvm() - if memory_pool.is_enabled() and dominfo.domid: - if not hvm : - if need_mem <= 4 * 1024: - guest_size = 32 - else: - guest_size = dominfo.image.getBitSize() - if guest_size == 32: - dom0_ballooning = 0 - else: #no ballooning as memory pool enabled - dom0_ballooning = xoptions.get_enable_dom0_ballooning() - dom0_alloc = get_dom0_current_alloc() - - retries = 0 - sleep_time = SLEEP_TIME_GROWTH - new_alloc = 0 - last_new_alloc = None - last_free = None - rlimit = RETRY_LIMIT - mem_need_balloon = 0 - left_memory_pool = 0 - mem_target = 0 - untouched_memory_pool = 0 - real_need_mem = need_mem - - # stop tmem from absorbing any more memory (must THAW when done!) - xc.tmem_control(0,TMEMC_FREEZE,-1, 0, 0, 0, "") - - # If unreasonable memory size is required, we give up waiting - # for ballooning or scrubbing, as if had retried. - physinfo = xc.physinfo() - free_mem = physinfo['free_memory'] - scrub_mem = physinfo['scrub_memory'] - total_mem = physinfo['total_memory'] - if memory_pool.is_enabled() and dominfo.domid: - if guest_size != 32 or hvm: - if need_mem > 4 * 1024: - dominfo.alloc_mem = need_mem - left_memory_pool = memory_pool.get_left_memory() - if need_mem > left_memory_pool: - dominfo.alloc_mem = 0 - raise VmError(('Not enough free memory' - ' so I cannot release any more. ' - 'I need %d KiB but only have %d in the pool.') % - (need_mem, memory_pool.get_left_memory())) - else: - untouched_memory_pool = memory_pool.get_untouched_memory() - if (left_memory_pool - untouched_memory_pool) > need_mem: - dom0_ballooning = 0 - else: - mem_need_balloon = need_mem - left_memory_pool + untouched_memory_pool - need_mem = free_mem + scrub_mem + mem_need_balloon - - if dom0_ballooning: - max_free_mem = total_mem - dom0_min_mem - else: - max_free_mem = total_mem - dom0_alloc - if need_mem >= max_free_mem: - retries = rlimit - - freeable_mem = free_mem + scrub_mem - if freeable_mem < need_mem and need_mem < max_free_mem: - # flush memory from tmem to scrub_mem and reobtain physinfo - need_tmem_kb = need_mem - freeable_mem - tmem_kb = xc.tmem_control(0,TMEMC_FLUSH,-1, need_tmem_kb, 0, 0, "") - log.debug("Balloon: tmem relinquished %d KiB of %d KiB requested.", - tmem_kb, need_tmem_kb) - physinfo = xc.physinfo() - free_mem = physinfo['free_memory'] - scrub_mem = physinfo['scrub_memory'] - - while retries < rlimit: - physinfo = xc.physinfo() - free_mem = physinfo['free_memory'] - scrub_mem = physinfo['scrub_memory'] - if free_mem >= need_mem: - if (guest_size != 32 or hvm) and dominfo.domid: - memory_pool.decrease_untouched_memory(mem_need_balloon) - memory_pool.decrease_memory(real_need_mem) - else: - log.debug("Balloon: %d KiB free; need %d; done.", - free_mem, need_mem) - return - - if retries == 0: - rlimit += ((need_mem - free_mem)/1024/1024) * RETRY_LIMIT_INCR - log.debug("Balloon: %d KiB free; %d to scrub; need %d; retries: %d.", - free_mem, scrub_mem, need_mem, rlimit) - - if dom0_ballooning: - dom0_alloc = get_dom0_current_alloc() - new_alloc = dom0_alloc - (need_mem - free_mem - scrub_mem) - if free_mem + scrub_mem >= need_mem: - if last_new_alloc == None: - log.debug("Balloon: waiting on scrubbing") - last_new_alloc = dom0_alloc - else: - if (new_alloc >= dom0_min_mem and - new_alloc != last_new_alloc): - new_alloc_mb = new_alloc / 1024 # Round down - log.debug("Balloon: setting dom0 target to %d MiB.", - new_alloc_mb) - dom0.setMemoryTarget(new_alloc_mb) - last_new_alloc = new_alloc - # Continue to retry, waiting for ballooning or scrubbing. - - time.sleep(sleep_time) - if retries < 2 * RETRY_LIMIT: - sleep_time += SLEEP_TIME_GROWTH - if last_free != None and last_free >= free_mem + scrub_mem: - retries += 1 - last_free = free_mem + scrub_mem - - # Not enough memory; diagnose the problem. - if not dom0_ballooning: - dominfo.alloc_mem = 0 - raise VmError(('Not enough free memory and enable-dom0-ballooning ' - 'is False, so I cannot release any more. ' - 'I need %d KiB but only have %d.') % - (need_mem, free_mem)) - elif new_alloc < dom0_min_mem: - dominfo.alloc_mem = 0 - raise VmError( - ('I need %d KiB, but dom0_min_mem is %d and shrinking to ' - '%d KiB would leave only %d KiB free.') % - (need_mem, dom0_min_mem, dom0_min_mem, - free_mem + scrub_mem + dom0_alloc - dom0_min_mem)) - else: - dom0_start_alloc_mb = get_dom0_current_alloc() / 1024 - dom0.setMemoryTarget(dom0_start_alloc_mb) - dominfo.alloc_mem = 0 - raise VmError( - ('Not enough memory is available, and dom0 cannot' - ' be shrunk any further')) - - finally: - # allow tmem to accept pages again - xc.tmem_control(0,TMEMC_THAW,-1, 0, 0, 0, "") - del xc diff --git a/tools/python/xen/xend/encode.py b/tools/python/xen/xend/encode.py deleted file mode 100644 index f47c18a1be..0000000000 --- a/tools/python/xen/xend/encode.py +++ /dev/null @@ -1,180 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -#============================================================================ - -"""Encoding for arguments to HTTP calls. - Uses the url-encoding with MIME type 'application/x-www-form-urlencoded' - if the data does not include files. Otherwise it uses the encoding with - MIME type 'multipart/form-data'. See the HTML4 spec for details. - - """ -import sys -import types -from StringIO import StringIO - -import urllib -import random -import md5 - -# Extract from HTML4 spec. -## The following example illustrates "multipart/form-data" -## encoding. Suppose we have the following form: - -##
-##

-## What is your name?
-## What files are you sending?
-## -##

- -## If the user enters "Larry" in the text input, and selects the text -## file "file1.txt", the user agent might send back the following data: - -## Content-Type: multipart/form-data; boundary=AaB03x - -## --AaB03x -## Content-Disposition: form-data; name="submit-name" - -## Larry -## --AaB03x -## Content-Disposition: form-data; name="files"; filename="file1.txt" -## Content-Type: text/plain - -## ... contents of file1.txt ... -## --AaB03x-- - -## If the user selected a second (image) file "file2.gif", the user agent -## might construct the parts as follows: - -## Content-Type: multipart/form-data; boundary=AaB03x - -## --AaB03x -## Content-Disposition: form-data; name="submit-name" - -## Larry -## --AaB03x -## Content-Disposition: form-data; name="files" -## Content-Type: multipart/mixed; boundary=BbC04y - -## --BbC04y -## Content-Disposition: file; filename="file1.txt" -## Content-Type: text/plain - -## ... contents of file1.txt ... -## --BbC04y -## Content-Disposition: file; filename="file2.gif" -## Content-Type: image/gif -## Content-Transfer-Encoding: binary - -## ...contents of file2.gif... -## --BbC04y-- -## --AaB03x-- - -__all__ = ['encode_data', 'encode_multipart', 'encode_form', 'mime_boundary' ] - -def data_values(d): - if isinstance(d, types.DictType): - return d.items() - else: - return d - -def encode_data(d): - """Encode some data for HTTP transport. - The encoding used is stored in 'Content-Type' in the headers. - - d data - sequence of tuples or dictionary - returns a 2-tuple of the headers and the encoded data - """ - val = ({}, None) - if d is None: return val - multipart = 0 - for (_, v) in data_values(d): - if encode_isfile(v): - multipart = 1 - break - if multipart: - val = encode_multipart(d) - else: - val = encode_form(d) - return val - -def encode_isfile(v): - if isinstance(v, types.FileType): - return 1 - if hasattr(v, 'readlines'): - return 1 - return 0 - -def encode_multipart(d): - boundary = mime_boundary() - hdr = { 'Content-Type': 'multipart/form-data; boundary=' + boundary } - out = StringIO() - for (k,v) in data_values(d): - out.write('--') - out.write(boundary) - out.write('\r\n') - if encode_isfile(v): - out.write('Content-Disposition: form-data; name="') - out.write(k) - if hasattr(v, 'name'): - out.write('"; filename="') - out.write(v.name) - out.write('"\r\n') - out.write('Content-Type: application/octet-stream\r\n') - out.write('\r\n') - for l in v.readlines(): - out.write(l) - else: - out.write('Content-Disposition: form-data; name="') - out.write(k) - out.write('"\r\n') - out.write('\r\n') - out.write(str(v)) - out.write('\r\n') - out.write('--') - out.write(boundary) - out.write('--') - out.write('\r\n') - return (hdr, out.getvalue()) - -def mime_boundary(): - random.seed() - m = md5.new() - for _ in range(0, 10): - c = chr(random.randint(1, 255)) - m.update(c) - b = m.hexdigest() - return b[0:16] - -def encode_form(d): - hdr = { 'Content-Type': 'application/x-www-form-urlencoded' } - val = urllib.urlencode(d) - return (hdr, val) - -def main(): - #d = {'a': 1, 'b': 'x y', 'c': file('conf.sxp') } - #d = {'a': 1, 'b': 'x y' } - d = [ ('a', 1), ('b', 'x y'), ('c', file('conf.sxp')) ] - #d = [ ('a', 1), ('b', 'x y')] - v = encode_data(d) - print v[0] - sys.stdout.write(v[1]) - print - -if __name__ == "__main__": - main() diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py deleted file mode 100644 index 54334ae4be..0000000000 --- a/tools/python/xen/xend/image.py +++ /dev/null @@ -1,1047 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2005 Mike Wray -# Copyright (C) 2005-2007 XenSource Ltd -#============================================================================ - - -import os, os.path, string -import re -import math -import time -import signal -import thread -import fcntl -import sys -import errno -import glob -import traceback -import platform - -import xen.lowlevel.xc -from xen.xend.XendConstants import * -from xen.xend.XendError import VmError, XendError, HVMRequired -from xen.xend.XendLogging import log -from xen.xend.XendOptions import instance as xenopts -from xen.xend.xenstore.xstransact import xstransact -from xen.xend.xenstore.xswatch import xswatch -from xen.xend import arch -from xen.xend import XendOptions -from xen.util import oshelp -from xen.util import utils -from xen.xend import osdep - -xc = xen.lowlevel.xc.xc() - -MAX_GUEST_CMDLINE = 1024 - -sentinel_path_prefix = '/var/run/xend/dm-' -sentinel_fifos_inuse = { } - -def cleanup_stale_sentinel_fifos(): - for path in glob.glob(sentinel_path_prefix + '*.fifo'): - if path in sentinel_fifos_inuse: continue - try: os.unlink(path) - except OSError, e: - log.warning('could not delete stale fifo %s: %s', - path, utils.exception_string(e)) - -def create(vm, vmConfig): - """Create an image handler for a vm. - - @return ImageHandler instance - """ - return findImageHandlerClass(vmConfig)(vm, vmConfig) - - -class ImageHandler: - """Abstract base class for image handlers. - - createImage() is called to configure and build the domain from its - kernel image and ramdisk etc. - - The method buildDomain() is used to build the domain, and must be - defined in a subclass. Usually this is the only method that needs - defining in a subclass. - - The method createDeviceModel() is called to create the domain device - model. - - The method destroyDeviceModel() is called to reap the device model - """ - - ostype = None - superpages = 0 - memory_sharing = 0 - - def __init__(self, vm, vmConfig): - self.vm = vm - - self.bootloader = False - self.use_tmp_kernel = False - self.use_tmp_ramdisk = False - self.kernel = None - self.ramdisk = None - self.cmdline = None - - self.configure(vmConfig) - - def configure(self, vmConfig): - """Config actions common to all unix-like domains.""" - if '_temp_using_bootloader' in vmConfig: - self.bootloader = True - self.kernel = vmConfig['_temp_kernel'] - self.cmdline = vmConfig['_temp_args'] - self.ramdisk = vmConfig['_temp_ramdisk'] - else: - self.kernel = vmConfig['PV_kernel'] - self.cmdline = vmConfig['PV_args'] - self.ramdisk = vmConfig['PV_ramdisk'] - # There a code-paths where use_tmp_xxx is not set at all; but if - # this is set, the variable itself is a boolean. - if 'use_tmp_kernel' in vmConfig and vmConfig['use_tmp_kernel']: - self.use_tmp_kernel = True - if 'use_tmp_ramdisk' in vmConfig and vmConfig['use_tmp_ramdisk']: - self.use_tmp_ramdisk = True - self.vm.storeVm(("image/ostype", self.ostype), - ("image/kernel", self.kernel), - ("image/cmdline", self.cmdline), - ("image/ramdisk", self.ramdisk)) - self.vm.permissionsVm("image/cmdline", { 'dom': self.vm.getDomid(), 'read': True } ) - - self.device_model = vmConfig['platform'].get('device_model') - - self.display = vmConfig['platform'].get('display') - self.xauthority = vmConfig['platform'].get('xauthority') - self.vncconsole = int(vmConfig['platform'].get('vncconsole', 0)) - self.dmargs = self.parseDeviceModelArgs(vmConfig) - self.pid = None - rtc_timeoffset = int(vmConfig['platform'].get('rtc_timeoffset', 0)) - if int(vmConfig['platform'].get('localtime', 0)): - if time.localtime(time.time())[8]: - rtc_timeoffset -= time.altzone - else: - rtc_timeoffset -= time.timezone - if rtc_timeoffset != 0: - xc.domain_set_time_offset(self.vm.getDomid(), rtc_timeoffset) - - self.cpuid = None - self.cpuid_check = None - if 'cpuid' in vmConfig: - self.cpuid = vmConfig['cpuid']; - if 'cpuid_check' in vmConfig: - self.cpuid_check = vmConfig['cpuid_check'] - - def cleanupTmpImages(self): - if self.use_tmp_kernel: - self.unlink(self.kernel) - if self.use_tmp_ramdisk: - self.unlink(self.ramdisk) - - def unlink(self, f): - if not f: return - try: - os.unlink(f) - except OSError, ex: - log.warning("error removing bootloader file '%s': %s", f, ex) - - - def createImage(self): - """Entry point to create domain memory image. - Override in subclass if needed. - """ - return self.createDomain() - - - def createDomain(self): - """Build the domain boot image. - """ - # Set params and call buildDomain(). - - if self.kernel and not os.path.isfile(self.kernel): - raise VmError('Kernel image does not exist: %s' % self.kernel) - if self.ramdisk and not os.path.isfile(self.ramdisk): - raise VmError('Kernel ramdisk does not exist: %s' % self.ramdisk) - if len(self.cmdline) >= MAX_GUEST_CMDLINE: - log.warning('kernel cmdline too long, domain %d', - self.vm.getDomid()) - - log.info("buildDomain os=%s dom=%d vcpus=%d", self.ostype, - self.vm.getDomid(), self.vm.getVCpuCount()) - - result = self.buildDomain() - - if isinstance(result, dict): - return result - else: - raise VmError('Building domain failed: ostype=%s dom=%d err=%s' - % (self.ostype, self.vm.getDomid(), str(result))) - - def getRequiredAvailableMemory(self, mem_kb): - """@param mem_kb The configured maxmem or memory, in KiB. - @return The corresponding required amount of memory for the domain, - also in KiB. This is normally the given mem_kb, but architecture- or - image-specific code may override this to add headroom where - necessary.""" - return mem_kb - - def getRequiredInitialReservation(self): - """@param mem_kb The configured memory, in KiB. - @return The corresponding required amount of memory to be free, also - in KiB. This is normally the same as getRequiredAvailableMemory, but - architecture- or image-specific code may override this to - add headroom where necessary.""" - return self.getRequiredAvailableMemory(self.vm.getMemoryTarget()) - - def getRequiredMaximumReservation(self): - """@param mem_kb The maximum possible memory, in KiB. - @return The corresponding required amount of memory to be free, also - in KiB. This is normally the same as getRequiredAvailableMemory, but - architecture- or image-specific code may override this to - add headroom where necessary.""" - return self.getRequiredAvailableMemory(self.vm.getMemoryMaximum()) - - def getRequiredShadowMemory(self, shadow_mem_kb, maxmem_kb): - """@param shadow_mem_kb The configured shadow memory, in KiB. - @param maxmem_kb The configured maxmem, in KiB. - @return The corresponding required amount of shadow memory, also in - KiB.""" - # PV domains don't need any shadow memory - return 0 - - def buildDomain(self): - """Build the domain. Define in subclass.""" - raise NotImplementedError() - - def prepareEnvironment(self): - """Prepare the environment for the execution of the domain. This - method is called before any devices are set up.""" - - domid = self.vm.getDomid() - - # Delete left-over pipes - try: - os.unlink('/var/run/tap/qemu-read-%d' % domid) - os.unlink('/var/run/tap/qemu-write-%d' % domid) - except: - pass - - # No device model, don't create pipes - if self.device_model is None: - return - - if platform.system() != 'SunOS': - # If we use a device model, the pipes for communication between - # blktapctrl and ioemu must be present before the devices are - # created (blktapctrl must access them for new block devices) - - try: - os.makedirs('/var/run/tap', 0755) - except: - pass - - try: - os.mkfifo('/var/run/tap/qemu-read-%d' % domid, 0600) - os.mkfifo('/var/run/tap/qemu-write-%d' % domid, 0600) - except OSError, e: - log.warn('Could not create blktap pipes for domain %d' % domid) - log.exception(e) - pass - - - # Return a list of cmd line args to the device models based on the - # xm config file - def parseDeviceModelArgs(self, vmConfig): - ret = ["-domain-name", str(self.vm.info['name_label'])] - - xen_extended_power_mgmt = int(vmConfig['platform'].get( - 'xen_extended_power_mgmt', 0)) - if xen_extended_power_mgmt != 0: - xstransact.Store("/local/domain/0/device-model/%i" - % self.vm.getDomid(), - ('xen_extended_power_mgmt', - xen_extended_power_mgmt)) - - # Find RFB console device, and if it exists, make QEMU enable - # the VNC console. - if int(vmConfig['platform'].get('nographic', 0)) != 0: - # skip vnc init if nographic is set - ret.append('-nographic') - return ret - - vram = str(vmConfig['platform'].get('videoram',4)) - ret.append('-videoram') - ret.append(vram) - - vnc_config = {} - has_vnc = int(vmConfig['platform'].get('vnc', 0)) != 0 - has_sdl = int(vmConfig['platform'].get('sdl', 0)) != 0 - opengl = 1 - keymap = vmConfig['platform'].get("keymap") - for dev_uuid in vmConfig['console_refs']: - dev_type, dev_info = vmConfig['devices'][dev_uuid] - if dev_type == 'vfb': - if 'keymap' in dev_info: - keymap = dev_info.get('keymap',{}) - if 'monitor' in dev_info: - ret.append("-serial") - ret.append(dev_info.get('monitor',{})) - ret.append("-monitor") - ret.append("null") - if 'serial' in dev_info: - ret.append("-serial") - ret.append(dev_info.get('serial',{})) - if int(dev_info.get('vnc', 0)) != 0 : - has_vnc = True - if int(dev_info.get('sdl', 0)) != 0 : - has_sdl = True - if has_sdl: - self.display = dev_info.get('display', self.display) - self.xauthority = dev_info.get('xauthority', self.xauthority) - opengl = int(dev_info.get('opengl', opengl)) - if has_vnc: - vnc_config = dev_info.get('other_config', {}) - break - - if keymap: - ret.append("-k") - ret.append(keymap) - - if has_vnc: - if not vnc_config: - for key in ('vncunused', 'vnclisten', 'vncdisplay', - 'vncpasswd'): - if key in vmConfig['platform']: - vnc_config[key] = vmConfig['platform'][key] - if vnc_config.has_key("vncpasswd"): - passwd = vnc_config["vncpasswd"] - else: - passwd = XendOptions.instance().get_vncpasswd_default() - vncopts = "" - if passwd: - self.vm.storeVm("vncpasswd", passwd) - self.vm.permissionsVm("vncpasswd", { 'dom': self.vm.getDomid(), 'read': True } ) - vncopts = vncopts + ",password" - log.debug("Stored a VNC password for vfb access") - else: - log.debug("No VNC passwd configured for vfb access") - - if XendOptions.instance().get_vnc_tls(): - vncx509certdir = XendOptions.instance().get_vnc_x509_cert_dir() - vncx509verify = XendOptions.instance().get_vnc_x509_verify() - - if not os.path.exists(vncx509certdir): - raise VmError("VNC x509 certificate dir %s does not exist" % vncx509certdir) - - if vncx509verify: - vncopts = vncopts + ",tls,x509verify=%s" % vncx509certdir - else: - vncopts = vncopts + ",tls,x509=%s" % vncx509certdir - - - vnclisten = vnc_config.get('vnclisten', - XendOptions.instance().get_vnclisten_address()) - vncdisplay = int(vnc_config.get('vncdisplay', 0)) - ret.append('-vnc') - ret.append("%s:%s%s" % (vnclisten, vncdisplay, vncopts)) - - if int(vnc_config.get('vncunused', 1)) != 0: - ret.append('-vncunused') - - if has_sdl: - ret.append('-sdl') - if int(vmConfig['platform'].get('opengl', opengl)) != 1 : - ret.append('-disable-opengl') - - if not has_sdl and not has_vnc : - ret.append('-nographic') - - if vmConfig['platform'].get('parallel'): - ret = ret + ["-parallel", vmConfig['platform'].get('parallel')] - - if int(vmConfig['platform'].get('monitor', 0)) != 0: - if vmConfig['platform'].get('monitor_path'): - ret = ret + ['-monitor', vmConfig['platform'].get('monitor_path')] - else: - ret = ret + ['-monitor', 'vc'] - - return ret - - def getDeviceModelArgs(self, restore = False): - args = [self.device_model] - args = args + ([ "-d", "%d" % self.vm.getDomid() ]) - args = args + self.dmargs - return args - - def _openSentinel(self, sentinel_path_fifo): - self.sentinel_fifo = file(sentinel_path_fifo, 'r') - self.sentinel_lock = thread.allocate_lock() - oshelp.fcntl_setfd_cloexec(self.sentinel_fifo, True) - sentinel_fifos_inuse[sentinel_path_fifo] = 1 - self.sentinel_path_fifo = sentinel_path_fifo - - def createDeviceModel(self, restore = False): - if self.device_model is None: - return - if self.pid: - return - # Execute device model. - #todo: Error handling - args = self.getDeviceModelArgs(restore) - env = dict(os.environ) - if self.display: - env['DISPLAY'] = self.display - if self.xauthority: - env['XAUTHORITY'] = self.xauthority - unique_id = "%i-%i" % (self.vm.getDomid(), time.time()) - sentinel_path = sentinel_path_prefix + unique_id - sentinel_path_fifo = sentinel_path + '.fifo' - os.mkfifo(sentinel_path_fifo, 0600) - sentinel_write = file(sentinel_path_fifo, 'r+') - self._openSentinel(sentinel_path_fifo) - self.vm.storeDom("image/device-model-fifo", sentinel_path_fifo) - xstransact.Mkdir("/local/domain/0/device-model/%i" % self.vm.getDomid()) - xstransact.SetPermissions("/local/domain/0/device-model/%i" % self.vm.getDomid(), - { 'dom': self.vm.getDomid(), 'read': True, 'write': True }) - log.info("spawning device models: %s %s", self.device_model, args) - # keep track of pid and spawned options to kill it later - - self.logfile = "/var/log/xen/qemu-dm-%s.log" % str(self.vm.info['name_label']) - - # rotate log - logfile_mode = os.O_WRONLY|os.O_CREAT|os.O_APPEND - logrotate_count = XendOptions.instance().get_qemu_dm_logrotate_count() - if logrotate_count > 0: - logfile_mode |= os.O_TRUNC - if os.path.exists("%s.%d" % (self.logfile, logrotate_count)): - os.unlink("%s.%d" % (self.logfile, logrotate_count)) - for n in range(logrotate_count - 1, 0, -1): - if os.path.exists("%s.%d" % (self.logfile, n)): - os.rename("%s.%d" % (self.logfile, n), - "%s.%d" % (self.logfile, (n + 1))) - if os.path.exists(self.logfile): - os.rename(self.logfile, self.logfile + ".1") - - null = os.open("/dev/null", os.O_RDONLY) - logfd = os.open(self.logfile, logfile_mode, 0666) - - sys.stderr.flush() - contract = osdep.prefork("%s:%d" % - (self.vm.getName(), self.vm.getDomid())) - pid = os.fork() - if pid == 0: #child - try: - osdep.postfork(contract) - os.dup2(null, 0) - os.dup2(logfd, 1) - os.dup2(logfd, 2) - oshelp.close_fds((sentinel_write.fileno(),)) - try: - os.execve(self.device_model, args, env) - except Exception, e: - print >>sys.stderr, ( - 'failed to set up fds or execute dm %s: %s' % - (self.device_model, utils.exception_string(e))) - os._exit(126) - except: - os._exit(127) - else: - osdep.postfork(contract, abandon=True) - self.pid = pid - os.close(null) - os.close(logfd) - sentinel_write.close() - self.vm.storeDom("image/device-model-pid", self.pid) - log.info("device model pid: %d", self.pid) - # we would very much prefer not to have a thread here and instead - # have a callback but sadly we don't have Twisted in xend - self.sentinel_thread = thread.start_new_thread(self._sentinel_watch,()) - if self.device_model.find('stubdom-dm') > -1 : - from xen.xend import XendDomain - domains = XendDomain.instance() - domains.domains_lock.release() - - count = 0 - while True: - orig_state = xstransact.Read("/local/domain/0/device-model/%i/state" - % self.vm.getDomid()) - # This can occur right after start-up - if orig_state != None: - break - - log.debug('createDeviceModel %i: orig_state is None, retrying' % self.vm.getDomid()) - - time.sleep(0.1) - count += 1 - if count > 100: - break - - domains.domains_lock.acquire() - - def signalDeviceModel(self, cmd, ret, par = None): - if self.device_model is None: - return - # Signal the device model to for action - if cmd is '' or ret is '': - raise VmError('need valid command and result when signal device model') - - count = 0 - while True: - orig_state = xstransact.Read("/local/domain/0/device-model/%i/state" - % self.vm.getDomid()) - # This can occur right after start-up - if orig_state != None: - break - - log.debug('signalDeviceModel: orig_state is None, retrying') - - time.sleep(0.1) - count += 1 - if count < 100: - continue - - raise VmError('Device model isn\'t ready for commands') - - if par is not None: - xstransact.Store("/local/domain/0/device-model/%i" - % self.vm.getDomid(), ('parameter', par)) - - xstransact.Store("/local/domain/0/device-model/%i" - % self.vm.getDomid(), ('command', cmd)) - # Wait for confirmation. Could do this with a watch but we'd - # still end up spinning here waiting for the watch to fire. - state = '' - count = 0 - while state != ret: - state = xstransact.Read("/local/domain/0/device-model/%i/state" - % self.vm.getDomid()) - time.sleep(0.1) - count += 1 - if count > 100: - raise VmError('Timed out waiting for device model action') - - #resotre orig state - xstransact.Store("/local/domain/0/device-model/%i" - % self.vm.getDomid(), ('state', orig_state)) - log.info("signalDeviceModel:restore dm state to %s", orig_state) - - def saveDeviceModel(self): - # Signal the device model to pause itself and save its state - self.signalDeviceModel('save', 'paused') - - def resumeDeviceModel(self): - if self.device_model is None: - return - # Signal the device model to resume activity after pausing to save. - xstransact.Store("/local/domain/0/device-model/%i" - % self.vm.getDomid(), ('command', 'continue')) - - def _dmfailed(self, message): - log.warning("domain %s: %s", self.vm.getName(), message) - try: - xc.domain_shutdown(self.vm.getDomid(), DOMAIN_CRASH) - except: - pass - - def recreate(self): - if self.device_model is None: - return - name = self.vm.getName() - sentinel_path_fifo = self.vm.readDom('image/device-model-fifo') - fifo_fd = -1 - log.debug("rediscovering %s", sentinel_path_fifo) - if sentinel_path_fifo is None: - log.debug("%s device model no sentinel, cannot rediscover", name) - else: - try: - # We open it O_WRONLY because that fails ENXIO if no-one - # has it open for reading (see SuSv3). The dm process got - # a read/write descriptor from our earlier invocation. - fifo_fd = os.open(sentinel_path_fifo, os.O_WRONLY|os.O_NONBLOCK) - except OSError, e: - if e.errno == errno.ENXIO: - self._dmfailed("%s device model no longer running"%name) - elif e.errno == errno.ENOENT: - log.debug("%s device model sentinel %s absent!", - name, sentinel_path_fifo) - else: - raise - if fifo_fd >= 0: - self._openSentinel(sentinel_path_fifo) - os.close(fifo_fd) - self.pid = self.vm.gatherDom(('image/device-model-pid', int)) - log.debug("%s device model rediscovered, pid %s sentinel fifo %s", - name, self.pid, sentinel_path_fifo) - self.sentinel_thread = thread.start_new_thread(self._sentinel_watch,()) - - def _sentinel_watch(self): - log.info("waiting for sentinel_fifo") - try: self.sentinel_fifo.read(1) - except OSError, e: pass - self.sentinel_lock.acquire() - if self.pid: - try: - (p,st) = os.waitpid(self.pid, os.WNOHANG) - if p == self.pid: - message = oshelp.waitstatus_description(st) - else: - # obviously it is malfunctioning, kill it now - try: - os.kill(self.pid, signal.SIGKILL) - message = "malfunctioning (closed sentinel), killed" - except: - message = "malfunctioning or died ?" - message = "pid %d: %s" % (self.pid, message) - except Exception, e: - message = "waitpid failed: %s" % utils.exception_string(e) - message = "device model failure: %s" % message - try: message += "; see %s " % self.logfile - except: pass - self._dmfailed(message) - self.pid = None - else: - log.info("%s device model terminated", self.vm.getName()) - self.sentinel_lock.release() - - def destroyDeviceModel(self): - if self.device_model is None: - return - self.sentinel_lock.acquire() - try: - stubdomid = self.vm.getStubdomDomid() - if stubdomid is not None : - from xen.xend import XendDomain - XendDomain.instance().domain_destroy(stubdomid) - elif self.pid: - try: - os.kill(self.pid, signal.SIGHUP) - except OSError, exn: - log.exception(exn) - # Try to reap the child every 100ms for 10s. Then SIGKILL it. - for i in xrange(100): - try: - (p, rv) = os.waitpid(self.pid, os.WNOHANG) - if p == self.pid: - break - except OSError: - # This is expected if Xend has been restarted within - # the life of this domain. In this case, we can kill - # the process, but we can't wait for it because it's - # not our child. We continue this loop, and after it is - # terminated make really sure the process is going away - # (SIGKILL). - pass - time.sleep(0.1) - else: - log.warning("DeviceModel %d took more than 10s " - "to terminate: sending SIGKILL" % self.pid) - try: - os.kill(self.pid, signal.SIGKILL) - os.waitpid(self.pid, 0) - except OSError: - # This happens if the process doesn't exist. - pass - finally: - self.pid = None - self.sentinel_lock.release() - - state = xstransact.Remove("/local/domain/0/device-model/%i" - % self.vm.getDomid()) - try: - os.unlink('/var/run/tap/qemu-read-%d' % self.vm.getDomid()) - os.unlink('/var/run/tap/qemu-write-%d' % self.vm.getDomid()) - except: - pass - try: - del sentinel_fifos_inuse[self.sentinel_path_fifo] - os.unlink(self.sentinel_path_fifo) - except: - pass - - def setCpuid(self): - xc.domain_set_policy_cpuid(self.vm.getDomid()) - - if self.cpuid is not None: - cpuid = self.cpuid - transformed = {} - for sinput, regs in cpuid.iteritems(): - inputs = sinput.split(',') - input = long(inputs[0]) - sub_input = None - if len(inputs) == 2: - sub_input = long(inputs[1]) - t = xc.domain_set_cpuid(self.vm.getDomid(), - input, sub_input, regs) - transformed[sinput] = t - self.cpuid = transformed - - if self.cpuid_check is not None: - cpuid_check = self.cpuid_check - transformed = {} - for sinput, regs_check in cpuid_check.iteritems(): - inputs = sinput.split(',') - input = long(inputs[0]) - sub_input = None - if len(inputs) == 2: - sub_input = long(inputs[1]) - t = xc.domain_check_cpuid(input, sub_input, regs_check) - transformed[sinput] = t - self.cpuid_check = transformed - -class LinuxImageHandler(ImageHandler): - - ostype = "linux" - flags = 0 - vhpt = 0 - - def configure(self, vmConfig): - ImageHandler.configure(self, vmConfig) - self.vramsize = int(vmConfig['platform'].get('videoram',4)) * 1024 - self.is_stubdom = (self.kernel.find('stubdom') >= 0) - self.superpages = int(vmConfig['superpages']) - - def buildDomain(self): - store_evtchn = self.vm.getStorePort() - console_evtchn = self.vm.getConsolePort() - - mem_mb = self.getRequiredInitialReservation() / 1024 - - log.debug("domid = %d", self.vm.getDomid()) - log.debug("memsize = %d", mem_mb) - log.debug("image = %s", self.kernel) - log.debug("store_evtchn = %d", store_evtchn) - log.debug("console_evtchn = %d", console_evtchn) - log.debug("cmdline = %s", self.cmdline) - log.debug("ramdisk = %s", self.ramdisk) - log.debug("vcpus = %d", self.vm.getVCpuCount()) - log.debug("features = %s", self.vm.getFeatures()) - log.debug("flags = %d", self.flags) - log.debug("superpages = %d", self.superpages) - - return xc.linux_build(domid = self.vm.getDomid(), - memsize = mem_mb, - image = self.kernel, - store_evtchn = store_evtchn, - console_evtchn = console_evtchn, - cmdline = self.cmdline, - ramdisk = self.ramdisk, - features = self.vm.getFeatures(), - flags = self.flags, - vhpt = self.vhpt, - superpages = self.superpages) - - def getBitSize(self): - return xc.getBitSize(image = self.kernel, - cmdline = self.cmdline, - features = self.vm.getFeatures() - ).get('type') - - def getRequiredAvailableMemory(self, mem_kb): - if self.is_stubdom : - mem_kb += self.vramsize - return mem_kb - - def getRequiredInitialReservation(self): - return self.vm.getMemoryTarget() - - def getRequiredMaximumReservation(self): - return self.vm.getMemoryMaximum() - - def parseDeviceModelArgs(self, vmConfig): - ret = ImageHandler.parseDeviceModelArgs(self, vmConfig) - if vmConfig['platform'].get('serial'): - ret = ["-serial", vmConfig['platform'].get('serial')] + ret - else: - ret = ["-serial", "pty"] + ret - return ret - - def getDeviceModelArgs(self, restore = False): - args = ImageHandler.getDeviceModelArgs(self, restore) - args = args + ([ "-M", "xenpv"]) - return args - - -class HVMImageHandler(ImageHandler): - - ostype = "hvm" - - def __init__(self, vm, vmConfig): - ImageHandler.__init__(self, vm, vmConfig) - self.shutdownWatch = None - self.rebootFeatureWatch = None - - def getBitSize(self): - return None - - def configure(self, vmConfig): - ImageHandler.configure(self, vmConfig) - - self.loader = vmConfig['platform'].get('loader') - - info = xc.xeninfo() - if 'hvm' not in info['xen_caps']: - raise HVMRequired() - - xen_platform_pci = int(vmConfig['platform'].get('xen_platform_pci',1)) - rtc_timeoffset = vmConfig['platform'].get('rtc_timeoffset') - - if not self.display : - self.display = '' - - store_dmargs = [ x for x in self.dmargs - if x not in ['-sdl', '-disable-opengl'] ] - try : - midx = store_dmargs.index('-monitor') - store_dmargs[midx + 1] = 'pty' - except ValueError : - pass - self.vm.storeVm(("image/dmargs", " ".join(store_dmargs)), - ("image/device-model", self.device_model), - ("image/display", self.display)) - self.vm.permissionsVm("image/dmargs", { 'dom': self.vm.getDomid(), 'read': True } ) - - if xen_platform_pci == 0: - disable_pf = 1 - log.info("No need to create platform device.[domid:%d]", self.vm.getDomid()) - else: - disable_pf = 0 - log.info("Need to create platform device.[domid:%d]", self.vm.getDomid()) - - xstransact.Store("/local/domain/0/device-model/%i"%self.vm.getDomid(), - ('disable_pf', disable_pf)) - self.vm.storeVm(("rtc/timeoffset", rtc_timeoffset)) - self.vm.permissionsVm("rtc/timeoffset", { 'dom': self.vm.getDomid(), 'read': True } ) - - self.apic = int(vmConfig['platform'].get('apic', 0)) - self.acpi = int(vmConfig['platform'].get('acpi', 0)) - self.guest_os_type = vmConfig['platform'].get('guest_os_type') - self.memory_sharing = int(vmConfig['memory_sharing']) - try: - xc.dom_set_memshr(self.vm.getDomid(), self.memory_sharing) - except: - pass - - # Return a list of cmd line args to the device models based on the - # xm config file - def parseDeviceModelArgs(self, vmConfig): - ret = ImageHandler.parseDeviceModelArgs(self, vmConfig) - ret = ret + ['-vcpus', str(self.vm.getVCpuCount())] - ret = ret + ['-vcpu_avail', hex(self.vm.getVCpuAvail())] - - if self.kernel: - log.debug("kernel = %s", self.kernel) - ret = ret + ['-kernel', self.kernel] - if self.ramdisk: - log.debug("ramdisk = %s", self.ramdisk) - ret = ret + ['-initrd', self.ramdisk] - if self.cmdline: - log.debug("cmdline = %s", self.cmdline) - ret = ret + ['-append', self.cmdline] - - - dmargs = [ 'boot', 'fda', 'fdb', 'soundhw', - 'localtime', 'serial', 'stdvga', 'isa', - 'acpi', 'usb', 'usbdevice', 'gfx_passthru' ] - - for a in dmargs: - v = vmConfig['platform'].get(a) - - # python doesn't allow '-' in variable names - if a == 'stdvga': a = 'std-vga' - if a == 'keymap': a = 'k' - - # Handle booleans gracefully - if a in ['localtime', 'std-vga', 'isa', 'usb', 'acpi']: - try: - if v != None: v = int(v) - if v: ret.append("-%s" % a) - except (ValueError, TypeError): - pass # if we can't convert it to a sane type, ignore it - elif a == 'serial': - if v: - if type(v) == str: - v = [v] - for s in v: - if s: - ret.append("-serial") - ret.append("%s" % s) - else: - if v: - ret.append("-%s" % a) - ret.append("%s" % v) - - if a in ['fda', 'fdb']: - if v: - if not os.path.isabs(v): - raise VmError("Floppy file %s does not exist." % v) - log.debug("args: %s, val: %s" % (a,v)) - - # Handle disk/network related options - mac = None - nics = 0 - - for devuuid in vmConfig['vbd_refs']: - devinfo = vmConfig['devices'][devuuid][1] - uname = devinfo.get('uname') - if uname is not None and 'file:' in uname: - (_, vbdparam) = string.split(uname, ':', 1) - if not os.path.isfile(vbdparam): - raise VmError('Disk image does not exist: %s' % - vbdparam) - - for devuuid in vmConfig['vif_refs']: - devinfo = vmConfig['devices'][devuuid][1] - dtype = devinfo.get('type', 'ioemu') - if dtype != 'ioemu': - continue - nics += 1 - mac = devinfo.get('mac') - if mac is None: - raise VmError("MAC address not specified or generated.") - bridge = devinfo.get('bridge', 'xenbr0') - model = devinfo.get('model', 'rtl8139') - ret.append("-net") - ret.append("nic,vlan=%d,macaddr=%s,model=%s" % - (nics, mac, model)) - vifname = "vif%d.%d-emu" % (self.vm.getDomid(), nics-1) - ret.append("-net") - if osdep.tapif_script is not None: - script=",script=%s,downscript=%s" % \ - (osdep.tapif_script, osdep.tapif_script) - else: - script="" - ret.append("tap,vlan=%d,ifname=%s,bridge=%s%s" % - (nics, vifname, bridge, script)) - - if nics == 0: - ret.append("-net") - ret.append("none") - - return ret - - def getDeviceModelArgs(self, restore = False): - args = ImageHandler.getDeviceModelArgs(self, restore) - args = args + ([ "-M", "xenfv"]) - if restore: - args = args + ([ "-loadvm", "/var/lib/xen/qemu-resume.%d" % - self.vm.getDomid() ]) - return args - - def buildDomain(self): - store_evtchn = self.vm.getStorePort() - - memmax_mb = self.getRequiredMaximumReservation() / 1024 - mem_mb = self.getRequiredInitialReservation() / 1024 - - log.debug("domid = %d", self.vm.getDomid()) - log.debug("image = %s", self.loader) - log.debug("store_evtchn = %d", store_evtchn) - log.debug("memsize = %d", memmax_mb) - log.debug("target = %d", mem_mb) - log.debug("vcpus = %d", self.vm.getVCpuCount()) - log.debug("vcpu_avail = %li", self.vm.getVCpuAvail()) - log.debug("acpi = %d", self.acpi) - log.debug("apic = %d", self.apic) - - rc = xc.hvm_build(domid = self.vm.getDomid(), - image = self.loader, - memsize = memmax_mb, - target = mem_mb, - vcpus = self.vm.getVCpuCount(), - vcpu_avail = self.vm.getVCpuAvail(), - acpi = self.acpi, - apic = self.apic) - rc['notes'] = { 'SUSPEND_CANCEL': 1 } - - rc['store_mfn'] = xc.hvm_get_param(self.vm.getDomid(), - HVM_PARAM_STORE_PFN) - xc.hvm_set_param(self.vm.getDomid(), HVM_PARAM_STORE_EVTCHN, - store_evtchn) - - console_mfn = xc.hvm_get_param(self.vm.getDomid(), HVM_PARAM_CONSOLE_PFN) - xc.gnttab_hvm_seed(domid = self.vm.getDomid(), - console_gmfn = console_mfn, - xenstore_gmfn = rc['store_mfn'], - console_domid = 0, - xenstore_domid = 0) - - return rc - - -class X86_HVM_ImageHandler(HVMImageHandler): - - def configure(self, vmConfig): - HVMImageHandler.configure(self, vmConfig) - self.pae = int(vmConfig['platform'].get('pae', 0)) - self.vramsize = int(vmConfig['platform'].get('videoram',4)) * 1024 - - def buildDomain(self): - xc.hvm_set_param(self.vm.getDomid(), HVM_PARAM_PAE_ENABLED, self.pae) - rc = HVMImageHandler.buildDomain(self) - self.setCpuid() - return rc - - def getBitSize(self): - return None - - def getRequiredAvailableMemory(self, mem_kb): - return mem_kb + self.vramsize - - def getRequiredInitialReservation(self): - return self.vm.getMemoryTarget() - - def getRequiredMaximumReservation(self): - return self.vm.getMemoryMaximum() - - def getRequiredShadowMemory(self, shadow_mem_kb, maxmem_kb): - # 256 pages (1MB) per vcpu, - # plus 1 page per MiB of RAM for the P2M map, - # plus 1 page per MiB of RAM to shadow the resident processes. - # This is higher than the minimum that Xen would allocate if no value - # were given (but the Xen minimum is for safety, not performance). - return max(4 * (256 * self.vm.getVCpuCount() + 2 * (maxmem_kb / 1024)), - shadow_mem_kb) - - -class X86_Linux_ImageHandler(LinuxImageHandler): - - def buildDomain(self): - # set physical mapping limit - # add an 8MB slack to balance backend allocations. - mem_kb = self.getRequiredMaximumReservation() + (8 * 1024) - xc.domain_set_memmap_limit(self.vm.getDomid(), mem_kb) - rc = LinuxImageHandler.buildDomain(self) - self.setCpuid() - return rc - -_handlers = { - "x86": { - "linux": X86_Linux_ImageHandler, - "hvm": X86_HVM_ImageHandler, - }, -} - -def findImageHandlerClass(image): - """Find the image handler class for an image config. - - @param image config - @return ImageHandler subclass or None - """ - image_type = image.image_type() - try: - return _handlers[arch.type][image_type] - except KeyError: - raise VmError('unknown image type: ' + image_type) - diff --git a/tools/python/xen/xend/osdep.py b/tools/python/xen/xend/osdep.py deleted file mode 100644 index b51dd2ee90..0000000000 --- a/tools/python/xen/xend/osdep.py +++ /dev/null @@ -1,268 +0,0 @@ -#!/usr/bin/env python -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# - -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. - -import os -import commands - -_xend_autorestart = { - "NetBSD": True, - "Linux": True, - "SunOS": False, -} - -_vif_script = { - "SunOS": "vif-vnic" -} - -_tapif_script = { - "Linux": "no", -} - -PROC_XEN_BALLOON = '/proc/xen/balloon' -SYSFS_XEN_MEMORY = '/sys/devices/system/xen_memory/xen_memory0' - -def _linux_balloon_stat_proc(label): - """Returns the value for the named label, or None if an error occurs.""" - - xend2linux_labels = { 'current' : 'Current allocation', - 'target' : 'Requested target', - 'low-balloon' : 'Low-mem balloon', - 'high-balloon' : 'High-mem balloon', - 'limit' : 'Xen hard limit' } - - f = file(PROC_XEN_BALLOON, 'r') - try: - for line in f: - keyvalue = line.split(':') - if keyvalue[0] == xend2linux_labels[label]: - values = keyvalue[1].split() - if values[0].isdigit(): - return int(values[0]) - else: - return None - return None - finally: - f.close() - -def _linux_balloon_stat_sysfs(label): - sysfiles = { 'target' : 'target_kb', - 'current' : 'info/current_kb', - 'low-balloon' : 'info/low_kb', - 'high-balloon' : 'info/high_kb', - 'limit' : 'info/hard_limit_kb' } - - name = os.path.join(SYSFS_XEN_MEMORY, sysfiles[label]) - f = file(name, 'r') - - val = f.read().strip() - if val.isdigit(): - return int(val) - return None - -def _linux_balloon_stat(label): - if os.access(PROC_XEN_BALLOON, os.F_OK): - return _linux_balloon_stat_proc(label) - elif os.access(SYSFS_XEN_MEMORY, os.F_OK): - return _linux_balloon_stat_sysfs(label) - return None - -def _netbsd_balloon_stat(label): - """Returns the value for the named label, or None if an error occurs.""" - - import commands - - xend2netbsd_labels = { 'current' : 'kern.xen.balloon.current', - 'target' : 'kern.xen.balloon.target', - 'low-balloon' : None, - 'high-balloon' : None, - 'limit' : None } - - cmdarg = xend2netbsd_labels[label] - if cmdarg is None: - return None - cmd = "/sbin/sysctl " + cmdarg - sysctloutput = commands.getoutput(cmd) - (name, value) = sysctloutput.split('=') - return int(value) - -def _solaris_balloon_stat(label): - """Returns the value for the named label, or None if an error occurs.""" - - import fcntl - import array - DEV_XEN_BALLOON = '/dev/xen/balloon' - BLN_IOCTL_CURRENT = 0x42410001 - BLN_IOCTL_TARGET = 0x42410002 - BLN_IOCTL_LOW = 0x42410003 - BLN_IOCTL_HIGH = 0x42410004 - BLN_IOCTL_LIMIT = 0x42410005 - label_to_ioctl = { 'current' : BLN_IOCTL_CURRENT, - 'target' : BLN_IOCTL_TARGET, - 'low-balloon' : BLN_IOCTL_LOW, - 'high-balloon' : BLN_IOCTL_HIGH, - 'limit' : BLN_IOCTL_LIMIT } - - f = file(DEV_XEN_BALLOON, 'r') - try: - values = array.array('L', [0]) - if fcntl.ioctl(f.fileno(), label_to_ioctl[label], values, 1) == 0: - return values[0] - else: - return None - finally: - f.close() - -_balloon_stat = { - "SunOS": _solaris_balloon_stat, - "NetBSD": _netbsd_balloon_stat, -} - -def _linux_get_cpuinfo(): - cpuinfo = {} - f = file('/proc/cpuinfo', 'r') - try: - p = -1 - d = {} - for line in f: - keyvalue = line.split(':') - if len(keyvalue) != 2: - continue - key = keyvalue[0].strip() - val = keyvalue[1].strip() - if key == 'processor': - if p != -1: - cpuinfo[p] = d - p = int(val) - d = {} - else: - d[key] = val - cpuinfo[p] = d - return cpuinfo - finally: - f.close() - -def _solaris_get_cpuinfo(): - cpuinfo = {} - - # call kstat to extrace specific cpu_info output - cmd = "/usr/bin/kstat -p -c misc -m cpu_info" - kstatoutput = commands.getoutput (cmd) - - # walk each line - for kstatline in kstatoutput.split('\n'): - - # split the line on - # module:cpu #:module#:name value - (module, cpunum, combo, namevalue) = kstatline.split (":") - - # check to see if this cpunum is already a key. If not, - # initialize an empty hash table - if not cpuinfo.has_key (int(cpunum)): - cpuinfo[int(cpunum)] = {} - - # split the namevalue output on whitespace - data = namevalue.split() - - # the key will be data[0] - key = data[0] - - # check the length of the data list. If it's larger than - # 2, join the rest of the list together with a space. - # Otherwise, value is just data[1] - if len (data) > 2: - value = ' '.join (data[1:]) - else: - value = data[1] - - # add this key/value pair to the cpuhash - cpuinfo[int(cpunum)][key] = value - - # Translate Solaris tokens into what Xend expects - for key in cpuinfo.keys(): - cpuinfo[key]["flags"] = "" - cpuinfo[key]["model name"] = cpuinfo[key]["brand"] - cpuinfo[key]["cpu MHz"] = cpuinfo[key]["clock_MHz"] - - # return the hash table - return cpuinfo - -def _netbsd_get_cpuinfo(): - import commands - cpuinfo = {} - - cmd = "/sbin/sysctl hw.ncpu" - sysctloutput = commands.getoutput(cmd) - (name, ncpu) = sysctloutput.split('=') - - for i in range(int(ncpu)): - if not cpuinfo.has_key(i): - cpuinfo[i] = {} - - # Translate NetBSD tokens into what xend expects - for key in cpuinfo.keys(): - cpuinfo[key]['flags'] = "" - cpuinfo[key]['vendor_id'] = "" - cpuinfo[key]['model name'] = "" - cpuinfo[key]['stepping'] = "" - cpuinfo[key]['cpu MHz'] = 0 - - return cpuinfo - - -_get_cpuinfo = { - "SunOS": _solaris_get_cpuinfo, - "NetBSD": _netbsd_get_cpuinfo -} - -def _default_prefork(name): - pass - -def _default_postfork(ct, abandon=False): - pass - -# call this for long-running processes that should survive a xend -# restart -def _solaris_prefork(name): - from xen.lowlevel import process - return process.activate(name) - -def _solaris_postfork(ct, abandon=False): - from xen.lowlevel import process - process.clear(ct) - if abandon: - process.abandon_latest() - -_get_prefork = { - "SunOS": _solaris_prefork -} - -_get_postfork = { - "SunOS": _solaris_postfork -} - -def _get(var, default=None): - return var.get(os.uname()[0], default) - -xend_autorestart = _get(_xend_autorestart) -vif_script = _get(_vif_script, "vif-bridge") -tapif_script = _get(_tapif_script) -lookup_balloon_stat = _get(_balloon_stat, _linux_balloon_stat) -get_cpuinfo = _get(_get_cpuinfo, _linux_get_cpuinfo) -prefork = _get(_get_prefork, _default_prefork) -postfork = _get(_get_postfork, _default_postfork) diff --git a/tools/python/xen/xend/server/BlktapController.py b/tools/python/xen/xend/server/BlktapController.py deleted file mode 100644 index 60079ebe81..0000000000 --- a/tools/python/xen/xend/server/BlktapController.py +++ /dev/null @@ -1,313 +0,0 @@ -# Copyright (c) 2005, XenSource Ltd. -import string, re, os - -from xen.xend.server.blkif import BlkifController -from xen.xend.XendLogging import log -from xen.util.xpopen import xPopen3 - -phantomDev = 0; -phantomId = 0; - -blktap1_disk_types = [ - 'aio', - 'sync', - 'vmdk', - 'ram', - 'qcow', - 'qcow2', - 'ioemu', - ] - -blktap2_disk_types = [ - 'aio', - 'ram', - 'qcow', - 'vhd', - 'remus', - ] - -blktap_disk_types = blktap1_disk_types + blktap2_disk_types - -def doexec(args, inputtext=None): - """Execute a subprocess, then return its return code, stdout and stderr""" - proc = xPopen3(args, True) - if inputtext != None: - proc.tochild.write(inputtext) - stdout = proc.fromchild - stderr = proc.childerr - rc = proc.wait() - return (rc,stdout,stderr) - -# blktap1 device controller -class BlktapController(BlkifController): - def __init__(self, vm): - BlkifController.__init__(self, vm) - - def frontendRoot(self): - """@see DevController#frontendRoot""" - - return "%s/device/vbd" % self.vm.getDomainPath() - - def getDeviceDetails(self, config): - (devid, back, front) = BlkifController.getDeviceDetails(self, config) - - phantomDevid = 0 - wrapped = False - - try: - imagetype = self.vm.info['image']['type'] - except: - imagetype = "" - - if imagetype == 'hvm': - tdevname = back['dev'] - index = ['c', 'd', 'e', 'f', 'g', 'h', 'i', \ - 'j', 'l', 'm', 'n', 'o', 'p'] - while True: - global phantomDev - global phantomId - import os, stat - - phantomId = phantomId + 1 - if phantomId == 16: - if index[phantomDev] == index[-1]: - if wrapped: - raise VmError(" No loopback block \ - devices are available. ") - wrapped = True - phantomDev = 0 - else: - phantomDev = phantomDev + 1 - phantomId = 1 - devname = 'xvd%s%d' % (index[phantomDev], phantomId) - try: - info = os.stat('/dev/%s' % devname) - except: - break - - vbd = { 'mode': 'w', 'device': devname } - fn = 'tap:%s' % back['params'] - - # recurse ... by creating the vbd, then fallthrough - # and finish creating the original device - - from xen.xend import XendDomain - dom0 = XendDomain.instance().privilegedDomain() - phantomDevid = dom0.create_phantom_vbd_with_vdi(vbd, fn) - # we need to wait for this device at a higher level - # the vbd that gets created will have a link to us - # and will let them do it there - - # add a hook to point to the phantom device, - # root path is always the same (dom0 tap) - if phantomDevid != 0: - front['phantom_vbd'] = '/local/domain/0/backend/tap/0/%s' \ - % str(phantomDevid) - - return (devid, back, front) - -class Blktap2Controller(BlktapController): - def __init__(self, vm): - BlktapController.__init__(self, vm) - - def backendPath(self, backdom, devid): - if self.deviceClass == 'tap2': - deviceClass = 'vbd' - else: - deviceClass = 'tap' - return "%s/backend/%s/%s/%d" % (backdom.getDomainPath(), - deviceClass, - self.vm.getDomid(), devid) - - def getDeviceDetails(self, config): - - (devid, back, front) = BlktapController.getDeviceDetails(self, config) - if self.deviceClass == 'tap2': - # since blktap2 uses blkback as a backend the 'params' feild contains - # the path to the blktap2 device (/dev/xen/blktap-2/tapdev*). As well, - # we need to store the params used to create the blktap2 device - # (tap:tapdisk::/) - tapdisk_uname = config.get('tapdisk_uname', '') - (_, tapdisk_params) = string.split(tapdisk_uname, ':', 1) - back['tapdisk-params'] = tapdisk_params - - return (devid, back, front) - - def getDeviceConfiguration(self, devid, transaction = None): - - # this is a blktap2 device, so we need to overwrite the 'params' feild - # with the actual blktap2 parameters. (the vbd parameters are of little - # use to us) - config = BlktapController.getDeviceConfiguration(self, devid, transaction) - if transaction is None: - tapdisk_params = self.readBackend(devid, 'tapdisk-params') - else: - tapdisk_params = self.readBackendTxn(transaction, devid, 'tapdisk-params') - if tapdisk_params: - config['uname'] = 'tap:' + tapdisk_params - - return config - - - def createDevice(self, config): - - uname = config.get('uname', '') - try: - (typ, subtyp, params, file) = string.split(uname, ':', 3) - if subtyp not in ('tapdisk', 'ioemu'): - raise ValueError('invalid subtype') - except: - (typ, params, file) = string.split(uname, ':', 2) - subtyp = 'tapdisk' - - if typ in ('tap'): - if subtyp in ('tapdisk', 'ioemu'): - if params not in blktap2_disk_types or \ - TapdiskController.check(): - # pass this device off to BlktapController - log.warn('WARNING: using deprecated blktap module') - self.deviceClass = 'tap' - devid = BlktapController.createDevice(self, config) - self.deviceClass = 'tap2' - return devid - - device = TapdiskController.create(params, file) - - # modify the configutration to create a blkback for the underlying - # blktap2 device. Note: we need to preserve the original tapdisk uname - # (it is used during save/restore and for managed domains). - config.update({'tapdisk_uname' : uname}) - config.update({'uname' : 'phy:' + device.rstrip()}) - - devid = BlkifController.createDevice(self, config) - config.update({'uname' : uname}) - config.pop('tapdisk_uname') - return devid - - # This function is called from a thread when the - # domain is detached from the disk. - def finishDeviceCleanup(self, backpath, path): - """Perform any device specific cleanup - - @backpath backend xenstore path. - @path frontend device path - - """ - - #Figure out what we're going to wait on. - self.waitForBackend_destroy(backpath) - TapdiskController.destroy(path) - -class TapdiskException(Exception): - pass - -class TapdiskController(object): - '''class which encapsulates all tapdisk control operations''' - - TAP_CTL = 'tap-ctl' - TAP_DEV = '/dev/xen/blktap-2/tapdev' - - class Tapdisk(object): - def __init__(self, pid=None, minor=-1, state=None, - dtype='', image=None, device=None): - self.pid = pid - self.minor = minor - self.state = state - self.dtype = dtype - self.image = image - self.device = device - - def __str__(self): - return 'image=%s pid=%s minor=%s state=%s type=%s device=%s' \ - % (self.image, self.pid, self.minor, self.state, self.dtype, - self.device) - - @staticmethod - def exc(*args): - rc, stdout, stderr = doexec([TapdiskController.TAP_CTL] + list(args)) - out, err = stdout.read().strip(), stderr.read().strip() - stdout.close() - stderr.close() - if rc: - raise TapdiskException('%s failed (%s %s %s)' % \ - (args, rc, out, err)) - return out - - @staticmethod - def check(): - try: - TapdiskController.exc('check') - return 0 - except Exception, e: - log.warn("tapdisk2 check failed: %s" % e) - return -1 - - @staticmethod - def list(): - tapdisks = [] - - _list = TapdiskController.exc('list') - if not _list: return [] - - for line in _list.splitlines(): - tapdisk = TapdiskController.Tapdisk() - - # Since 'tap-ctl list' does not escape blanks in the path, hard-code the current format using 4 pairs to prevent splitting the path - for pair in line.split(None, 3): - key, value = pair.split('=', 1) - if key == 'pid': - tapdisk.pid = value - elif key == 'minor': - tapdisk.minor = int(value) - if tapdisk.minor >= 0: - tapdisk.device = '%s%s' % \ - (TapdiskController.TAP_DEV, tapdisk.minor) - elif key == 'state': - tapdisk.state = value - elif key == 'args' and value.find(':') != -1: - tapdisk.dtype, tapdisk.image = value.split(':', 1) - - tapdisks.append(tapdisk) - - return tapdisks - - @staticmethod - def fromDevice(device): - if device.startswith(TapdiskController.TAP_DEV): - minor = os.minor(os.stat(device).st_rdev) - tapdisks = filter(lambda x: x.minor == minor, - TapdiskController.list()) - if len(tapdisks) == 1: - return tapdisks[0] - return None - - @staticmethod - def create(dtype, image): - return TapdiskController.exc('create', '-a%s:%s' % (dtype, image)) - - @staticmethod - def destroy(device): - tapdisk = TapdiskController.fromDevice(device) - if tapdisk: - if tapdisk.pid: - TapdiskController.exc('destroy', - '-p%s' % tapdisk.pid, - '-m%s' % tapdisk.minor) - else: - TapdiskController.exc('free', '-m%s' % tapdisk.minor) - - @staticmethod - def pause(device): - tapdisk = TapdiskController.fromDevice(device) - if tapdisk and tapdisk.pid: - TapdiskController.exc('pause', - '-p%s' % tapdisk.pid, - '-m%s' % tapdisk.minor) - - @staticmethod - def unpause(device): - tapdisk = TapdiskController.fromDevice(device) - if tapdisk and tapdisk.pid: - TapdiskController.exc('unpause', - '-p%s' % tapdisk.pid, - '-m%s' % tapdisk.minor) diff --git a/tools/python/xen/xend/server/ConsoleController.py b/tools/python/xen/xend/server/ConsoleController.py deleted file mode 100644 index bb746f399a..0000000000 --- a/tools/python/xen/xend/server/ConsoleController.py +++ /dev/null @@ -1,38 +0,0 @@ -from xen.xend.server.DevController import DevController -from xen.xend.XendLogging import log - -from xen.xend.XendError import VmError - -class ConsoleController(DevController): - """A dummy controller for us to represent serial and vnc - console devices with persistent UUIDs. - """ - - valid_cfg = ['location', 'uuid', 'protocol'] - - def __init__(self, vm): - DevController.__init__(self, vm) - self.hotplug = False - - def getDeviceDetails(self, config): - back = dict([(k, config[k]) for k in self.valid_cfg if k in config]) - return (self.allocateDeviceID(), back, {}) - - - def getDeviceConfiguration(self, devid, transaction = None): - result = DevController.getDeviceConfiguration(self, devid, transaction) - if transaction is None: - devinfo = self.readBackend(devid, *self.valid_cfg) - else: - devinfo = self.readBackendTxn(transaction, devid, *self.valid_cfg) - config = dict(zip(self.valid_cfg, devinfo)) - config = dict([(key, val) for key, val in config.items() - if val != None]) - return config - - def migrate(self, deviceConfig, network, dst, step, domName): - return 0 - - def destroyDevice(self, devid, force): - DevController.destroyDevice(self, devid, True) - diff --git a/tools/python/xen/xend/server/DevConstants.py b/tools/python/xen/xend/server/DevConstants.py deleted file mode 100644 index ed5fd2978c..0000000000 --- a/tools/python/xen/xend/server/DevConstants.py +++ /dev/null @@ -1,49 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2005 XenSource Ltd -#============================================================================ - -from xen.xend import XendOptions - -xoptions = XendOptions.instance() - -DEVICE_CREATE_TIMEOUT = xoptions.get_device_create_timeout(); -DEVICE_DESTROY_TIMEOUT = xoptions.get_device_destroy_timeout(); -HOTPLUG_STATUS_NODE = "hotplug-status" -HOTPLUG_ERROR_NODE = "hotplug-error" -HOTPLUG_STATUS_ERROR = "error" -HOTPLUG_STATUS_BUSY = "busy" - -Connected = 1 -Error = 2 -Missing = 3 -Timeout = 4 -Busy = 5 -Disconnected = 6 - -xenbusState = { - 'Unknown' : 0, - 'Initialising' : 1, - 'InitWait' : 2, - 'Initialised' : 3, - 'Connected' : 4, - 'Closing' : 5, - 'Closed' : 6, - 'Reconfiguring' : 7, - 'Reconfigured' : 8, - } -xenbusState.update(dict(zip(xenbusState.values(), xenbusState.keys()))) - diff --git a/tools/python/xen/xend/server/DevController.py b/tools/python/xen/xend/server/DevController.py deleted file mode 100644 index 0431cc2f1f..0000000000 --- a/tools/python/xen/xend/server/DevController.py +++ /dev/null @@ -1,677 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2005 XenSource Ltd -#============================================================================ - -from threading import Event -import types - -from xen.xend import sxp, XendOptions -from xen.xend.XendError import VmError -from xen.xend.XendLogging import log -import xen.xend.XendConfig -from xen.xend.server.DevConstants import * - -from xen.xend.xenstore.xstransact import xstransact, complete -from xen.xend.xenstore.xswatch import xswatch -import xen.xend.server.DevConstants -import os, re - -xoptions = XendOptions.instance() - - -class DevController: - """Abstract base class for a device controller. Device controllers create - appropriate entries in the store to trigger the creation, reconfiguration, - and destruction of devices in guest domains. Each subclass of - DevController is responsible for a particular device-class, and - understands the details of configuration specific to that device-class. - - DevController itself provides the functionality common to all device - creation tasks, as well as providing an interface to XendDomainInfo for - triggering those events themselves. - """ - - # Set when registered. - deviceClass = None - - - ## public: - - def __init__(self, vm): - self.vm = vm - self.hotplug = True - - def createDevice(self, config): - """Trigger the creation of a device with the given configuration. - - @return The ID for the newly created device. - """ - (devid, back, front) = self.getDeviceDetails(config) - if devid is None: - return 0 - - self.setupDevice(config) - - (backpath, frontpath) = self.addStoreEntries(config, devid, back, - front) - - import xen.xend.XendDomain - xd = xen.xend.XendDomain.instance() - backdom_name = config.get('backend') - if backdom_name is None: - backdom = xen.xend.XendDomain.DOM0_ID - else: - bd = xd.domain_lookup_nr(backdom_name) - backdom = bd.getDomid() - count = 0 - while True: - t = xstransact() - try: - if devid in self.deviceIDs(t): - if 'dev' in back: - dev_str = '%s (%d, %s)' % (back['dev'], devid, - self.deviceClass) - else: - dev_str = '%s (%s)' % (devid, self.deviceClass) - - raise VmError("Device %s is already connected." % dev_str) - - if count == 0: - log.debug('DevController: writing %s to %s.', - str(front), frontpath) - log.debug('DevController: writing %s to %s.', - str(xen.xend.XendConfig.scrub_password(back)), backpath) - elif count % 50 == 0: - log.debug( - 'DevController: still waiting to write device entries.') - - devpath = self.devicePath(devid) - - t.remove(frontpath) - t.remove(backpath) - t.remove(devpath) - - t.mkdir(backpath) - t.set_permissions(backpath, - {'dom': backdom }, - {'dom' : self.vm.getDomid(), - 'read' : True }) - t.mkdir(frontpath) - t.set_permissions(frontpath, - {'dom': self.vm.getDomid()}, - {'dom': backdom, 'read': True}) - - t.write2(frontpath, front) - t.write2(backpath, back) - - t.mkdir(devpath) - t.write2(devpath, { - 'backend' : backpath, - 'backend-id' : "%i" % backdom, - 'frontend' : frontpath, - 'frontend-id' : "%i" % self.vm.getDomid() - }) - - if t.commit(): - return devid - - count += 1 - except: - t.abort() - raise - - - def waitForDevices(self): - log.debug("Waiting for devices %s.", self.deviceClass) - return map(self.waitForDevice, self.deviceIDs()) - - - def waitForDevice(self, devid): - log.debug("Waiting for %s.", devid) - - if not self.hotplug: - return - - (status, err) = self.waitForBackend(devid) - - if status == Timeout: - self.destroyDevice(devid, False) - raise VmError("Device %s (%s) could not be connected. " - "Hotplug scripts not working." % - (devid, self.deviceClass)) - - elif status == Error: - self.destroyDevice(devid, False) - if err is None: - raise VmError("Device %s (%s) could not be connected. " - "Backend device not found." % - (devid, self.deviceClass)) - else: - raise VmError("Device %s (%s) could not be connected. " - "%s" % (devid, self.deviceClass, err)) - elif status == Missing: - # Don't try to destroy the device; it's already gone away. - raise VmError("Device %s (%s) could not be connected. " - "Device not found." % (devid, self.deviceClass)) - - elif status == Busy: - self.destroyDevice(devid, False) - if err is None: - err = "Busy." - raise VmError("Device %s (%s) could not be connected.\n%s" % - (devid, self.deviceClass, err)) - - - def waitForDevice_destroy(self, devid, backpath): - log.debug("Waiting for %s - destroyDevice.", devid) - - if not self.hotplug: - return - - status = self.waitForBackend_destroy(backpath) - - if status == Timeout: - raise VmError("Device %s (%s) could not be disconnected. " % - (devid, self.deviceClass)) - - def waitForDevice_reconfigure(self, devid): - log.debug("Waiting for %s - reconfigureDevice.", devid) - - (status, err) = self.waitForBackend_reconfigure(devid) - - if status == Timeout: - raise VmError("Device %s (%s) could not be reconfigured. " % - (devid, self.deviceClass)) - - - def reconfigureDevice(self, devid, config): - """Reconfigure the specified device. - - The implementation here just raises VmError. This may be overridden - by those subclasses that can reconfigure their devices. - """ - raise VmError('%s devices may not be reconfigured' % self.deviceClass) - - - def destroyDevice(self, devid, force): - """Destroy the specified device. - - @param devid The device ID, or something device-specific from which - the device ID can be determined (such as a guest-side device name). - - The implementation here simply deletes the appropriate paths from the - store. This may be overridden by subclasses who need to perform other - tasks on destruction. The implementation here accepts integer device - IDs or paths containg integer deviceIDs, e.g. vfb/0. Subclasses may - accept other values and convert them to integers before passing them - here. - """ - - dev = self.convertToDeviceNumber(devid) - - # Modify online status /before/ updating state (latter is watched by - # drivers, so this ordering avoids a race). - self.writeBackend(dev, 'online', "0") - self.writeBackend(dev, 'state', str(xenbusState['Closing'])) - - if force: - frontpath = self.frontendPath(dev) - backpath = self.readVm(dev, "backend") - if backpath: - xstransact.Remove(backpath) - xstransact.Remove(frontpath) - - # xstransact.Remove(self.devicePath()) ?? Below is the same ? - self.vm._removeVm("device/%s/%d" % (self.deviceClass, dev)) - - def configurations(self, transaction = None): - return map(lambda x: self.configuration(x, transaction), self.deviceIDs(transaction)) - - - def configuration(self, devid, transaction = None): - """@return an s-expression giving the current configuration of the - specified device. This would be suitable for giving to {@link - #createDevice} in order to recreate that device.""" - configDict = self.getDeviceConfiguration(devid, transaction) - sxpr = [self.deviceClass] - for key, val in configDict.items(): - if isinstance(val, (types.ListType, types.TupleType)): - for v in val: - if v != None: - sxpr.append([key, v]) - else: - if val != None: - sxpr.append([key, val]) - return sxpr - - def sxprs(self): - """@return an s-expression describing all the devices of this - controller's device-class. - """ - return xstransact.ListRecursive(self.frontendRoot()) - - - def sxpr(self, devid): - """@return an s-expression describing the specified device. - """ - return [self.deviceClass, ['dom', self.vm.getDomid(), - 'id', devid]] - - - def getDeviceConfiguration(self, devid, transaction = None): - """Returns the configuration of a device. - - @note: Similar to L{configuration} except it returns a dict. - @return: dict - """ - if transaction is None: - backdomid = xstransact.Read(self.devicePath(devid), "backend-id") - else: - backdomid = transaction.read(self.devicePath(devid) + "/backend-id") - - if backdomid is None: - raise VmError("Device %s not connected" % devid) - - return {'backend': int(backdomid)} - - def getAllDeviceConfigurations(self): - all_configs = {} - for devid in self.deviceIDs(): - config_dict = self.getDeviceConfiguration(devid) - all_configs[devid] = config_dict - return all_configs - - - def convertToDeviceNumber(self, devid): - try: - return int(devid) - except ValueError: - # Does devid contain devicetype/deviceid? - # Propogate exception if unable to find an integer devid - return int(type(devid) is str and devid.split('/')[-1] or None) - - ## protected: - - def getDeviceDetails(self, config): - """Compute the details for creation of a device corresponding to the - given configuration. These details consist of a tuple of (devID, - backDetails, frontDetails), where devID is the ID for the new device, - and backDetails and frontDetails are the device configuration - specifics for the backend and frontend respectively. - - backDetails and frontDetails should be dictionaries, the keys and - values of which will be used as paths in the store. There is no need - for these dictionaries to include the references from frontend to - backend, nor vice versa, as these will be handled by DevController. - - Abstract; must be implemented by every subclass. - - @return (devID, backDetails, frontDetails), as specified above. - """ - - raise NotImplementedError() - - def setupDevice(self, config): - """ Setup device from config. - """ - return - - def migrate(self, deviceConfig, network, dst, step, domName): - """ Migration of a device. The 'network' parameter indicates - whether the device is network-migrated (True). 'dst' then gives - the hostname of the machine to migrate to. - This function is called for 4 steps: - If step == 0: Check whether the device is ready to be migrated - or can at all be migrated; return a '-1' if - the device is NOT ready, a '0' otherwise. If it is - not ready ( = not possible to migrate this device), - migration will not take place. - step == 1: Called immediately after step 0; migration - of the kernel has started; - step == 2: Called after the suspend has been issued - to the domain and the domain is not scheduled anymore. - Synchronize with what was started in step 1, if necessary. - Now the device should initiate its transfer to the - given target. Since there might be more than just - one device initiating a migration, this step should - put the process performing the transfer into the - background and return immediately to achieve as much - concurrency as possible. - step == 3: Synchronize with the migration of the device that - was initiated in step 2. - Make sure that the migration has finished and only - then return from the call. - """ - tool = xoptions.get_external_migration_tool() - if tool: - log.info("Calling external migration tool for step %d" % step) - fd = os.popen("%s -type %s -step %d -host %s -domname %s" % - (tool, self.deviceClass, step, dst, domName)) - for line in fd: - log.info(line.rstrip()) - rc = fd.close() - if rc: - raise VmError('Migration tool returned %d' % (rc >> 8)) - return 0 - - - def recover_migrate(self, deviceConfig, network, dst, step, domName): - """ Recover from device migration. The given step was the - last one that was successfully executed. - """ - tool = xoptions.get_external_migration_tool() - if tool: - log.info("Calling external migration tool") - fd = os.popen("%s -type %s -step %d -host %s -domname %s -recover" % - (tool, self.deviceClass, step, dst, domName)) - for line in fd: - log.info(line.rstrip()) - rc = fd.close() - if rc: - raise VmError('Migration tool returned %d' % (rc >> 8)) - return 0 - - - def getDomid(self): - """Stub to {@link XendDomainInfo.getDomid}, for use by our - subclasses. - """ - return self.vm.getDomid() - - - def allocateDeviceID(self): - """Allocate a device ID, allocating them consecutively on a - per-domain, per-device-class basis, and using the store to record the - next available ID. - - This method is available to our subclasses, though it is not - compulsory to use it; subclasses may prefer to allocate IDs based upon - the device configuration instead. - """ - path = self.frontendMiscPath() - return complete(path, self._allocateDeviceID) - - - def _allocateDeviceID(self, t): - result = t.read("nextDeviceID") - if result: - result = int(result) - else: - result = 0 - t.write("nextDeviceID", str(result + 1)) - return result - - - def removeBackend(self, devid, *args): - frontpath = self.frontendPath(devid) - backpath = xstransact.Read(frontpath, "backend") - if backpath: - return xstransact.Remove(backpath, *args) - else: - raise VmError("Device %s not connected" % devid) - - def readVm(self, devid, *args): - devpath = self.devicePath(devid) - if devpath: - return xstransact.Read(devpath, *args) - else: - raise VmError("Device config %s not found" % devid) - - def readBackend(self, devid, *args): - backpath = self.readVm(devid, "backend") - if backpath: - return xstransact.Read(backpath, *args) - else: - raise VmError("Device %s not connected" % devid) - - def readBackendTxn(self, transaction, devid, *args): - backpath = self.readVm(devid, "backend") - if backpath: - paths = map(lambda x: backpath + "/" + x, args) - return transaction.read(*paths) - else: - raise VmError("Device %s not connected" % devid) - - def readFrontend(self, devid, *args): - return xstransact.Read(self.frontendPath(devid), *args) - - def readFrontendTxn(self, transaction, devid, *args): - paths = map(lambda x: self.frontendPath(devid) + "/" + x, args) - return transaction.read(*paths) - - def deviceIDs(self, transaction = None): - """@return The IDs of each of the devices currently configured for - this instance's deviceClass. - """ - fe = self.deviceRoot() - - if transaction: - return map(lambda x: int(x.split('/')[-1]), transaction.list(fe)) - else: - return map(int, xstransact.List(fe)) - - - def writeBackend(self, devid, *args): - backpath = self.readVm(devid, "backend") - - if backpath: - xstransact.Write(backpath, *args) - else: - raise VmError("Device %s not connected" % devid) - - -## private: - - def addStoreEntries(self, config, devid, backDetails, frontDetails): - """Add to backDetails and frontDetails the entries to be written in - the store to trigger creation of a device. The backend domain ID is - taken from the given config, paths for frontend and backend are - computed, and these are added to the backDetails and frontDetails - dictionaries for writing to the store, including references from - frontend to backend and vice versa. - - @return A pair of (backpath, frontpath). backDetails and frontDetails - will have been updated appropriately, also. - - @param config The configuration of the device, as given to - {@link #createDevice}. - @param devid As returned by {@link #getDeviceDetails}. - @param backDetails As returned by {@link #getDeviceDetails}. - @param frontDetails As returned by {@link #getDeviceDetails}. - """ - - import xen.xend.XendDomain - xd = xen.xend.XendDomain.instance() - - backdom_name = config.get('backend') - if backdom_name: - backdom = xd.domain_lookup_nr(backdom_name) - else: - backdom = xd.privilegedDomain() - - if not backdom: - raise VmError("Cannot configure device for unknown backend %s" % - backdom_name) - - frontpath = self.frontendPath(devid) - backpath = self.backendPath(backdom, devid) - - frontDetails.update({ - 'backend' : backpath, - 'backend-id' : "%i" % backdom.getDomid(), - 'state' : str(xenbusState['Initialising']) - }) - - if self.vm.native_protocol: - frontDetails.update({'protocol' : self.vm.native_protocol}) - - backDetails.update({ - 'domain' : self.vm.getName(), - 'frontend' : frontpath, - 'frontend-id' : "%i" % self.vm.getDomid(), - 'state' : str(xenbusState['Initialising']), - 'online' : "1" - }) - - return (backpath, frontpath) - - - def waitForBackend(self, devid): - frontpath = self.frontendPath(devid) - # lookup a phantom - phantomPath = xstransact.Read(frontpath, 'phantom_vbd') - if phantomPath is not None: - log.debug("Waiting for %s's phantom %s.", devid, phantomPath) - statusPath = phantomPath + '/' + HOTPLUG_STATUS_NODE - ev = Event() - result = { 'status': Timeout } - xswatch(statusPath, hotplugStatusCallback, ev, result) - ev.wait(DEVICE_CREATE_TIMEOUT) - err = xstransact.Read(statusPath, HOTPLUG_ERROR_NODE) - if result['status'] != Connected: - return (result['status'], err) - - backpath = self.readVm(devid, "backend") - - if backpath: - statusPath = backpath + '/' + HOTPLUG_STATUS_NODE - ev = Event() - result = { 'status': Timeout } - - xswatch(statusPath, hotplugStatusCallback, ev, result) - - ev.wait(DEVICE_CREATE_TIMEOUT) - - err = xstransact.Read(backpath, HOTPLUG_ERROR_NODE) - - return (result['status'], err) - else: - return (Missing, None) - - - def waitForBackend_destroy(self, backpath): - - statusPath = backpath + '/' + HOTPLUG_STATUS_NODE - ev = Event() - result = { 'status': Timeout } - - xswatch(statusPath, deviceDestroyCallback, ev, result) - - ev.wait(DEVICE_DESTROY_TIMEOUT) - - return result['status'] - - def waitForBackend_reconfigure(self, devid): - frontpath = self.frontendPath(devid) - backpath = xstransact.Read(frontpath, "backend") - if backpath: - statusPath = backpath + '/' + "state" - ev = Event() - result = { 'status': Timeout } - - xswatch(statusPath, xenbusStatusCallback, ev, result) - - ev.wait(DEVICE_CREATE_TIMEOUT) - - return (result['status'], None) - else: - return (Missing, None) - - - def backendPath(self, backdom, devid): - """Construct backend path given the backend domain and device id. - - @param backdom [XendDomainInfo] The backend domain info.""" - - return "%s/backend/%s/%s/%d" % (backdom.getDomainPath(), - self.deviceClass, - self.vm.getDomid(), devid) - - - def frontendPath(self, devid): - return "%s/%d" % (self.frontendRoot(), devid) - - - def frontendRoot(self): - return "%s/device/%s" % (self.vm.getDomainPath(), self.deviceClass) - - def frontendMiscPath(self): - return "%s/device-misc/%s" % (self.vm.getDomainPath(), - self.deviceClass) - - def deviceRoot(self): - """Return the /vm/device. Because backendRoot assumes the - backend domain is 0""" - return "%s/device/%s" % (self.vm.vmpath, self.deviceClass) - - def devicePath(self, devid): - """Return the /device entry of the given VM. We use it to store - backend/frontend locations""" - return "%s/device/%s/%s" % (self.vm.vmpath, - self.deviceClass, devid) - -def hotplugStatusCallback(statusPath, ev, result): - log.debug("hotplugStatusCallback %s.", statusPath) - - status = xstransact.Read(statusPath) - - if status is not None: - if status == HOTPLUG_STATUS_ERROR: - result['status'] = Error - elif status == HOTPLUG_STATUS_BUSY: - result['status'] = Busy - else: - result['status'] = Connected - else: - return 1 - - log.debug("hotplugStatusCallback %d.", result['status']) - - ev.set() - return 0 - - -def deviceDestroyCallback(statusPath, ev, result): - log.debug("deviceDestroyCallback %s.", statusPath) - - status = xstransact.Read(statusPath) - - if status is None: - result['status'] = Disconnected - else: - return 1 - - log.debug("deviceDestroyCallback %d.", result['status']) - - ev.set() - return 0 - - -def xenbusStatusCallback(statusPath, ev, result): - log.debug("xenbusStatusCallback %s.", statusPath) - - status = xstransact.Read(statusPath) - - if status == str(xenbusState['Connected']): - result['status'] = Connected - else: - return 1 - - log.debug("xenbusStatusCallback %d.", result['status']) - - ev.set() - return 0 diff --git a/tools/python/xen/xend/server/SSLXMLRPCServer.py b/tools/python/xen/xend/server/SSLXMLRPCServer.py deleted file mode 100644 index 1bbd636a4f..0000000000 --- a/tools/python/xen/xend/server/SSLXMLRPCServer.py +++ /dev/null @@ -1,103 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2007 XenSource Inc. -#============================================================================ - - -""" -HTTPS wrapper for an XML-RPC server interface. Requires PyOpenSSL (Debian -package python-pyopenssl). -""" - -import socket - -from OpenSSL import SSL - -from xen.util.xmlrpclib2 import XMLRPCRequestHandler, TCPXMLRPCServer - - -class SSLXMLRPCRequestHandler(XMLRPCRequestHandler): - def setup(self): - self.connection = self.request - self.rfile = socket._fileobject(self.request, "rb", self.rbufsize) - self.wfile = socket._fileobject(self.request, "wb", self.wbufsize) - -# -# Taken from pyOpenSSL-0.6 examples (public-domain) -# - -class SSLWrapper: - """ - """ - def __init__(self, conn): - """ - Connection is not yet a new-style class, - so I'm making a proxy instead of subclassing. - """ - self.__dict__["conn"] = conn - def __getattr__(self, name): - return getattr(self.__dict__["conn"], name) - def __setattr__(self, name, value): - setattr(self.__dict__["conn"], name, value) - - def close(self): - self.shutdown() - return self.__dict__["conn"].close() - - def shutdown(self, how=1): - """ - SimpleXMLRpcServer.doPOST calls shutdown(1), - and Connection.shutdown() doesn't take - an argument. So we just discard the argument. - """ - # Block until the shutdown is complete - self.__dict__["conn"].shutdown() - self.__dict__["conn"].shutdown() - - def accept(self): - """ - This is the other part of the shutdown() workaround. - Since servers create new sockets, we have to infect - them with our magic. :) - """ - c, a = self.__dict__["conn"].accept() - return (SSLWrapper(c), a) - -# -# End of pyOpenSSL-0.6 example code. -# - -class SSLXMLRPCServer(TCPXMLRPCServer): - def __init__(self, addr, allowed, xenapi, logRequests = 1, - ssl_key_file = None, ssl_cert_file = None): - - TCPXMLRPCServer.__init__(self, addr, allowed, xenapi, - SSLXMLRPCRequestHandler, logRequests) - - if not ssl_key_file or not ssl_cert_file: - raise ValueError("SSLXMLRPCServer requires ssl_key_file " - "and ssl_cert_file to be set.") - - # make a SSL socket - ctx = SSL.Context(SSL.SSLv23_METHOD) - ctx.set_options(SSL.OP_NO_SSLv2) - ctx.use_privatekey_file (ssl_key_file) - ctx.use_certificate_file(ssl_cert_file) - self.socket = SSLWrapper(SSL.Connection(ctx, - socket.socket(self.address_family, - self.socket_type))) - self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - self.server_bind() - self.server_activate() diff --git a/tools/python/xen/xend/server/SrvDaemon.py b/tools/python/xen/xend/server/SrvDaemon.py deleted file mode 100644 index 0a330f15b0..0000000000 --- a/tools/python/xen/xend/server/SrvDaemon.py +++ /dev/null @@ -1,420 +0,0 @@ -########################################################### -## Xen controller daemon -## Copyright (c) 2004, K A Fraser (University of Cambridge) -## Copyright (C) 2004, Mike Wray -## Copyright (C) 2005, XenSource Ltd -########################################################### - -import os -import os.path -import signal -import stat -import sys -import threading -import time -import linecache -import pwd -import re -import traceback - -import xen.lowlevel.xc - -from xen.xend.XendLogging import log -from xen.xend import osdep -from xen.util import mkdir - -import relocate -import udevevent -import SrvServer -from params import * - - -XEND_PROCESS_NAME = 'xend' - - -class Daemon: - """The xend daemon. - """ - def __init__(self): - self.traceon = False - self.tracefile = None - self.traceindent = 0 - self.child = 0 - self.traceLock = threading.Lock() - - - def cleanup_xend(self, kill): - """Clean up the Xend pidfile. - If a running process is found, kills it if 'kill' is true. - - @param kill: whether to kill the process - @return running process id or 0 - """ - running = 0 - pid = read_pid(XEND_PID_FILE) - if find_process(pid, XEND_PROCESS_NAME): - if kill: - os.kill(pid, signal.SIGTERM) - else: - running = pid - if running == 0 and os.path.isfile(XEND_PID_FILE): - os.remove(XEND_PID_FILE) - return running - - - def reloadConfig(self): - """ - """ - pid = read_pid(XEND_PID_FILE) - if find_process(pid, XEND_PROCESS_NAME): - os.kill(pid, signal.SIGHUP) - - - def status(self): - """Returns the status of the xend daemon. - The return value is defined by the LSB: - 0 Running - 3 Not running - """ - if self.cleanup_xend(False) == 0: - return 3 - else: - return 0 - - - def fork_pid(self): - """Fork and write the pid of the child to XEND_PID_FILE. - - @return: pid of child in parent, 0 in child - """ - - self.child = os.fork() - - if self.child: - # Parent - pidfile = open(XEND_PID_FILE, 'w') - try: - pidfile.write(str(self.child)) - finally: - pidfile.close() - - return self.child - - - def daemonize(self): - # Detach from TTY. - - # Become the group leader (already a child process) - os.setsid() - - # Fork, this allows the group leader to exit, - # which means the child can never again regain control of the - # terminal - if os.fork(): - os._exit(0) - - # Detach from standard file descriptors, and redirect them to - # /dev/null or the log as appropriate. - # We open the log file first, so that we can diagnose a failure to do - # so _before_ we close stderr. - try: - parent = os.path.dirname(XEND_DEBUG_LOG) - mkdir.parents(parent, stat.S_IRWXU) - fd = os.open(XEND_DEBUG_LOG, os.O_WRONLY|os.O_CREAT|os.O_APPEND, 0666) - except Exception, exn: - print >>sys.stderr, exn - print >>sys.stderr, ("Xend failed to open %s. Exiting!" % - XEND_DEBUG_LOG) - sys.exit(1) - - os.close(0) - os.close(1) - os.close(2) - if XEND_DEBUG: - os.open('/dev/null', os.O_RDONLY) - os.dup(fd) - os.dup(fd) - else: - os.open('/dev/null', os.O_RDWR) - os.dup(0) - os.dup(fd) - os.close(fd) - - print >>sys.stderr, ("Xend started at %s." % - time.asctime(time.localtime())) - - - def start(self, trace=0): - """Attempts to start the daemons. - The return value is defined by the LSB: - 0 Success - 4 Insufficient privileges - """ - xend_pid = self.cleanup_xend(False) - - if self.set_user(): - return 4 - os.chdir("/") - - if xend_pid > 0: - # Trying to run an already-running service is a success. - return 0 - - ret = 0 - - # If we're not going to create a daemon, simply - # call the run method right here. - if not XEND_DAEMONIZE: - self.tracing(trace) - self.run(None) - return ret - - # we use a pipe to communicate between the parent and the child process - # this way we know when the child has actually initialized itself so - # we can avoid a race condition during startup - - r,w = os.pipe() - if os.fork(): - os.close(w) - r = os.fdopen(r, 'r') - try: - s = r.read() - finally: - r.close() - if not len(s): - ret = 1 - else: - ret = int(s) - else: - os.close(r) - # Child - self.daemonize() - self.tracing(trace) - - # If Xend proper segfaults, then we want to restart it. Thus, - # we fork a child for running Xend itself, and if it segfaults - # (or exits any way other than cleanly) then we run it again. - # The first time through we want the server to write to the (r,w) - # pipe created above, so that we do not exit until the server is - # ready to receive requests. All subsequent restarts we don't - # want this behaviour, or the pipe will eventually fill up, so - # we just pass None into run in subsequent cases (by clearing w - # in the parent of the first fork). On some operating systems, - # restart is managed externally, so we won't fork, and just exit. - while True: - - if not osdep.xend_autorestart: - self.run(os.fdopen(w, 'w')) - os._exit(0) - - pid = self.fork_pid() - if pid: - if w is not None: - os.close(w) - w = None - - (_, status) = os.waitpid(pid, 0) - - if os.WIFEXITED(status): - code = os.WEXITSTATUS(status) - log.info('Xend exited with status %d.', code) - sys.exit(code) - - if os.WIFSIGNALED(status): - sig = os.WTERMSIG(status) - - if sig in (signal.SIGINT, signal.SIGTERM): - log.info('Xend stopped due to signal %d.', sig) - sys.exit(0) - else: - log.fatal( - 'Xend died due to signal %d! Restarting it.', - sig) - else: - self.run(w and os.fdopen(w, 'w') or None) - # if we reach here, the child should quit. - os._exit(0) - - return ret - - def tracing(self, traceon): - """Turn tracing on or off. - - @param traceon: tracing flag - """ - if traceon == self.traceon: - return - self.traceon = traceon - if traceon: - self.tracefile = open(XEND_TRACE_FILE, 'w+', 1) - self.traceindent = 0 - sys.settrace(self.trace) - try: - threading.settrace(self.trace) # Only in Python >= 2.3 - except: - pass - - def print_trace(self, string): - self.tracefile.write("%s: "% threading.currentThread().getName()) - for i in range(self.traceindent): - ch = " " - if (i % 5): - ch = ' ' - else: - ch = '|' - self.tracefile.write(ch) - self.tracefile.write(string) - - def trace(self, frame, event, arg): - self.traceLock.acquire() - try: - if not self.traceon: - print >>self.tracefile - print >>self.tracefile, '-' * 20, 'TRACE OFF', '-' * 20 - self.tracefile.close() - self.tracefile = None - return None - if event == 'call': - code = frame.f_code - filename = code.co_filename - m = re.search('.*xend/(.*)', filename) - if not m: - return None - modulename = m.group(1) - if modulename.endswith('.pyc'): - modulename = modulename[:-1] - if modulename == 'sxp.py' or \ - modulename == 'XendLogging.py' or \ - modulename == 'XendMonitor.py' or \ - modulename == 'server/SrvServer.py': - return None - self.traceindent += 1 - self.print_trace("> %s:%s\n" - % (modulename, code.co_name)) - elif event == 'line': - filename = frame.f_code.co_filename - lineno = frame.f_lineno - self.print_trace("%4d %s" % - (lineno, linecache.getline(filename, lineno))) - elif event == 'return': - code = frame.f_code - filename = code.co_filename - m = re.search('.*xend/(.*)', filename) - if not m: - return None - modulename = m.group(1) - self.print_trace("< %s:%s\n" - % (modulename, code.co_name)) - self.traceindent -= 1 - elif event == 'exception': - self.print_trace("! Exception:\n") - (ex, val, tb) = arg - traceback.print_exception(ex, val, tb, 10, self.tracefile) - #del tb - return self.trace - finally: - self.traceLock.release() - - def set_user(self): - # Set the UID. - try: - os.setuid(pwd.getpwnam(XEND_USER)[2]) - return 0 - except KeyError: - print >>sys.stderr, "Error: no such user '%s'" % XEND_USER - return 1 - - def stop(self): - return self.cleanup_xend(True) - - def run(self, status): - try: - log.info("Xend Daemon started") - - xc = xen.lowlevel.xc.xc() - xinfo = xc.xeninfo() - log.info("Xend changeset: %s.", xinfo['xen_changeset']) - del xc - - relocate.listenRelocation() - udevevent.listenUdevEvent() - servers = SrvServer.create() - servers.start(status) - del servers - - except Exception, ex: - print >>sys.stderr, 'Exception starting xend:', ex - if XEND_DEBUG: - traceback.print_exc() - log.exception("Exception starting xend (%s)" % ex) - if status: - status.write('1') - status.close() - sys.exit(1) - -def instance(): - global inst - try: - inst - except: - inst = Daemon() - return inst - - -def read_pid(pidfile): - """Read process id from a file. - - @param pidfile: file to read - @return pid or 0 - """ - if os.path.isfile(pidfile) and os.path.getsize(pidfile): - try: - f = open(pidfile, 'r') - try: - return int(f.read()) - finally: - f.close() - except: - return 0 - else: - return 0 - - -def find_process(pid, name): - """Search for a process. - - @param pid: process id - @param name: process name - @return: pid if found, 0 otherwise - """ - running = 0 - if pid: - lines = os.popen('ps %d 2>/dev/null' % pid).readlines() - exp = '^ *%d.+%s' % (pid, name) - for line in lines: - if re.search(exp, line): - running = pid - break - return running - - -def main(argv = None): - global XEND_DAEMONIZE - - XEND_DAEMONIZE = False - if argv is None: - argv = sys.argv - - try: - daemon = instance() - - r,w = os.pipe() - daemon.run(os.fdopen(w, 'w')) - return 0 - except Exception, exn: - log.fatal(exn) - return 1 - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/tools/python/xen/xend/server/SrvDmesg.py b/tools/python/xen/xend/server/SrvDmesg.py deleted file mode 100644 index 18c453af26..0000000000 --- a/tools/python/xen/xend/server/SrvDmesg.py +++ /dev/null @@ -1,52 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2005 XenSource Ltd -#============================================================================ - - -from xen.xend import XendDmesg - -from xen.web.SrvDir import SrvDir - - -class SrvDmesg(SrvDir): - """Xen Dmesg output. - """ - - def __init__(self): - SrvDir.__init__(self) - self.xd = XendDmesg.instance() - - def render_POST(self, req): - self.perform(req) - - def render_GET(self, req): - if self.use_sxp(req): - req.setHeader("Content-Type", "text/plain") - req.write(self.info()) - else: - req.write('') - self.print_path(req) - req.write('
')
-            req.write(self.info())
-            req.write('
') - - def info(self): - return self.xd.info() - - def op_clear(self, _1, _2): - self.xd.clear() - return 0 diff --git a/tools/python/xen/xend/server/SrvDomain.py b/tools/python/xen/xend/server/SrvDomain.py deleted file mode 100644 index aa07b7ab19..0000000000 --- a/tools/python/xen/xend/server/SrvDomain.py +++ /dev/null @@ -1,329 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2005 Xensource Ltd -#============================================================================ - -from xen.web import http - -from xen.xend import sxp -from xen.xend import XendDomain -from xen.xend.Args import FormFn -from xen.xend.XendLogging import log - -from xen.web.SrvDir import SrvDir - -class SrvDomain(SrvDir): - """Service managing a single domain. - """ - - def __init__(self, dom): - SrvDir.__init__(self) - self.dom = dom - self.xd = XendDomain.instance() - - def op_configure(self, _, req): - """Configure an existing domain. - Configure is unusual in that it requires a domain id, - not a domain name. - """ - fn = FormFn(self.xd.domain_configure, - [['dom', 'int'], - ['config', 'sxpr']]) - return fn(req.args, {'dom': self.dom.domid}) - - def op_unpause(self, _1, _2): - val = self.xd.domain_unpause(self.dom.domid) - return val - - def op_pause(self, _1, _2): - val = self.xd.domain_pause(self.dom.domid) - return val - - def acceptCommand(self, req): - req.setResponseCode(http.ACCEPTED) - req.setHeader("Location", "%s/.." % req.prePathURL()) - - def op_rename(self, _, req): - self.acceptCommand(req) - return self.dom.setName(req.args['name'][0]) - - def op_shutdown(self, _, req): - self.acceptCommand(req) - return self.dom.shutdown(req.args['reason'][0]) - - def op_delete(self, _, req): - self.acceptCommand(req) - return self.xd.domain_delete(self.dom.getName()) - - def op_start(self, _, req): - self.acceptCommand(req) - paused = False - if 'paused' in req.args and req.args['paused'] == [1]: - paused = True - log.debug("Starting domain " + self.dom.getName() + " " + str(paused)) - return self.xd.domain_start(self.dom.getName(), paused) - - def op_sysrq(self, _, req): - self.acceptCommand(req) - return self.dom.send_sysrq(int(req.args['key'][0])) - - def op_wait_for_devices(self, _, req): - self.acceptCommand(req) - return self.dom.waitForDevices() - - def op_destroy(self, _, req): - self.acceptCommand(req) - return self.xd.domain_destroy(self.dom.domid) - - def op_save(self, op, req): - self.acceptCommand(req) - return req.threadRequest(self.do_save, op, req) - - def do_save(self, _, req): - return self.xd.domain_save(self.dom.domid, req.args['file'][0]) - - def op_dump(self, op, req): - self.acceptCommand(req) - return req.threadRequest(self.do_dump, op, req) - - def do_dump(self, _, req): - fn = FormFn(self.xd.domain_dump, - [['dom', 'int'], - ['file', 'str'], - ['live', 'int'], - ['crash', 'int'], - ['reset', 'int']]) - return fn(req.args, {'dom': self.dom.domid}) - - def op_migrate(self, op, req): - return req.threadRequest(self.do_migrate, op, req) - - def do_migrate(self, _, req): - fn = FormFn(self.xd.domain_migrate, - [['dom', 'int'], - ['destination', 'str'], - ['live', 'int'], - ['port', 'int'], - ['node', 'int'], - ['ssl', 'int'], - ['change_home_server', 'bool']]) - return fn(req.args, {'dom': self.dom.domid}) - - def op_pincpu(self, _, req): - fn = FormFn(self.xd.domain_pincpu, - [['dom', 'str'], - ['vcpu', 'str'], - ['cpumap', 'str']]) - val = fn(req.args, {'dom': self.dom.getName()}) - return val - - def op_cpu_sedf_get(self, _, req): - fn = FormFn(self.xd.domain_cpu_sedf_get, - [['dom', 'int']]) - val = fn(req.args, {'dom': self.dom.domid}) - return val - - - def op_cpu_sedf_set(self, _, req): - fn = FormFn(self.xd.domain_cpu_sedf_set, - [['dom', 'int'], - ['period', 'int'], - ['slice', 'int'], - ['latency', 'int'], - ['extratime', 'int'], - ['weight', 'int']]) - val = fn(req.args, {'dom': self.dom.domid}) - return val - - def op_domain_sched_credit_get(self, _, req): - fn = FormFn(self.xd.domain_sched_credit_get, - [['dom', 'str']]) - val = fn(req.args, {'dom': self.dom.getName()}) - return val - - - def op_domain_sched_credit_set(self, _, req): - fn = FormFn(self.xd.domain_sched_credit_set, - [['dom', 'str'], - ['weight', 'int'], - ['cap', 'int']]) - val = fn(req.args, {'dom': self.dom.getName()}) - return val - - def op_domain_sched_credit2_get(self, _, req): - fn = FormFn(self.xd.domain_sched_credit2_get, - [['dom', 'str']]) - val = fn(req.args, {'dom': self.dom.getName()}) - return val - - - def op_domain_sched_credit2_set(self, _, req): - fn = FormFn(self.xd.domain_sched_credit2_set, - [['dom', 'str'], - ['weight', 'int']]) - val = fn(req.args, {'dom': self.dom.getName()}) - return val - - def op_maxmem_set(self, _, req): - return self.call(self.dom.setMemoryMaximum, - [['memory', 'int']], - req) - - def call(self, fn, args, req): - return FormFn(fn, args)(req.args) - - - def op_mem_target_set(self, _, req): - return self.call(self.dom.setMemoryTarget, - [['target', 'int']], - req) - - def op_devices(self, _, req): - return self.call(self.dom.getDeviceSxprs, - [['type', 'str']], - req) - - def op_device_create(self, _, req): - return self.call(self.dom.device_create, - [['config', 'sxpr']], - req) - - def op_device_destroy(self, _, req): - return self.call(self.dom.destroyDevice, - [['type', 'str'], - ['dev', 'str'], - ['force', 'int'], - ['rm_cfg', 'int']], - req) - - def op_device_configure(self, _, req): - return self.call(self.dom.device_configure, - [['config', 'sxpr'], - ['dev', 'str']], - req) - - - def op_vif_limit_set(self, _, req): - fn = FormFn(self.xd.domain_vif_limit_set, - [['dom', 'int'], - ['vif', 'int'], - ['credit', 'int'], - ['period', 'int']]) - val = fn(req.args, {'dom': self.dom.domid}) - return val - - def op_set_vcpus(self, _, req): - return self.call(self.dom.setVCpuCount, - [['vcpus', 'int']], - req) - - - def op_vcpuinfo(self, _1, req): - return self.call(self.dom.getVCPUInfo, [], req) - - - def op_reset(self, _, req): - self.acceptCommand(req) - return self.xd.domain_reset(self.dom.getName()) - - def op_do_get_pauseflag(self, op, req): - self.acceptCommand(req) - return req.threadRequest(self.do_get_pauseflag, op, req) - - def do_get_pauseflag(self, _, req): - return self.xd.domain_getpauseflag(self.dom.getName(), req) - - def op_do_set_pauseflag(self, op, req): - self.acceptCommand(req) - return req.threadRequest(self.do_set_pauseflag, op, req) - - def do_set_pauseflag(self, _, req): - return self.xd.domain_setpauseflag(self.dom.getName(), req) - - def op_usb_add(self, op, req): - self.acceptCommand(req) - return req.threadRequest(self.do_usb_add, op, req) - - def do_usb_add(self, _, req): - return self.xd.domain_usb_add(self.dom.getName(), req) - - def op_usb_del(self, op, req): - self.acceptCommand(req) - return req.threadRequest(self.do_usb_del, op, req) - - def do_usb_del(self, _, req): - return self.xd.domain_usb_del(self.dom.getName(), req) - - def render_POST(self, req): - return self.perform(req) - - def render_GET(self, req): - op = req.args.get('op') - - if op and op[0] in ['vcpuinfo']: - return self.perform(req) - - # - # XXX SMH: below may be useful once again if we ever try to get - # the raw 'web' interface to xend working once more. But for now - # is useless and out of date (i.e. no ops called 'v???' anymore). - # - # if op and op[0] in ['vifs', 'vif', 'vbds', 'vbd', 'mem_target_set']: - # return self.perform(req) - if self.use_sxp(req): - req.setHeader("Content-Type", sxp.mime_type) - sxp.show(self.dom.sxpr(), out=req) - else: - req.write('') - self.print_path(req) - #self.ls() - req.write('

%s

' % self.dom) - self.form(req) - req.write('') - return '' - - def form(self, req): - url = req.prePathURL() - req.write('
' % url) - req.write('') - req.write('') - req.write('
') - - req.write('
' % url) - req.write('') - req.write('
') - - req.write('
' % url) - req.write('') - req.write('
') - - req.write('
' % url) - req.write('') - req.write('Poweroff') - req.write('Halt') - req.write('Reboot') - req.write('
') - - req.write('
' % url) - req.write('
') - req.write(' To file: ') - req.write('
') - - req.write('
' % url) - req.write('
') - req.write(' To host: ') - req.write('Live') - req.write('
') diff --git a/tools/python/xen/xend/server/SrvDomainDir.py b/tools/python/xen/xend/server/SrvDomainDir.py deleted file mode 100644 index dcd79b07ce..0000000000 --- a/tools/python/xen/xend/server/SrvDomainDir.py +++ /dev/null @@ -1,222 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -#============================================================================ - -import traceback -from StringIO import StringIO - -from xen.web import http - -from xen.xend import sxp -from xen.xend import XendDomain -from xen.xend.XendDomainInfo import XendDomainInfo -from xen.xend.Args import FormFn -from xen.xend.XendError import XendError -from xen.xend.XendLogging import log -from xen.xend.XendConstants import DOM_STATE_RUNNING - -from xen.web.SrvDir import SrvDir -from SrvDomain import SrvDomain - - -class SrvDomainDir(SrvDir): - """Service that manages the domain directory. - """ - - def __init__(self): - SrvDir.__init__(self) - self.xd = XendDomain.instance() - - def domain(self, x): - dom = self.xd.domain_lookup(x) - return SrvDomain(dom) - - def get(self, x): - v = SrvDir.get(self, x) - if v is not None: - return v - else: - return self.domain(x) - - def op_create(self, _, req): - """Create a domain. - Expects the domain config in request parameter 'config' in SXP format. - """ - ok = 0 - errmsg = '' - try: - configstring = req.args.get('config')[0] - #print 'op_create>', 'config:', configstring - pin = sxp.Parser() - pin.input(configstring) - pin.input_eof() - config = pin.get_val() - ok = 1 - except sxp.ParseError, ex: - errmsg = 'Invalid configuration ' + str(ex) - except Exception, ex: - print 'op_create> Exception in config', ex - traceback.print_exc() - errmsg = 'Configuration error ' + str(ex) - if not ok: - raise XendError(errmsg) - try: - dominfo = self.xd.domain_create(config) - return self._op_create_cb(dominfo, configstring, req) - except Exception, ex: - print 'op_create> Exception creating domain:' - traceback.print_exc() - raise XendError("Error creating domain: " + str(ex)) - - def _op_create_cb(self, dominfo, configstring, req): - """Callback to handle domain creation. - """ - dom = dominfo.getName() - domurl = "%s/%s" % (req.prePathURL(), dom) - req.setResponseCode(http.CREATED, "created") - req.setHeader("Location", domurl) - if self.use_sxp(req): - return dominfo.sxpr() - else: - out = StringIO() - print >> out, ('

Created Domain %s

' - % (domurl, dom)) - print >> out, '

'
-            print >> out, configstring
-            print >> out, '

' - val = out.getvalue() - out.close() - return val - - def op_new(self, _, req): - """Define a new domain. - Expects the domain config in request parameter 'config' in SXP format. - """ - ok = 0 - errmsg = '' - try: - configstring = req.args.get('config')[0] - #print 'op_create>', 'config:', configstring - pin = sxp.Parser() - pin.input(configstring) - pin.input_eof() - config = pin.get_val() - ok = 1 - except sxp.ParseError, ex: - errmsg = 'Invalid configuration ' + str(ex) - except Exception, ex: - print 'op_create> Exception in config', ex - traceback.print_exc() - errmsg = 'Configuration error ' + str(ex) - if not ok: - raise XendError(errmsg) - try: - self.xd.domain_new(config) - except Exception, ex: - print 'op_create> Exception creating domain:' - traceback.print_exc() - raise XendError("Error creating domain: " + str(ex)) - - def op_restore(self, op, req): - """Restore a domain from file. - - """ - return req.threadRequest(self.do_restore, op, req) - - def do_restore(self, _, req): - fn = FormFn(self.xd.domain_restore, - [['file', 'str']]) - dominfo = fn(req.args) - dom = dominfo.getName() - domurl = "%s/%s" % (req.prePathURL(), dom) - req.setResponseCode(http.CREATED) - req.setHeader("Location", domurl) - if self.use_sxp(req): - return dominfo.sxpr() - else: - out = StringIO() - print >> out, ('

Created Domain %s

' - % (domurl, dom)) - val = out.getvalue() - out.close() - return val - - - def op_list(self, _, req): - """List the details for this domain.""" - self._list(req, True) - - - def render_POST(self, req): - return self.perform(req) - - def render_GET(self, req): - self._list(req, 'detail' in req.args and req.args['detail'] == ['1']) - - - def _list(self, req, detail): - if self.use_sxp(req): - req.setHeader("Content-Type", sxp.mime_type) - self.ls_domain(req, detail, True) - else: - req.write("") - self.print_path(req) - self.ls(req) - self.ls_domain(req, detail, False) - self.form(req) - req.write("") - - - def ls_domain(self, req, detail, use_sxp): - url = req.prePathURL() - if not url.endswith('/'): - url += '/' - if use_sxp: - if detail: - sxp.show(map(XendDomainInfo.sxpr, self.xd.list()), out=req) - else: - state = DOM_STATE_RUNNING - if 'state' in req.args and len(req.args['state']) > 0: - state = req.args['state'][0] - log.trace("Listing domains in state " + str(state)) - sxp.show(self.xd.list_names(state), out=req) - else: - domains = self.xd.list_sorted() - req.write('
    ') - for d in domains: - req.write( - '
  • Domain %s: id = %s, memory = %d' - % (url, d.getName(), d.getName(), d.getDomid(), - d.getMemoryTarget())) - req.write('
  • ') - req.write('
') - - - def form(self, req): - """Generate the form(s) for domain dir operations. - """ - req.write('
' - % req.prePathURL()) - req.write('') - req.write('Config
') - req.write('
') - - req.write('
' - % req.prePathURL()) - req.write('') - req.write('State
') - req.write('
') - diff --git a/tools/python/xen/xend/server/SrvNode.py b/tools/python/xen/xend/server/SrvNode.py deleted file mode 100644 index 1f9030daee..0000000000 --- a/tools/python/xen/xend/server/SrvNode.py +++ /dev/null @@ -1,64 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -#============================================================================ - - -from xen.web.SrvDir import SrvDir -from xen.xend import sxp -from xen.xend import XendNode -from xen.xend.Args import FormFn - -class SrvNode(SrvDir): - """Information about the node. - """ - - def __init__(self): - SrvDir.__init__(self) - self.xn = XendNode.instance() - self.add('dmesg', 'SrvDmesg') - self.add('log', 'SrvXendLog') - - def op_shutdown(self, _1, _2): - val = self.xn.shutdown() - return val - - def op_reboot(self, _1, _2): - val = self.xn.reboot() - return val - - def render_POST(self, req): - return self.perform(req) - - def render_GET(self, req): - if self.use_sxp(req): - req.setHeader("Content-Type", sxp.mime_type) - sxp.show(['node'] + self.info(), out=req) - else: - url = req.prePathURL() - if not url.endswith('/'): - url += '/' - req.write('') - self.print_path(req) - req.write('
    ') - for d in self.info(): - req.write('
  • %10s: %s' % (d[0], str(d[1]))) - req.write('
  • Xen dmesg output' % url) - req.write('
  • Xend log' % url) - req.write('
') - req.write('') - - def info(self): - return self.xn.info() diff --git a/tools/python/xen/xend/server/SrvRoot.py b/tools/python/xen/xend/server/SrvRoot.py deleted file mode 100644 index bd194f3a38..0000000000 --- a/tools/python/xen/xend/server/SrvRoot.py +++ /dev/null @@ -1,43 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2005 XenSource Ltd -#============================================================================ - -from xen.web.SrvDir import SrvDir - -class SrvRoot(SrvDir): - """The root of the xend server. - """ - - """Server sub-components. Each entry is (name, class), where - 'name' is the entry name and 'class' is the name of its class. - """ - #todo Get this list from the XendOptions config. - subdirs = [ - ('node', 'SrvNode' ), - ('domain', 'SrvDomainDir' ), - ('vnet', 'SrvVnetDir' ), - ] - - def __init__(self): - SrvDir.__init__(self) - for (name, klass) in self.subdirs: - self.add(name, klass) - for (name, klass) in self.subdirs: - self.get(name) - - def __repr__(self): - return "" %(id(self), self.table.keys()) diff --git a/tools/python/xen/xend/server/SrvServer.py b/tools/python/xen/xend/server/SrvServer.py deleted file mode 100644 index 9f581f0b07..0000000000 --- a/tools/python/xen/xend/server/SrvServer.py +++ /dev/null @@ -1,261 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2006 XenSource Ltd. -#============================================================================ - -"""Example xend HTTP - - Can be accessed from a browser or from a program. - Do 'python SrvServer.py' to run the server. - Then point a web browser at http://localhost:8000/xend and follow the links. - Most are stubs, except /domain which has a list of domains and a 'create domain' - button. - - You can also access the server from a program. - Do 'python XendClient.py' to run a few test operations. - - The data served differs depending on the client (as defined by User-Agent - and Accept in the HTTP headers). If the client is a browser, data - is returned in HTML, with interactive forms. If the client is a program, - data is returned in SXP format, with no forms. - - The server serves to the world by default. To restrict it to the local host - change 'interface' in main(). - - Mike Wray -""" -# todo Support security settings etc. in the config file. -# todo Support command-line args. - -import fcntl -import re -import time -import signal -from threading import Thread - -from xen.web.httpserver import HttpServer, UnixHttpServer - -from xen.xend import XendNode, XendOptions, XendAPI -from xen.xend.XendLogging import log -from xen.xend.XendClient import XEN_API_SOCKET -from xen.xend.XendDomain import instance as xenddomain -from xen.xend.XendCPUPool import XendCPUPool -from xen.web.SrvDir import SrvDir - -from SrvRoot import SrvRoot -from XMLRPCServer import XMLRPCServer - -xoptions = XendOptions.instance() - - -class XendServers: - - def __init__(self, root): - self.servers = [] - self.root = root - self.running = False - self.cleaningUp = False - self.reloadingConfig = False - - def add(self, server): - self.servers.append(server) - - def cleanup(self, signum = 0, frame = None, reloading = False): - log.debug("SrvServer.cleanup()") - self.cleaningUp = True - for server in self.servers: - try: - server.shutdown() - except: - pass - - # clean up domains for those that have on_xend_stop - if not reloading: - xenddomain().cleanup_domains() - - self.running = False - - - def reloadConfig(self, signum = 0, frame = None): - log.debug("SrvServer.reloadConfig()") - self.reloadingConfig = True - self.cleanup(signum, frame, reloading = True) - - def start(self, status): - # Running the network script will spawn another process, which takes - # the status fd with it unless we set FD_CLOEXEC. Failing to do this - # causes the read in SrvDaemon to hang even when we have written here. - if status: - fcntl.fcntl(status, fcntl.F_SETFD, fcntl.FD_CLOEXEC) - - # Prepare to catch SIGTERM (received when 'xend stop' is executed) - # and call each server's cleanup if possible - signal.signal(signal.SIGTERM, self.cleanup) - signal.signal(signal.SIGHUP, self.reloadConfig) - - while True: - threads = [] - for server in self.servers: - if server.ready: - continue - - thread = Thread(target=server.run, - name=server.__class__.__name__) - thread.setDaemon(True) - thread.start() - threads.append(thread) - - # check for when all threads have initialized themselves and then - # close the status pipe - - retryCount = 0 - threads_left = True - while threads_left: - threads_left = False - - for server in self.servers: - if not server.ready: - threads_left = True - break - - if threads_left: - time.sleep(.5) - retryCount += 1 - if retryCount > 60: - for server in self.servers: - if not server.ready: - log.error("Server " + - server.__class__.__name__ + - " did not initialise!") - break - - if status: - status.write('0') - status.close() - status = None - - # auto start pools before domains are started - try: - XendCPUPool.autostart_pools() - except Exception, e: - log.exception("Failed while autostarting pools") - - # Reaching this point means we can auto start domains - try: - xenddomain().autostart_domains() - except Exception, e: - log.exception("Failed while autostarting domains") - - # loop to keep main thread alive until it receives a SIGTERM - self.running = True - while self.running: - time.sleep(100000000) - - if self.reloadingConfig: - log.info("Restarting all XML-RPC and Xen-API servers...") - self.cleaningUp = False - self.reloadingConfig = False - xoptions.set_config() - self.servers = [] - _loadConfig(self, self.root, True) - else: - break - -def _loadConfig(servers, root, reload): - if xoptions.get_xend_http_server(): - servers.add(HttpServer(root, - xoptions.get_xend_address(), - xoptions.get_xend_port())) - if xoptions.get_xend_unix_server(): - path = xoptions.get_xend_unix_path() - log.info('unix path=' + path) - servers.add(UnixHttpServer(root, path)) - - api_cfg = xoptions.get_xen_api_server() - if api_cfg: - try: - for server_cfg in api_cfg: - # Parse the xen-api-server config - - ssl_key_file = None - ssl_cert_file = None - auth_method = XendAPI.AUTH_NONE - hosts_allowed = None - - host_addr = server_cfg[0].split(':', 1) - if len(host_addr) == 1: - if host_addr[0].lower() == 'unix': - use_tcp = False - host = 'localhost' - port = 0 - else: - use_tcp = True - host = '' - port = int(host_addr[0]) - else: - use_tcp = True - host = str(host_addr[0]) - port = int(host_addr[1]) - - if len(server_cfg) > 1: - if server_cfg[1] in [XendAPI.AUTH_PAM, XendAPI.AUTH_NONE]: - auth_method = server_cfg[1] - - if len(server_cfg) > 2 and len(server_cfg[2]): - hosts_allowed = map(re.compile, server_cfg[2].split(' ')) - - if len(server_cfg) > 4: - # SSL key and cert file - ssl_key_file = server_cfg[3] - ssl_cert_file = server_cfg[4] - - - servers.add(XMLRPCServer(auth_method, True, use_tcp = use_tcp, - ssl_key_file = ssl_key_file, - ssl_cert_file = ssl_cert_file, - host = host, port = port, - path = XEN_API_SOCKET, - hosts_allowed = hosts_allowed)) - - except (ValueError, TypeError), exn: - log.exception('Xen API Server init failed') - log.error('Xen-API server configuration %s is invalid.', api_cfg) - - if xoptions.get_xend_tcp_xmlrpc_server(): - addr = xoptions.get_xend_tcp_xmlrpc_server_address() - port = xoptions.get_xend_tcp_xmlrpc_server_port() - ssl_key_file = xoptions.get_xend_tcp_xmlrpc_server_ssl_key_file() - ssl_cert_file = xoptions.get_xend_tcp_xmlrpc_server_ssl_cert_file() - - if ssl_key_file and ssl_cert_file: - servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False, use_tcp = True, - ssl_key_file = ssl_key_file, - ssl_cert_file = ssl_cert_file, - host = addr, port = port)) - else: - servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False, use_tcp = True, - host = addr, port = port)) - - if xoptions.get_xend_unix_xmlrpc_server(): - servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False)) - - -def create(): - root = SrvDir() - root.putChild('xend', SrvRoot()) - servers = XendServers(root) - _loadConfig(servers, root, False) - return servers diff --git a/tools/python/xen/xend/server/SrvVnetDir.py b/tools/python/xen/xend/server/SrvVnetDir.py deleted file mode 100644 index 5dc5b591b2..0000000000 --- a/tools/python/xen/xend/server/SrvVnetDir.py +++ /dev/null @@ -1,128 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -#============================================================================ - -from xen.xend import sxp -from xen.xend.Args import FormFn -from xen.xend import PrettyPrint -from xen.xend import XendVnet -from xen.xend.XendError import XendError - -from xen.web.SrvDir import SrvDir - -class SrvVnet(SrvDir): - - def __init__(self, vnetinfo): - SrvDir.__init__(self) - self.vnetinfo = vnetinfo - self.xvnet = XendVnet.instance() - - def op_delete(self, op, req): - val = self.xvnet.vnet_delete(self.vnetinfo.id) - return val - - def render_POST(self, req): - return self.perform(req) - - def render_GET(self, req): - if self.use_sxp(req): - req.setHeader("Content-Type", sxp.mime_type) - sxp.show(self.vnetinfo.sxpr(), out=req) - else: - req.write('') - self.print_path(req) - req.write('

Vnet %s

' % self.vnetinfo.id) - req.write("
")
-            PrettyPrint.prettyprint(self.vnetinfo.sxpr(), out=req)
-            req.write("
") - self.form(req) - req.write('') - return '' - - def form(self, req): - url = req.prePathURL() - req.write('
' % url) - req.write('') - req.write('
') - -class SrvVnetDir(SrvDir): - """Vnet directory. - """ - - def __init__(self): - SrvDir.__init__(self) - self.xvnet = XendVnet.instance() - - def vnet(self, x): - val = None - vnetinfo = self.xvnet.vnet_get(x) - if not vnetinfo: - raise XendError('No such vnet ' + str(x)) - val = SrvVnet(vnetinfo) - return val - - def get(self, x): - v = SrvDir.get(self, x) - if v is not None: - return v - v = self.vnet(x) - return v - - def op_create(self, op, req): - fn = FormFn(self.xvnet.vnet_create, - [['config', 'sxpr']]) - val = fn(req.args, {}) - return val - - def render_POST(self, req): - return self.perform(req) - - def render_GET(self, req): - if self.use_sxp(req): - req.setHeader("Content-Type", sxp.mime_type) - self.ls_vnet(req, 1) - else: - req.write("") - self.print_path(req) - self.ls(req) - self.ls_vnet(req) - self.form(req) - req.write("") - - def ls_vnet(self, req, use_sxp=0): - url = req.prePathURL() - if not url.endswith('/'): - url += '/' - if use_sxp: - vnets = self.xvnet.vnet_ls() - sxp.show(vnets, out=req) - else: - vnets = self.xvnet.vnets() - vnets.sort(lambda x, y: cmp(x.id, y.id)) - req.write('
    ') - for v in vnets: - req.write('
  • Vnet %s' % (url, v.id, v.id)) - req.write('
  • ') - req.write('
') - - def form(self, req): - """Generate the form(s) for vnet dir operations. - """ - req.write('
' - % req.prePathURL()) - req.write('') - req.write('Config
') - req.write('
') diff --git a/tools/python/xen/xend/server/SrvXendLog.py b/tools/python/xen/xend/server/SrvXendLog.py deleted file mode 100644 index a0dc67aa2d..0000000000 --- a/tools/python/xen/xend/server/SrvXendLog.py +++ /dev/null @@ -1,37 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2005 XenSource Ltd -#============================================================================ - -from xen.web import static - -from xen.xend import XendLogging - -from xen.web.SrvDir import SrvDir - -class SrvXendLog(SrvDir): - """Xend log. - """ - - def __init__(self): - SrvDir.__init__(self) - self.logfile = static.File(XendLogging.getLogFilename(), - defaultType="text/plain") - self.logfile.type = "text/plain" - self.logfile.encoding = None - - def render_GET(self, req): - return self.logfile.render(req) diff --git a/tools/python/xen/xend/server/XMLRPCServer.py b/tools/python/xen/xend/server/XMLRPCServer.py deleted file mode 100644 index e3a82dcf4d..0000000000 --- a/tools/python/xen/xend/server/XMLRPCServer.py +++ /dev/null @@ -1,273 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2006 Anthony Liguori -# Copyright (C) 2006 XenSource Ltd. -#============================================================================ - -import errno -import socket -import types -import xmlrpclib -from xen.util.xmlrpclib2 import UnixXMLRPCServer, TCPXMLRPCServer -try: - from SSLXMLRPCServer import SSLXMLRPCServer - ssl_enabled = True -except ImportError: - ssl_enabled = False - -from xen.xend import XendAPI, XendDomain, XendDomainInfo, XendNode -from xen.xend import XendLogging, XendDmesg -from xen.xend.XendClient import XML_RPC_SOCKET -from xen.xend.XendConstants import DOM_STATE_RUNNING -from xen.xend.XendLogging import log -from xen.xend.XendError import XendInvalidDomain -from xen.xend.XendCPUPool import XendCPUPool - -# vcpu_avail is a long and is not needed by the clients. It's far easier -# to just remove it then to try and marshal the long. -def fixup_sxpr(sexpr): - ret = [] - for k in sexpr: - if type(k) in (list, tuple): - if len(k) != 2 or k[0] != 'vcpu_avail': - ret.append(fixup_sxpr(k)) - else: - ret.append(k) - return ret - -def lookup(domid): - info = XendDomain.instance().domain_lookup(domid) - return info - -def dispatch(domid, fn, args): - info = lookup(domid) - return getattr(info, fn)(*args) - -def domain(domid, full = 0): - info = lookup(domid) - return fixup_sxpr(info.sxpr(not full)) - -def domains(detail = True, full = False): - return domains_with_state(detail, DOM_STATE_RUNNING, full) - -def domains_with_state(detail, state, full): - if detail: - domains = XendDomain.instance().list_sorted(state) - ret = [] - for dom in domains: - try: - ret.append(fixup_sxpr(dom.sxpr(not full))) - except: - log.warn("Failed to query SXPR for domain %s" % str(dom)) - pass - return ret - else: - return XendDomain.instance().list_names(state) - -def domain_create(config): - info = XendDomain.instance().domain_create(config) - return fixup_sxpr(info.sxpr()) - -def domain_restore(src, paused=False): - info = XendDomain.instance().domain_restore(src, paused) - return fixup_sxpr(info.sxpr()) - -def get_log(): - f = open(XendLogging.getLogFilename(), 'r') - try: - return f.read() - finally: - f.close() - -methods = ['device_create', 'device_configure', - 'destroyDevice','getDeviceSxprs', - 'setMemoryTarget', 'setName', 'setVCpuCount', 'shutdown', - 'send_sysrq', 'getVCPUInfo', 'waitForDevices', - 'getRestartCount', 'getBlockDeviceClass'] - -exclude = ['domain_create', 'domain_restore'] - -POOL_FUNCS = ['pool_create', 'pool_new', 'pool_start', 'pool_list', - 'pool_destroy', 'pool_delete', 'pool_cpu_add', 'pool_cpu_remove', - 'pool_migrate'] - -class XMLRPCServer: - def __init__(self, auth, use_xenapi, use_tcp = False, - ssl_key_file = None, ssl_cert_file = None, - host = "localhost", port = 8006, path = XML_RPC_SOCKET, - hosts_allowed = None): - - self.use_tcp = use_tcp - self.port = port - self.host = host - self.path = path - self.hosts_allowed = hosts_allowed - - self.ssl_key_file = ssl_key_file - self.ssl_cert_file = ssl_cert_file - - self.ready = False - self.running = True - self.auth = auth - self.xenapi = use_xenapi and XendAPI.XendAPI(auth) or None - - def run(self): - authmsg = (self.auth == XendAPI.AUTH_NONE and - "; authentication has been disabled for this server." or - ".") - - try: - if self.use_tcp: - using_ssl = self.ssl_key_file and self.ssl_cert_file - - log.info("Opening %s XML-RPC server on %s%d%s", - using_ssl and 'HTTPS' or 'TCP', - self.host and '%s:' % self.host or - 'all interfaces, port ', - self.port, authmsg) - - if using_ssl: - if not ssl_enabled: - raise ValueError("pyOpenSSL not installed. " - "Unable to start HTTPS XML-RPC server") - self.server = SSLXMLRPCServer( - (self.host, self.port), - self.hosts_allowed, - self.xenapi is not None, - logRequests = False, - ssl_key_file = self.ssl_key_file, - ssl_cert_file = self.ssl_cert_file) - else: - self.server = TCPXMLRPCServer( - (self.host, self.port), - self.hosts_allowed, - self.xenapi is not None, - logRequests = False) - - else: - log.info("Opening Unix domain socket XML-RPC server on %s%s", - self.path, authmsg) - self.server = UnixXMLRPCServer(self.path, self.hosts_allowed, - self.xenapi is not None, - logRequests = False) - except socket.error, exn: - log.error('Cannot start server: %s!', exn.args[1]) - ready = True - running = False - return - except Exception, e: - log.exception('Cannot start server: %s!', e) - ready = True - running = False - return - - # Register Xen API Functions - # ------------------------------------------------------------------- - # exportable functions are ones that do not begin with '_' - # and has the 'api' attribute. - - for meth_name in dir(self.xenapi): - if meth_name[0] != '_': - meth = getattr(self.xenapi, meth_name) - if callable(meth) and hasattr(meth, 'api'): - self.server.register_function(meth, getattr(meth, 'api')) - - self.server.register_instance(XendAPI.XendAPIAsyncProxy(self.xenapi)) - - # Legacy deprecated xm xmlrpc api - # -------------------------------------------------------------------- - - # Functions in XendDomainInfo - for name in methods: - fn = eval("lambda domid, *args: dispatch(domid, '%s', args)"%name) - self.server.register_function(fn, "xend.domain.%s" % name) - - inst = XendDomain.instance() - - for name in dir(inst): - fn = getattr(inst, name) - if name.startswith("domain_") and callable(fn): - if name not in exclude: - self.server.register_function(fn, "xend.domain.%s" % name[7:]) - - # Functions in XendPool - for name in POOL_FUNCS: - fn = getattr(XendCPUPool, name) - self.server.register_function(fn, "xend.cpu_pool.%s" % name[5:]) - - # Functions in XendNode and XendDmesg - for type, lst, n in [(XendNode, - ['info', 'pciinfo', 'send_debug_keys', - 'tmem_list', 'tmem_freeze', 'tmem_thaw', - 'tmem_flush', 'tmem_destroy', 'tmem_set_weight', - 'tmem_set_cap', 'tmem_set_compress', - 'tmem_query_freeable_mb', 'tmem_shared_auth'], - 'node'), - (XendDmesg, ['info', 'clear'], 'node.dmesg')]: - inst = type.instance() - for name in lst: - self.server.register_function(getattr(inst, name), - "xend.%s.%s" % (n, name)) - - # A few special cases - self.server.register_function(domain, 'xend.domain') - self.server.register_function(domains, 'xend.domains') - self.server.register_function(domains_with_state, - 'xend.domains_with_state') - self.server.register_function(get_log, 'xend.node.log') - self.server.register_function(domain_create, 'xend.domain.create') - self.server.register_function(domain_restore, 'xend.domain.restore') - - # A couple of the security functions - from xen.util.xsm import xsm as security - for name in security.xmlrpc_exports: - fn = getattr(security, name) - self.server.register_function(fn, "xend.security.%s" % name) - - self.server.register_introspection_functions() - self.ready = True - - # Custom runloop so we can cleanup when exiting. - # ----------------------------------------------------------------- - try: - while self.running: - self.server.handle_request() - finally: - self.shutdown() - - def cleanup(self): - log.debug('XMLRPCServer.cleanup()') - if hasattr(self, 'server'): - try: - # This is here to make sure the socket is actually - # cleaned up when close() is called. Otherwise - # SO_REUSEADDR doesn't take effect. To replicate, - # try 'xend reload' and look for EADDRINUSE. - # - # May be caued by us calling close() outside of - # the listen()ing thread. - self.server.socket.shutdown(2) - except socket.error, e: - pass # ignore any socket errors - try: - self.server.socket.close() - except socket.error, e: - pass - - def shutdown(self): - self.running = False - if self.ready: - self.ready = False - self.cleanup() diff --git a/tools/python/xen/xend/server/__init__.py b/tools/python/xen/xend/server/__init__.py deleted file mode 100644 index 8b13789179..0000000000 --- a/tools/python/xen/xend/server/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tools/python/xen/xend/server/blkif.py b/tools/python/xen/xend/server/blkif.py deleted file mode 100644 index 60e162534f..0000000000 --- a/tools/python/xen/xend/server/blkif.py +++ /dev/null @@ -1,221 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2005, 2006 XenSource Inc. -#============================================================================ - -import re -import string -import os - -from xen.util import blkif -import xen.util.xsm.xsm as security -from xen.xend.XendError import VmError -from xen.xend.server.DevController import DevController -from xen.util import xsconstants, auxbin - -class BlkifController(DevController): - """Block device interface controller. Handles all block devices - for a domain. - """ - - def __init__(self, vm): - """Create a block device controller. - """ - DevController.__init__(self, vm) - - def _isValidProtocol(self, protocol): - if protocol in ('phy', 'file', 'tap'): - return True - - return os.access(auxbin.scripts_dir() + '/block-%s' % protocol, os.X_OK) - - - def getDeviceDetails(self, config): - """@see DevController.getDeviceDetails""" - uname = config.get('uname', '') - dev = config.get('dev', '') - - if 'ioemu:' in dev: - (_, dev) = string.split(dev, ':', 1) - try: - (dev, dev_type) = string.split(dev, ':', 1) - except ValueError: - dev_type = "disk" - - if not uname: - if dev_type == 'cdrom': - (typ, params) = ("", "") - else: - raise VmError( - 'Block device must have physical details specified') - else: - try: - (typ, params) = string.split(uname, ':', 1) - if not self._isValidProtocol(typ): - raise VmError('Block device type "%s" is invalid.' % typ) - except ValueError: - raise VmError( - 'Block device must have physical details specified') - - mode = config.get('mode', 'r') - if mode not in ('r', 'w', 'w!'): - raise VmError('Invalid mode') - - back = {'dev' : dev, - 'type' : typ, - 'params' : params, - 'mode' : mode, - } - - uuid = config.get('uuid') - if uuid: - back['uuid'] = uuid - - bootable = config.get('bootable', None) - if bootable != None: - back['bootable'] = str(bootable) - - if security.on() == xsconstants.XS_POLICY_USE: - self.do_access_control(config, uname) - - (device_path, devid) = blkif.blkdev_name_to_number(dev) - if devid is None: - raise VmError('Unable to find number for device (%s)' % (dev)) - - front = { device_path : "%i" % devid, - 'device-type' : dev_type - } - - protocol = config.get('protocol') - if protocol: - front['protocol'] = protocol - - return (devid, back, front) - - def do_access_control(self, config, uname): - (label, ssidref, policy) = \ - security.get_res_security_details(uname) - domain_label = self.vm.get_security_label() - if domain_label: - rc = security.res_security_check_xapi(label, ssidref, policy, - domain_label) - if rc == 0: - raise VmError("VM's access to block device '%s' denied" % - uname) - else: - from xen.util.acmpolicy import ACM_LABEL_UNLABELED - if label != ACM_LABEL_UNLABELED: - raise VmError("VM must have a security label to access " - "block device '%s'" % uname) - - def reconfigureDevice(self, _, config): - """@see DevController.reconfigureDevice""" - (devid, new_back, new_front) = self.getDeviceDetails(config) - - (dev, mode) = self.readBackend(devid, 'dev', 'mode') - dev_type = self.readFrontend(devid, 'device-type') - - if (dev_type == 'cdrom' and new_front['device-type'] == 'cdrom' and - dev == new_back['dev'] and mode == 'r'): - # dummy device - self.writeBackend(devid, - 'type', new_back['type'], - 'params', '') - # new backend-device - self.writeBackend(devid, - 'type', new_back['type'], - 'params', new_back['params']) - return new_back.get('uuid') - else: - raise VmError('Refusing to reconfigure device %s:%d to %s' % - (self.deviceClass, devid, config)) - - - def getDeviceConfiguration(self, devid, transaction = None): - """Returns the configuration of a device. - - @note: Similar to L{configuration} except it returns a dict. - @return: dict - """ - config = DevController.getDeviceConfiguration(self, devid, transaction) - if transaction is None: - devinfo = self.readBackend(devid, 'dev', 'type', 'params', 'mode', - 'uuid', 'bootable') - else: - devinfo = self.readBackendTxn(transaction, devid, - 'dev', 'type', 'params', 'mode', 'uuid', - 'bootable') - dev, typ, params, mode, uuid, bootable = devinfo - - if dev: - if transaction is None: - dev_type = self.readFrontend(devid, 'device-type') - else: - dev_type = self.readFrontendTxn(transaction, devid, 'device-type') - if dev_type: - dev += ':' + dev_type - config['dev'] = dev - if typ and params: - config['uname'] = typ +':' + params - else: - config['uname'] = None - if mode: - config['mode'] = mode - if uuid: - config['uuid'] = uuid - if bootable != None: - config['bootable'] = int(bootable) - - proto = self.readFrontend(devid, 'protocol') - if proto: - config['protocol'] = proto - - return config - - def destroyDevice(self, devid, force): - """@see DevController.destroyDevice""" - - # vbd device IDs can be either string or integer. Further, the - # following string values are possible: - # - devicetype/deviceid (vbd/51728) - # - devicetype/devicename (/dev/xvdb) - # - devicename (xvdb) - # Let our superclass handle integer or devicetype/deviceid forms. - # If we are given a device name form, then look up the device ID - # from it, and destroy that ID instead. - try: - DevController.destroyDevice(self, devid, force) - except ValueError: - dev = self.convertToDeviceNumber(devid) - - for i in self.deviceIDs(): - if i == dev: - DevController.destroyDevice(self, i, force) - return - raise VmError("Device %s not connected" % devid) - - def convertToDeviceNumber(self, devid): - try: - dev = int(devid) - except ValueError: - if type(devid) is not str: - raise VmError("devid %s is wrong type" % str(devid)) - try: - dev = devid.split('/')[-1] - dev = int(dev) - except ValueError: - (device_path, dev) = blkif.blkdev_name_to_number(dev) - return dev diff --git a/tools/python/xen/xend/server/iopif.py b/tools/python/xen/xend/server/iopif.py deleted file mode 100644 index 4c6e612465..0000000000 --- a/tools/python/xen/xend/server/iopif.py +++ /dev/null @@ -1,102 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2005 XenSource Ltd -# Copyright (C) 2005 Jody Belka -#============================================================================ - - -import types - -import xen.lowlevel.xc - -from xen.xend.XendError import VmError - -from xen.xend.server.DevController import DevController - - -xc = xen.lowlevel.xc.xc() - - -def parse_ioport(val): - """Parse an i/o port field. - """ - if isinstance(val, types.StringType): - radix = 10 - if val.startswith('0x') or val.startswith('0X'): - radix = 16 - v = int(val, radix) - else: - v = val - return v - - -class IOPortsController(DevController): - - valid_cfg = ['to', 'from', 'uuid'] - - def __init__(self, vm): - DevController.__init__(self, vm) - - def getDeviceConfiguration(self, devid, transaction = None): - result = DevController.getDeviceConfiguration(self, devid, transaction) - if transaction is None: - devinfo = self.readBackend(devid, *self.valid_cfg) - else: - devinfo = self.readBackendTxn(transaction, devid, *self.valid_cfg) - config = dict(zip(self.valid_cfg, devinfo)) - config = dict([(key, val) for key, val in config.items() - if val != None]) - return config - - def getDeviceDetails(self, config): - """@see DevController.getDeviceDetails""" - - def get_param(field): - try: - val = config.get(field) - - if not val: - raise VmError('ioports: Missing %s config setting' % field) - - return parse_ioport(val) - except: - raise VmError('ioports: Invalid config setting %s: %s' % - (field, val)) - - io_from = get_param('from') - io_to = get_param('to') - - if io_to < io_from or io_to >= 65536: - raise VmError('ioports: Invalid i/o range: %s - %s' % - (io_from, io_to)) - - rc = xc.domain_ioport_permission(domid = self.getDomid(), - first_port = io_from, - nr_ports = io_to - io_from + 1, - allow_access = True) - - if rc < 0: - #todo non-fatal - raise VmError( - 'ioports: Failed to configure legacy i/o range: %s - %s' % - (io_from, io_to)) - - back = dict([(k, config[k]) for k in self.valid_cfg if k in config]) - return (self.allocateDeviceID(), back, {}) - - def waitForDevice(self, devid): - # don't wait for hotplug - return diff --git a/tools/python/xen/xend/server/irqif.py b/tools/python/xen/xend/server/irqif.py deleted file mode 100644 index 723f34652a..0000000000 --- a/tools/python/xen/xend/server/irqif.py +++ /dev/null @@ -1,95 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2005 XenSource Ltd -# Copyright (C) 2005 Jody Belka -#============================================================================ -# This code based on tools/python/xen/xend/server/iopif.py and modified -# to handle interrupts -#============================================================================ - - -import types - -import xen.lowlevel.xc - -from xen.xend import sxp -from xen.xend.XendError import VmError - -from xen.xend.server.DevController import DevController - - -xc = xen.lowlevel.xc.xc() - - -class IRQController(DevController): - - def __init__(self, vm): - DevController.__init__(self, vm) - - valid_cfg = ['irq', 'uuid'] - - def getDeviceConfiguration(self, devid, transaction = None): - result = DevController.getDeviceConfiguration(self, devid, transaction) - if transaction is None: - devinfo = self.readBackend(devid, *self.valid_cfg) - else: - devinfo = self.readBackendTxn(transaction, devid, *self.valid_cfg) - config = dict(zip(self.valid_cfg, devinfo)) - config = dict([(key, val) for key, val in config.items() - if val != None]) - return config - - def getDeviceDetails(self, config): - """@see DevController.getDeviceDetails""" - - def get_param(field): - try: - val = config.get(field) - - if not val: - raise VmError('irq: Missing %s config setting' % field) - - if isinstance(val, types.StringType): - return int(val,10) - radix = 10 - else: - return val - except: - raise VmError('irq: Invalid config setting %s: %s' % - (field, val)) - - pirq = get_param('irq') - - rc = xc.physdev_map_pirq(domid = self.getDomid(), - index = pirq, - pirq = pirq) - if rc < 0: - raise VmError('irq: Failed to map irq %x' % (pirq)) - - rc = xc.domain_irq_permission(domid = self.getDomid(), - pirq = pirq, - allow_access = True) - - if rc < 0: - #todo non-fatal - raise VmError( - 'irq: Failed to configure irq: %d' % (pirq)) - back = dict([(k, config[k]) for k in self.valid_cfg if k in config]) - return (self.allocateDeviceID(), back, {}) - - def waitForDevice(self, devid): - # don't wait for hotplug - return diff --git a/tools/python/xen/xend/server/netif.py b/tools/python/xen/xend/server/netif.py deleted file mode 100644 index 1f0d2a047b..0000000000 --- a/tools/python/xen/xend/server/netif.py +++ /dev/null @@ -1,218 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2005 XenSource Ltd -#============================================================================ - - -"""Support for virtual network interfaces. -""" - -import os -import random -import re - -from xen.xend import XendOptions, sxp -from xen.xend.server.DevController import DevController -from xen.xend.XendError import VmError -from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance -import xen.util.xsm.xsm as security -from xen.util import xsconstants - -from xen.xend.XendLogging import log - -xoptions = XendOptions.instance() - -def randomMAC(): - """Generate a random MAC address. - - Uses OUI (Organizationally Unique Identifier) 00-16-3E, allocated to - Xensource, Inc. The OUI list is available at - http://standards.ieee.org/regauth/oui/oui.txt. - - The remaining 3 fields are random, with the first bit of the first - random field set 0. - - @return: MAC address string - """ - mac = [ 0x00, 0x16, 0x3e, - random.randint(0x00, 0x7f), - random.randint(0x00, 0xff), - random.randint(0x00, 0xff) ] - return ':'.join(map(lambda x: "%02x" % x, mac)) - -rate_re = re.compile("^([0-9]+)([GMK]?)([Bb])/s(@([0-9]+)([mu]?)s)?$") - -def parseRate(ratestr): - """if parsing fails this will return default of unlimited rate""" - bytes_per_interval = 0xffffffffL # 0xffffffff # big default - interval_usecs = 0L # disabled - - m = rate_re.match(ratestr) - if m: - bytes_per_sec = long(m.group(1)) - - if m.group(2) == 'G': - bytes_per_sec *= 1000 * 1000 * 1000 - elif m.group(2) == 'M': - bytes_per_sec *= 1000 * 1000 - elif m.group(2) == 'K': - bytes_per_sec *= 1000 - - if m.group(3) == 'b': - bytes_per_sec /= 8 - - if m.group(5) is None: - interval_usecs = 50000L # 50ms default - else: - interval_usecs = long(m.group(5)) - if m.group(6) == '': - interval_usecs *= 1000 * 1000 - elif m.group(6) == 'm': - interval_usecs *= 1000 - - bytes_per_interval = (bytes_per_sec * interval_usecs) / 1000000L - - # overflow / underflow checking: default to unlimited rate - if bytes_per_interval == 0 or bytes_per_interval > 0xffffffffL or \ - interval_usecs == 0 or interval_usecs > 0xffffffffL: - bytes_per_interval = 0xffffffffL - interval_usecs = 0L - - return "%lu,%lu" % (bytes_per_interval, interval_usecs) - - -class NetifController(DevController): - """Network interface controller. Handles all network devices for a domain. - """ - - def __init__(self, vm): - DevController.__init__(self, vm) - - def getDeviceDetails(self, config): - """@see DevController.getDeviceDetails""" - - script = config.get('script', xoptions.get_vif_script()) - typ = config.get('type') - bridge = config.get('bridge') - mac = config.get('mac') - vifname = config.get('vifname') - rate = config.get('rate') - uuid = config.get('uuid') - ipaddr = config.get('ip') - model = config.get('model') - accel = config.get('accel') - sec_lab = config.get('security_label') - - if not mac: - raise VmError("MAC address not specified or generated.") - - devid = self.allocateDeviceID() - - back = { 'script' : script, - 'mac' : mac } - if typ: - back['type'] = typ - if ipaddr: - back['ip'] = ipaddr - if bridge: - back['bridge'] = bridge - if vifname: - back['vifname'] = vifname - if rate: - back['rate'] = rate - if uuid: - back['uuid'] = uuid - if model: - back['model'] = model - if accel: - back['accel'] = accel - if sec_lab: - back['security_label'] = sec_lab - - back['handle'] = "%i" % devid - back['script'] = os.path.join(xoptions.network_script_dir, script) - if rate: - back['rate'] = parseRate(rate) - - front = {} - if typ != 'ioemu': - front = { 'handle' : "%i" % devid, - 'mac' : mac } - - if security.on() == xsconstants.XS_POLICY_USE: - self.do_access_control(config) - - return (devid, back, front) - - - def do_access_control(self, config): - """ do access control checking. Throws a VMError if access is denied """ - domain_label = self.vm.get_security_label() - stes = XSPolicyAdminInstance().get_stes_of_vmlabel(domain_label) - res_label = config.get('security_label') - if len(stes) > 1 or res_label: - if not res_label: - raise VmError("'VIF' must be labeled") - (label, ssidref, policy) = \ - security.security_label_to_details(res_label) - if domain_label: - rc = security.res_security_check_xapi(label, ssidref, - policy, - domain_label) - if rc == 0: - raise VmError("VM's access to network device denied. " - "Check labeling") - else: - raise VmError("VM must have a security label to access " - "network device") - - - def getDeviceConfiguration(self, devid, transaction = None): - """@see DevController.configuration""" - - result = DevController.getDeviceConfiguration(self, devid, transaction) - - for x in ( 'script', 'ip', 'bridge', 'mac', - 'type', 'vifname', 'rate', 'uuid', 'model', 'accel', - 'security_label'): - if transaction is None: - y = self.readBackend(devid, x) - else: - y = self.readBackendTxn(transaction, devid, x) - if y: - result[x] = y - - return result - - # match a VIF ID from xenstore, or a MAC address stored in the domain config - def convertToDeviceNumber(self, devid): - try: - return int(devid) - except ValueError: - if type(devid) is not str: - raise VmError("devid %s is wrong type" % str(devid)) - try: - dev = devid.split('/')[-1] - return (int(dev)) - except ValueError: - devs = [d for d in self.vm.info.all_devices_sxpr() - if d[0] == 'vif'] - for nr in range(len(devs)): - dev_type, dev_info = devs[nr] - if (sxp.child_value(dev_info, 'mac').lower() == - devid.lower()): - return nr - raise VmError("unknown devid %s" % str(devid)) diff --git a/tools/python/xen/xend/server/netif2.py b/tools/python/xen/xend/server/netif2.py deleted file mode 100644 index a098c13b5c..0000000000 --- a/tools/python/xen/xend/server/netif2.py +++ /dev/null @@ -1,163 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2005 XenSource Ltd -# Copyright (C) 2008 Citrix Systems Inc. -#============================================================================ -# -# Based closely on netif.py. -# - -"""Support for virtual network interfaces, version 2. -""" - -import os -import random -import re -import time - -from xen.xend import XendOptions -from xen.xend.server.DevController import DevController -from xen.xend.XendError import VmError -from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance -from xen.xend.xenstore.xstransact import xstransact -import xen.util.xsm.xsm as security - -from xen.xend.XendLogging import log - -xoptions = XendOptions.instance() - -def randomMAC(): - """Generate a random MAC address. - - Uses OUI (Organizationally Unique Identifier) 00-16-3E, allocated to - Xensource, Inc. The OUI list is available at - http://standards.ieee.org/regauth/oui/oui.txt. - - The remaining 3 fields are random, with the first bit of the first - random field set 0. - - @return: MAC address string - """ - mac = [ 0x00, 0x16, 0x3e, - random.randint(0x00, 0x7f), - random.randint(0x00, 0xff), - random.randint(0x00, 0xff) ] - return ':'.join(map(lambda x: "%02x" % x, mac)) - -class NetifController2(DevController): - def __init__(self, vm): - DevController.__init__(self, vm) - - def getDeviceDetails(self, config): - """@see DevController.getDeviceDetails""" - - devid = self.allocateDeviceID() - - bridge = config.get('bridge') - back_mac = config.get('back_mac') - if not back_mac: - if bridge: - back_mac = "fe:ff:ff:ff:ff:ff" - else: - back_mac = randomMAC() - front_mac = config.get('front_mac') or randomMAC() - front_trust = config.get("trusted") or "0" - back_trust = config.get("back_trusted") or "1" - max_bypasses = config.get("max_bypasses") or "5" - pdev = config.get('pdev') - front_filter = config.get("front_filter_mac") - if front_filter == None: - if back_trust == "0": - front_filter = "1" - else: - front_filter = "0" - back_filter = config.get("filter_mac") - if back_filter == None: - if front_trust == "0": - back_filter = "1" - else: - back_filter = "0" - back = { 'mac': back_mac, 'remote-mac': front_mac, - 'handle': "%i" % devid, 'local-trusted': back_trust, - 'remote-trusted': front_trust, 'filter-mac': back_filter, - 'max-bypasses': max_bypasses } - - front = { 'mac': front_mac, 'remote-mac': back_mac, - 'local-trusted': front_trust, 'remote-trusted': back_trust, - 'filter-mac': front_filter } - - if bridge: - back['bridge'] = bridge - - if pdev: - back['pdev'] = pdev - - return (devid, back, front) - - def getDeviceConfiguration(self, devid, transaction = None): - """@see DevController.configuration""" - - if transaction is None: - read_fn = xstransact.Read - else: - read_fn = transaction.read - def front_read(x): - return read_fn(frontpath + x) - def back_read(x): - return read_fn(backpath + x) - - result = DevController.getDeviceConfiguration(self, devid, transaction) - - dev = self.convertToDeviceNumber(devid) - frontpath = self.frontendPath(dev) + "/" - - backpath = front_read("backend") + "/" - - front_mac = front_read("mac") - back_mac = back_read("mac") - - front_trusted = back_read("remote-trusted") - back_trusted = back_read("local-trusted") - max_bypasses = back_read("max-bypasses") - - bridge = back_read("bridge") - - pdev = back_read("pdev") - - if front_mac: - result["front_mac"] = front_mac - if back_mac: - result["back_mac"] = back_mac - if front_trusted: - result["front_trusted"] = front_trusted - if back_trusted: - result["back_trusted"] = back_trusted - if bridge: - result["bridge"] = bridge - if pdev: - result["pdev"] = pdev - if max_bypasses: - result["max-bypasses"] = max_bypasses - return result - - def destroyDevice(self, devid, force): - dev = self.convertToDeviceNumber(devid) - self.writeBackend(dev, "online", "0") - if force: - self.writeBackend(dev, "shutdown-request", "force") - else: - self.writeBackend(dev, "shutdown-request", "normal") - self.vm._removeVm("device/%s/%d" % (self.deviceClass, dev)) diff --git a/tools/python/xen/xend/server/params.py b/tools/python/xen/xend/server/params.py deleted file mode 100644 index c7099e2506..0000000000 --- a/tools/python/xen/xend/server/params.py +++ /dev/null @@ -1,46 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -#============================================================================ - -import os - -def getenv(var, val, conv=None): - """Get a value from the environment, with optional conversion. - - @param var name of environment variable - @param val default value - @param conv conversion function to apply to env value - @return converted value or default - """ - try: - v = os.getenv(var) - if v is None: - v = val - else: - print var, '=', v - if conv: - v = conv(v) - except: - v = val - return v - -# The following parameters could be placed in a configuration file. -XEND_PID_FILE = '/var/run/xend.pid' -XEND_TRACE_FILE = '/var/log/xen/xend.trace' -XEND_DEBUG_LOG = '/var/log/xen/xend-debug.log' -XEND_USER = 'root' -XEND_DEBUG = getenv("XEND_DEBUG", 0, conv=int) -XEND_DAEMONIZE = getenv("XEND_DAEMONIZE", not XEND_DEBUG, conv=int) diff --git a/tools/python/xen/xend/server/pciif.py b/tools/python/xen/xend/server/pciif.py deleted file mode 100644 index 165953f15f..0000000000 --- a/tools/python/xen/xend/server/pciif.py +++ /dev/null @@ -1,596 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2005 XenSource Ltd -#============================================================================ - - -import types -import time - -from xen.xend import sxp -from xen.xend import XendOptions -xoptions = XendOptions.instance() - -from xen.xend import arch -from xen.xend.XendError import VmError -from xen.xend.XendLogging import log -from xen.xend.XendConstants import * - -from xen.xend.server.DevController import DevController -from xen.xend.server.DevConstants import xenbusState - -import xen.lowlevel.xc - -from xen.util.pci import * -import resource -import re - -from xen.xend.server.pciquirk import * -from xen.xend.xenstore.xstransact import xstransact -from xen.xend.xenstore.xswatch import xswatch - -xc = xen.lowlevel.xc.xc() - -#Calculate PAGE_SHIFT: number of bits to shift an address to get the page number -PAGE_SIZE = resource.getpagesize() -PAGE_SHIFT = 0 -t = PAGE_SIZE -while not (t&1): - t>>=1 - PAGE_SHIFT+=1 - -def parse_hex(val): - try: - if isinstance(val, types.StringTypes): - return int(val, 16) - else: - return val - except ValueError: - return None - -def get_assigned_pci_devices(domid): - dev_str_list = [] - path = '/local/domain/0/backend/pci/%u/0/' % domid - num_devs = xstransact.Read(path + 'num_devs'); - if num_devs is None or num_devs == "": - return dev_str_list - num_devs = int(num_devs) - for i in range(num_devs): - dev_str = xstransact.Read(path + 'dev-%i' % i) - dev_str_list = dev_str_list + [dev_str] - return dev_str_list - -def get_all_assigned_pci_devices(domid = 0): - dom_list = xstransact.List('/local/domain') - pci_str_list = [] - ti = 0 - ts = xstransact.Read('/local/domain/' + str(domid) + '/target') - if ts is not None : - ti = int(ts) - for d in dom_list: - target = xstransact.Read('/local/domain/' + d + '/target') - if int(d) is not ti and target is None : - pci_str_list = pci_str_list + get_assigned_pci_devices(int(d)) - return pci_str_list - -class PciController(DevController): - - def __init__(self, vm): - self.aerStateWatch = None - DevController.__init__(self, vm) - - - def getDeviceDetails(self, config): - """@see DevController.getDeviceDetails""" - back = {} - pcidevid = 0 - pci_defopts = [] - - if 'pci_msitranslate' in self.vm.info['platform']: - pci_defopts.append(['msitranslate', - str(self.vm.info['platform']['pci_msitranslate'])]) - if 'pci_power_mgmt' in self.vm.info['platform']: - pci_defopts.append(['power_mgmt', - str(self.vm.info['platform']['pci_power_mgmt'])]) - - for pci_config in config.get('devs', []): - domain = parse_hex(pci_config.get('domain', 0)) - bus = parse_hex(pci_config.get('bus', 0)) - slot = parse_hex(pci_config.get('slot', 0)) - func = parse_hex(pci_config.get('func', 0)) - vdevfn = parse_hex(pci_config.get('vdevfn', \ - '0x%02x' % AUTO_PHP_SLOT)) - - optslist = [] - if pci_config.has_key('opts'): - optslist += pci_config['opts'] - if optslist or pci_defopts: - opts = serialise_pci_opts( - append_default_pci_opts(optslist, pci_defopts)) - back['opts-%i' % pcidevid] = opts - - back['dev-%i' % pcidevid] = "%04x:%02x:%02x.%01x" % \ - (domain, bus, slot, func) - back['uuid-%i' % pcidevid] = pci_config.get('uuid', '') - back['key-%i' % pcidevid] = pci_config.get('key', '') - back['vdevfn-%i' % pcidevid] = "%02x" % vdevfn - pcidevid += 1 - - back['num_devs']=str(pcidevid) - back['uuid'] = config.get('uuid','') - - return (0, back, {}) - - def reconfigureDevice_find(self, devid, nsearch_dev, match_dev): - for j in range(nsearch_dev): - if match_dev == self.readBackend(devid, 'dev-%i' % j): - return j - return None - - def reconfigureDevice(self, _, config): - """@see DevController.reconfigureDevice""" - (devid, back, front) = self.getDeviceDetails(config) - num_devs = int(back['num_devs']) - states = config.get('states', []) - num_olddevs = int(self.readBackend(devid, 'num_devs')) - - for i in range(num_devs): - try: - dev = back['dev-%i' % i] - state = states[i] - uuid = back['uuid-%i' %i] - key = back['key-%i' %i] - opts = '' - if 'opts-%i' % i in back: - opts = back['opts-%i' % i] - except: - raise XendError('Error reading config') - - if state == 'Initialising': - devno = self.reconfigureDevice_find(devid, num_olddevs, dev) - if devno == None: - devno = num_olddevs + i - log.debug('Attaching PCI device %s.' % dev) - attaching = True - else: - log.debug('Reconfiguring PCI device %s.' % dev) - attaching = False - - self.setupOneDevice(parse_pci_name(dev)) - - self.writeBackend(devid, 'dev-%i' % devno, dev) - self.writeBackend(devid, 'state-%i' % devno, - str(xenbusState['Initialising'])) - self.writeBackend(devid, 'uuid-%i' % devno, uuid) - self.writeBackend(devid, 'key-%i' % devno, key) - if len(opts) > 0: - self.writeBackend(devid, 'opts-%i' % devno, opts) - if back.has_key('vdevfn-%i' % i): - self.writeBackend(devid, 'vdevfn-%i' % devno, - back['vdevfn-%i' % i]) - - # If a device is being attached then num_devs will grow - if attaching: - self.writeBackend(devid, 'num_devs', str(devno + 1)) - - elif state == 'Closing': - # PCI device detachment - devno = self.reconfigureDevice_find(devid, num_olddevs, dev) - if devno == None: - raise XendError('Device %s is not connected' % dev) - log.debug('Detaching device %s' % dev) - self.writeBackend(devid, 'state-%i' % devno, - str(xenbusState['Closing'])) - - else: - raise XendError('Error configuring device %s: invalid state %s' - % (dev,state)) - - self.writeBackend(devid, 'state', str(xenbusState['Reconfiguring'])) - - return self.readBackend(devid, 'uuid') - - - def getDeviceConfiguration(self, devid, transaction = None): - result = DevController.getDeviceConfiguration(self, devid, transaction) - num_devs = self.readBackend(devid, 'num_devs') - pci_devs = [] - - for i in range(int(num_devs)): - pci_dev = parse_pci_name(self.readBackend(devid, 'dev-%d' % i)) - - # Per device uuid info - pci_dev['uuid'] = self.readBackend(devid, 'uuid-%d' % i) - pci_dev['key'] = self.readBackend(devid, 'key-%d' % i) - pci_dev['vdevfn'] = '0x%s' % self.readBackend(devid, - 'vdevfn-%d' % i) - - #append opts info - opts = self.readBackend(devid, 'opts-%d' % i) - if opts is not None: - pci_dev['opts'] = opts - - pci_devs.append(pci_dev) - - result['devs'] = pci_devs - result['uuid'] = self.readBackend(devid, 'uuid') - return result - - def configuration(self, devid, transaction = None): - """Returns SXPR for devices on domain. - - @note: we treat this dict especially to convert to - SXP because it is not a straight dict of strings.""" - - configDict = self.getDeviceConfiguration(devid, transaction) - sxpr = [self.deviceClass] - - # remove devs - devs = configDict.pop('devs', []) - - for dev in devs: - dev_sxpr = ['dev'] - for dev_key, dev_val in dev.items(): - if dev_key == 'opts': - opts_sxpr = pci_opts_list_to_sxp(split_pci_opts(dev_val)) - dev_sxpr = sxp.merge(dev_sxpr, opts_sxpr) - else: - dev_sxpr.append([dev_key, dev_val]) - sxpr.append(dev_sxpr) - - for key, val in configDict.items(): - if type(val) == type(list()): - for v in val: - sxpr.append([key, v]) - else: - sxpr.append([key, val]) - - return sxpr - - def CheckSiblingDevices(self, domid, dev): - """ Check if all sibling devices of dev are owned by pciback or pci-stub - """ - if not self.vm.info.is_hvm(): - return - - group_str = xc.get_device_group(domid, dev.domain, dev.bus, dev.slot, dev.func) - if group_str == "": - return - - #group string format xx:xx.x,xx:xx.x, - for i in group_str.split(','): - if i == '': - continue - pci_dev = parse_pci_name(i) - pci_dev['domain'] = '%04x' % dev.domain - try: - sdev = PciDevice(pci_dev) - except Exception, e: - #no dom0 drivers bound to sdev - continue - - if sdev.driver!='pciback' and sdev.driver!='pci-stub': - raise VmError(("pci: PCI Backend and pci-stub don't "+ \ - "own sibling device %s of device %s"\ - )%(sdev.name, dev.name)) - return - - def setupOneDevice(self, pci_dev): - """ Attach I/O resources for device to frontend domain - """ - fe_domid = self.getDomid() - - try: - dev = PciDevice(pci_dev) - except Exception, e: - raise VmError("pci: failed to locate device and "+ - "parse its resources - "+str(e)) - - if dev.driver!='pciback' and dev.driver!='pci-stub': - raise VmError(("pci: PCI Backend and pci-stub don't own "+ \ - "device %s") %(dev.name)) - - self.CheckSiblingDevices(fe_domid, dev) - - if dev.driver == 'pciback': - PCIQuirk(dev) - - if not self.vm.info.is_hvm() and not self.vm.info.is_stubdom() : - # Setup IOMMU device assignment - bdf = xc.assign_device(fe_domid, pci_dict_to_xc_str(pci_dev)) - pci_str = pci_dict_to_bdf_str(pci_dev) - if bdf > 0: - raise VmError("Failed to assign device to IOMMU (%s)" % pci_str) - log.debug("pci: assign device %s" % pci_str) - - for (start, size) in dev.ioports: - log.debug('pci: enabling ioport 0x%x/0x%x'%(start,size)) - rc = xc.domain_ioport_permission(domid = fe_domid, first_port = start, - nr_ports = size, allow_access = True) - if rc<0: - raise VmError(('pci: failed to configure I/O ports on device '+ - '%s - errno=%d')%(dev.name,rc)) - - for (start, size) in dev.iomem: - # Convert start/size from bytes to page frame sizes - start_pfn = start>>PAGE_SHIFT - # Round number of pages up to nearest page boundary (if not on one) - nr_pfns = (size+(PAGE_SIZE-1))>>PAGE_SHIFT - - log.debug('pci: enabling iomem 0x%x/0x%x pfn 0x%x/0x%x'% \ - (start,size,start_pfn,nr_pfns)) - rc = xc.domain_iomem_permission(domid = fe_domid, - first_pfn = start_pfn, - nr_pfns = nr_pfns, - allow_access = True) - if rc<0: - raise VmError(('pci: failed to configure I/O memory on device '+ - '%s - errno=%d')%(dev.name,rc)) - - if dev.irq > 0: - rc = xc.physdev_map_pirq(domid = fe_domid, - index = dev.irq, - pirq = dev.irq) - if rc < 0: - raise VmError(('pci: failed to map irq on device '+ - '%s - errno=%d')%(dev.name,rc)) - if dev.irq>0: - log.debug('pci: enabling irq %d'%dev.irq) - rc = xc.domain_irq_permission(domid = fe_domid, pirq = dev.irq, - allow_access = True) - if rc<0: - raise VmError(('pci: failed to configure irq on device '+ - '%s - errno=%d')%(dev.name,rc)) - - def dev_check_assignability_and_do_FLR(self, config): - pci_dev_list = config.get('devs', []) - pci_str_list = map(pci_dict_to_bdf_str, pci_dev_list) - - if len(pci_str_list) != len(set(pci_str_list)): - raise VmError('pci: duplicate devices specified in guest config?') - - strict_check = xoptions.get_pci_dev_assign_strict_check() - devs = [] - for pci_dev in pci_dev_list: - try: - dev = PciDevice(pci_dev) - except Exception, e: - raise VmError("pci: failed to locate device and "+ - "parse its resources - "+str(e)) - if dev.driver!='pciback' and dev.driver!='pci-stub': - raise VmError(("pci: PCI Backend and pci-stub don't own device"\ - " %s") %(dev.name)) - - devs.append(dev) - - if dev.has_non_page_aligned_bar and strict_check: - raise VmError("pci: %s: non-page-aligned MMIO BAR found." % dev.name) - - # Check if there is intermediate PCIe switch bewteen the device and - # Root Complex. - if self.vm.info.is_hvm() and dev.is_behind_switch_lacking_acs() \ - and strict_check: - err_msg = 'pci: to avoid potential security issue, %s is not'+\ - ' allowed to be assigned to guest since it is behind'+\ - ' PCIe switch that does not support or enable ACS.' - raise VmError(err_msg % dev.name) - - if (dev.dev_type == DEV_TYPE_PCIe_ENDPOINT) and not dev.pcie_flr: - if dev.bus == 0: - # We cope with this case by using the Dstate transition - # method or some vendor specific methods for now. - err_msg = 'pci: %s: it is on bus 0, but has no PCIe' +\ - ' FLR Capability. Will try the Dstate transition'+\ - ' method or some vendor specific methods if available.' - log.warn(err_msg % dev.name) - else: - if not self.vm.info.is_hvm(): - continue - if not strict_check: - continue - - funcs = dev.find_all_the_multi_functions() - dev.devs_check_driver(funcs) - for f in funcs: - if not f in pci_str_list: - # f has been assigned to other guest? - if f in get_all_assigned_pci_devices(): - err_msg = 'pci: %s must be co-assigned to' + \ - ' the same guest with %s' - raise VmError(err_msg % (f, dev.name)) - elif dev.dev_type == DEV_TYPE_PCI: - if dev.bus == 0: - if not dev.pci_af_flr: - # We cope with this case by using the Dstate transition - # method or some vendor specific methods for now. - err_msg = 'pci: %s: it is on bus 0, but has no PCI' +\ - ' Advanced Capabilities for FLR. Will try the'+\ - ' Dstate transition method or some vendor' +\ - ' specific methods if available.' - log.warn(err_msg % dev.name) - else: - if not self.vm.info.is_hvm(): - continue - if not strict_check: - continue - - # All devices behind the uppermost PCI/PCI-X bridge must be\ - # co-assigned to the same guest. - devs_str = dev.find_coassigned_pci_devices(True) - # Remove the element 0 which is a bridge - del devs_str[0] - - dev.devs_check_driver(devs_str) - for s in devs_str: - if not s in pci_str_list: - # s has been assigned to other guest? - if s in get_all_assigned_pci_devices(): - err_msg = 'pci: %s must be co-assigned to the'+\ - ' same guest with %s' - raise VmError(err_msg % (s, dev.name)) - # try to do FLR - for dev in devs: - dev.do_FLR(self.vm.info.is_hvm(), strict_check) - - def setupDevice(self, config): - """Setup devices from config - """ - pci_dev_list = config.get('devs', []) - for d in pci_dev_list: - self.setupOneDevice(d) - wPath = '/local/domain/0/backend/pci/%u/0/aerState' % (self.getDomid()) - self.aerStateWatch = xswatch(wPath, self._handleAerStateWatch) - log.debug('pci: register aer watch %s', wPath) - return - - def _handleAerStateWatch(self, _): - log.debug('XendDomainInfo.handleAerStateWatch') - if self.getDomid() == 0: - raise XendError('Domain 0 cannot be shutdown') - readPath = '/local/domain/0/backend/pci/%u/0/aerState' % (self.getDomid()) - action = xstransact.Read(readPath) - if action and action=='aerfail': - log.debug('shutdown domain because of aer handle error') - self.vm.shutdown('poweroff') - return True - - - def cleanupOneDevice(self, pci_dev): - """ Detach I/O resources for device from frontend domain - """ - fe_domid = self.getDomid() - - try: - dev = PciDevice(pci_dev) - except Exception, e: - raise VmError("pci: failed to locate device and "+ - "parse its resources - "+str(e)) - - if dev.driver!='pciback' and dev.driver!='pci-stub': - raise VmError(("pci: PCI Backend and pci-stub don't own device "+ \ - "%s") %(dev.name)) - - # Need to do FLR here before deassign device in order to terminate - # DMA transaction, etc - dev.do_FLR(self.vm.info.is_hvm(), - xoptions.get_pci_dev_assign_strict_check()) - - if not self.vm.info.is_stubdom() : - bdf = xc.deassign_device(fe_domid, pci_dict_to_xc_str(pci_dev)) - pci_str = pci_dict_to_bdf_str(pci_dev) - if bdf > 0: - raise VmError("Failed to deassign device from IOMMU (%s)" % pci_str) - log.debug("pci: Deassign device %s" % pci_str) - - for (start, size) in dev.ioports: - log.debug('pci: disabling ioport 0x%x/0x%x'%(start,size)) - rc = xc.domain_ioport_permission(domid = fe_domid, first_port = start, - nr_ports = size, allow_access = False) - if rc<0: - raise VmError(('pci: failed to configure I/O ports on device '+ - '%s - errno=%d')%(dev.name,rc)) - - for (start, size) in dev.iomem: - # Convert start/size from bytes to page frame sizes - start_pfn = start>>PAGE_SHIFT - # Round number of pages up to nearest page boundary (if not on one) - nr_pfns = (size+(PAGE_SIZE-1))>>PAGE_SHIFT - - log.debug('pci: disabling iomem 0x%x/0x%x pfn 0x%x/0x%x'% \ - (start,size,start_pfn,nr_pfns)) - rc = xc.domain_iomem_permission(domid = fe_domid, - first_pfn = start_pfn, - nr_pfns = nr_pfns, - allow_access = False) - if rc<0: - raise VmError(('pci: failed to configure I/O memory on device '+ - '%s - errno=%d')%(dev.name,rc)) - - if dev.irq>0: - log.debug('pci: disabling irq %d'%dev.irq) - rc = xc.domain_irq_permission(domid = fe_domid, pirq = dev.irq, - allow_access = False) - if rc<0: - raise VmError(('pci: failed to configure irq on device '+ - '%s - errno=%d')%(dev.name,rc)) - - def cleanupDevice(self, devid): - """ Detach I/O resources for device and cleanup xenstore nodes - after reconfigure. - - @param devid: The device ID - @type devid: int - @return: Return the number of devices connected - @rtype: int - """ - num_devs = int(self.readBackend(devid, 'num_devs')) - new_num_devs = 0 - for i in range(num_devs): - try: - state = int(self.readBackend(devid, 'state-%i' % i)) - except: - state = xenbusState['Unknown'] - - if state == xenbusState['Closing']: - # Detach I/O resources. - pci_dev = parse_pci_name(self.readBackend(devid, 'dev-%i' % i)) - # In HVM case, I/O resources are disabled in ioemu. - self.cleanupOneDevice(pci_dev) - # Remove xenstore nodes. - list = ['dev', 'vdev', 'state', 'uuid', 'vdevfn', 'key'] - if self.readBackend(devid, 'opts-%i' % i) is not None: - list.append('opts') - for key in list: - self.removeBackend(devid, '%s-%i' % (key, i)) - else: - new_num_devs = new_num_devs + 1 - if new_num_devs == i + 1: - continue - - list = ['dev', 'vdev', 'state', 'uuid', 'opts', 'vdevfn', 'key'] - for key in list: - tmp = self.readBackend(devid, '%s-%i' % (key, i)) - if tmp is None: - continue - self.removeBackend(devid, '%s-%i' % (key, i)) - self.writeBackend(devid, - '%s-%i' % (key, new_num_devs - 1), tmp) - - self.writeBackend(devid, 'num_devs', str(new_num_devs)) - - return new_num_devs - - def destroyDevice(self, devid, force): - DevController.destroyDevice(self, devid, True) - log.debug('pci: unregister aer watch') - self.unwatchAerState() - - def unwatchAerState(self): - """Remove the watch on the domain's aerState node, if any.""" - try: - try: - if self.aerStateWatch: - self.aerStateWatch.unwatch() - finally: - self.aerStateWatch = None - except: - log.exception("Unwatching aerState failed.") - - def waitForBackend(self,devid): - return (0, "ok - no hotplug") - - def migrate(self, config, network, dst, step, domName): - raise XendError('Migration not permitted with assigned PCI device.') diff --git a/tools/python/xen/xend/server/pciquirk.py b/tools/python/xen/xend/server/pciquirk.py deleted file mode 100644 index ba56ebdf8b..0000000000 --- a/tools/python/xen/xend/server/pciquirk.py +++ /dev/null @@ -1,149 +0,0 @@ -from xen.xend.XendLogging import log -from xen.xend.XendError import XendError, VmError -import sys -import os.path -from xen.xend.sxp import * -from xen.util import auxbin - -QUIRK_SYSFS_NODE = "/sys/bus/pci/drivers/pciback/quirks" -QUIRK_CONFIG_FILE = auxbin.xen_configdir() + "/xend-pci-quirks.sxp" -PERMISSIVE_CONFIG_FILE = auxbin.xen_configdir() + "/xend-pci-permissive.sxp" -PERMISSIVE_SYSFS_NODE = "/sys/bus/pci/drivers/pciback/permissive" - -class PCIQuirk: - def __init__(self, dev): - self.vendor = dev.vendor - self.device = dev.device - self.subvendor = dev.subvendor - self.subdevice = dev.subdevice - self.domain = dev.domain - self.bus = dev.bus - self.slot = dev.slot - self.func = dev.func - - self.devid = "%04x:%04x:%04x:%04x" % (self.vendor, self.device, - self.subvendor, self.subdevice) - self.pciid = dev.name - self.quirks = self.__getQuirksByID() - - self.__sendQuirks() - self.__sendPermDevs() - - def __matchPCIdev( self, list ): - ret = False - if list == None: - return False - for id in list: - if id.startswith(self.devid[:9]): # id's vendor and device ID match - skey = id.split(':') - size = len(skey) - if (size == 2): # subvendor/subdevice not suplied - ret = True - break - elif (size == 4): # check subvendor/subdevice - # check subvendor - subven = '%04x' % self.subvendor - if ((skey[2] != 'FFFF') and - (skey[2] != 'ffff') and - (skey[2] != subven)): - continue - # check subdevice - subdev = '%04x' % self.subdevice - if ((skey[3] != 'FFFF') and - (skey[3] != 'ffff') and - (skey[3] != subdev)): - continue - ret = True - break - else: - log.debug("WARNING: invalid configuration entry: %s" % id) - ret = False - break - return ret - - def __getQuirksByID( self ): - if os.path.exists(QUIRK_CONFIG_FILE): - try: - fin = file(QUIRK_CONFIG_FILE, 'rb') - try: - pci_quirks_config = parse(fin) - finally: - fin.close() - if pci_quirks_config is None: - pci_quirks_config = ['xend-pci-quirks'] - else: - pci_quirks_config.insert(0, 'xend-pci-quirks') - self.pci_quirks_config = pci_quirks_config - except Exception, ex: - raise XendError("Reading config file %s: %s" % - (QUIRK_CONFIG_FILE, str(ex))) - else: - log.info("Config file does not exist: %s" % QUIRK_CONFIG_FILE) - self.pci_quirks_config = ['xend-pci-quirks'] - - devices = children(self.pci_quirks_config) - for dev in devices: - ids = child_at(child(dev,'pci_ids'),0) - fields = child_at(child(dev,'pci_config_space_fields'),0) - if self.__matchPCIdev( ids ): - log.info("Quirks found for PCI device [%s]" % self.devid) - return fields - - log.info("NO quirks found for PCI device [%s]" % self.devid) - return [] - - def __sendQuirks(self): - for quirk in self.quirks: - log.debug("Quirk Info: %04x:%02x:%02x.%1x-%s" % (self.domain, - self.bus, self.slot, self.func, quirk)) - try: - f = file(QUIRK_SYSFS_NODE ,"w") - f.write( "%04x:%02x:%02x.%1x-%s" % (self.domain, self.bus, - self.slot, self.func, quirk) ) - f.close() - except Exception, e: - raise VmError("pci: failed to open/write/close quirks " + - "sysfs node - " + str(e)) - - def __devIsUnconstrained( self ): - if os.path.exists(PERMISSIVE_CONFIG_FILE): - try: - fin = file(PERMISSIVE_CONFIG_FILE, 'rb') - try: - pci_perm_dev_config = parse(fin) - finally: - fin.close() - if pci_perm_dev_config is None: - pci_perm_dev_config = [''] - else: - pci_perm_dev_config.insert(0, '') - except Exception, ex: - raise XendError("Reading config file %s: %s" % - (PERMISSIVE_CONFIG_FILE,str(ex))) - else: - log.info("Config file does not exist: %s" % PERMISSIVE_CONFIG_FILE) - pci_perm_dev_config = ['xend-pci-perm-devs'] - - self.pci_perm_dev_config = pci_perm_dev_config - devices = child_at(child(self.pci_perm_dev_config, - 'unconstrained_dev_ids'),0) - if self.__matchPCIdev( devices ): - log.debug("Permissive mode enabled for PCI device [%s]" % - self.devid) - return True - log.debug("Permissive mode NOT enabled for PCI device [%s]" % - self.devid) - return False - - def __sendPermDevs(self): - if self.__devIsUnconstrained( ): - log.debug("Unconstrained device: %04x:%02x:%02x.%1x" % - (self.domain, self.bus, self.slot, self.func)) - try: - f = file(PERMISSIVE_SYSFS_NODE ,"w") - f.write( "%04x:%02x:%02x.%1x" % (self.domain, self.bus, - self.slot, self.func)) - f.close() - except Exception, e: - raise VmError("pci: failed to open/write/close permissive " + - "sysfs node: " + str(e)) diff --git a/tools/python/xen/xend/server/relocate.py b/tools/python/xen/xend/server/relocate.py deleted file mode 100644 index 6aa6f83d40..0000000000 --- a/tools/python/xen/xend/server/relocate.py +++ /dev/null @@ -1,173 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -# Copyright (C) 2005 XenSource Ltd -#============================================================================ - -import re -import os -import sys -import StringIO -import threading - -from xen.web import protocol, tcp, unix, connection - -from xen.xend import sxp -from xen.xend import XendDomain -from xen.xend import XendOptions -from xen.xend.XendError import XendError -from xen.xend.XendLogging import log - - -class RelocationProtocol(protocol.Protocol): - """Asynchronous handler for a connected relocation socket. - """ - - def __init__(self): - protocol.Protocol.__init__(self) - self.parser = sxp.Parser() - - def dataReceived(self, data): - try: - self.parser.input(data) - while(self.parser.ready()): - val = self.parser.get_val() - res = self.dispatch(val) - self.send_result(res) - if self.parser.at_eof(): - self.close() - except SystemExit: - raise - except: - self.send_error() - - def close(self): - if self.transport: - self.transport.close() - - def send_reply(self, sxpr): - io = StringIO.StringIO() - sxp.show(sxpr, out=io) - print >> io - io.seek(0) - if self.transport: - return self.transport.write(io.getvalue()) - else: - return 0 - - def send_result(self, res): - if res is None: - resp = ['ok'] - else: - resp = ['ok', res] - return self.send_reply(resp) - - def send_error(self): - (extype, exval) = sys.exc_info()[:2] - return self.send_reply(['err', - ['type', str(extype)], - ['value', str(exval)]]) - - def opname(self, name): - return 'op_' + name.replace('.', '_') - - def operror(self, name, _): - raise XendError('Invalid operation: ' +name) - - def dispatch(self, req): - op_name = sxp.name(req) - op_method_name = self.opname(op_name) - op_method = getattr(self, op_method_name, self.operror) - return op_method(op_name, req) - - def op_help(self, _1, _2): - def nameop(x): - if x.startswith('op_'): - return x[3:].replace('_', '.') - else: - return x - - l = [ nameop(k) for k in dir(self) if k.startswith('op_') ] - return l - - def op_quit(self, _1, _2): - self.close() - - def op_receive(self, name, _): - if self.transport: - self.send_reply(["ready", name]) - try: - XendDomain.instance().domain_restore_fd( - self.transport.sock.fileno(), relocating=True) - except: - self.send_error() - self.close() - else: - log.error(name + ": no transport") - raise XendError(name + ": no transport") - - def op_sslreceive(self, name, _): - if self.transport: - self.send_reply(["ready", name]) - p2cread, p2cwrite = os.pipe() - from xen.util import oshelp - oshelp.fcntl_setfd_cloexec(p2cwrite, True) - threading.Thread(target=connection.SSLSocketServerConnection.recv2fd, - args=(self.transport.sock, p2cwrite)).start() - try: - XendDomain.instance().domain_restore_fd(p2cread, - relocating=True) - except: - os.close(p2cread) - os.close(p2cwrite) - self.send_error() - self.close() - else: - log.error(name + ": no transport") - raise XendError(name + ": no transport") - - -def listenRelocation(): - xoptions = XendOptions.instance() - if xoptions.get_xend_unix_server(): - path = '/var/lib/xend/relocation-socket' - unix.UnixListener(path, RelocationProtocol) - - interface = xoptions.get_xend_relocation_address() - - hosts_allow = xoptions.get_xend_relocation_hosts_allow() - if hosts_allow == '': - hosts_allow = None - else: - hosts_allow = map(re.compile, hosts_allow.split(" ")) - - if xoptions.get_xend_relocation_server(): - port = xoptions.get_xend_relocation_port() - tcp.TCPListener(RelocationProtocol, port, interface = interface, - hosts_allow = hosts_allow) - - if xoptions.get_xend_relocation_ssl_server(): - port = xoptions.get_xend_relocation_ssl_port() - ssl_key_file = xoptions.get_xend_relocation_server_ssl_key_file() - ssl_cert_file = xoptions.get_xend_relocation_server_ssl_cert_file() - - if ssl_key_file and ssl_cert_file: - tcp.SSLTCPListener(RelocationProtocol, port, interface = interface, - hosts_allow = hosts_allow, - ssl_key_file = ssl_key_file, - ssl_cert_file = ssl_cert_file) - else: - raise XendError("ssl_key_file or ssl_cert_file for ssl relocation server is missing.") - diff --git a/tools/python/xen/xend/server/tests/__init__.py b/tools/python/xen/xend/server/tests/__init__.py deleted file mode 100644 index 8d1c8b69c3..0000000000 --- a/tools/python/xen/xend/server/tests/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tools/python/xen/xend/server/tests/test_controllers.py b/tools/python/xen/xend/server/tests/test_controllers.py deleted file mode 100644 index dd2677500d..0000000000 --- a/tools/python/xen/xend/server/tests/test_controllers.py +++ /dev/null @@ -1,81 +0,0 @@ -import os -import re -import unittest - -import xen.xend.XendOptions - -xen.xend.XendOptions.XendOptions.config_default = '/dev/null' - -from xen.xend.server import netif - - -FAKE_DOMID = 42 -FAKE_DEVID = 63 - - -xoptions = xen.xend.XendOptions.instance() - - -class test_controllers(unittest.TestCase): - - def testNetif(self): - controller = self.controllerInstance(netif.NetifController) - - self.assertNetif(controller.getDeviceDetails({}), None) - self.assertNetif( - controller.getDeviceDetails({'mac': 'aa:bb:cc:dd:ee:ff'}), - 'aa:bb:cc:dd:ee:ff') - - - - def assertNetif(self, results, expectedMac): - - (devid, backdets, frontdets) = results - - self.assertEqual(devid, FAKE_DEVID) - - self.assertEqual(backdets['handle'], str(FAKE_DEVID)) - self.assertEqual(backdets['script'], - os.path.join(xoptions.network_script_dir, - xoptions.get_vif_script())) - self.assertValidMac(backdets['mac'], expectedMac) - - self.assertEqual(frontdets['handle'], str(FAKE_DEVID)) - self.assertValidMac(frontdets['mac'], expectedMac) - - - MAC_REGEXP = re.compile('^' + - ':'.join([r'[0-9a-f][0-9a-f]' - for i in range(0, 6)]) + - '$') - - def assertValidMac(self, mac, expected): - if expected: - self.assertEqual(mac, expected) - else: - self.assert_(self.MAC_REGEXP.match(mac)) - - - def controllerInstance(self, cls): - """Allocate an instance of the given controller class, and override - methods as appropriate so that we can run tests without needing - Xenstored.""" - - result = cls(FakeXendDomainInfo()) - - result.allocateDeviceID = fakeID - - return result - - -class FakeXendDomainInfo: - def getDomainPath(self): - return "/test/fake/domain/%d/" % FAKE_DOMID - - -def fakeID(): - return FAKE_DEVID - - -def test_suite(): - return unittest.makeSuite(test_controllers) diff --git a/tools/python/xen/xend/server/udevevent.py b/tools/python/xen/xend/server/udevevent.py deleted file mode 100644 index 6d61b8ed17..0000000000 --- a/tools/python/xen/xend/server/udevevent.py +++ /dev/null @@ -1,92 +0,0 @@ -import socket - -from xen.web import protocol, unix - -from xen.xend.XendLogging import log -from xen.xend import XendNode -from xen.xend import XendOptions - -UDEV_EVENT_PATH = '\0/org/xen/xend/udev_event' - -class UdevEventProtocol(protocol.Protocol): - - def __init__(self): - protocol.Protocol.__init__(self) - - def dataReceived(self, data): - udev_event = {} - for entry in data.split('\0'): - try: - opt, val = entry.split("=") - udev_event[opt] = val - except (TypeError, ValueError): - pass - if udev_event.get('ACTION', None) is None: - log.warn("Invalid udev event received") - return - - log.debug("udev event received: %s", udev_event) - - self._process_event(udev_event) - - def _process_event(self, udev_event): - try: - if (udev_event.get('SUBSYSTEM', None) == 'pci'): - pci_name = udev_event.get('PCI_SLOT_NAME', None) - if (udev_event['ACTION'] == 'add'): - log.info("Adding pci device %s", pci_name) - XendNode.instance().add_PPCI(pci_name) - elif (udev_event['ACTION'] == 'remove'): - log.info("Removing pci device %s", pci_name) - XendNode.instance().remove_PPCI(pci_name) - - elif (udev_event.get('SUBSYSTEM', None) == 'scsi'): - hctl = None - devpath = udev_event.get('DEVPATH', None) - if devpath: - hctl = devpath.split('/')[-1] - if len(hctl.split(':')) != 4: - hctl = None - if hctl is None: - # By any possibility, if an HCTL isn't gotten from - # the udev event, the udev event is ignored. - log.warn("Invalid udev event about scsi received") - return - - if (udev_event['ACTION'] == 'add'): - log.info("Adding scsi device %s", hctl) - XendNode.instance().add_PSCSI(hctl) - elif (udev_event['ACTION'] == 'remove'): - log.info("Removing scsi device %s", hctl) - XendNode.instance().remove_PSCSI(hctl) - - elif (udev_event.get('SUBSYSTEM', None) == 'usb'): - busid = udev_event.get('KERNEL', None) - if busid: - if len(busid.split(':')) != 2: - return - if (udev_event['ACTION'] == 'add'): - log.info("Adding usb device %s", busid) - XendNode.instance().add_usbdev(busid) - elif (udev_event['ACTION'] == 'remove'): - log.info("Removing usb device %s", busid) - XendNode.instance().remove_usbdev(busid) - - elif (udev_event.get('SUBSYSTEM', None) == 'net'): - interface = udev_event.get('INTERFACE', None) - if (udev_event['ACTION'] == 'add'): - log.info("Adding net device %s", interface) - XendNode.instance().add_network(interface) - elif (udev_event['ACTION'] == 'remove'): - log.info("Removing net device %s", interface) - XendNode.instance().remove_network(interface) - - except Exception, e: - log.warn("error while processing udev event(): %s" % str(e)) - - -def listenUdevEvent(): - xoptions = XendOptions.instance() - if xoptions.get_xend_udev_event_server(): - unix.UnixDgramListener(UDEV_EVENT_PATH, UdevEventProtocol) - diff --git a/tools/python/xen/xend/server/vfbif.py b/tools/python/xen/xend/server/vfbif.py deleted file mode 100644 index 80e81b1eea..0000000000 --- a/tools/python/xen/xend/server/vfbif.py +++ /dev/null @@ -1,91 +0,0 @@ -from xen.xend.server.DevController import DevController -from xen.xend.XendLogging import log - -from xen.xend.XendError import VmError -import xen.xend -import os - -CONFIG_ENTRIES = ['type', 'vncdisplay', 'vnclisten', 'vncpasswd', 'vncunused', - 'display', 'xauthority', 'keymap', 'vnc', 'sdl', 'uuid', - 'location', 'protocol', 'opengl'] - -class VfbifController(DevController): - """Virtual frame buffer controller. Handles all vfb devices for a domain. - Note that we only support a single vfb per domain at the moment. - """ - - def __init__(self, vm): - DevController.__init__(self, vm) - - def getDeviceDetails(self, config): - """@see DevController.getDeviceDetails""" - - back = dict([(k, str(config[k])) for k in CONFIG_ENTRIES - if config.has_key(k)]) - - devid = 0 - return (devid, back, {}) - - - def getDeviceConfiguration(self, devid, transaction = None): - result = DevController.getDeviceConfiguration(self, devid, transaction) - - if transaction is None: - devinfo = self.readBackend(devid, *CONFIG_ENTRIES) - else: - devinfo = self.readBackendTxn(transaction, devid, *CONFIG_ENTRIES) - return dict([(CONFIG_ENTRIES[i], devinfo[i]) - for i in range(len(CONFIG_ENTRIES)) - if devinfo[i] is not None]) - - def waitForDevice(self, devid): - # is a qemu-dm managed device, don't wait for hotplug for these. - return - - def reconfigureDevice(self, _, config): - """ Only allow appending location information of vnc port into - xenstore.""" - - if 'location' in config: - (devid, back, front) = self.getDeviceDetails(config) - self.writeBackend(devid, 'location', config['location']) - return back.get('uuid') - - raise VmError('Refusing to reconfigure device vfb:%d' % devid) - - def destroyDevice(self, devid, force): - # remove the backend xenstore entries no matter what - # because we kill qemu-dm with extreme prejudice - # not giving it a chance to remove them itself - DevController.destroyDevice(self, devid, True) - - - def migrate(self, deviceConfig, network, dst, step, domName): - # Handled by qemu-dm so no action needed - return 0 - - -class VkbdifController(DevController): - """Virtual keyboard controller. Handles all vkbd devices for a domain. - """ - - def getDeviceDetails(self, config): - """@see DevController.getDeviceDetails""" - devid = 0 - back = {} - front = {} - return (devid, back, front) - - def waitForDevice(self, config): - # is a qemu-dm managed device, don't wait for hotplug for these. - return - - def destroyDevice(self, devid, force): - # remove the backend xenstore entries no matter what - # because we kill qemu-dm with extreme prejudice - # not giving it a chance to remove them itself - DevController.destroyDevice(self, devid, True) - - def migrate(self, deviceConfig, network, dst, step, domName): - # Handled by qemu-dm so no action needed - return 0 diff --git a/tools/python/xen/xend/server/vscsiif.py b/tools/python/xen/xend/server/vscsiif.py deleted file mode 100644 index 9657e4f4a8..0000000000 --- a/tools/python/xen/xend/server/vscsiif.py +++ /dev/null @@ -1,246 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2007 FUJITSU Limited -# Based on the blkif.py -#============================================================================ - - -"""Support for VSCSI Devices. -""" -import re -import string - -import types - -from xen.xend import sxp -from xen.xend.XendError import VmError -from xen.xend.XendLogging import log - -from xen.xend.server.DevController import DevController -from xen.xend.server.DevConstants import xenbusState -from xen.xend.xenstore.xstransact import xstransact - -class VSCSIController(DevController): - """VSCSI Devices. - """ - def __init__(self, vm): - """Create a VSCSI Devices. - """ - DevController.__init__(self, vm) - - - def sxprs(self): - """@see DevController.sxprs""" - devslist = [] - for devid in self.deviceIDs(): - vscsi_devs = self.readBackendList(devid, "vscsi-devs") - vscsipath = "vscsi-devs/" - devs = [] - vscsi_config = [] - for dev in vscsi_devs: - devpath = vscsipath + dev - backstate = self.readBackend(devid, devpath + '/state') - pdev = self.readBackend(devid, devpath + '/p-dev') - pdevname = self.readBackend(devid, devpath + '/p-devname') - vdev = self.readBackend(devid, devpath + '/v-dev') - localdevid = self.readBackend(devid, devpath + '/devid') - frontstate = self.readFrontend(devid, devpath + '/state') - devs.append(['dev', \ - ['state', backstate], \ - ['devid', localdevid], \ - ['p-dev', pdev], \ - ['p-devname', pdevname], \ - ['v-dev', vdev], \ - ['frontstate', frontstate] ]) - - vscsi_config.append(['devs', devs]) - state = self.readFrontend(devid, 'state') - vscsi_config.append(['state', state]) - hostmode = self.readBackend(devid, 'feature-host') - vscsi_config.append(['feature-host', hostmode]) - backid = self.readFrontend(devid, 'backend-id') - vscsi_config.append(['backend-id', backid]) - backpath = self.readFrontend(devid, 'backend') - vscsi_config.append(['backend', backpath]) - - devslist.append([devid, vscsi_config]) - - return devslist - - - def getDeviceDetails(self, config): - """@see DevController.getDeviceDetails""" - back = {} - vscsipath = "vscsi-devs/" - for vscsi_config in config.get('devs', []): - localdevid = self.allocateDeviceID() - # vscsi-devs/dev-0 - devpath = vscsipath + 'dev-%i' % localdevid - back[devpath] = "" - pdev = vscsi_config.get('p-dev', '') - back[devpath + '/p-dev'] = pdev - pdevname = vscsi_config.get('p-devname', '') - back[devpath + '/p-devname'] = pdevname - vdev = vscsi_config.get('v-dev', '') - back[devpath + '/v-dev'] = vdev - state = vscsi_config.get('state', xenbusState['Unknown']) - back[devpath + '/state'] = str(state) - devid = vscsi_config.get('devid', '') - back[devpath + '/devid'] = str(devid) - - host_mode = config.get('feature-host','') - back['feature-host'] = str(host_mode) - back['uuid'] = config.get('uuid','') - devid = int(devid) - return (devid, back, {}) - - - def readBackendList(self, devid, *args): - frontpath = self.frontendPath(devid) - backpath = xstransact.Read(frontpath + "/backend") - if backpath: - paths = map(lambda x: backpath + "/" + x, args) - return xstransact.List(*paths) - - - def getDeviceConfiguration(self, devid, transaction = None): - config = DevController.getDeviceConfiguration(self, devid, transaction) - - vscsi_devs = [] - - devs = self.readBackendList(devid, "vscsi-devs") - vscsipath = "vscsi-devs/" - for dev in devs: - devpath = vscsipath + dev - pdev = self.readBackend(devid, devpath + '/p-dev') - pdevname = self.readBackend(devid, devpath + '/p-devname') - vdev = self.readBackend(devid, devpath + '/v-dev') - state = self.readBackend(devid, devpath + '/state') - localdevid = self.readBackend(devid, devpath + '/devid') - dev_dict = {'p-dev': pdev, - 'p-devname': pdevname, - 'v-dev': vdev, - 'state': state, - 'devid': localdevid } - vscsi_devs.append(dev_dict) - - config['devs'] = vscsi_devs - config['feature-host'] = self.readBackend(devid, 'feature-host') - config['uuid'] = self.readBackend(devid, 'uuid') - return config - - - def configuration(self, devid, transaction = None): - """Returns SXPR for devices on domain. - @note: we treat this dict especially to convert to - SXP because it is not a straight dict of strings.""" - - configDict = self.getDeviceConfiguration(devid, transaction) - sxpr = [self.deviceClass] - - # remove devs - devs = configDict.pop('devs', []) - - for dev in devs: - dev_sxpr = ['dev'] - for dev_item in dev.items(): - dev_sxpr.append(list(dev_item)) - sxpr.append(dev_sxpr) - - for key, val in configDict.items(): - if type(val) == type(list()): - for v in val: - sxpr.append([key, v]) - else: - sxpr.append([key, val]) - - return sxpr - - - def reconfigureDevice(self, _, config): - """@see DevController.reconfigureDevice""" - (devid, back, front) = self.getDeviceDetails(config) - devid = int(devid) - vscsi_config = config['devs'][0] - state = vscsi_config.get('state', xenbusState['Unknown']) - driver_state = self.readBackend(devid, 'state') - - if str(xenbusState['Connected']) != driver_state: - raise VmError("Driver status is not connected") - - uuid = self.readBackend(devid, 'uuid') - if state == xenbusState['Initialising']: - back['uuid'] = uuid - self.writeBackend(devid, back) - - elif state == xenbusState['Closing']: - found = False - devs = self.readBackendList(devid, "vscsi-devs") - hostmode = int(self.readBackend(devid, 'feature-host')) - vscsipath = "vscsi-devs/" - vdev = vscsi_config.get('v-dev', '') - - for dev in devs: - devpath = vscsipath + dev - old_vdev = self.readBackend(devid, devpath + '/v-dev') - - if hostmode == 1: - #At hostmode, all v-dev that belongs to devid is deleted. - found = True - self.writeBackend(devid, devpath + '/state', \ - str(xenbusState['Closing'])) - elif vdev == old_vdev: - found = True - self.writeBackend(devid, devpath + '/state', \ - str(xenbusState['Closing'])) - break - - if not found: - raise VmError("Device %s not connected" % vdev) - - else: - raise XendError("Error configuring device invalid " - "state '%s'" % xenbusState[state]) - - self.writeBackend(devid, 'state', str(xenbusState['Reconfiguring'])) - return self.readBackend(devid, 'uuid') - - - def cleanupDevice(self, devid): - devs = self.readBackendList(devid, "vscsi-devs") - vscsipath = "vscsi-devs/" - new_num_devs = 0 - - for dev in devs: - new_num_devs = new_num_devs + 1 - devpath = vscsipath + dev - devstate = self.readBackend(devid, devpath + '/state') - - if str(xenbusState['Closed']) == devstate: - self.removeBackend(devid, devpath) - frontpath = self.frontendPath(devid) - xstransact.Remove(frontpath + '/' + devpath) - new_num_devs = new_num_devs - 1 - - frontpath = self.frontendPath(devid) - front_devstate = xstransact.Read(frontpath + '/' + devpath) - if front_devstate is not None: - if str(xenbusState['Closed']) == front_devstate: - self.removeBackend(devid, devpath) - xstransact.Remove(frontpath + '/' + devpath) - new_num_devs = new_num_devs - 1 - - return new_num_devs - diff --git a/tools/python/xen/xend/server/vusbif.py b/tools/python/xen/xend/server/vusbif.py deleted file mode 100644 index 7b37e6ef7d..0000000000 --- a/tools/python/xen/xend/server/vusbif.py +++ /dev/null @@ -1,126 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2009, FUJITSU LABORATORIES LTD. -# Author: Noboru Iwamatsu -#============================================================================ - -"""Support for virtual USB host controllers. -""" -import re -import string - -import types - -from xen.xend import sxp -from xen.xend.XendError import VmError -from xen.xend.XendLogging import log - -from xen.xend.server.DevController import DevController -from xen.xend.server.DevConstants import xenbusState -from xen.xend.xenstore.xstransact import xstransact - -from xen.util import vusb_util - -class VUSBController(DevController): - """VUSB Devices. - """ - def __init__(self, vm): - """Create a VUSB Devices. - """ - DevController.__init__(self, vm) - - def sxprs(self): - """@see DevController.sxprs""" - devslist = [] - for devid in self.deviceIDs(): - vusb_config = [] - backid = self.readFrontend(devid, 'backend-id') - vusb_config.append(['backend-id', backid]) - state = self.readFrontend(devid, 'state') - vusb_config.append(['state', state]) - backpath = self.readFrontend(devid, 'backend') - vusb_config.append(['backend', backpath]) - usbver = self.readBackend(devid, 'usb-ver') - vusb_config.append(['usb-ver', usbver]) - numports = self.readBackend(devid, 'num-ports') - vusb_config.append(['num-ports', numports]) - - portpath = "port/" - ports = ['port'] - for i in range(1, int(numports) + 1): - bus = self.readBackend(devid, portpath + '%i' % i) - ports.append(['%i' % i, str(bus)]) - - vusb_config.append(ports) - devslist.append([devid, vusb_config]) - - return devslist - - def getDeviceDetails(self, config): - """@see DevController.getDeviceDetails""" - back = {} - devid = self.allocateDeviceID() - usbver = config.get('usb-ver', '') - numports = config.get('num-ports', '') - back['usb-ver'] = str(usbver) - back['num-ports'] = str(numports) - for i in range(1, int(numports) + 1): - back['port/%i' % i] = config['port-%i' % i] - return (devid, back, {}) - - def getDeviceConfiguration(self, devid, transaction = None): - """@see DevController.configuration""" - config = DevController.getDeviceConfiguration(self, devid, transaction) - if transaction is None: - hcinfo = self.readBackend(devid, 'usb-ver', 'num-ports') - else: - hcinfo = self.readBackendTxn(transaction, devid, - 'usb-ver', 'num-ports') - (usbver, numports) = hcinfo - config['usb-ver'] = str(usbver) - config['num-ports'] = str(numports) - for i in range(1, int(numports) + 1): - if transaction is None: - config['port-%i' % i] = self.readBackend(devid, 'port/%i' % i) - else: - config['port-%i' % i] = self.readBackendTxn(transaction, devid, - 'port/%i' % i) - return config - - def reconfigureDevice(self, devid, config): - """@see DevController.reconfigureDevice""" - cur_config = self.getDeviceConfiguration(devid) - - numports = cur_config['num-ports'] - for i in range(1, int(numports) + 1): - if config.has_key('port-%i' % i): - if not config['port-%i' % i] == cur_config['port-%i' % i]: - if not cur_config['port-%i' % i] == "": - vusb_util.unbind_usb_device(cur_config['port-%i' % i]) - self.writeBackend(devid, 'port/%i' % i, - config['port-%i' % i]) - if not config['port-%i' % i] == "": - vusb_util.bind_usb_device(config['port-%i' % i]) - - return self.readBackend(devid, 'uuid') - - def waitForBackend(self, devid): - return (0, "ok - no hotplug") - - def waitForBackend_destroy(self, backpath): - return 0 - - def migrate(self, deviceConfig, network, dst, step, domName): - raise VmError('Migration not permitted with assigned USB device.') diff --git a/tools/python/xen/xend/sxp.py b/tools/python/xen/xend/sxp.py deleted file mode 100644 index c87270f070..0000000000 --- a/tools/python/xen/xend/sxp.py +++ /dev/null @@ -1,765 +0,0 @@ -#!/usr/bin/env python -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray -#============================================================================ - -""" -Input-driven parsing for s-expression (sxp) format. -Create a parser: pin = Parser(); -Then call pin.input(buf) with your input. -Call pin.input_eof() when done. -Use pin.read() to see if a value has been parsed, pin.get_val() -to get a parsed value. You can call ready and get_val at any time - -you don't have to wait until after calling input_eof. - -""" -from __future__ import generators - -import sys -import types -import errno -import string -from StringIO import StringIO - -__all__ = [ - "mime_type", - "ParseError", - "Parser", - "atomp", - "show", - "show_xml", - "elementp", - "name", - "attributes", - "attribute", - "children", - "child", - "child_at", - "child0", - "child1", - "child2", - "child3", - "child4", - "child_value", - "has_id", - "with_id", - "child_with_id", - "elements", - "merge", - "to_string", - "from_string", - "all_from_string", - "parse", - ] - -mime_type = "application/sxp" - -escapes = { - 'a': '\a', - 'b': '\b', - 't': '\t', - 'n': '\n', - 'v': '\v', - 'f': '\f', - 'r': '\r', - '\\': '\\', - '\'': '\'', - '\"': '\"'} - -k_list_open = "(" -k_list_close = ")" -k_attr_open = "@" -k_eval = "!" - -escapes_rev = {} -for k in escapes: - escapes_rev[escapes[k]] = k - -class ParseError(StandardError): - - def __init__(self, parser, value): - self.parser = parser - self.value = value - - def __str__(self): - return self.value - -class ParserState: - - def __init__(self, fn, parent=None): - self.parent = parent - self.buf = '' - self.val = [] - self.delim = None - self.fn = fn - - def push(self, fn): - return ParserState(fn, parent=self) - -class Parser: - - def __init__(self): - self.error = sys.stderr - self.reset() - - def reset(self): - self.val = [] - self.eof = 0 - self.err = 0 - self.line_no = 0 - self.char_no = 0 - self.state = None - - def push_state(self, fn): - self.state = self.state.push(fn) - - def pop_state(self): - val = self.state - self.state = self.state.parent - if self.state and self.state.fn == self.state_start: - # Return to start state - produce the value. - self.val += self.state.val - self.state.val = [] - return val - - def in_class(self, c, s): - return s.find(c) >= 0 - - def in_space_class(self, c): - return self.in_class(c, ' \t\n\v\f\r') - - def is_separator(self, c): - return self.in_class(c, '{}()<>[];') - - def in_comment_class(self, c): - return self.in_class(c, '#') - - def in_string_quote_class(self, c): - return self.in_class(c, '"\'') - - def in_printable_class(self, c): - return self.in_class(c, string.printable) - - def set_error_stream(self, error): - self.error = error - - def has_error(self): - return self.err > 0 - - def at_eof(self): - return self.eof - - def input_eof(self): - self.eof = 1 - self.input_char(-1) - - def input(self, buf): - if not buf or len(buf) == 0: - self.input_eof() - else: - for c in buf: - self.input_char(c) - - def input_char(self, c): - if self.at_eof(): - pass - elif c == '\n': - self.line_no += 1 - self.char_no = 0 - else: - self.char_no += 1 - - if self.state is None: - self.begin_start(None) - self.state.fn(c) - - def ready(self): - return len(self.val) > 0 - - def get_val(self): - v = self.val[0] - self.val = self.val[1:] - return v - - def get_all(self): - return self.val - - def begin_start(self, c): - self.state = ParserState(self.state_start) - - def end_start(self): - self.val += self.state.val - self.pop_state() - - def state_start(self, c): - if self.at_eof(): - self.end_start() - elif self.in_space_class(c): - pass - elif self.in_comment_class(c): - self.begin_comment(c) - elif c == k_list_open: - self.begin_list(c) - elif c == k_list_close: - raise ParseError(self, "syntax error: "+c) - elif self.in_string_quote_class(c): - self.begin_string(c) - elif self.in_printable_class(c): - self.begin_atom(c) - elif c == chr(4): - # ctrl-D, EOT: end-of-text. - self.input_eof() - else: - raise ParseError(self, "invalid character: code %d" % ord(c)) - - def begin_comment(self, c): - self.push_state(self.state_comment) - self.state.buf += c - - def end_comment(self): - self.pop_state() - - def state_comment(self, c): - if c == '\n' or self.at_eof(): - self.end_comment() - else: - self.state.buf += c - - def begin_string(self, c): - self.push_state(self.state_string) - self.state.delim = c - - def end_string(self): - val = self.state.buf - self.state.parent.val.append(val) - self.pop_state() - - def state_string(self, c): - if self.at_eof(): - raise ParseError(self, "unexpected EOF") - elif c == self.state.delim: - self.end_string() - elif c == '\\': - self.push_state(self.state_escape) - else: - self.state.buf += c - - def state_escape(self, c): - if self.at_eof(): - raise ParseError(self, "unexpected EOF") - d = escapes.get(c) - if d: - self.state.parent.buf += d - self.pop_state() - elif c == 'x': - self.state.fn = self.state_hex - self.state.val = 0 - elif c in string.octdigits: - self.state.fn = self.state_octal - self.state.val = 0 - self.input_char(c) - else: - # ignore escape if it doesn't match anything we know - self.state.parent.buf += '\\' - self.pop_state() - - def state_octal(self, c): - def octaldigit(c): - self.state.val *= 8 - self.state.val += ord(c) - ord('0') - self.state.buf += c - if self.state.val < 0 or self.state.val > 0xff: - raise ParseError(self, "invalid octal escape: out of range " + self.state.buf) - if len(self.state.buf) == 3: - octaldone() - - def octaldone(): - d = chr(self.state.val) - self.state.parent.buf += d - self.pop_state() - - if self.at_eof(): - raise ParseError(self, "unexpected EOF") - elif '0' <= c <= '7': - octaldigit(c) - elif len(self.state.buf): - octaldone() - self.input_char(c) - - def state_hex(self, c): - def hexdone(): - d = chr(self.state.val) - self.state.parent.buf += d - self.pop_state() - - def hexdigit(c, d): - self.state.val *= 16 - self.state.val += ord(c) - ord(d) - self.state.buf += c - if self.state.val < 0 or self.state.val > 0xff: - raise ParseError(self, "invalid hex escape: out of range " + self.state.buf) - if len(self.state.buf) == 2: - hexdone() - - if self.at_eof(): - raise ParseError(self, "unexpected EOF") - elif '0' <= c <= '9': - hexdigit(c, '0') - elif 'A' <= c <= 'F': - hexdigit(c, 'A') - elif 'a' <= c <= 'f': - hexdigit(c, 'a') - elif len(buf): - hexdone() - self.input_char(c) - - def begin_atom(self, c): - self.push_state(self.state_atom) - self.state.buf = c - - def end_atom(self): - val = self.state.buf - self.state.parent.val.append(val) - self.pop_state() - - def state_atom(self, c): - if self.at_eof(): - self.end_atom() - elif (self.is_separator(c) or - self.in_space_class(c) or - self.in_comment_class(c)): - self.end_atom() - self.input_char(c) - else: - self.state.buf += c - - def begin_list(self, c): - self.push_state(self.state_list) - - def end_list(self): - val = self.state.val - self.state.parent.val.append(val) - self.pop_state() - - def state_list(self, c): - if self.at_eof(): - raise ParseError(self, "unexpected EOF") - elif c == k_list_close: - self.end_list() - else: - self.state_start(c) - -def atomp(sxpr): - """Check if an sxpr is an atom. - """ - if sxpr == '': - return 0 - if sxpr.isalnum() or sxpr == '@': - return 1 - for c in sxpr: - if c in string.whitespace: return 0 - if c in '"\'\\(){}[]<>$#&%^': return 0 - if c in string.ascii_letters: continue - if c in string.digits: continue - if c in '.-_:/~': continue - return 0 - return 1 - -def show(sxpr, out=sys.stdout): - """Print an sxpr in bracketed (lisp-style) syntax. - """ - if isinstance(sxpr, (types.ListType, types.TupleType)): - out.write(k_list_open) - i = 0 - for x in sxpr: - if i: out.write(' ') - show(x, out) - i += 1 - out.write(k_list_close) - elif isinstance(sxpr, (types.IntType, types.FloatType)): - out.write(str(sxpr)) - elif isinstance(sxpr, types.StringType) and atomp(sxpr): - out.write(sxpr) - else: - out.write(repr(str(sxpr))) - -def show_xml(sxpr, out=sys.stdout): - """Print an sxpr in XML syntax. - """ - if isinstance(sxpr, (types.ListType, types.TupleType)): - element = name(sxpr) - out.write('<%s' % element) - for attr in attributes(sxpr): - out.write(' %s=%s' % (attr[0], attr[1])) - out.write('>') - i = 0 - for x in children(sxpr): - if i: out.write(' ') - show_xml(x, out) - i += 1 - out.write('' % element) - elif isinstance(sxpr, types.StringType) and atomp(sxpr): - out.write(sxpr) - else: - out.write(str(sxpr)) - -def elementp(sxpr, elt=None): - """Check if an sxpr is an element of the given type. - - sxpr sxpr - elt element type - """ - return (isinstance(sxpr, (types.ListType, types.TupleType)) - and len(sxpr) - and (None == elt or sxpr[0] == elt)) - -def name(sxpr): - """Get the element name of an sxpr. - If the sxpr is not an element (i.e. it's an atomic value) its name - is None. - - sxpr - - returns name (None if not an element). - """ - val = None - if isinstance(sxpr, types.StringType): - val = sxpr - elif isinstance(sxpr, (types.ListType, types.TupleType)) and len(sxpr): - val = sxpr[0] - return val - -def attributes(sxpr): - """Get the attribute list of an sxpr. - - sxpr - - returns attribute list - """ - val = [] - if isinstance(sxpr, (types.ListType, types.TupleType)) and len(sxpr) > 1: - attr = sxpr[1] - if elementp(attr, k_attr_open): - val = attr[1:] - return val - -def attribute(sxpr, key, val=None): - """Get an attribute of an sxpr. - - sxpr sxpr - key attribute key - val default value (default None) - - returns attribute value - """ - for x in attributes(sxpr): - if x[0] == key: - val = x[1] - break - return val - -def children(sxpr, elt=None): - """Get children of an sxpr. - - sxpr sxpr - elt optional element type to filter by - - returns children (filtered by elt if specified) - """ - val = [] - if isinstance(sxpr, (types.ListType, types.TupleType)) and len(sxpr) > 1: - i = 1 - x = sxpr[i] - if elementp(x, k_attr_open): - i += 1 - val = sxpr[i : ] - if elt: - def iselt(x): - return elementp(x, elt) - val = filter(iselt, val) - return val - -def child(sxpr, elt, val=None): - """Get the first child of the given element type. - - sxpr sxpr - elt element type - val default value - """ - for x in children(sxpr): - if elementp(x, elt): - val = x - break - return val - -def child_at(sxpr, index, val=None): - """Get the child at the given index (zero-based). - - sxpr sxpr - index index - val default value - """ - kids = children(sxpr) - if len(kids) > index: - val = kids[index] - return val - -def child0(sxpr, val=None): - """Get the zeroth child. - """ - return child_at(sxpr, 0, val) - -def child1(sxpr, val=None): - """Get the first child. - """ - return child_at(sxpr, 1, val) - -def child2(sxpr, val=None): - """Get the second child. - """ - return child_at(sxpr, 2, val) - -def child3(sxpr, val=None): - """Get the third child. - """ - return child_at(sxpr, 3, val) - -def child4(sxpr, val=None): - """Get the fourth child. - """ - return child_at(sxpr, 4, val) - -def child_value(sxpr, elt, val=None): - """Get the value of the first child of the given element type. - Assumes the child has an atomic value. - - sxpr sxpr - elt element type - val default value - """ - kid = child(sxpr, elt) - if kid: - val = child_at(kid, 0, val) - return val - -def has_id(sxpr, id): - """Test if an s-expression has a given id. - """ - return attribute(sxpr, 'id') == id - -def with_id(sxpr, id, val=None): - """Find the first s-expression with a given id, at any depth. - - sxpr s-exp or list - id id - val value if not found (default None) - - return s-exp or val - """ - if isinstance(sxpr, (types.ListType, types.TupleType)): - for n in sxpr: - if has_id(n, id): - val = n - break - v = with_id(n, id) - if v is None: continue - val = v - break - return val - -def child_with_id(sxpr, id, val=None): - """Find the first child with a given id. - - sxpr s-exp or list - id id - val value if not found (default None) - - return s-exp or val - """ - if isinstance(sxpr, (types.ListType, types.TupleType)): - for n in sxpr: - if has_id(n, id): - val = n - break - return val - -def elements(sxpr, ctxt=None): - """Generate elements (at any depth). - Visit elements in pre-order. - Values generated are (node, context) - The context is None if there is no parent, otherwise - (index, parent, context) where index is the node's index w.r.t its parent, - and context is the parent's context. - - sxpr s-exp - - returns generator - """ - yield (sxpr, ctxt) - i = 0 - for n in children(sxpr): - if isinstance(n, (types.ListType, types.TupleType)): - # Calling elements() recursively does not generate recursively, - # it just returns a generator object. So we must iterate over it. - for v in elements(n, (i, sxpr, ctxt)): - yield v - i += 1 - -def merge(s1, s2): - """Merge sxprs s1 and s2. - Returns an sxpr containing all the fields from s1 and s2, with - entries in s1 overriding s2. Recursively merges fields. - - @param s1 sxpr - @param s2 sxpr - @return merged sxpr - """ - if s1 is None: - val = s2 - elif s2 is None: - val = s1 - elif elementp(s1): - name1 = name(s1) - (m1, v1) = child_map(s1) - (m2, v2) = child_map(s2) - val = [name1] - for (k1, f1) in m1.items(): - merge_list(val, f1, m2.get(k1, [])) - for (k2, f2) in m2.items(): - if k2 in m1: continue - val.extend(f2) - val.extend(v1) - else: - val = s1 - return val - -def merge_list(sxpr, l1, l2): - """Merge element lists l1 and l2 into sxpr. - The lists l1 and l2 are all element with the same name. - Values from l1 are merged with values in l2 and stored in sxpr. - If one list is longer than the other the excess values are used - as they are. - - @param sxpr to merge into - @param l1 sxpr list - @param l2 sxpr list - @return modified sxpr - """ - n1 = len(l1) - n2 = len(l2) - nmin = min(n1, n2) - for i in range(0, nmin): - sxpr.append(merge(l1[i], l2[i])) - for i in range(nmin, n1): - sxpr.append(l1[i]) - for i in range(nmin, n2): - sxpr.append(l2[i]) - return sxpr - -def child_map(sxpr): - """Get a dict of the elements in sxpr and a list of its values. - The dict maps element name to the list of elements with that name, - and the list is the non-element children. - - @param sxpr - @return (dict, list) - """ - m = {} - v = [] - for x in children(sxpr): - if elementp(x): - n = name(x) - l = m.get(n, []) - l.append(x) - m[n] = l - else: - v.append(x) - return (m, v) - -def to_string(sxpr): - """Convert an sxpr to a string. - - sxpr sxpr - returns string - """ - io = StringIO() - show(sxpr, io) - io.seek(0) - val = io.getvalue() - io.close() - return val - -def from_string(s): - """Create an sxpr by parsing a string. - - s string - returns sxpr - """ - if s == '': - return [] - - io = StringIO(s) - vals = parse(io) - if vals is []: - return None - else: - return vals[0] - - -def all_from_string(s): - """Create an sxpr list by parsing a string. - - s string - returns sxpr list - """ - io = StringIO(s) - vals = parse(io) - return vals - -def parse(io): - """Completely parse all input from 'io'. - - io input file object - returns list of values, None if incomplete - raises ParseError on parse error - """ - pin = Parser() - while 1: - buf = io.readline() - pin.input(buf) - if len(buf) == 0: - break - if pin.ready(): - val = pin.get_all() - else: - val = None - return val - - -if __name__ == '__main__': - print ">main" - pin = Parser() - while 1: - buf = sys.stdin.read(1024) - #buf = sys.stdin.readline() - pin.input(buf) - while pin.ready(): - val = pin.get_val() - print - print '****** val=', val - if len(buf) == 0: - break - diff --git a/tools/python/xen/xend/tests/__init__.py b/tools/python/xen/xend/tests/__init__.py deleted file mode 100644 index 8d1c8b69c3..0000000000 --- a/tools/python/xen/xend/tests/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tools/python/xen/xend/tests/test_XendConfig.py b/tools/python/xen/xend/tests/test_XendConfig.py deleted file mode 100644 index 472a49eae8..0000000000 --- a/tools/python/xen/xend/tests/test_XendConfig.py +++ /dev/null @@ -1,42 +0,0 @@ -import unittest - -import xen.xend.XendConfig as XendConfig - - -class test_XendConfig(unittest.TestCase): - - def testParseFromSXP(self): - cfg = XendConfig.XendConfig( - sxp_obj = ( - ['vm', - ['bootloader_args', '-q --default_args="root=/dev/sda1 ro" --extra_args="quiet" /images/VM1.sda'], - ['bootloader', '/usr/bin/pygrub'], - ['device', ['vif', ['mac', '00:16:3E:4C:D1:00'], ['script', 'vif-bridge'], ['bridge', 'xenbr0']]], - ['device', ['vif', ['mac', '00:16:3E:48:56:26'], ['script', 'vif-bridge'], ['bridge', 'vbridge0']]], - ['device', ['vbd', ['uname', 'phy:/images/VM1.sda'], ['dev', 'sda'], ['mode', 'w']]], - ['device', ['vbd', ['uname', 'phy:/images/VM1.sdb'], ['dev', 'sdb'], ['mode', 'w']]], - ['memory', '256'], ['name', 'VM1'], ['on_crash', 'restart'], - ['uuid', '10927a76-fe27-49b2-8f57-2970b7bbed6c'], ['vcpus', '1'] - ])) - - self.assertEqual(cfg['uuid'], '10927a76-fe27-49b2-8f57-2970b7bbed6c') - self.assertEqual(cfg['name_label'], 'VM1') - self.assertEqual(cfg['memory_static_max'], 256) - - ordered_refs = cfg.ordered_device_refs() - self.assertEqual(cfg['devices'][ordered_refs[0]][0], 'vbd') - self.assertEqual(cfg['devices'][ordered_refs[1]][0], 'vbd') - self.assertEqual(cfg['devices'][ordered_refs[2]][0], 'vif') - self.assertEqual(cfg['devices'][ordered_refs[3]][0], 'vif') - self.assertEqual(cfg['devices'][ordered_refs[0]][1]['uname'], - 'phy:/images/VM1.sda') - self.assertEqual(cfg['devices'][ordered_refs[1]][1]['uname'], - 'phy:/images/VM1.sdb') - self.assertEqual(cfg['devices'][ordered_refs[2]][1]['mac'], - '00:16:3E:4C:D1:00') - self.assertEqual(cfg['devices'][ordered_refs[3]][1]['mac'], - '00:16:3E:48:56:26') - - -def test_suite(): - return unittest.makeSuite(test_XendConfig) diff --git a/tools/python/xen/xend/tests/test_sxp.py b/tools/python/xen/xend/tests/test_sxp.py deleted file mode 100644 index dab27198f3..0000000000 --- a/tools/python/xen/xend/tests/test_sxp.py +++ /dev/null @@ -1,39 +0,0 @@ -import unittest - -import xen.xend.sxp - - -class test_sxp(unittest.TestCase): - - def testAllFromString(self): - def t(inp, expected): - self.assertEqual(xen.xend.sxp.all_from_string(inp), expected) - - t('String', ['String']) - t('(String Thing)', [['String', 'Thing']]) - t('(String) (Thing)', [['String'], ['Thing']]) - - - def testParseFixed(self): - fin = file('../xen/xend/tests/xend-config.sxp', 'rb') - try: - config = xen.xend.sxp.parse(fin) - self.assertEqual( - xen.xend.sxp.child_value( - config, - 'xend-relocation-hosts-allow'), - '^localhost$ ^localhost\\.localdomain$') - finally: - fin.close() - - - def testParseConfigExample(self): - fin = file('../../examples/xend-config.sxp', 'rb') - try: - config = xen.xend.sxp.parse(fin) - finally: - fin.close() - - -def test_suite(): - return unittest.makeSuite(test_sxp) diff --git a/tools/python/xen/xend/tests/test_uuid.py b/tools/python/xen/xend/tests/test_uuid.py deleted file mode 100644 index d96c9043e1..0000000000 --- a/tools/python/xen/xend/tests/test_uuid.py +++ /dev/null @@ -1,30 +0,0 @@ -import unittest - -from xen.xend import uuid - - -class test_uuid(unittest.TestCase): - - def testStringRoundtrip(self): - def t(inp): - self.assertEqual(uuid.fromString(uuid.toString(inp)), inp) - - t(uuid.create()) - t(uuid.create()) - t(uuid.create()) - t(uuid.create()) - t(uuid.create()) - - - def testToFromString(self): - def t(inp, expected): - self.assertEqual(uuid.toString(inp), expected) - self.assertEqual(uuid.fromString(expected), inp) - - t([0 for _ in range(0, 16)], "00000000-0000-0000-0000-000000000000") - t([185, 158, 125, 206, 250, 178, 125, 57, 2, 6, 162, 74, 178, 236, - 196, 5], "b99e7dce-fab2-7d39-0206-a24ab2ecc405") - - -def test_suite(): - return unittest.makeSuite(test_uuid) diff --git a/tools/python/xen/xend/tests/xend-config.sxp b/tools/python/xen/xend/tests/xend-config.sxp deleted file mode 100644 index 8f9ec5b8e0..0000000000 --- a/tools/python/xen/xend/tests/xend-config.sxp +++ /dev/null @@ -1,131 +0,0 @@ -# -*- sh -*- - -# -# Xend configuration file. -# - -# This example configuration is appropriate for an installation that -# utilizes a bridged network configuration. Access to xend via http -# is disabled. - -# Commented out entries show the default for that entry, unless otherwise -# specified. - -#(logfile /var/log/xend.log) -#(loglevel DEBUG) - -#(xend-http-server no) -#(xend-unix-server no) -#(xend-tcp-xmlrpc-server no) -#(xend-unix-xmlrpc-server yes) -#(xend-relocation-server no) -(xend-relocation-server yes) - -#(xend-unix-path /var/lib/xend/xend-socket) - -# Port xend should use for the HTTP interface, if xend-http-server is set. -#(xend-port 8000) - -# Port xend should use for the relocation interface, if xend-relocation-server -# is set. -#(xend-relocation-port 8002) - -# Address xend should listen on for HTTP connections, if xend-http-server is -# set. -# Specifying 'localhost' prevents remote connections. -# Specifying the empty string '' (the default) allows all connections. -#(xend-address '') -#(xend-address localhost) - -# Address xend should listen on for relocation-socket connections, if -# xend-relocation-server is set. -# Meaning and default as for xend-address above. -#(xend-relocation-address '') - -# The hosts allowed to talk to the relocation port. If this is empty (the -# default), then all connections are allowed (assuming that the connection -# arrives on a port and interface on which we are listening; see -# xend-relocation-port and xend-relocation-address above). Otherwise, this -# should be a space-separated sequence of regular expressions. Any host with -# a fully-qualified domain name or an IP address that matches one of these -# regular expressions will be accepted. -# -# For example: -# (xend-relocation-hosts-allow '^localhost$ ^.*\\.example\\.org$') -# -#(xend-relocation-hosts-allow '') -(xend-relocation-hosts-allow '^localhost$ ^localhost\\.localdomain$') - -# The limit (in kilobytes) on the size of the console buffer -#(console-limit 1024) - -## -# To bridge network traffic, like this: -# -# -# dom0: ----------------- bridge -> real eth0 -> the network -# | -# domU: fake eth0 -> vifN.0 -+ -# -# use -# -# (network-script network-bridge) -# -# Your default ethernet device is used as the outgoing interface, by default. -# To use a different one (e.g. eth1) use -# -# (network-script 'network-bridge netdev=eth1') -# -# The bridge is named xenbr0, by default. To rename the bridge, use -# -# (network-script 'network-bridge bridge=') -# -# It is possible to use the network-bridge script in more complicated -# scenarios, such as having two outgoing interfaces, with two bridges, and -# two fake interfaces per guest domain. To do things like this, write -# yourself a wrapper script, and call network-bridge from it, as appropriate. -# -(network-script network-bridge) - -# The script used to control virtual interfaces. This can be overridden on a -# per-vif basis when creating a domain or a configuring a new vif. The -# vif-bridge script is designed for use with the network-bridge script, or -# similar configurations. -# -# If you have overridden the bridge name using -# (network-script 'network-bridge bridge=') then you may wish to do the -# same here. The bridge name can also be set when creating a domain or -# configuring a new vif, but a value specified here would act as a default. -# -# If you are using only one bridge, the vif-bridge script will discover that, -# so there is no need to specify it explicitly. -# -(vif-script vif-bridge) - - -## Use the following if network traffic is routed, as an alternative to the -# settings for bridged networking given above. -#(network-script network-route) -#(vif-script vif-route) - - -## Use the following if network traffic is routed with NAT, as an alternative -# to the settings for bridged networking given above. -#(network-script network-nat) -#(vif-script vif-nat) - - -# Dom0 will balloon out when needed to free memory for domU. -# dom0-min-mem is the lowest memory level (in MB) dom0 will get down to. -# If dom0-min-mem=0, dom0 will never balloon out. -(dom0-min-mem 196) - -# In SMP system, dom0 will use dom0-cpus # of CPUS -# If dom0-cpus = 0, dom0 will take all cpus available -(dom0-cpus 0) - -# Whether to enable core-dumps when domains crash. -#(enable-dump no) - -# The tool used for initiating virtual device migration -#(external-migration-tool '') diff --git a/tools/python/xen/xend/uuid.py b/tools/python/xen/xend/uuid.py deleted file mode 100644 index 7fe52cb335..0000000000 --- a/tools/python/xen/xend/uuid.py +++ /dev/null @@ -1,69 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2005 Mike Wray -# Copyright (C) 2005 XenSource Ltd -#============================================================================ - - -"""Universal Unique Identifiers (UUIDs). By default, UUIDs generated here are -purely random, with no internal structure. However, they are the same size, -and are formatted by the same conventions, as the UUIDs in the Open Software -Foundation's Distributed Computing Environment (OSF DCE). This allows Xend to -be used with UUIDs generated as per the DCE specification, should that be -required. These UUIDs are also, by no coincidence, the same size as the -'handle' stored by the Xen hypervisor along with the domain structure.""" - - -import commands -import random - - -def getUuidUuidgen(randomly = True): - """Generate a UUID using the command uuidgen. - - If randomly is true (default) generates a random uuid. - If randomly is false generates a time-based uuid. - """ - cmd = "uuidgen" - if randomly: - cmd += " -r" - else: - cmd += " -t" - return fromString(commands.getoutput(cmd)) - - -def getUuidRandom(): - """Generate a random UUID.""" - - return [ random.randint(0, 255) for _ in range(0, 16) ] - - -#uuidFactory = getUuidUuidgen -uuidFactory = getUuidRandom - - -def toString(u): - return "-".join(["%02x" * 4, "%02x" * 2, "%02x" * 2, "%02x" * 2, - "%02x" * 6]) % tuple(u) - -def fromString(s): - s = s.replace('-', '') - return [ int(s[i : i + 2], 16) for i in range(0, 32, 2) ] - -def create(): - return uuidFactory() - -def createString(): - return toString(create()) diff --git a/tools/python/xen/xend/xend b/tools/python/xen/xend/xend deleted file mode 100644 index 9ef021054c..0000000000 --- a/tools/python/xen/xend/xend +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/env python -# -*- mode: python; -*- -#============================================================================ -# Copyright (C) 2004 Mike Wray -# Copyright (C) 2005-2006 XenSource Inc -#============================================================================ - -"""Xen management daemon. - Provides console server and HTTP management api. - - Run: - xend start - - Restart: - xend restart - - The daemon is stopped with: - xend stop - - The daemon should reconnect to device control interfaces - and recover its state when restarted. - - On Solaris, the daemons are SMF managed, and you should not attempt - to start xend by hand. -""" -import fcntl -import glob -import os -import os.path -import sys -import socket -import signal -import time -import commands - -from xen.xend.server import SrvDaemon - -class CheckError(ValueError): - pass - -def hline(): - print >>sys.stderr, "*" * 70 - -def msg(message): - print >>sys.stderr, "*" * 3, message - -def check_logging(): - """Check python logging is installed and raise an error if not. - Logging is standard from Python 2.3 on. - """ - try: - import logging - except ImportError: - hline() - msg("Python logging is not installed.") - msg("Use 'make install-logging' at the xen root to install.") - msg("") - msg("Alternatively download and install from") - msg("http://www.red-dove.com/python_logging.html") - hline() - raise CheckError("logging is not installed") - -def check_user(): - """Check that the effective user id is 0 (root). - """ - if os.geteuid() != 0: - hline() - msg("Xend must be run as root.") - hline() - raise CheckError("invalid user") - -def start_daemon(daemon, *args): - if os.fork() == 0: - os.execvp(daemon, (daemon,) + args) - -def start_blktapctrl(): - start_daemon("blktapctrl", "") - -def main(): - try: - check_logging() - check_user() - except CheckError: - sys.exit(1) - - daemon = SrvDaemon.instance() - if not sys.argv[1:]: - print 'usage: %s {start|stop|reload|restart}' % sys.argv[0] - elif sys.argv[1] == 'start': - if os.uname()[0] != "SunOS": - start_blktapctrl() - return daemon.start() - elif sys.argv[1] == 'trace_start': - start_blktapctrl() - return daemon.start(trace=1) - elif sys.argv[1] == 'stop': - return daemon.stop() - elif sys.argv[1] == 'reload': - return daemon.reloadConfig() - elif sys.argv[1] == 'restart': - start_blktapctrl() - return daemon.stop() or daemon.start() - elif sys.argv[1] == 'status': - return daemon.status() - else: - print 'not an option:', sys.argv[1] - return 1 - -if __name__ == '__main__': - sys.exit(main()) diff --git a/tools/python/xen/xend/xenstore/__init__.py b/tools/python/xen/xend/xenstore/__init__.py deleted file mode 100644 index fb12065059..0000000000 --- a/tools/python/xen/xend/xenstore/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2005 Mike Wray -#============================================================================ diff --git a/tools/python/xen/xend/xenstore/tests/__init__.py b/tools/python/xen/xend/xenstore/tests/__init__.py deleted file mode 100644 index 139597f9cb..0000000000 --- a/tools/python/xen/xend/xenstore/tests/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/tools/python/xen/xend/xenstore/tests/stress_xs.py b/tools/python/xen/xend/xenstore/tests/stress_xs.py deleted file mode 100644 index 647eb8bdd7..0000000000 --- a/tools/python/xen/xend/xenstore/tests/stress_xs.py +++ /dev/null @@ -1,121 +0,0 @@ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# Copyright (c) 2005 XenSource Ltd - - -import random -import sys -import threading -import time - -import xen.lowlevel.xs - -from xen.xend.xenstore import xsutil -from xen.xend.xenstore.xstransact import xstransact -from xen.xend.xenstore.xswatch import xswatch - - -PATH = '/tool/stress_xs' - - -def stress(): - xstransact.Remove(PATH) - xstransact.Mkdir(PATH) - - xswatch(PATH, watch_callback) - - def do(f): - t = threading.Thread(target=stress_write) - t.setDaemon(True) - t.start() - - do(stress_write) - do(stress_get_domain_path) - do(stress_get_domain_path_xsutil) - do(stress_open_close) - - while True: - # Wait for Ctrl-C. - time.sleep(100000000) - - -def stress_write(): - xstransact.Write(PATH, 'key', '1') - while True: - val = xstransact.Gather(PATH, ('key', int)) - xstransact.Store(PATH, ('key', val + 1)) - - random_sleep() - - -def stress_get_domain_path(): - xs_handle = xen.lowlevel.xs.xs() - - domid = 0 - while True: - xs_handle.get_domain_path(domid) - domid += 1 - - random_sleep() - - -def stress_get_domain_path_xsutil(): - domid = 0 - while True: - xsutil.GetDomainPath(domid) - domid += 1 - - random_sleep() - - -def stress_open_close(): - while True: - xs_handle = xen.lowlevel.xs.xs() - - try: - try: - trans = xs_handle.transaction_start() - val = int(xs_handle.read(trans, PATH + '/key')) - xs_handle.write(trans, PATH + '/key', str(val + 1)) - xs_handle.transaction_end(trans, False) - except: - xs_handle.transaction_end(trans, True) - - random_sleep() - finally: - del xs_handle - - -def watch_callback(path): - random_sleep() - return True - - -def random_sleep(): - d = random.randint(-50000, 500) - if d > 0: - time.sleep(d / 1000.0) - - -def main(argv = None): - if argv is None: - argv = sys.argv - - stress() - - return 0 - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/tools/python/xen/xend/xenstore/xstransact.py b/tools/python/xen/xend/xenstore/xstransact.py deleted file mode 100644 index af07298067..0000000000 --- a/tools/python/xen/xend/xenstore/xstransact.py +++ /dev/null @@ -1,368 +0,0 @@ -# Copyright (C) 2005 Christian Limpach -# Copyright (C) 2005 XenSource Ltd - -# This file is subject to the terms and conditions of the GNU General -# Public License. See the file "COPYING" in the main directory of -# this archive for more details. - -from xen.xend.xenstore.xsutil import xshandle - -class xstransact: - """WARNING: Be very careful if you're instantiating an xstransact object - yourself (i.e. not using the capitalized static helpers like .Read(). - It is essential that you clean up the object in place via - t.commit/abort(): GC can happen at any time, including contexts where - it's not safe to to use the shared xenstore socket fd. In particular, - if xend forks, and GC occurs, we can have two processes trying to - use the same xenstore fd, and all hell breaks loose. - """ - - - def __init__(self, path = ""): - - self.in_transaction = False # Set this temporarily -- if this - # constructor fails, then we need to - # protect __del__. - - assert path is not None - self.path = path.rstrip("/") - self.transaction = xshandle().transaction_start() - self.in_transaction = True - - def __del__(self): - # see above. - if self.in_transaction: - raise RuntimeError("ERROR: GC of live transaction") - - def commit(self): - if not self.in_transaction: - raise RuntimeError - self.in_transaction = False - rc = xshandle().transaction_end(self.transaction, False) - self.transaction = "0" - return rc - - def abort(self): - if not self.in_transaction: - return True - self.in_transaction = False - rc = xshandle().transaction_end(self.transaction, True) - self.transaction = "0" - return rc - - def _read(self, key): - path = self.prependPath(key) - try: - return xshandle().read(self.transaction, path) - except RuntimeError, ex: - raise RuntimeError(ex.args[0], - '%s, while reading %s' % (ex.args[1], path)) - - def read(self, *args): - """If no arguments are given, return the value at this transaction's - path. If one argument is given, treat that argument as a subpath to - this transaction's path, and return the value at that path. - Otherwise, treat each argument as a subpath to this transaction's - path, and return a list composed of the values at each of those - instead. - """ - if len(args) == 0: - return xshandle().read(self.transaction, self.path) - if len(args) == 1: - return self._read(args[0]) - ret = [] - for key in args: - ret.append(self._read(key)) - return ret - - def _write(self, key, data): - path = self.prependPath(key) - try: - xshandle().write(self.transaction, path, data) - except RuntimeError, ex: - raise RuntimeError(ex.args[0], - ('%s, while writing %s : %s' % - (ex.args[1], path, str(data)))) - - def write(self, *args): - if len(args) == 0: - raise TypeError - if isinstance(args[0], dict): - for d in args: - if not isinstance(d, dict): - raise TypeError - for key in d.keys(): - try: - self._write(key, d[key]) - except TypeError, msg: - raise TypeError('Writing %s: %s: %s' % - (key, str(d[key]), msg)) - elif isinstance(args[0], list): - for l in args: - if not len(l) == 2: - raise TypeError - self._write(l[0], l[1]) - elif len(args) % 2 == 0: - for i in range(len(args) / 2): - self._write(args[i * 2], args[i * 2 + 1]) - else: - raise TypeError - - def _remove(self, key): - path = self.prependPath(key) - return xshandle().rm(self.transaction, path) - - def remove(self, *args): - """If no arguments are given, remove this transaction's path. - Otherwise, treat each argument as a subpath to this transaction's - path, and remove each of those instead. - """ - if len(args) == 0: - xshandle().rm(self.transaction, self.path) - else: - for key in args: - self._remove(key) - - def _list(self, key): - path = self.prependPath(key) - l = xshandle().ls(self.transaction, path) - if l: - return map(lambda x: key + "/" + x, l) - return [] - - def list(self, *args): - """If no arguments are given, list this transaction's path, returning - the entries therein, or the empty list if no entries are found. - Otherwise, treat each argument as a subpath to this transaction's - path, and return the cumulative listing of each of those instead. - """ - if len(args) == 0: - ret = xshandle().ls(self.transaction, self.path) - if ret is None: - return [] - else: - return ret - else: - ret = [] - for key in args: - ret.extend(self._list(key)) - return ret - - - def list_recursive_(self, subdir, keys): - ret = [] - for key in keys: - new_subdir = subdir + "/" + key - l = xshandle().ls(self.transaction, new_subdir) - if l: - ret.append([key, self.list_recursive_(new_subdir, l)]) - else: - ret.append([key, xshandle().read(self.transaction, new_subdir)]) - return ret - - - def list_recursive(self, *args): - """If no arguments are given, list this transaction's path, returning - the entries therein, or the empty list if no entries are found. - Otherwise, treat each argument as a subpath to this transaction's - path, and return the cumulative listing of each of those instead. - """ - if len(args) == 0: - args = self.list() - if args is None or len(args) == 0: - return [] - - return self.list_recursive_(self.path, args) - - - def gather(self, *args): - if len(args) and type(args[0]) != tuple: - args = args, - ret = [] - for tup in args: - if len(tup) == 2: - (key, fn) = tup - defval = None - else: - (key, fn, defval) = tup - - val = self._read(key) - # If fn is str, then this will successfully convert None to 'None' - # (which we don't want). If it is int or float, then it will - # throw ValueError on any non-convertible value. We check - # explicitly for None, using defval instead, but allow ValueError - # to propagate. - if val is None: - val = defval - else: - val = fn(val) - ret.append(val) - if len(ret) == 1: - return ret[0] - return ret - - def store(self, *args): - if len(args) and type(args[0]) != tuple: - args = args, - for tup in args: - if len(tup) == 2: - (key, val) = tup - try: - fmt = { str : "%s", - int : "%i", - float : "%f", - long : "%li", - type(None) : None }[type(val)] - except KeyError: - raise TypeError - else: - (key, val, fmt) = tup - if val is None: - self._remove(key) - else: - self._write(key, fmt % val) - - - def mkdir(self, *args): - if len(args) == 0: - xshandle().mkdir(self.transaction, self.path) - else: - for key in args: - xshandle().mkdir(self.transaction, self.prependPath(key)) - - - def get_permissions(self, *args): - """If no arguments are given, return the permissions at this - transaction's path. If one argument is given, treat that argument as - a subpath to this transaction's path, and return the permissions at - that path. Otherwise, treat each argument as a subpath to this - transaction's path, and return a list composed of the permissions at - each of those instead. - """ - if len(args) == 0: - return xshandle().get_permissions(self.transaction, self.path) - if len(args) == 1: - return self._get_permissions(args[0]) - ret = [] - for key in args: - ret.append(self._get_permissions(key)) - return ret - - - def _get_permissions(self, key): - path = self.prependPath(key) - try: - return xshandle().get_permissions(self.transaction, path) - except RuntimeError, ex: - raise RuntimeError(ex.args[0], - '%s, while getting permissions from %s' % - (ex.args[1], path)) - - - def set_permissions(self, *args): - if len(args) == 0: - raise TypeError - elif isinstance(args[0], str): - self.callRebased(args[0], self.set_permissions, *args[1:]) - else: - if not self.path: - raise RuntimeError('Cannot set permissions on the root') - - xshandle().set_permissions(self.transaction, self.path, - list(args)) - - - def remove2(self, middlePath, *args): - self.callRebased(middlePath, self.remove, *args) - - - def write2(self, middlePath, *args): - self.callRebased(middlePath, self.write, *args) - - - def callRebased(self, middlePath, func, *args): - oldpath = self.path - self.path = self.prependPath(middlePath) - try: - func(*args) - finally: - self.path = oldpath - - - def prependPath(self, key): - if self.path: - return self.path + '/' + key - else: - return key - - - def Read(cls, path, *args): - """If only one argument is given (path), return the value stored at - that path. If two arguments are given, treat the second argument as a - subpath within the first, and return the value at the composed path. - Otherwise, treat each argument after the first as a subpath to the - given path, and return a list composed of the values at each of those - instead. This operation is performed inside a transaction. - """ - return complete(path, lambda t: t.read(*args)) - Read = classmethod(Read) - - def Write(cls, path, *args): - complete(path, lambda t: t.write(*args)) - Write = classmethod(Write) - - def Remove(cls, path, *args): - """If only one argument is given (path), remove it. Otherwise, treat - each further argument as a subpath to the given path, and remove each - of those instead. This operation is performed inside a transaction. - """ - complete(path, lambda t: t.remove(*args)) - Remove = classmethod(Remove) - - def List(cls, path, *args): - """If only one argument is given (path), list its contents, returning - the entries therein, or the empty list if no entries are found. - Otherwise, treat each further argument as a subpath to the given path, - and return the cumulative listing of each of those instead. This - operation is performed inside a transaction. - """ - return complete(path, lambda t: t.list(*args)) - List = classmethod(List) - - def ListRecursive(cls, path, *args): - """If only one argument is given (path), list its contents - recursively, returning the entries therein, or the empty list if no - entries are found. Otherwise, treat each further argument as a - subpath to the given path, and return the cumulative listing of each - of those instead. This operation is performed inside a transaction. - """ - return complete(path, lambda t: t.list_recursive(*args)) - ListRecursive = classmethod(ListRecursive) - - def Gather(cls, path, *args): - return complete(path, lambda t: t.gather(*args)) - Gather = classmethod(Gather) - - def Store(cls, path, *args): - complete(path, lambda t: t.store(*args)) - Store = classmethod(Store) - - def SetPermissions(cls, path, *args): - complete(path, lambda t: t.set_permissions(*args)) - SetPermissions = classmethod(SetPermissions) - - def Mkdir(cls, path, *args): - complete(path, lambda t: t.mkdir(*args)) - Mkdir = classmethod(Mkdir) - - -def complete(path, f): - while True: - t = xstransact(path) - try: - result = f(t) - if t.commit(): - return result - except: - t.abort() - raise diff --git a/tools/python/xen/xend/xenstore/xsutil.py b/tools/python/xen/xend/xenstore/xsutil.py deleted file mode 100644 index b1bf69daf5..0000000000 --- a/tools/python/xen/xend/xenstore/xsutil.py +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (C) 2005 Christian Limpach - -# This file is subject to the terms and conditions of the GNU General -# Public License. See the file "COPYING" in the main directory of -# this archive for more details. - -import threading -import xen.lowlevel.xs - -xs_lock = threading.Lock() -xs_handle = None - -def xshandle(): - global xs_handle, xs_lock - if not xs_handle: - xs_lock.acquire() - if not xs_handle: - xs_handle = xen.lowlevel.xs.xs() - xs_lock.release() - return xs_handle - -def IntroduceDomain(domid, page, port): - return xshandle().introduce_domain(domid, page, port) - -def SetTarget(domid, target): - return xshandle().set_target(domid, target) - -def GetDomainPath(domid): - return xshandle().get_domain_path(domid) - -def ResumeDomain(domid): - return xshandle().resume_domain(domid) diff --git a/tools/python/xen/xend/xenstore/xswatch.py b/tools/python/xen/xend/xenstore/xswatch.py deleted file mode 100644 index 04651686fd..0000000000 --- a/tools/python/xen/xend/xenstore/xswatch.py +++ /dev/null @@ -1,80 +0,0 @@ -# Copyright (C) 2005 Christian Limpach -# Copyright (C) 2005 XenSource Ltd - -# This file is subject to the terms and conditions of the GNU General -# Public License. See the file "COPYING" in the main directory of -# this archive for more details. - -import errno -import threading -from xen.xend.xenstore.xsutil import xshandle - - -class xswatch: - - ## - # Create a watch on the given path in the store. The watch will fire - # immediately, then subsequently each time the watched path is changed, - # until the watch is deregistered, either by the return value from the - # watch callback being False, or by an explicit call to unwatch. - # - # @param fn The function to be called when the watch fires. This function - # should take the path that has changed as its first argument, followed by - # the extra arguments given to this constructor, if any. It should return - # True if the watch is to remain registered, or False if it is to be - # deregistered. - # - def __init__(self, path, fn, *args, **kwargs): - self.path = path - self.fn = fn - self.args = args - self.kwargs = kwargs - watchStart() - xs.watch(path, self) - - - def unwatch(self): - xs.unwatch(self.path, self) - - -watchThread = None -xs = None -xslock = threading.Lock() - -def watchStart(): - global watchThread - global xs - - xslock.acquire() - try: - if watchThread: - return - xs = xshandle() - watchThread = threading.Thread(name="Watcher", target=watchMain) - watchThread.setDaemon(True) - watchThread.start() - finally: - xslock.release() - - -def watchMain(): - while True: - try: - we = xs.read_watch() - watch = we[1] - res = watch.fn(we[0], *watch.args, **watch.kwargs) - if not res: - try: - watch.unwatch() - except RuntimeError, exn: - if exn.args[0] == errno.ENOENT: - # The watch has already been unregistered -- that's - # fine. - pass - else: - raise - except: - pass - # Ignore this exception -- there's no point throwing it - # further on because that will just kill the watcher thread, - # which achieves nothing. diff --git a/tools/python/xen/xm/XenAPI.py b/tools/python/xen/xm/XenAPI.py deleted file mode 100644 index f459cec602..0000000000 --- a/tools/python/xen/xm/XenAPI.py +++ /dev/null @@ -1,206 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2006-2007 XenSource Inc. -#============================================================================ -# -# Parts of this file are based upon xmlrpclib.py, the XML-RPC client -# interface included in the Python distribution. -# -# Copyright (c) 1999-2002 by Secret Labs AB -# Copyright (c) 1999-2002 by Fredrik Lundh -# -# By obtaining, using, and/or copying this software and/or its -# associated documentation, you agree that you have read, understood, -# and will comply with the following terms and conditions: -# -# Permission to use, copy, modify, and distribute this software and -# its associated documentation for any purpose and without fee is -# hereby granted, provided that the above copyright notice appears in -# all copies, and that both that copyright notice and this permission -# notice appear in supporting documentation, and that the name of -# Secret Labs AB or the author not be used in advertising or publicity -# pertaining to distribution of the software without specific, written -# prior permission. -# -# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD -# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- -# ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR -# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY -# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS -# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE -# OF THIS SOFTWARE. -# -------------------------------------------------------------------- - -import xmlrpclib - -import xen.util.xmlrpcclient as xmlrpcclient - -errormap = { - "INTERNAL_ERROR": "Internal error: %(1)s.", - "MAP_DUPLICATE_KEY": "This map already contains %(1)s -> %(2)s.", - "MESSAGE_METHOD_UNKNOWN": "The method %(1)s is unsupported.", - "MESSAGE_PARAMETER_COUNT_MISMATCH": "The method %(1)s takes %(2)s argument(s) (%(3)s given).", - "SESSION_AUTHENTICATION_FAILED": "Permission denied.", - "VALUE_NOT_SUPPORTED": "Value \"%(2)s\" for %(1)s is not supported by this server. The server said \"%(3)s\".", - "HANDLE_INVALID": "The %(1)s handle %(2)s is invalid.", - "OPERATION_NOT_ALLOWED": "You attempted an operation that was not allowed.", - "NETWORK_ALREADY_CONNECTED": "The network you specified already has a PIF attached to it, and so another one may not be attached.", - "SECURITY_ERROR": "%(2)s", - } - -class Failure(Exception): - def __init__(self, details): - try: - # If this failure is MESSAGE_PARAMETER_COUNT_MISMATCH, then we - # correct the return values here, to account for the fact that we - # transparently add the session handle as the first argument. - if details[0] == 'MESSAGE_PARAMETER_COUNT_MISMATCH': - details[2] = str(int(details[2]) - 1) - details[3] = str(int(details[3]) - 1) - - self.details = details - except Exception, exn: - self.details = ['INTERNAL_ERROR', 'Client-side: ' + str(exn)] - - def __str__(self): - try: - return errormap[self.details[0]] % self._details_map() - except TypeError, exn: - return "Message database broken: %s.\nXen-API failure: %s" % \ - (exn, str(self.details)) - except Exception, exn: - import sys - print >>sys.stderr, exn - return "Xen-API failure: %s" % str(self.details) - - def _details_map(self): - return dict([(str(i), self.details[i]) - for i in range(len(self.details))]) - - -_RECONNECT_AND_RETRY = (lambda _ : ()) - - -class Session(xmlrpcclient.ServerProxy): - """A server proxy and session manager for communicating with Xend using - the Xen-API. - - Example: - - session = Session('http://localhost:9363/') - session.login_with_password('me', 'mypassword') - session.xenapi.VM.start(vm_uuid) - session.xenapi.session.logout() - - For now, this class also supports the legacy XML-RPC API, using - session.xend.domain('Domain-0') and similar. This support will disappear - once there is a working Xen-API replacement for every call in the legacy - API. - """ - - def __init__(self, uri, transport=None, encoding=None, verbose=0, - allow_none=1): - xmlrpcclient.ServerProxy.__init__(self, uri, transport, encoding, - verbose, allow_none) - self._session = None - self.last_login_method = None - self.last_login_params = None - - - def getSession(self): - return self._session - - def xenapi_request(self, methodname, params): - if methodname.startswith('login'): - self._login(methodname, params) - return None - else: - retry_count = 0 - while retry_count < 3: - full_params = (self._session,) + params - result = _parse_result(getattr(self, methodname)(*full_params)) - if result == _RECONNECT_AND_RETRY: - retry_count += 1 - if self.last_login_method: - self._login(self.last_login_method, - self.last_login_params) - else: - raise xmlrpclib.Fault(401, 'You must log in') - else: - return result - raise xmlrpclib.Fault( - 500, 'Tried 3 times to get a valid session, but failed') - - - def _login(self, method, params): - result = _parse_result(getattr(self, 'session.%s' % method)(*params)) - if result == _RECONNECT_AND_RETRY: - raise xmlrpclib.Fault( - 500, 'Received SESSION_INVALID when logging in') - self._session = result - self.last_login_method = method - self.last_login_params = params - - - def __getattr__(self, name): - if name == 'xenapi': - return _Dispatcher(self.xenapi_request, None) - elif name.startswith('login'): - return lambda *params: self._login(name, params) - else: - return xmlrpcclient.ServerProxy.__getattr__(self, name) - - -def _parse_result(result): - if type(result) != dict or 'Status' not in result: - raise xmlrpclib.Fault(500, 'Missing Status in response from server: ' + str(result)) - if result['Status'] == 'Success': - if 'Value' in result: - return result['Value'] - else: - raise xmlrpclib.Fault(500, - 'Missing Value in response from server') - else: - if 'ErrorDescription' in result: - if result['ErrorDescription'][0] == 'SESSION_INVALID': - return _RECONNECT_AND_RETRY - else: - raise Failure(result['ErrorDescription']) - else: - raise xmlrpclib.Fault( - 500, 'Missing ErrorDescription in response from server') - - -# Based upon _Method from xmlrpclib. -class _Dispatcher: - def __init__(self, send, name): - self.__send = send - self.__name = name - - def __repr__(self): - if self.__name: - return '' % self.__name - else: - return '' - - def __getattr__(self, name): - if self.__name is None: - return _Dispatcher(self.__send, name) - else: - return _Dispatcher(self.__send, "%s.%s" % (self.__name, name)) - - def __call__(self, *args): - return self.__send(self.__name, args) diff --git a/tools/python/xen/xm/__init__.py b/tools/python/xen/xm/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tools/python/xen/xm/addlabel.py b/tools/python/xen/xm/addlabel.py deleted file mode 100644 index 45fde491c2..0000000000 --- a/tools/python/xen/xm/addlabel.py +++ /dev/null @@ -1,274 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2006 International Business Machines Corp. -# Author: Reiner Sailer -# Author: Bryan D. Payne -#============================================================================ - -"""Labeling a domain configuration file or a resource. -""" -import os -import sys - -import xen.util.xsm.xsm as security -from xen.xm.opts import OptionError -from xen.util import xsconstants, auxbin -from xen.xm import main as xm_main -from xen.xm.main import server - -def help(): - return """ - Format: xm addlabel