ia64/xen-unstable

changeset 1595:3d3f21585b96

bitkeeper revision 1.1023 (40dfd4c063gTkLqyHluwXpqo4MI7Zw)

Merge http://xen.bkbits.net:8080/xeno-unstable.bk
into gandalf.hpl.hp.com:/var/bk/xeno-unstable.bk
author xenbk@gandalf.hpl.hp.com
date Mon Jun 28 08:20:16 2004 +0000 (2004-06-28)
parents 5b1f0d05d6ca c8e677f40f9d
children 48a1cf52dfaf c5d25124f417
files .rootkeys extras/mini-os/h/hypervisor.h linux-2.4.26-xen-sparse/mkbuildtree tools/Makefile tools/examples/xc_physinfo.py tools/examples/xm_dom_control.py tools/examples/xmdefaults tools/examples/xmnetbsd tools/misc/Makefile tools/xc/lib/Makefile tools/xc/py/Xc.c tools/xc/py/setup.py tools/xen/Makefile tools/xen/lib/__init__.py tools/xen/lib/ext/__init__.py tools/xen/lib/util/__init__.py tools/xen/lib/util/console_client.py tools/xen/lib/util/ip.py tools/xen/lib/util/tempfile.py tools/xen/lib/xend/Args.py tools/xen/lib/xend/EventServer.py tools/xen/lib/xend/EventTypes.py tools/xen/lib/xend/PrettyPrint.py tools/xen/lib/xend/XendBridge.py tools/xen/lib/xend/XendClient.py tools/xen/lib/xend/XendConsole.py tools/xen/lib/xend/XendDB.py tools/xen/lib/xend/XendDomain.py tools/xen/lib/xend/XendDomainConfig.py tools/xen/lib/xend/XendDomainInfo.py tools/xen/lib/xend/XendMigrate.py tools/xen/lib/xend/XendNode.py tools/xen/lib/xend/XendRoot.py tools/xen/lib/xend/XendVnet.py tools/xen/lib/xend/__init__.py tools/xen/lib/xend/encode.py tools/xen/lib/xend/server/SrvBase.py tools/xen/lib/xend/server/SrvConsole.py tools/xen/lib/xend/server/SrvConsoleDir.py tools/xen/lib/xend/server/SrvDaemon.py tools/xen/lib/xend/server/SrvDeviceDir.py tools/xen/lib/xend/server/SrvDir.py tools/xen/lib/xend/server/SrvDomain.py tools/xen/lib/xend/server/SrvDomainDir.py tools/xen/lib/xend/server/SrvEventDir.py tools/xen/lib/xend/server/SrvNode.py tools/xen/lib/xend/server/SrvRoot.py tools/xen/lib/xend/server/SrvServer.py tools/xen/lib/xend/server/SrvVnetDir.py tools/xen/lib/xend/server/__init__.py tools/xen/lib/xend/server/blkif.py tools/xen/lib/xend/server/channel.py tools/xen/lib/xend/server/console.py tools/xen/lib/xend/server/controller.py tools/xen/lib/xend/server/cstruct.py tools/xen/lib/xend/server/domain.py tools/xen/lib/xend/server/messages.py tools/xen/lib/xend/server/netif.py tools/xen/lib/xend/server/params.py tools/xen/lib/xend/sxp.py tools/xen/lib/xm/__init__.py tools/xen/lib/xm/create.py tools/xen/lib/xm/main.py tools/xen/lib/xm/opts.py tools/xen/lib/xm/shutdown.py tools/xen/netfix tools/xen/setup.py tools/xen/xend tools/xen/xm tools/xenctl/Makefile tools/xenctl/lib/__init__.py tools/xenctl/lib/console_client.py tools/xenctl/lib/ip.py tools/xenctl/lib/tempfile.py tools/xenctl/lib/utils.py tools/xenctl/setup.py tools/xend-old/Makefile tools/xend-old/lib/__init__.py tools/xend-old/lib/blkif.py tools/xend-old/lib/console.py tools/xend-old/lib/domain_controller.h tools/xend-old/lib/main.py tools/xend-old/lib/manager.py tools/xend-old/lib/netif.py tools/xend-old/lib/utils.c tools/xend-old/setup.py tools/xend-old/xend tools/xend/Makefile tools/xend/lib/__init__.py tools/xend/lib/blkif.py tools/xend/lib/console.py tools/xend/lib/domain_controller.h tools/xend/lib/main.py tools/xend/lib/manager.py tools/xend/lib/netif.py tools/xend/lib/utils.c tools/xend/setup.py tools/xend/xend tools/xenmgr/Makefile tools/xenmgr/lib/Args.py tools/xenmgr/lib/EventServer.py tools/xenmgr/lib/EventTypes.py tools/xenmgr/lib/PrettyPrint.py tools/xenmgr/lib/XendBridge.py tools/xenmgr/lib/XendClient.py tools/xenmgr/lib/XendConsole.py tools/xenmgr/lib/XendDB.py tools/xenmgr/lib/XendDomain.py tools/xenmgr/lib/XendDomainConfig.py tools/xenmgr/lib/XendDomainInfo.py tools/xenmgr/lib/XendMigrate.py tools/xenmgr/lib/XendNode.py tools/xenmgr/lib/XendRoot.py tools/xenmgr/lib/XendVnet.py tools/xenmgr/lib/__init__.py tools/xenmgr/lib/encode.py tools/xenmgr/lib/server/SrvBase.py tools/xenmgr/lib/server/SrvConsole.py tools/xenmgr/lib/server/SrvConsoleDir.py tools/xenmgr/lib/server/SrvConsoleServer.py tools/xenmgr/lib/server/SrvDeviceDir.py tools/xenmgr/lib/server/SrvDir.py tools/xenmgr/lib/server/SrvDomain.py tools/xenmgr/lib/server/SrvDomainDir.py tools/xenmgr/lib/server/SrvEventDir.py tools/xenmgr/lib/server/SrvNode.py tools/xenmgr/lib/server/SrvRoot.py tools/xenmgr/lib/server/SrvServer.py tools/xenmgr/lib/server/SrvVnetDir.py tools/xenmgr/lib/server/__init__.py tools/xenmgr/lib/server/blkif.py tools/xenmgr/lib/server/channel.py tools/xenmgr/lib/server/console.py tools/xenmgr/lib/server/controller.py tools/xenmgr/lib/server/cstruct.py tools/xenmgr/lib/server/domain.py tools/xenmgr/lib/server/messages.py tools/xenmgr/lib/server/netif.py tools/xenmgr/lib/server/params.py tools/xenmgr/lib/sxp.py tools/xenmgr/lib/xm/__init__.py tools/xenmgr/lib/xm/create.py tools/xenmgr/lib/xm/main.py tools/xenmgr/lib/xm/opts.py tools/xenmgr/lib/xm/shutdown.py tools/xenmgr/netfix tools/xenmgr/setup.py tools/xenmgr/xend tools/xenmgr/xenmgrd tools/xenmgr/xm tools/xentrace/Makefile tools/xu/Makefile tools/xu/lib/__init__.py tools/xu/lib/domain_controller.h tools/xu/lib/xu.c tools/xu/setup.py
line diff
     1.1 --- a/.rootkeys	Sun Jun 27 22:35:07 2004 +0000
     1.2 +++ b/.rootkeys	Mon Jun 28 08:20:16 2004 +0000
     1.3 @@ -161,10 +161,9 @@ 40278d94cIUWl2eRgnwZtr4hTyWT1Q tools/exa
     1.4  40278d91ZjLhxdjjrGe8HEdwHLj5xQ tools/examples/netbsd
     1.5  401d7e16NpnVrFSsR7lKKKfTwCYvWA tools/examples/xc_dom_control.py
     1.6  401d7e16RJj-lbtsVEjua6HYAIiKiA tools/examples/xc_dom_create.py
     1.7 -403b7cf7J7FsSSoEPGhx6gXR4pIdZg tools/examples/xc_physinfo.py
     1.8 -40c9c4684Wfg8VgMKtRFa_ULi2e_tQ tools/examples/xm_dom_control.py
     1.9  40c9c468pXANclL7slGaoD0kSrIwoQ tools/examples/xm_dom_create.py
    1.10  40cf2937oKlROYOJTN8GWwWM5AmjBg tools/examples/xmdefaults
    1.11 +40dfd40auJwNnb8NoiSnRkvZaaXkUg tools/examples/xmnetbsd
    1.12  3f776bd2Xd-dUcPKlPN2vG89VGtfvQ tools/misc/Makefile
    1.13  40ab2cfawIw8tsYo0dQKtp83h4qfTQ tools/misc/fakei386xen
    1.14  3f6dc136ZKOjd8PIqLbFBl_v-rnkGg tools/misc/miniterm/Makefile
    1.15 @@ -197,82 +196,85 @@ 40589968UQFnJeOMn8UIFLbXBuwXjw tools/xc/
    1.16  3fbd0a3dTwnDcfdw0-v46dPbX98zDw tools/xc/py/Makefile
    1.17  3fbd0a42l40lM0IICw2jXbQBVZSdZg tools/xc/py/Xc.c
    1.18  3fbd0a40yT6G3M9hMpaz5xTUdl0E4g tools/xc/py/setup.py
    1.19 -4055ee41IfFazrwadCH2J72nz-A9YA tools/xenctl/Makefile
    1.20 -4055ee4b_4Rvns_KzE12csI14EKK6Q tools/xenctl/lib/__init__.py
    1.21 -4055ee4dwy4l0MghZosxoiu6zmhc9Q tools/xenctl/lib/console_client.py
    1.22 -40c9c468IienauFHQ_xJIcqnPJ8giQ tools/xenctl/lib/ip.py
    1.23 -4059c6a0pnxhG8hwSOivXybbGOwuXw tools/xenctl/lib/tempfile.py
    1.24 -3fbd4bd6GtGwZGxYUJPOheYIR7bPaA tools/xenctl/lib/utils.py
    1.25 -4055ee44Bu6oP7U0WxxXypbUt4dNPQ tools/xenctl/setup.py
    1.26 -40431ac64Hj4ixUnKmlugZKhXPFE_Q tools/xend/Makefile
    1.27 -4055ad95Se-FqttgxollqOAAHB94zA tools/xend/lib/__init__.py
    1.28 -4092738fMRGC9fFBcPRCWaJaj9U3ag tools/xend/lib/blkif.py
    1.29 -4055ad97wMLUj0BZT0e_T0EwQN0Bvw tools/xend/lib/console.py
    1.30 -4048c0ddsF0WrU7HUzTvg1MJoCIfWg tools/xend/lib/domain_controller.h
    1.31 -4054a301VEag2GwrBrFBna5U1BGlLA tools/xend/lib/main.py
    1.32 -4055ad9ah9IuC3sJT2c_gYIFY5Tw_g tools/xend/lib/manager.py
    1.33 -409ba2e729HhE7fEra4B5EqX-F8Xzw tools/xend/lib/netif.py
    1.34 -40431ac8wrUEj-XM7B8smFtx_HA7lQ tools/xend/lib/utils.c
    1.35 -4054a2fdkdATEnRw-U7AUlgu-6JiUA tools/xend/setup.py
    1.36 -4056cd26Qyp09iNoOjrvzg8KYzSqOw tools/xend/xend
    1.37 -40c9c468icGyC5RAF1bRKsCXPDCvsA tools/xenmgr/Makefile
    1.38 -40c9c468SNuObE_YWARyS0hzTPSzKg tools/xenmgr/lib/Args.py
    1.39 -40c9c468Um_qc66OQeLEceIz1pgD5g tools/xenmgr/lib/EventServer.py
    1.40 -40c9c468U8EVl0d3G--8YXVg6VJD3g tools/xenmgr/lib/EventTypes.py
    1.41 -40c9c468QJTEuk9g4qHxGpmIi70PEQ tools/xenmgr/lib/PrettyPrint.py
    1.42 -40d8915cyoVA0hJxiBFNymL7YvDaRg tools/xenmgr/lib/XendBridge.py
    1.43 -40c9c4688m3eqnC8fhLu1APm36VOVA tools/xenmgr/lib/XendClient.py
    1.44 -40c9c468t6iIKTjwuYoe-UMCikDcOQ tools/xenmgr/lib/XendConsole.py
    1.45 -40c9c468WnXs6eOUSff23IIGI4kMfQ tools/xenmgr/lib/XendDB.py
    1.46 -40c9c468fSl3H3IypyT0ppkbb0ZT9A tools/xenmgr/lib/XendDomain.py
    1.47 -40c9c468bbKq3uC7_fuNUkiMMjArdw tools/xenmgr/lib/XendDomainConfig.py
    1.48 -40c9c4685ykq87_n1kVUbMr9flx9fg tools/xenmgr/lib/XendDomainInfo.py
    1.49 -40c9c46854nsHmuxHQHncKk5rAs5NA tools/xenmgr/lib/XendMigrate.py
    1.50 -40c9c468M96gA1EYDvNa5w5kQNYLFA tools/xenmgr/lib/XendNode.py
    1.51 -40c9c4686jruMyZIqiaZRMiMoqMJtg tools/xenmgr/lib/XendRoot.py
    1.52 -40c9c468xzANp6o2D_MeCYwNmOIUsQ tools/xenmgr/lib/XendVnet.py
    1.53 -40c9c468x191zetrVlMnExfsQWHxIQ tools/xenmgr/lib/__init__.py
    1.54 -40c9c468S2YnCEKmk4ey8XQIST7INg tools/xenmgr/lib/encode.py
    1.55 -40c9c468DCpMe542varOolW1Xc68ew tools/xenmgr/lib/server/SrvBase.py
    1.56 -40c9c468IxQabrKJSWs0aEjl-27mRQ tools/xenmgr/lib/server/SrvConsole.py
    1.57 -40c9c4689Io5bxfbYIfRiUvsiLX0EQ tools/xenmgr/lib/server/SrvConsoleDir.py
    1.58 -40c9c468woSmBByfeXA4o_jGf2gCgA tools/xenmgr/lib/server/SrvConsoleServer.py
    1.59 -40c9c468kACsmkqjxBWKHRo071L26w tools/xenmgr/lib/server/SrvDeviceDir.py
    1.60 -40c9c468EQZJVkCLds-OhesJVVyZbQ tools/xenmgr/lib/server/SrvDir.py
    1.61 -40c9c468TyHZUq8sk0FF_vxM6Sozrg tools/xenmgr/lib/server/SrvDomain.py
    1.62 -40c9c469WzajDjutou3X7FmL9hMf3g tools/xenmgr/lib/server/SrvDomainDir.py
    1.63 -40c9c469-8mYEJJTAR6w_ClrJRAfwQ tools/xenmgr/lib/server/SrvEventDir.py
    1.64 -40c9c4694eu5759Dehr4Uhakei0EMg tools/xenmgr/lib/server/SrvNode.py
    1.65 -40c9c469TaZ83ypsrktmPSHLEZiP5w tools/xenmgr/lib/server/SrvRoot.py
    1.66 -40c9c469W3sgDMbBJYQdz5wbQweL0Q tools/xenmgr/lib/server/SrvServer.py
    1.67 -40c9c469aq7oXrE1Ngqf3_lBqL0RoQ tools/xenmgr/lib/server/SrvVnetDir.py
    1.68 -40c9c469Y_aimoOFfUZoS-4eV8gEKg tools/xenmgr/lib/server/__init__.py
    1.69 -40c9c4692hckPol_EK0EGB16ZyDsyQ tools/xenmgr/lib/server/blkif.py
    1.70 -40c9c469N2-b3GqpLHHHPZykJPLVvA tools/xenmgr/lib/server/channel.py
    1.71 -40c9c469hJ_IlatRne-9QEa0-wlquw tools/xenmgr/lib/server/console.py
    1.72 -40c9c469UcNJh_NuLU0ytorM0Lk5Ow tools/xenmgr/lib/server/controller.py
    1.73 -40c9c469vHh-qLiiubdbKEQbJf18Zw tools/xenmgr/lib/server/cstruct.py
    1.74 -40d83983OXjt-y3HjSCcuoPp9rzvmw tools/xenmgr/lib/server/domain.py
    1.75 -40c9c469yrm31i60pGKslTi2Zgpotg tools/xenmgr/lib/server/messages.py
    1.76 -40c9c46925x-Rjb0Cv2f1-l2jZrPYg tools/xenmgr/lib/server/netif.py
    1.77 -40c9c469ZqILEQ8x6yWy0_51jopiCg tools/xenmgr/lib/server/params.py
    1.78 -40c9c469LNxLVizOUpOjEaTKKCm8Aw tools/xenmgr/lib/sxp.py
    1.79 -40d05079aFRp6NQdo5wIh5Ly31c0cg tools/xenmgr/lib/xm/__init__.py
    1.80 -40cf2937gKQcATgXKGtNeWb1PDH5nA tools/xenmgr/lib/xm/create.py
    1.81 -40cf2937isyS250zyd0Q2GuEDoNXfQ tools/xenmgr/lib/xm/main.py
    1.82 -40cf2937PSslwBliN1g7ofDy2H_RhA tools/xenmgr/lib/xm/opts.py
    1.83 -40cf2937Z8WCNOnO2FcWdubvEAF9QQ tools/xenmgr/lib/xm/shutdown.py
    1.84 -40c9c469kT0H9COWzA4XzPBjWK0WsA tools/xenmgr/netfix
    1.85 -40c9c469n2RRwCmjWdjdyyVRWKmgWg tools/xenmgr/setup.py
    1.86 -40c9c4697z76HDfkCLdMhmaEwzFoNQ tools/xenmgr/xend
    1.87 -40c9c469JkN47d1oXi-e0RjAP-C6uQ tools/xenmgr/xenmgrd
    1.88 -40cf2937dqM1jWW87O5OoOYND8leuA tools/xenmgr/xm
    1.89 +40c9c468icGyC5RAF1bRKsCXPDCvsA tools/xen/Makefile
    1.90 +40dc4076hGpwa8-sWRN0jtXZeQJuKg tools/xen/lib/__init__.py
    1.91 +40dfd40aMOhnw_cQLve9462UR5yYxQ tools/xen/lib/ext/__init__.py
    1.92 +40dfd40aGqGkiopOOgJxSF4iCbHM0Q tools/xen/lib/util/__init__.py
    1.93 +4055ee4dwy4l0MghZosxoiu6zmhc9Q tools/xen/lib/util/console_client.py
    1.94 +40c9c468IienauFHQ_xJIcqnPJ8giQ tools/xen/lib/util/ip.py
    1.95 +4059c6a0pnxhG8hwSOivXybbGOwuXw tools/xen/lib/util/tempfile.py
    1.96 +40c9c468SNuObE_YWARyS0hzTPSzKg tools/xen/lib/xend/Args.py
    1.97 +40c9c468Um_qc66OQeLEceIz1pgD5g tools/xen/lib/xend/EventServer.py
    1.98 +40c9c468U8EVl0d3G--8YXVg6VJD3g tools/xen/lib/xend/EventTypes.py
    1.99 +40c9c468QJTEuk9g4qHxGpmIi70PEQ tools/xen/lib/xend/PrettyPrint.py
   1.100 +40d8915cyoVA0hJxiBFNymL7YvDaRg tools/xen/lib/xend/XendBridge.py
   1.101 +40c9c4688m3eqnC8fhLu1APm36VOVA tools/xen/lib/xend/XendClient.py
   1.102 +40c9c468t6iIKTjwuYoe-UMCikDcOQ tools/xen/lib/xend/XendConsole.py
   1.103 +40c9c468WnXs6eOUSff23IIGI4kMfQ tools/xen/lib/xend/XendDB.py
   1.104 +40c9c468fSl3H3IypyT0ppkbb0ZT9A tools/xen/lib/xend/XendDomain.py
   1.105 +40c9c468bbKq3uC7_fuNUkiMMjArdw tools/xen/lib/xend/XendDomainConfig.py
   1.106 +40c9c4685ykq87_n1kVUbMr9flx9fg tools/xen/lib/xend/XendDomainInfo.py
   1.107 +40c9c46854nsHmuxHQHncKk5rAs5NA tools/xen/lib/xend/XendMigrate.py
   1.108 +40c9c468M96gA1EYDvNa5w5kQNYLFA tools/xen/lib/xend/XendNode.py
   1.109 +40c9c4686jruMyZIqiaZRMiMoqMJtg tools/xen/lib/xend/XendRoot.py
   1.110 +40c9c468xzANp6o2D_MeCYwNmOIUsQ tools/xen/lib/xend/XendVnet.py
   1.111 +40c9c468x191zetrVlMnExfsQWHxIQ tools/xen/lib/xend/__init__.py
   1.112 +40c9c468S2YnCEKmk4ey8XQIST7INg tools/xen/lib/xend/encode.py
   1.113 +40c9c468DCpMe542varOolW1Xc68ew tools/xen/lib/xend/server/SrvBase.py
   1.114 +40c9c468IxQabrKJSWs0aEjl-27mRQ tools/xen/lib/xend/server/SrvConsole.py
   1.115 +40c9c4689Io5bxfbYIfRiUvsiLX0EQ tools/xen/lib/xend/server/SrvConsoleDir.py
   1.116 +40c9c468woSmBByfeXA4o_jGf2gCgA tools/xen/lib/xend/server/SrvDaemon.py
   1.117 +40c9c468kACsmkqjxBWKHRo071L26w tools/xen/lib/xend/server/SrvDeviceDir.py
   1.118 +40c9c468EQZJVkCLds-OhesJVVyZbQ tools/xen/lib/xend/server/SrvDir.py
   1.119 +40c9c468TyHZUq8sk0FF_vxM6Sozrg tools/xen/lib/xend/server/SrvDomain.py
   1.120 +40c9c469WzajDjutou3X7FmL9hMf3g tools/xen/lib/xend/server/SrvDomainDir.py
   1.121 +40c9c469-8mYEJJTAR6w_ClrJRAfwQ tools/xen/lib/xend/server/SrvEventDir.py
   1.122 +40c9c4694eu5759Dehr4Uhakei0EMg tools/xen/lib/xend/server/SrvNode.py
   1.123 +40c9c469TaZ83ypsrktmPSHLEZiP5w tools/xen/lib/xend/server/SrvRoot.py
   1.124 +40c9c469W3sgDMbBJYQdz5wbQweL0Q tools/xen/lib/xend/server/SrvServer.py
   1.125 +40c9c469aq7oXrE1Ngqf3_lBqL0RoQ tools/xen/lib/xend/server/SrvVnetDir.py
   1.126 +40c9c469Y_aimoOFfUZoS-4eV8gEKg tools/xen/lib/xend/server/__init__.py
   1.127 +40c9c4692hckPol_EK0EGB16ZyDsyQ tools/xen/lib/xend/server/blkif.py
   1.128 +40c9c469N2-b3GqpLHHHPZykJPLVvA tools/xen/lib/xend/server/channel.py
   1.129 +40c9c469hJ_IlatRne-9QEa0-wlquw tools/xen/lib/xend/server/console.py
   1.130 +40c9c469UcNJh_NuLU0ytorM0Lk5Ow tools/xen/lib/xend/server/controller.py
   1.131 +40c9c469vHh-qLiiubdbKEQbJf18Zw tools/xen/lib/xend/server/cstruct.py
   1.132 +40d83983OXjt-y3HjSCcuoPp9rzvmw tools/xen/lib/xend/server/domain.py
   1.133 +40c9c469yrm31i60pGKslTi2Zgpotg tools/xen/lib/xend/server/messages.py
   1.134 +40c9c46925x-Rjb0Cv2f1-l2jZrPYg tools/xen/lib/xend/server/netif.py
   1.135 +40c9c469ZqILEQ8x6yWy0_51jopiCg tools/xen/lib/xend/server/params.py
   1.136 +40c9c469LNxLVizOUpOjEaTKKCm8Aw tools/xen/lib/xend/sxp.py
   1.137 +40d05079aFRp6NQdo5wIh5Ly31c0cg tools/xen/lib/xm/__init__.py
   1.138 +40cf2937gKQcATgXKGtNeWb1PDH5nA tools/xen/lib/xm/create.py
   1.139 +40cf2937isyS250zyd0Q2GuEDoNXfQ tools/xen/lib/xm/main.py
   1.140 +40cf2937PSslwBliN1g7ofDy2H_RhA tools/xen/lib/xm/opts.py
   1.141 +40cf2937Z8WCNOnO2FcWdubvEAF9QQ tools/xen/lib/xm/shutdown.py
   1.142 +40c9c469kT0H9COWzA4XzPBjWK0WsA tools/xen/netfix
   1.143 +40c9c469n2RRwCmjWdjdyyVRWKmgWg tools/xen/setup.py
   1.144 +40c9c4697z76HDfkCLdMhmaEwzFoNQ tools/xen/xend
   1.145 +40cf2937dqM1jWW87O5OoOYND8leuA tools/xen/xm
   1.146 +40431ac64Hj4ixUnKmlugZKhXPFE_Q tools/xend-old/Makefile
   1.147 +4055ad95Se-FqttgxollqOAAHB94zA tools/xend-old/lib/__init__.py
   1.148 +4092738fMRGC9fFBcPRCWaJaj9U3ag tools/xend-old/lib/blkif.py
   1.149 +4055ad97wMLUj0BZT0e_T0EwQN0Bvw tools/xend-old/lib/console.py
   1.150 +4048c0ddsF0WrU7HUzTvg1MJoCIfWg tools/xend-old/lib/domain_controller.h
   1.151 +4054a301VEag2GwrBrFBna5U1BGlLA tools/xend-old/lib/main.py
   1.152 +4055ad9ah9IuC3sJT2c_gYIFY5Tw_g tools/xend-old/lib/manager.py
   1.153 +409ba2e729HhE7fEra4B5EqX-F8Xzw tools/xend-old/lib/netif.py
   1.154 +40431ac8wrUEj-XM7B8smFtx_HA7lQ tools/xend-old/lib/utils.c
   1.155 +4054a2fdkdATEnRw-U7AUlgu-6JiUA tools/xend-old/setup.py
   1.156 +4056cd26Qyp09iNoOjrvzg8KYzSqOw tools/xend-old/xend
   1.157  403a3edbrr8RE34gkbR40zep98SXbg tools/xentrace/Makefile
   1.158  40a107afN60pFdURgBv9KwEzgRl5mQ tools/xentrace/formats
   1.159  4050c413PhhLNAYk3TEwP37i_iLw9Q tools/xentrace/xentrace.8
   1.160  403a3edbVpV2E_wq1zeEkJ_n4Uu2eg tools/xentrace/xentrace.c
   1.161  403a3edblCUrzSj0mmKhO5HOPrOrSQ tools/xentrace/xentrace_format
   1.162  4050c413NtuyIq5lsYJV4P7KIjujXw tools/xentrace/xentrace_format.1
   1.163 +40dfd40a0QtsSGigB9TCpVGWZmhlNA tools/xu/Makefile
   1.164 +40dc4076St6AmPTmQPrtQ6LGHPxGmw tools/xu/lib/__init__.py
   1.165 +40dc4076pVeE1kEEWzcUaNZin65kCA tools/xu/lib/domain_controller.h
   1.166 +40dc4076CwBYRTUQDdbdU1L6KcLgSw tools/xu/lib/xu.c
   1.167 +40dc4076FyWUYS2nX9YufgglUzKX2A tools/xu/setup.py
   1.168  3f72f1bdJPsV3JCnBqs9ddL9tr6D2g xen/COPYING
   1.169  3ddb79bcbOVHh38VJzc97-JEGD4dJQ xen/Makefile
   1.170  3ddb79bcWnTwYsQRWl_PaneJfa6p0w xen/Rules.mk
     2.1 --- a/extras/mini-os/h/hypervisor.h	Sun Jun 27 22:35:07 2004 +0000
     2.2 +++ b/extras/mini-os/h/hypervisor.h	Mon Jun 28 08:20:16 2004 +0000
     2.3 @@ -13,7 +13,7 @@
     2.4  
     2.5  /* include the hypervisor interface */
     2.6  #include <hypervisor-ifs/hypervisor-if.h>
     2.7 -#include "../../../tools/xend/lib/domain_controller.h"
     2.8 +#include "../../../tools/xu/lib/domain_controller.h"
     2.9  
    2.10  /*
    2.11   * a placeholder for the start of day information passed up from the hypervisor
     3.1 --- a/linux-2.4.26-xen-sparse/mkbuildtree	Sun Jun 27 22:35:07 2004 +0000
     3.2 +++ b/linux-2.4.26-xen-sparse/mkbuildtree	Mon Jun 28 08:20:16 2004 +0000
     3.3 @@ -114,7 +114,7 @@ relative_lndir ../../../${RS}/../xen/inc
     3.4  
     3.5  # Another special symlink: to the shared definitions for the control interface
     3.6  cd ..
     3.7 -ln -sf ../../${RS}/../tools/xend/lib/domain_controller.h
     3.8 +ln -sf ../../${RS}/../tools/xu/lib/domain_controller.h
     3.9  
    3.10  # The remainder are the i386 -> xen-i386 links
    3.11  ln -sf ../asm-i386/a.out.h 
     4.1 --- a/tools/Makefile	Sun Jun 27 22:35:07 2004 +0000
     4.2 +++ b/tools/Makefile	Mon Jun 28 08:20:16 2004 +0000
     4.3 @@ -1,21 +1,19 @@
     4.4  
     4.5  all:	
     4.6  	$(MAKE) -C xc
     4.7 +	$(MAKE) -C xu
     4.8  	$(MAKE) -C misc
     4.9  	$(MAKE) -C examples
    4.10  	$(MAKE) -C xentrace
    4.11 -	$(MAKE) -C xenctl
    4.12 -	$(MAKE) -C xend
    4.13 -	$(MAKE) -C xenmgr
    4.14 +	$(MAKE) -C xen
    4.15  
    4.16  install: all
    4.17  	$(MAKE) -C xc install
    4.18 +	$(MAKE) -C xu install
    4.19  	$(MAKE) -C misc install
    4.20  	$(MAKE) -C examples install
    4.21  	$(MAKE) -C xentrace install
    4.22 -	$(MAKE) -C xenctl install
    4.23 -	$(MAKE) -C xend install
    4.24 -	$(MAKE) -C xenmgr install
    4.25 +	$(MAKE) -C xen install
    4.26  
    4.27  dist: $(TARGET)
    4.28  	$(MAKE) prefix=`pwd`/../../install dist=yes install
    4.29 @@ -23,10 +21,9 @@ dist: $(TARGET)
    4.30  
    4.31  clean:
    4.32  	$(MAKE) -C xc clean
    4.33 +	$(MAKE) -C xu clean
    4.34  	$(MAKE) -C misc clean
    4.35  	$(MAKE) -C examples clean
    4.36  	$(MAKE) -C xentrace clean
    4.37 -	$(MAKE) -C xenctl clean
    4.38 -	$(MAKE) -C xend clean
    4.39 -	$(MAKE) -C xenmgr clean
    4.40 +	$(MAKE) -C xen clean
    4.41  
     5.1 --- a/tools/examples/xc_physinfo.py	Sun Jun 27 22:35:07 2004 +0000
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,20 +0,0 @@
     5.4 -#!/usr/bin/env python
     5.5 -
     5.6 -# Get information about the physical host machine
     5.7 -
     5.8 -import Xc
     5.9 -
    5.10 -xc = Xc.new()
    5.11 -
    5.12 -info = xc.physinfo()
    5.13 -
    5.14 -fmt_info = [ ( 'CPU cores', info['cores']),
    5.15 -             ('Hyperthreads per core', info['ht_per_core']),
    5.16 -             ('CPU Speed (MHz)', info['cpu_khz'] / 1000),
    5.17 -             ('Total physical mem (MB)', info['total_pages'] / 256),
    5.18 -             ('Free physical mem (MB)', info['free_pages'] / 256) ]
    5.19 -      
    5.20 -
    5.21 -for (item, val) in fmt_info:
    5.22 -    print "%-23s" % item, ':', val
    5.23 -
     6.1 --- a/tools/examples/xm_dom_control.py	Sun Jun 27 22:35:07 2004 +0000
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,235 +0,0 @@
     6.4 -#!/usr/bin/env python
     6.5 -
     6.6 -import sys
     6.7 -import re
     6.8 -import string
     6.9 -import time
    6.10 -import os
    6.11 -import os.path
    6.12 -import signal
    6.13 -
    6.14 -from xenmgr import sxp
    6.15 -from xenmgr.XendClient import server
    6.16 -
    6.17 -# usage: xc_dom_control [command] <params>
    6.18 -#
    6.19 -# this script isn't very smart, but it'll do for now.
    6.20 -#
    6.21 -
    6.22 -def usage (rc=0):
    6.23 -    if rc:
    6.24 -        out = sys.stderr
    6.25 -    else:
    6.26 -        out = sys.stdout
    6.27 -    print >> out, """
    6.28 -Usage: %s [command] <params>
    6.29 -
    6.30 -  help                   -- print usage
    6.31 -  pause     [dom]        -- pause a domain
    6.32 -  unpause   [dom]        -- un-pause a domain
    6.33 -  shutdown  [dom] [[-w]] -- request a domain to shutdown (can specify 'all')
    6.34 -                            (optionally wait for complete shutdown)
    6.35 -  destroy   [dom]        -- immediately terminate a domain
    6.36 -  pincpu    [dom] [cpu]  -- pin a domain to the specified CPU
    6.37 -  suspend   [dom] [file] -- write domain's memory to a file and terminate
    6.38 -			    (resume by re-running xc_dom_create with -L option)
    6.39 -  unwatch   [dom]        -- kill the auto-restart daemon for a domain
    6.40 -  list                   -- print info about all domains
    6.41 -  listvbds               -- print info about all virtual block devs
    6.42 -  cpu_bvtset [dom] [mcuadv] [warp] [warpl] [warpu]
    6.43 -                         -- set BVT scheduling parameters for domain
    6.44 -  cpu_bvtslice [slice]   -- set default BVT scheduler slice
    6.45 -  cpu_atropos_set [dom] [period] [slice] [latency] [xtratime]
    6.46 -                         -- set Atropos scheduling parameters for domain
    6.47 -  cpu_rrobin_slice [slice] -- set Round Robin scheduler slice
    6.48 -  vif_stats [dom] [vif]  -- get stats for a given network vif
    6.49 -  vif_addip [dom] [vif] [ip]  -- add an IP address to a given vif
    6.50 -  vif_setsched [dom] [vif] [bytes] [usecs] -- rate limit vif bandwidth
    6.51 -  vif_getsched [dom] [vif] -- print vif's scheduling parameters
    6.52 -  vbd_add [dom] [uname] [dev] [mode] -- make disk/partition uname available to 
    6.53 -                            domain as dev e.g. 'vbd_add 2 phy:sda3 hda1 w'
    6.54 -  vbd_remove [dom] [dev] -- remove disk or partition attached as 'dev' 
    6.55 -""" % sys.argv[0]
    6.56 -    if rc: sys.exit(rc)
    6.57 -
    6.58 -if len(sys.argv) < 2: usage(1)
    6.59 -cmd = sys.argv[1]
    6.60 -
    6.61 -#todo: replace all uses of xc with the new api.
    6.62 -import Xc; xc = Xc.new()
    6.63 -
    6.64 -rc = ''
    6.65 -dom = None
    6.66 -
    6.67 -
    6.68 -def auto_restart_pid_file(dom):
    6.69 -    # The auto-restart daemon's pid file.
    6.70 -    return '/var/run/xendomains/%d.pid' % dom
    6.71 -
    6.72 -def auto_restart_pid(dom):
    6.73 -    watcher = auto_restart_pid_file(dom)
    6.74 -    if os.path.isfile(watcher):
    6.75 -        fd = open(watcher,'r')
    6.76 -        pid = int(fd.readline())
    6.77 -    else:
    6.78 -        pid = None
    6.79 -    return pid
    6.80 - 
    6.81 -def auto_restart_kill(dom):
    6.82 -    #todo: replace this - tell xend not to restart any more.
    6.83 -    # Kill a domain's auto restart daemon.
    6.84 -    pid = auto_restart_pid(dom)
    6.85 -    if pid:
    6.86 -        os.kill(pid, signal.SIGTERM)
    6.87 -
    6.88 -
    6.89 -if len( sys.argv ) > 2 and re.match('\d+$', sys.argv[2]):
    6.90 -    dom = long(sys.argv[2])
    6.91 -
    6.92 -if cmd == "help":
    6.93 -    usage()
    6.94 -    
    6.95 -elif cmd == 'pause':
    6.96 -    rc = server.xend_domain_pause(dom)
    6.97 -
    6.98 -elif cmd == 'unpause':
    6.99 -    rc = server.xend_domain_unpause(dom)    
   6.100 -
   6.101 -elif cmd == 'shutdown':
   6.102 -    doms = []
   6.103 -    shutdown = []
   6.104 -    if dom != None:
   6.105 -        doms = [ dom ]
   6.106 -    elif sys.argv[2] == 'all':
   6.107 -        doms = server.xend_domains()
   6.108 -        doms.remove('0')
   6.109 -    for d in doms:
   6.110 -        ret = server.xend_domain_shutdown(d)
   6.111 -        if ret == 0:
   6.112 -            shutdown.append(d)
   6.113 -        else:
   6.114 -            rc = ret
   6.115 -
   6.116 -    wait = (len(sys.argv) == 4 and sys.argv[3] == "-w")
   6.117 -    if wait:
   6.118 -        # wait for all domains we shut down to terminate
   6.119 -        for dom in shutdown:
   6.120 -            while True:
   6.121 -                info = server.xend_domain(dom)
   6.122 -                if not info: break
   6.123 -                time.sleep(1)
   6.124 -
   6.125 -elif cmd == 'destroy':
   6.126 -    rc = server.xend_domain_halt(dom)    
   6.127 -
   6.128 -elif cmd == 'pincpu':
   6.129 -    if len(sys.argv) < 4: usage(1)
   6.130 -    cpu = int(sys.argv[3])
   6.131 -    rc = server.xend_domain_pincpu(dom, cpu)
   6.132 -
   6.133 -elif cmd == 'list':
   6.134 -    print 'Dom  Name             Mem(MB)  CPU  State  Time(s)'
   6.135 -    doms = server.xend_domains()
   6.136 -    doms.sort()
   6.137 -    for dom in doms:
   6.138 -        info = server.xend_domain(dom)
   6.139 -        d = {}
   6.140 -        d['dom'] = int(dom)
   6.141 -        d['name'] = sxp.child_value(info, 'name', '??')
   6.142 -        d['mem'] = int(sxp.child_value(info, 'memory', '0'))
   6.143 -        d['cpu'] = int(sxp.child_value(info, 'cpu', '0'))
   6.144 -        d['state'] = sxp.child_value(info, 'state', '??')
   6.145 -        d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
   6.146 -        print ("%(dom)-4d %(name)-16s %(mem)7d %(cpu)3d %(state)5s %(cpu_time)8.2f" % d)
   6.147 -
   6.148 -elif cmd == 'unwatch':
   6.149 -    auto_restart_kill(dom)
   6.150 -
   6.151 -elif cmd == 'listvbds':
   6.152 -    print 'Dom   Dev   Mode   Size(MB)'
   6.153 -    for dom in server.xend_domains():
   6.154 -        for vbd in server.xend_domain_vbds(dom):
   6.155 -            info = server.xend_domain_vbd(vbd)
   6.156 -            v['vbd'] = vbd
   6.157 -            v['size'] = int(sxp.get_child_value(info, 'size', '0'))
   6.158 -            v['mode'] = sxp.get_child_value(info, 'mode', '??')
   6.159 -            vbd['size_mb'] = vbd['nr_sectors'] / 2048
   6.160 -            print ('%(dom)-4d  %(vbd)04x  %(mode)-2s      %(size)d' % v)
   6.161 -
   6.162 -elif cmd == 'suspend':
   6.163 -    if len(sys.argv) < 4: usage(1)
   6.164 -    file = os.path.abspath(sys.argv[3])
   6.165 -    auto_restart_kill(dom)
   6.166 -    rc = server.xend_domain_save(dom, file, progress=1)
   6.167 -
   6.168 -elif cmd == 'cpu_bvtslice':
   6.169 -    if len(sys.argv) < 3: usage(1)
   6.170 -    slice = sys.argv[2]
   6.171 -    rc = server.xend_node_cpu_bvt_slice_set(slice)
   6.172 -
   6.173 -elif cmd == 'cpu_bvtset':
   6.174 -    if len(sys.argv) < 7: usage(1)
   6.175 -    (mcuadv, warp, warpl, warpu) = map(int, sys.argv[3:7])
   6.176 -    
   6.177 -    rc = server.xend_domain_cpu_bvt_set(dom, mcuadv, warp, warpl, warpu)
   6.178 -    
   6.179 -elif cmd == 'vif_stats':
   6.180 -    if len(sys.argv) < 4: usage(1)
   6.181 -    vif = int(sys.argv[3])
   6.182 -
   6.183 -    print server.xend_domain_vif_stats(dom, vif)
   6.184 -
   6.185 -elif cmd == 'vif_addip':
   6.186 -    if len(sys.argv) < 5: usage(1)
   6.187 -    vif = int(sys.argv[3])
   6.188 -    ip  = sys.argv[4]
   6.189 -    rc = server.xend_domain_vif_addip(dom, vif, ip)
   6.190 -
   6.191 -elif cmd == 'vif_setsched':
   6.192 -    if len(sys.argv) < 6: usage(1)
   6.193 -    (vif, bytes, usecs) = map(int, sys.argv[3:6])
   6.194 -    rc = server.xend_domain_vif_scheduler_set(dom, vif, bytes, usecs)
   6.195 -
   6.196 -elif cmd == 'vif_getsched':
   6.197 -    if len(sys.argv) < 4: usage(1)
   6.198 -    vif = int(sys.argv[3])
   6.199 -    print server.xend_domain_vif_scheduler_get(dom, vif)
   6.200 -
   6.201 -elif cmd == 'vbd_add':
   6.202 -    if len(sys.argv) < 6: usage(1)
   6.203 -    uname = sys.argv[3]
   6.204 -    dev = sys.argv[4]
   6.205 -    mode = sys.argv[5]
   6.206 -    try:
   6.207 -        vbd = server.xend_domain_vbd_add(dom, uname, dev, mode)
   6.208 -    except StandardError, ex:
   6.209 -        print "Error:", ex
   6.210 -        sys.exit(1)
   6.211 -    print "Added disk/partition %s to domain %d as device %s (%x)" % (uname, dom, dev, vbd)
   6.212 -
   6.213 -elif cmd == 'vbd_remove':
   6.214 -    if len(sys.argv) < 4: usage(1)
   6.215 -    dev = sys.argv[3]
   6.216 -    vbd = server.xend_domain_vbd_remove(dom, dev)
   6.217 -    if vbd < 0:
   6.218 -	print "Failed"
   6.219 -	sys.exit(1)
   6.220 -    else:
   6.221 -	print "Removed disk/partition attached as device %s (%x) in domain %d" % (dev, vbd, dom)
   6.222 -
   6.223 -elif cmd == 'cpu_atropos_set': # args: dom period slice latency xtratime
   6.224 -    if len(sys.argv) < 6: usage(1)
   6.225 -    (period, slice, latency, xtratime) = map(int, sys.argv[3:7])
   6.226 -    rc = server.xend_domain_cpu_atropos_set(
   6.227 -        dom, period, slice, latency, xtratime)
   6.228 -
   6.229 -elif cmd == 'cpu_rrobin_slice':
   6.230 -    if len(sys.argv) < 3: usage(1)
   6.231 -    slice = int(sys.argv[2])
   6.232 -    rc = server.xend_node_rrobin_set(slice=slice)
   6.233 -
   6.234 -else:
   6.235 -    usage(1)
   6.236 -
   6.237 -if rc != '':
   6.238 -    print "return code %d" % rc
     7.1 --- a/tools/examples/xmdefaults	Sun Jun 27 22:35:07 2004 +0000
     7.2 +++ b/tools/examples/xmdefaults	Mon Jun 28 08:20:16 2004 +0000
     7.3 @@ -44,10 +44,9 @@ cpu = vmid  # set based on vmid (mod num
     7.4  # Number of network interfaces. Default is 1.
     7.5  #nics=1
     7.6  
     7.7 -# List of MAC addresses for the network interfaces.
     7.8 -# If there aren't enough addresses for all the interfaces
     7.9 -# the rest get random MACs.
    7.10 -#mac = [ "aa:00:00:00:00:11" ]
    7.11 +# Optionally define mac and/or bridge for the network interfaces.
    7.12 +# Random MACs are assigned if not given.
    7.13 +#vif = [ 'mac=aa:00:00:00:00:11, bridge=nbe-br' ]
    7.14  
    7.15  #----------------------------------------------------------------------------
    7.16  # Define the disk devices you want the domain to have access to, and
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/tools/examples/xmnetbsd	Mon Jun 28 08:20:16 2004 +0000
     8.3 @@ -0,0 +1,102 @@
     8.4 +#  -*- mode: python; -*-
     8.5 +#============================================================================
     8.6 +# Python defaults setup for 'xm create'.
     8.7 +# Edit this file to reflect the configuration of your system.
     8.8 +# This file expects the variable 'vmid' to be set.
     8.9 +#============================================================================
    8.10 +
    8.11 +def config_usage ():
    8.12 +    print >>sys.stderr,"""
    8.13 +The config file '%s' requires the following variable to be defined:
    8.14 + vmid             -- Numeric identifier for the new domain, used to calculate
    8.15 +                     the VM's IP address and root partition. E.g. -Dvmid=1
    8.16 +""" % config_file
    8.17 +
    8.18 +
    8.19 +try:
    8.20 +    vmid = int(vmid) # convert to integer
    8.21 +except:
    8.22 +    raise ValueError, "Variable 'vmid' must be an integer"
    8.23 +
    8.24 +if vmid <= 0:
    8.25 +    raise ValueError, "Variable 'vmid' must be greater than 0" 
    8.26 +
    8.27 +#----------------------------------------------------------------------------
    8.28 +# Kernel image file.
    8.29 +image = "/boot/netbsd"
    8.30 +
    8.31 +# The domain build function.
    8.32 +builder='netbsd'
    8.33 +
    8.34 +# Initial memory allocation (in megabytes) for the new domain.
    8.35 +memory = 16
    8.36 +
    8.37 +# A handy name for your new domain.
    8.38 +name = "NetBSD VM %d" % vmid
    8.39 +
    8.40 +#----------------------------------------------------------------------------
    8.41 +# Define network interfaces.
    8.42 +
    8.43 +# Number of network interfaces. Default is 1.
    8.44 +#nics=1
    8.45 +
    8.46 +# Optionally define mac and/or bridge for the network interfaces.
    8.47 +# Random MACs are assigned if not given.
    8.48 +#vif = [ 'mac=aa:00:00:00:00:11, bridge=nbe-br' ]
    8.49 +
    8.50 +# Specify IP address(es), for the new domain.  You need to
    8.51 +# configure IP addrs within the domain just as you do normally.  This
    8.52 +# is just to let Xen know about them so it can route packets
    8.53 +# appropriately.
    8.54 +
    8.55 +#ipaddr = [ xenctl.utils.add_offset_to_ip(xenctl.utils.get_current_ipaddr(),vmid),
    8.56 +#           xenctl.utils.add_offset_to_ip('169.254.1.0',vmid),
    8.57 +#           ]
    8.58 +
    8.59 +#----------------------------------------------------------------------------
    8.60 +# Define the disk devices you want the domain to have access to, and
    8.61 +# what you want them accessible as.
    8.62 +# Each disk entry is of the form phy:DEV,VDEV,MODE
    8.63 +# where DEV is the device, VDEV is the device name the domain will see,
    8.64 +# and MODE is r for read-only, w for read-write.
    8.65 +
    8.66 +#disk = [ 'phy:sda%d,sda1,w' % (7+vmid),
    8.67 +#         'phy:sda6,sda6,r' ]
    8.68 +
    8.69 +#----------------------------------------------------------------------------
    8.70 +# Set the kernel command line for the new domain.
    8.71 +# You only need to define the IP parameters and hostname if the domain's
    8.72 +# IP config doesn't, e.g. in ifcfg-eth0 or via DHCP.
    8.73 +# You can use 'extra' to set the runlevel and custom environment
    8.74 +# variables used by custom rc scripts (e.g. VMID=, usr= ).
    8.75 +
    8.76 +# Set if you want dhcp to allocate the IP address.
    8.77 +#dhcp="dhcp"
    8.78 +# Set netmask.
    8.79 +#netmask=
    8.80 +# Set default gateway.
    8.81 +#gateway=
    8.82 +# Set the hostname.
    8.83 +#hostname= "vm%d" % vmid
    8.84 +
    8.85 +# Set root device.
    8.86 +root = "/dev/sda1 ro"
    8.87 +
    8.88 +# Root device for nfs.
    8.89 +#root = "/dev/nfs"
    8.90 +# The nfs server.
    8.91 +#nfs_server = '169.254.1.0'  
    8.92 +# Root directory on the nfs server.
    8.93 +#nfs_root   = '/full/path/to/root/directory'
    8.94 +
    8.95 +# Sets runlevel 4 and the device for /usr.
    8.96 +#extra = "4 VMID=%d usr=/dev/sda6" % vmid
    8.97 +extra = "4 VMID=%d bootdev=xennet0" % vmid
    8.98 +
    8.99 +
   8.100 +#----------------------------------------------------------------------------
   8.101 +# Set according to whether you want the domain  restarted when it exits.
   8.102 +# The default is False.
   8.103 +#restart = True
   8.104 +
   8.105 +#============================================================================
     9.1 --- a/tools/misc/Makefile	Sun Jun 27 22:35:07 2004 +0000
     9.2 +++ b/tools/misc/Makefile	Mon Jun 28 08:20:16 2004 +0000
     9.3 @@ -3,7 +3,7 @@ CC         = gcc
     9.4  CFLAGS     = -Wall -O3 
     9.5  EXTRA_INC  = -I../../xen/include/hypervisor-ifs
     9.6  EXTRA_INC += -I../../linux-xen-sparse/include -I../xc/lib
     9.7 -EXTRA_INC += -I../xend/lib
     9.8 +EXTRA_INC += -I../xu/lib
     9.9  
    9.10  HDRS     = $(wildcard *.h)
    9.11  SRCS     = $(wildcard *.c)
    10.1 --- a/tools/xc/lib/Makefile	Sun Jun 27 22:35:07 2004 +0000
    10.2 +++ b/tools/xc/lib/Makefile	Mon Jun 28 08:20:16 2004 +0000
    10.3 @@ -6,7 +6,7 @@ SONAME   = libxc.so.$(MAJOR)
    10.4  CC       = gcc
    10.5  CFLAGS   = -c -Werror -O3 -fno-strict-aliasing
    10.6  CFLAGS  += -I../../../xen/include/hypervisor-ifs
    10.7 -CFLAGS  += -I../../xend/lib
    10.8 +CFLAGS  += -I../../xu/lib
    10.9  CFLAGS  += -I../../../linux-xen-sparse/include
   10.10  
   10.11  HDRS     = $(wildcard *.h)
    11.1 --- a/tools/xc/py/Xc.c	Sun Jun 27 22:35:07 2004 +0000
    11.2 +++ b/tools/xc/py/Xc.c	Mon Jun 28 08:20:16 2004 +0000
    11.3 @@ -20,6 +20,8 @@
    11.4  #define PyMODINIT_FUNC DL_EXPORT(void)
    11.5  #endif
    11.6  
    11.7 +#define XENPKG "xen.ext.xc"
    11.8 +
    11.9  static PyObject *xc_error, *zero;
   11.10  
   11.11  typedef struct {
   11.12 @@ -187,112 +189,73 @@ static PyObject *pyxc_domain_getinfo(PyO
   11.13      return list;
   11.14  }
   11.15  
   11.16 -static PyObject *pyxc_linux_save(PyObject *self,
   11.17 -                                 PyObject *args,
   11.18 -                                 PyObject *kwds)
   11.19 -{
   11.20 -    XcObject *xc = (XcObject *)self;
   11.21 -
   11.22 -    u32   dom;
   11.23 -    char *state_file;
   11.24 -    int   progress = 1, live = -1, debug = 0;
   11.25 -    unsigned int flags = 0;
   11.26 -
   11.27 -    static char *kwd_list[] = { "dom", "state_file", "progress", 
   11.28 -                                "live", "debug", NULL };
   11.29 -
   11.30 -    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|iii", kwd_list, 
   11.31 -                                      &dom, &state_file, &progress, 
   11.32 -                                      &live, &debug) )
   11.33 -        return NULL;
   11.34 -
   11.35 -    if (progress)  flags |= XCFLAGS_VERBOSE;
   11.36 -    if (live == 1) flags |= XCFLAGS_LIVE;
   11.37 -    if (debug)     flags |= XCFLAGS_DEBUG;
   11.38 -
   11.39 -    if ( strncmp(state_file,"tcp:", strlen("tcp:")) == 0 )
   11.40 -    {
   11.41 +static PyObject *tcp_save(XcObject *xc, u32 dom, char *url, unsigned flags){
   11.42  #define max_namelen 64
   11.43 -        char server[max_namelen];
   11.44 -        char *port_s;
   11.45 -        int port=777;
   11.46 -        int sd = -1;
   11.47 -        struct hostent *h;
   11.48 -        struct sockaddr_in s;
   11.49 -        int sockbufsize;
   11.50 -        int rc = -1;
   11.51 +    char server[max_namelen];
   11.52 +    char *port_s;
   11.53 +    int port=777;
   11.54 +    int sd = -1;
   11.55 +    struct hostent *h;
   11.56 +    struct sockaddr_in s;
   11.57 +    int sockbufsize;
   11.58 +    int rc = -1;
   11.59 +    
   11.60 +    int writerfn(void *fd, const void *buf, size_t count) {
   11.61 +        int tot = 0, rc;
   11.62 +        do {
   11.63 +            rc = write( (int) fd, ((char*)buf)+tot, count-tot );
   11.64 +            if ( rc < 0 ) { perror("WRITE"); return rc; };
   11.65 +            tot += rc;
   11.66 +        }
   11.67 +        while ( tot < count );
   11.68 +        return 0;
   11.69 +    }
   11.70 +    
   11.71 +    strncpy( server, url+strlen("tcp://"), max_namelen);
   11.72 +    server[max_namelen-1]='\0';
   11.73 +    if ( (port_s = strchr(server,':')) != NULL ) {
   11.74 +        *port_s = '\0';
   11.75 +        port = atoi(port_s+1);
   11.76 +    }
   11.77 +    printf("X server=%s port=%d\n",server,port);
   11.78 +    h = gethostbyname(server);
   11.79 +    sd = socket(AF_INET, SOCK_STREAM,0);
   11.80 +    if (sd < 0) goto serr;
   11.81 +    s.sin_family = AF_INET;
   11.82 +    bcopy ( h->h_addr, &(s.sin_addr.s_addr), h->h_length);
   11.83 +    s.sin_port = htons(port);
   11.84 +    if ( connect(sd, (struct sockaddr *) &s, sizeof(s)) ) goto serr;
   11.85 +    sockbufsize=128*1024;
   11.86 +    if ( setsockopt(sd, SOL_SOCKET, SO_SNDBUF, &sockbufsize, sizeof sockbufsize) < 0 ) goto serr;
   11.87  
   11.88 -        int writerfn(void *fd, const void *buf, size_t count)
   11.89 -        {
   11.90 -            int tot = 0, rc;
   11.91 -            do {
   11.92 -                rc = write( (int) fd, ((char*)buf)+tot, count-tot );
   11.93 -                if ( rc < 0 ) { perror("WRITE"); return rc; };
   11.94 -                tot += rc;
   11.95 -            }
   11.96 -            while ( tot < count );
   11.97 -            return 0;
   11.98 -        }
   11.99 -
  11.100 -        if (live == -1) flags |= XCFLAGS_LIVE; /* default to live for tcp */
  11.101 -
  11.102 -        strncpy( server, state_file+strlen("tcp://"), max_namelen);
  11.103 -        server[max_namelen-1]='\0';
  11.104 -        if ( (port_s = strchr(server,':')) != NULL )
  11.105 -        {
  11.106 -            *port_s = '\0';
  11.107 -            port = atoi(port_s+1);
  11.108 -        }
  11.109 -
  11.110 -        printf("X server=%s port=%d\n",server,port);
  11.111 - 
  11.112 -        h = gethostbyname(server);
  11.113 -        sd = socket (AF_INET,SOCK_STREAM,0);
  11.114 -        if ( sd < 0 )
  11.115 -            goto serr;
  11.116 -        s.sin_family = AF_INET;
  11.117 -        bcopy ( h->h_addr, &(s.sin_addr.s_addr), h->h_length);
  11.118 -        s.sin_port = htons(port);
  11.119 -        if ( connect(sd, (struct sockaddr *) &s, sizeof(s)) ) 
  11.120 -            goto serr;
  11.121 -
  11.122 -        sockbufsize=128*1024;
  11.123 -        if ( setsockopt(sd, SOL_SOCKET, SO_SNDBUF, 
  11.124 -                        &sockbufsize, sizeof sockbufsize) < 0 ) 
  11.125 -            goto serr;
  11.126 -
  11.127 -        if ( xc_linux_save(xc->xc_handle, dom, flags, 
  11.128 -                           writerfn, (void*)sd) == 0 )
  11.129 -        {
  11.130 -            if ( read( sd, &rc, sizeof(int) ) != sizeof(int) )
  11.131 -                goto serr;
  11.132 +    if ( xc_linux_save(xc->xc_handle, dom, flags, writerfn, (void*)sd) == 0 ) {
  11.133 +        if ( read( sd, &rc, sizeof(int) ) != sizeof(int) ) goto serr;
  11.134    
  11.135 -            if ( rc == 0 )
  11.136 -            {
  11.137 +        if ( rc == 0 ) {
  11.138                  printf("Migration succesful -- destroy local copy\n");
  11.139                  xc_domain_destroy(xc->xc_handle, dom);
  11.140                  close(sd);
  11.141                  Py_INCREF(zero);
  11.142                  return zero;
  11.143 -            }
  11.144 -            else
  11.145 -                errno = rc;
  11.146 +        } else {
  11.147 +            errno = rc;
  11.148          }
  11.149 +    }
  11.150  
  11.151 -    serr:
  11.152 -        printf("Migration failed -- restart local copy\n");
  11.153 -        xc_domain_unpause(xc->xc_handle, dom);
  11.154 -        PyErr_SetFromErrno(xc_error);
  11.155 -        if ( sd >= 0 ) close(sd);
  11.156 -        return NULL;
  11.157 -    }    
  11.158 -    else
  11.159 -    {
  11.160 +  serr:
  11.161 +    printf("Migration failed -- restart local copy\n");
  11.162 +    xc_domain_unpause(xc->xc_handle, dom);
  11.163 +    PyErr_SetFromErrno(xc_error);
  11.164 +    if ( sd >= 0 ) close(sd);
  11.165 +    return NULL;
  11.166 +
  11.167 +}
  11.168 +
  11.169 +static PyObject *file_save(XcObject *xc, u32 dom, char *state_file, unsigned flags){
  11.170          int fd = -1;
  11.171          gzFile gfd = NULL;
  11.172  
  11.173 -        int writerfn(void *fd, const void *buf, size_t count)
  11.174 -        {
  11.175 +        int writerfn(void *fd, const void *buf, size_t count) {
  11.176              int rc;
  11.177              while ( ((rc = gzwrite( (gzFile*)fd, (void*)buf, count)) == -1) && 
  11.178                      (errno = EINTR) )
  11.179 @@ -300,30 +263,24 @@ static PyObject *pyxc_linux_save(PyObjec
  11.180              return ! (rc == count);
  11.181          }
  11.182  
  11.183 -        if (strncmp(state_file,"file:",strlen("file:")) == 0)
  11.184 +        if (strncmp(state_file,"file:",strlen("file:")) == 0){
  11.185              state_file += strlen("file:");
  11.186 +        }
  11.187  
  11.188 -        if ( (fd = open(state_file, O_CREAT|O_EXCL|O_WRONLY, 0644)) == -1 )
  11.189 -        {
  11.190 +        if ( (fd = open(state_file, O_CREAT|O_EXCL|O_WRONLY, 0644)) == -1 ) {
  11.191              perror("Could not open file for writing");
  11.192              goto err;
  11.193          }
  11.194 -
  11.195          /*
  11.196           * Compression rate 1: we want speed over compression. 
  11.197           * We're mainly going for those zero pages, after all.
  11.198           */
  11.199 -
  11.200 -        if ( (gfd = gzdopen(fd, "wb1")) == NULL )
  11.201 -        {
  11.202 +        if ( (gfd = gzdopen(fd, "wb1")) == NULL ) {
  11.203              perror("Could not allocate compression state for state file");
  11.204              close(fd);
  11.205              goto err;
  11.206          }
  11.207 -
  11.208 -
  11.209 -        if ( xc_linux_save(xc->xc_handle, dom, flags, writerfn, gfd) == 0 )
  11.210 -        {
  11.211 +        if ( xc_linux_save(xc->xc_handle, dom, flags, writerfn, gfd) == 0 ) {
  11.212              /* kill domain. We don't want to do this for checkpointing, but
  11.213                 if we don't do it here I think people will hurt themselves
  11.214                 by accident... */
  11.215 @@ -337,14 +294,45 @@ static PyObject *pyxc_linux_save(PyObjec
  11.216  
  11.217      err:
  11.218          PyErr_SetFromErrno(xc_error);
  11.219 -        if ( gfd != NULL )
  11.220 -            gzclose(gfd);
  11.221 -        if ( fd >= 0 )
  11.222 -            close(fd);
  11.223 +        if ( gfd != NULL ) gzclose(gfd);
  11.224 +        if ( fd >= 0 ) close(fd);
  11.225          unlink(state_file);
  11.226          return NULL;
  11.227 +}
  11.228 +
  11.229 +static PyObject *pyxc_linux_save(PyObject *self,
  11.230 +                                 PyObject *args,
  11.231 +                                 PyObject *kwds)
  11.232 +{
  11.233 +    XcObject *xc = (XcObject *)self;
  11.234 +
  11.235 +    u32   dom;
  11.236 +    char *state_file;
  11.237 +    int   progress = 1, live = -1, debug = 0;
  11.238 +    unsigned int flags = 0;
  11.239 +    PyObject *val = NULL;
  11.240 +
  11.241 +    static char *kwd_list[] = { "dom", "state_file", "progress", 
  11.242 +                                "live", "debug", NULL };
  11.243 +
  11.244 +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|iii", kwd_list, 
  11.245 +                                      &dom, &state_file, &progress, 
  11.246 +                                      &live, &debug) )
  11.247 +        goto exit;
  11.248 +
  11.249 +    if (progress)  flags |= XCFLAGS_VERBOSE;
  11.250 +    if (live == 1) flags |= XCFLAGS_LIVE;
  11.251 +    if (debug)     flags |= XCFLAGS_DEBUG;
  11.252 +
  11.253 +    if ( strncmp(state_file,"tcp:", strlen("tcp:")) == 0 ) {
  11.254 +        /* default to live for tcp */
  11.255 +        if (live == -1) flags |= XCFLAGS_LIVE;
  11.256 +        val = tcp_save(xc, dom, state_file, flags);
  11.257 +    } else {
  11.258 +        val = file_save(xc, dom, state_file, flags);
  11.259      }
  11.260 -
  11.261 +  exit:
  11.262 +    return val;
  11.263  }
  11.264  
  11.265  static PyObject *pyxc_linux_restore(PyObject *self,
  11.266 @@ -1335,18 +1323,18 @@ static PyTypeObject PyXcType = {
  11.267  };
  11.268  
  11.269  static PyMethodDef PyXc_methods[] = {
  11.270 -    { "new", PyXc_new, METH_VARARGS, "Create a new Xc object." },
  11.271 +    { "new", PyXc_new, METH_VARARGS, "Create a new " XENPKG " object." },
  11.272      { NULL, NULL, 0, NULL }
  11.273  };
  11.274  
  11.275 -PyMODINIT_FUNC initXc(void)
  11.276 +PyMODINIT_FUNC initxc(void)
  11.277  {
  11.278      PyObject *m, *d;
  11.279  
  11.280 -    m = Py_InitModule("Xc", PyXc_methods);
  11.281 +    m = Py_InitModule(XENPKG, PyXc_methods);
  11.282  
  11.283      d = PyModule_GetDict(m);
  11.284 -    xc_error = PyErr_NewException("Xc.error", NULL, NULL);
  11.285 +    xc_error = PyErr_NewException(XENPKG ".error", NULL, NULL);
  11.286      PyDict_SetItemString(d, "error", xc_error);
  11.287  
  11.288      zero = PyInt_FromLong(0);
    12.1 --- a/tools/xc/py/setup.py	Sun Jun 27 22:35:07 2004 +0000
    12.2 +++ b/tools/xc/py/setup.py	Mon Jun 28 08:20:16 2004 +0000
    12.3 @@ -1,11 +1,14 @@
    12.4  
    12.5  from distutils.core import setup, Extension
    12.6  
    12.7 -module = Extension("Xc",
    12.8 +module = Extension("xc",
    12.9                     extra_compile_args   = ["-fno-strict-aliasing"],
   12.10                     include_dirs         = ["../lib"],
   12.11                     library_dirs         = ["../lib"],
   12.12                     libraries            = ["xc"],
   12.13                     sources              = ["Xc.c"])
   12.14  
   12.15 -setup(name = "Xc", version = "1.0", ext_modules = [module])
   12.16 +setup(name = "xc",
   12.17 +      version = "1.0",
   12.18 +      ext_package = "xen.ext",
   12.19 +      ext_modules = [module])
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/tools/xen/Makefile	Mon Jun 28 08:20:16 2004 +0000
    13.3 @@ -0,0 +1,19 @@
    13.4 +
    13.5 +all:
    13.6 +	python setup.py build
    13.7 +
    13.8 +install: all
    13.9 +	if [ "$(prefix)" = "" ]; then                   \
   13.10 +	    python setup.py install;                    \
   13.11 +	elif [ "$(dist)" = "yes" ]; then                \
   13.12 +	    python setup.py install --home="$(prefix)"; \
   13.13 +	else                                            \
   13.14 +	    python setup.py install --root="$(prefix)"; \
   13.15 +	fi
   13.16 +	mkdir -p $(prefix)/usr/sbin
   13.17 +	install -m0755 xend $(prefix)/usr/sbin
   13.18 +	install -m0755 netfix $(prefix)/usr/sbin
   13.19 +	install -m0755 xm $(prefix)/usr/sbin
   13.20 +
   13.21 +clean:
   13.22 +	rm -rf build *.pyc *.pyo *.o *.a *~
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/tools/xen/lib/__init__.py	Mon Jun 28 08:20:16 2004 +0000
    14.3 @@ -0,0 +1,1 @@
    14.4 + 
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/tools/xen/lib/ext/__init__.py	Mon Jun 28 08:20:16 2004 +0000
    15.3 @@ -0,0 +1,1 @@
    15.4 + 
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/tools/xen/lib/util/__init__.py	Mon Jun 28 08:20:16 2004 +0000
    16.3 @@ -0,0 +1,1 @@
    16.4 + 
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/tools/xen/lib/util/console_client.py	Mon Jun 28 08:20:16 2004 +0000
    17.3 @@ -0,0 +1,82 @@
    17.4 +#!/usr/bin/env python
    17.5 +
    17.6 +##############################################
    17.7 +# Console client for Xen guest OSes
    17.8 +# Copyright (c) 2004, K A Fraser
    17.9 +##############################################
   17.10 +
   17.11 +import errno, os, signal, socket, struct, sys
   17.12 +
   17.13 +from termios import *
   17.14 +# Indexes into termios.tcgetattr() list.
   17.15 +IFLAG  = 0
   17.16 +OFLAG  = 1
   17.17 +CFLAG  = 2
   17.18 +LFLAG  = 3
   17.19 +ISPEED = 4
   17.20 +OSPEED = 5
   17.21 +CC     = 6
   17.22 +
   17.23 +def __child_death(signum, frame):
   17.24 +    global stop
   17.25 +    stop = True
   17.26 +
   17.27 +def __recv_from_sock(sock):
   17.28 +    global stop
   17.29 +    stop = False
   17.30 +    while not stop:
   17.31 +        try:
   17.32 +            data = sock.recv(1024)
   17.33 +            os.write(1, data)
   17.34 +        except socket.error, error:
   17.35 +            if error[0] != errno.EINTR:
   17.36 +                raise
   17.37 +    os.wait()
   17.38 +
   17.39 +def __send_to_sock(sock):
   17.40 +    while 1:
   17.41 +        data = os.read(0,1024)
   17.42 +        if ord(data[0]) == ord(']')-64:
   17.43 +            break
   17.44 +        try:
   17.45 +            sock.send(data)
   17.46 +        except socket.error, error:
   17.47 +            if error[0] == errno.EPIPE:
   17.48 +                sys.exit(0)
   17.49 +            if error[0] != errno.EINTR:
   17.50 +                raise
   17.51 +    sys.exit(0)
   17.52 +
   17.53 +def connect(host,port):
   17.54 +    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
   17.55 +    sock.connect((host,port))
   17.56 +
   17.57 +    oattrs = tcgetattr(0)
   17.58 +    nattrs = tcgetattr(0)
   17.59 +    nattrs[IFLAG] = nattrs[IFLAG] & ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON)
   17.60 +    nattrs[OFLAG] = nattrs[OFLAG] & ~(OPOST)
   17.61 +    nattrs[CFLAG] = nattrs[CFLAG] & ~(CSIZE | PARENB)
   17.62 +    nattrs[CFLAG] = nattrs[CFLAG] | CS8
   17.63 +    nattrs[LFLAG] = nattrs[LFLAG] & ~(ECHO | ICANON | IEXTEN | ISIG)
   17.64 +    nattrs[CC][VMIN] = 1
   17.65 +    nattrs[CC][VTIME] = 0
   17.66 +
   17.67 +    if os.fork():
   17.68 +        signal.signal(signal.SIGCHLD, __child_death)
   17.69 +        print "************ REMOTE CONSOLE: CTRL-] TO QUIT ********"
   17.70 +        tcsetattr(0, TCSAFLUSH, nattrs)
   17.71 +        try:
   17.72 +            __recv_from_sock(sock)
   17.73 +        finally:
   17.74 +            tcsetattr(0, TCSAFLUSH, oattrs)
   17.75 +            print
   17.76 +            print "************ REMOTE CONSOLE EXITED *****************"
   17.77 +    else:
   17.78 +        signal.signal(signal.SIGPIPE, signal.SIG_IGN)
   17.79 +        __send_to_sock(sock)
   17.80 +
   17.81 +if __name__ == '__main__':
   17.82 +    if len(sys.argv) != 3:
   17.83 +        print sys.argv[0] + " <host> <port>"
   17.84 +        sys.exit(1)
   17.85 +    connect(str(sys.argv[1]),int(sys.argv[2]))
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/tools/xen/lib/util/ip.py	Mon Jun 28 08:20:16 2004 +0000
    18.3 @@ -0,0 +1,113 @@
    18.4 +import os
    18.5 +import re
    18.6 +import socket
    18.7 +import struct
    18.8 +
    18.9 +def readlines(fd):
   18.10 +    """Version of readlines safe against EINTR.
   18.11 +    """
   18.12 +    import errno
   18.13 +    
   18.14 +    lines = []
   18.15 +    while 1:
   18.16 +        try:
   18.17 +            line = fd.readline()
   18.18 +        except IOError, ex:
   18.19 +            if ex.errno == errno.EINTR:
   18.20 +                continue
   18.21 +            else:
   18.22 +                raise
   18.23 +        if line == '': break
   18.24 +        lines.append(line)
   18.25 +    return lines
   18.26 +
   18.27 +def readline(fd):
   18.28 +    """Version of readline safe against EINTR.
   18.29 +    """
   18.30 +    while 1:
   18.31 +        try:
   18.32 +            return fd.readline()
   18.33 +        except IOError, ex:
   18.34 +            if ex.errno == errno.EINTR:
   18.35 +                continue
   18.36 +            else:
   18.37 +                raise
   18.38 +
   18.39 +##### Networking-related functions
   18.40 +
   18.41 +"""Bridge for network backend.
   18.42 +When bridging is used, eth0 may not have an IP address,
   18.43 +as it may have been moved onto the bridge.
   18.44 +"""
   18.45 +NBE_BRIDGE = 'nbe-br'
   18.46 +
   18.47 +def get_current_ipaddr(dev='eth0'):
   18.48 +    """Return a string containing the primary IP address for the given
   18.49 +    network interface (default 'eth0').
   18.50 +    """
   18.51 +    fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' )
   18.52 +    lines = readlines(fd)
   18.53 +    for line in lines:
   18.54 +        m = re.search( '^\s+inet addr:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*',
   18.55 +                       line )
   18.56 +        if m:
   18.57 +            return m.group(1)
   18.58 +    if dev == 'eth0':
   18.59 +        return get_current_ipaddr(NBE_BRIDGE)
   18.60 +    return None
   18.61 +
   18.62 +def get_current_ipmask(dev='eth0'):
   18.63 +    """Return a string containing the primary IP netmask for the given
   18.64 +    network interface (default 'eth0').
   18.65 +    """
   18.66 +    fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' )
   18.67 +    lines = readlines(fd)
   18.68 +    for line in lines:
   18.69 +        m = re.search( '^.+Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*',
   18.70 +                       line )
   18.71 +        if m:
   18.72 +            return m.group(1)
   18.73 +    if dev == 'eth0':
   18.74 +        return get_current_ipmask(NBE_BRIDGE)
   18.75 +    return None
   18.76 +
   18.77 +def get_current_ipgw(dev='eth0'):
   18.78 +    """Return a string containing the IP gateway for the given
   18.79 +    network interface (default 'eth0').
   18.80 +    """
   18.81 +    fd = os.popen( '/sbin/route -n' )
   18.82 +    lines = readlines(fd)
   18.83 +    for line in lines:
   18.84 +        m = re.search( '^\S+\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)' +
   18.85 +                       '\s+\S+\s+\S*G.*' + dev + '.*', line )
   18.86 +        if m:
   18.87 +            return m.group(1)
   18.88 +    if dev == 'eth0':
   18.89 +        return get_current_ipgw(NBE_BRIDGE)
   18.90 +    return None
   18.91 +
   18.92 +def inet_aton(addr):
   18.93 +    """Convert an IP addr in IPv4 dot notation into an int.
   18.94 +    """
   18.95 +    b = socket.inet_aton(addr)
   18.96 +    return struct.unpack('!I', b)[0]
   18.97 +
   18.98 +def inet_ntoa(n):
   18.99 +    """Convert an int into an IP addr in IPv4 dot notation.
  18.100 +    """
  18.101 +    b = struct.pack('!I', n)
  18.102 +    return socket.inet_ntoa(b)
  18.103 +
  18.104 +def add_offset_to_ip(addr, offset):
  18.105 +    """Add a numerical offset to an IP addr in IPv4 dot notation.
  18.106 +    """
  18.107 +    n = inet_aton(addr)
  18.108 +    n += offset
  18.109 +    return inet_ntoa(n)
  18.110 +
  18.111 +def check_subnet( ip, network, netmask ):
  18.112 +    n_ip = inet_aton(ip)
  18.113 +    n_net = inet_aton(network)
  18.114 +    n_mask = inet_aton(netmask)
  18.115 +    return (n_ip & n_mask) == (n_net & n_mask)
  18.116 +
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/tools/xen/lib/util/tempfile.py	Mon Jun 28 08:20:16 2004 +0000
    19.3 @@ -0,0 +1,451 @@
    19.4 +"""Temporary files.
    19.5 +
    19.6 +This module provides generic, low- and high-level interfaces for
    19.7 +creating temporary files and directories.  The interfaces listed
    19.8 +as "safe" just below can be used without fear of race conditions.
    19.9 +Those listed as "unsafe" cannot, and are provided for backward
   19.10 +compatibility only.
   19.11 +
   19.12 +This module also provides some data items to the user:
   19.13 +
   19.14 +  TMP_MAX  - maximum number of names that will be tried before
   19.15 +             giving up.
   19.16 +  template - the default prefix for all temporary names.
   19.17 +             You may change this to control the default prefix.
   19.18 +  tempdir  - If this is set to a string before the first use of
   19.19 +             any routine from this module, it will be considered as
   19.20 +             another candidate location to store temporary files.
   19.21 +"""
   19.22 +
   19.23 +__all__ = [
   19.24 +    "NamedTemporaryFile", "TemporaryFile", # high level safe interfaces
   19.25 +    "mkstemp", "mkdtemp",                  # low level safe interfaces
   19.26 +    "mktemp",                              # deprecated unsafe interface
   19.27 +    "TMP_MAX", "gettempprefix",            # constants
   19.28 +    "tempdir", "gettempdir"
   19.29 +   ]
   19.30 +
   19.31 +
   19.32 +# Imports.
   19.33 +
   19.34 +import os as _os
   19.35 +import errno as _errno
   19.36 +from random import Random as _Random
   19.37 +
   19.38 +if _os.name == 'mac':
   19.39 +    import Carbon.Folder as _Folder
   19.40 +    import Carbon.Folders as _Folders
   19.41 +
   19.42 +try:
   19.43 +    import fcntl as _fcntl
   19.44 +    # If PYTHONCASEOK is set on Windows, stinking FCNTL.py gets
   19.45 +    # imported, and we don't get an ImportError then.  Provoke
   19.46 +    # an AttributeError instead in that case.
   19.47 +    _fcntl.fcntl
   19.48 +except (ImportError, AttributeError):
   19.49 +    def _set_cloexec(fd):
   19.50 +        pass
   19.51 +else:
   19.52 +    def _set_cloexec(fd):
   19.53 +        flags = _fcntl.fcntl(fd, _fcntl.F_GETFD, 0)
   19.54 +        if flags >= 0:
   19.55 +            # flags read successfully, modify
   19.56 +            flags |= _fcntl.FD_CLOEXEC
   19.57 +            _fcntl.fcntl(fd, _fcntl.F_SETFD, flags)
   19.58 +
   19.59 +
   19.60 +try:
   19.61 +    import thread as _thread
   19.62 +except ImportError:
   19.63 +    import dummy_thread as _thread
   19.64 +_allocate_lock = _thread.allocate_lock
   19.65 +
   19.66 +_text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL
   19.67 +if hasattr(_os, 'O_NOINHERIT'):
   19.68 +    _text_openflags |= _os.O_NOINHERIT
   19.69 +if hasattr(_os, 'O_NOFOLLOW'):
   19.70 +    _text_openflags |= _os.O_NOFOLLOW
   19.71 +
   19.72 +_bin_openflags = _text_openflags
   19.73 +if hasattr(_os, 'O_BINARY'):
   19.74 +    _bin_openflags |= _os.O_BINARY
   19.75 +
   19.76 +if hasattr(_os, 'TMP_MAX'):
   19.77 +    TMP_MAX = _os.TMP_MAX
   19.78 +else:
   19.79 +    TMP_MAX = 10000
   19.80 +
   19.81 +template = "tmp"
   19.82 +
   19.83 +tempdir = None
   19.84 +
   19.85 +# Internal routines.
   19.86 +
   19.87 +_once_lock = _allocate_lock()
   19.88 +
   19.89 +class _RandomNameSequence:
   19.90 +    """An instance of _RandomNameSequence generates an endless
   19.91 +    sequence of unpredictable strings which can safely be incorporated
   19.92 +    into file names.  Each string is six characters long.  Multiple
   19.93 +    threads can safely use the same instance at the same time.
   19.94 +
   19.95 +    _RandomNameSequence is an iterator."""
   19.96 +
   19.97 +    characters = ("abcdefghijklmnopqrstuvwxyz" +
   19.98 +                  "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
   19.99 +                  "0123456789-_")
  19.100 +
  19.101 +    def __init__(self):
  19.102 +        self.mutex = _allocate_lock()
  19.103 +        self.rng = _Random()
  19.104 +        self.normcase = _os.path.normcase
  19.105 +
  19.106 +    def __iter__(self):
  19.107 +        return self
  19.108 +
  19.109 +    def next(self):
  19.110 +        m = self.mutex
  19.111 +        c = self.characters
  19.112 +        choose = self.rng.choice
  19.113 +
  19.114 +        m.acquire()
  19.115 +        try:
  19.116 +            letters = [choose(c) for dummy in "123456"]
  19.117 +        finally:
  19.118 +            m.release()
  19.119 +
  19.120 +        return self.normcase(''.join(letters))
  19.121 +
  19.122 +def _candidate_tempdir_list():
  19.123 +    """Generate a list of candidate temporary directories which
  19.124 +    _get_default_tempdir will try."""
  19.125 +
  19.126 +    dirlist = []
  19.127 +
  19.128 +    # First, try the environment.
  19.129 +    for envname in 'TMPDIR', 'TEMP', 'TMP':
  19.130 +        dirname = _os.getenv(envname)
  19.131 +        if dirname: dirlist.append(dirname)
  19.132 +
  19.133 +    # Failing that, try OS-specific locations.
  19.134 +    if _os.name == 'mac':
  19.135 +        try:
  19.136 +            fsr = _Folder.FSFindFolder(_Folders.kOnSystemDisk,
  19.137 +                                              _Folders.kTemporaryFolderType, 1)
  19.138 +            dirname = fsr.as_pathname()
  19.139 +            dirlist.append(dirname)
  19.140 +        except _Folder.error:
  19.141 +            pass
  19.142 +    elif _os.name == 'riscos':
  19.143 +        dirname = _os.getenv('Wimp$ScrapDir')
  19.144 +        if dirname: dirlist.append(dirname)
  19.145 +    elif _os.name == 'nt':
  19.146 +        dirlist.extend([ r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ])
  19.147 +    else:
  19.148 +        dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ])
  19.149 +
  19.150 +    # As a last resort, the current directory.
  19.151 +    try:
  19.152 +        dirlist.append(_os.getcwd())
  19.153 +    except (AttributeError, _os.error):
  19.154 +        dirlist.append(_os.curdir)
  19.155 +
  19.156 +    return dirlist
  19.157 +
  19.158 +def _get_default_tempdir():
  19.159 +    """Calculate the default directory to use for temporary files.
  19.160 +    This routine should be called exactly once.
  19.161 +
  19.162 +    We determine whether or not a candidate temp dir is usable by
  19.163 +    trying to create and write to a file in that directory.  If this
  19.164 +    is successful, the test file is deleted.  To prevent denial of
  19.165 +    service, the name of the test file must be randomized."""
  19.166 +
  19.167 +    namer = _RandomNameSequence()
  19.168 +    dirlist = _candidate_tempdir_list()
  19.169 +    flags = _text_openflags
  19.170 +
  19.171 +    for dir in dirlist:
  19.172 +        if dir != _os.curdir:
  19.173 +            dir = _os.path.normcase(_os.path.abspath(dir))
  19.174 +        # Try only a few names per directory.
  19.175 +        for seq in xrange(100):
  19.176 +            name = namer.next()
  19.177 +            filename = _os.path.join(dir, name)
  19.178 +            try:
  19.179 +                fd = _os.open(filename, flags, 0600)
  19.180 +                fp = _os.fdopen(fd, 'w')
  19.181 +                fp.write('blat')
  19.182 +                fp.close()
  19.183 +                _os.unlink(filename)
  19.184 +                del fp, fd
  19.185 +                return dir
  19.186 +            except (OSError, IOError), e:
  19.187 +                if e[0] != _errno.EEXIST:
  19.188 +                    break # no point trying more names in this directory
  19.189 +                pass
  19.190 +    raise IOError, (_errno.ENOENT,
  19.191 +                    ("No usable temporary directory found in %s" % dirlist))
  19.192 +
  19.193 +_name_sequence = None
  19.194 +
  19.195 +def _get_candidate_names():
  19.196 +    """Common setup sequence for all user-callable interfaces."""
  19.197 +
  19.198 +    global _name_sequence
  19.199 +    if _name_sequence is None:
  19.200 +        _once_lock.acquire()
  19.201 +        try:
  19.202 +            if _name_sequence is None:
  19.203 +                _name_sequence = _RandomNameSequence()
  19.204 +        finally:
  19.205 +            _once_lock.release()
  19.206 +    return _name_sequence
  19.207 +
  19.208 +
  19.209 +def _mkstemp_inner(dir, pre, suf, flags):
  19.210 +    """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile."""
  19.211 +
  19.212 +    names = _get_candidate_names()
  19.213 +
  19.214 +    for seq in xrange(TMP_MAX):
  19.215 +        name = names.next()
  19.216 +        file = _os.path.join(dir, pre + name + suf)
  19.217 +        try:
  19.218 +            fd = _os.open(file, flags, 0600)
  19.219 +            _set_cloexec(fd)
  19.220 +            return (fd, file)
  19.221 +        except OSError, e:
  19.222 +            if e.errno == _errno.EEXIST:
  19.223 +                continue # try again
  19.224 +            raise
  19.225 +
  19.226 +    raise IOError, (_errno.EEXIST, "No usable temporary file name found")
  19.227 +
  19.228 +
  19.229 +# User visible interfaces.
  19.230 +
  19.231 +def gettempprefix():
  19.232 +    """Accessor for tempdir.template."""
  19.233 +    return template
  19.234 +
  19.235 +tempdir = None
  19.236 +
  19.237 +def gettempdir():
  19.238 +    """Accessor for tempdir.tempdir."""
  19.239 +    global tempdir
  19.240 +    if tempdir is None:
  19.241 +        _once_lock.acquire()
  19.242 +        try:
  19.243 +            if tempdir is None:
  19.244 +                tempdir = _get_default_tempdir()
  19.245 +        finally:
  19.246 +            _once_lock.release()
  19.247 +    return tempdir
  19.248 +
  19.249 +def mkstemp(suffix="", prefix=template, dir=None, text=False):
  19.250 +    """mkstemp([suffix, [prefix, [dir, [text]]]])
  19.251 +    User-callable function to create and return a unique temporary
  19.252 +    file.  The return value is a pair (fd, name) where fd is the
  19.253 +    file descriptor returned by os.open, and name is the filename.
  19.254 +
  19.255 +    If 'suffix' is specified, the file name will end with that suffix,
  19.256 +    otherwise there will be no suffix.
  19.257 +
  19.258 +    If 'prefix' is specified, the file name will begin with that prefix,
  19.259 +    otherwise a default prefix is used.
  19.260 +
  19.261 +    If 'dir' is specified, the file will be created in that directory,
  19.262 +    otherwise a default directory is used.
  19.263 +
  19.264 +    If 'text' is specified and true, the file is opened in text
  19.265 +    mode.  Else (the default) the file is opened in binary mode.  On
  19.266 +    some operating systems, this makes no difference.
  19.267 +
  19.268 +    The file is readable and writable only by the creating user ID.
  19.269 +    If the operating system uses permission bits to indicate whether a
  19.270 +    file is executable, the file is executable by no one. The file
  19.271 +    descriptor is not inherited by children of this process.
  19.272 +
  19.273 +    Caller is responsible for deleting the file when done with it.
  19.274 +    """
  19.275 +
  19.276 +    if dir is None:
  19.277 +        dir = gettempdir()
  19.278 +
  19.279 +    if text:
  19.280 +        flags = _text_openflags
  19.281 +    else:
  19.282 +        flags = _bin_openflags
  19.283 +
  19.284 +    return _mkstemp_inner(dir, prefix, suffix, flags)
  19.285 +
  19.286 +
  19.287 +def mkdtemp(suffix="", prefix=template, dir=None):
  19.288 +    """mkdtemp([suffix, [prefix, [dir]]])
  19.289 +    User-callable function to create and return a unique temporary
  19.290 +    directory.  The return value is the pathname of the directory.
  19.291 +
  19.292 +    Arguments are as for mkstemp, except that the 'text' argument is
  19.293 +    not accepted.
  19.294 +
  19.295 +    The directory is readable, writable, and searchable only by the
  19.296 +    creating user.
  19.297 +
  19.298 +    Caller is responsible for deleting the directory when done with it.
  19.299 +    """
  19.300 +
  19.301 +    if dir is None:
  19.302 +        dir = gettempdir()
  19.303 +
  19.304 +    names = _get_candidate_names()
  19.305 +
  19.306 +    for seq in xrange(TMP_MAX):
  19.307 +        name = names.next()
  19.308 +        file = _os.path.join(dir, prefix + name + suffix)
  19.309 +        try:
  19.310 +            _os.mkdir(file, 0700)
  19.311 +            return file
  19.312 +        except OSError, e:
  19.313 +            if e.errno == _errno.EEXIST:
  19.314 +                continue # try again
  19.315 +            raise
  19.316 +
  19.317 +    raise IOError, (_errno.EEXIST, "No usable temporary directory name found")
  19.318 +
  19.319 +def mktemp(suffix="", prefix=template, dir=None):
  19.320 +    """mktemp([suffix, [prefix, [dir]]])
  19.321 +    User-callable function to return a unique temporary file name.  The
  19.322 +    file is not created.
  19.323 +
  19.324 +    Arguments are as for mkstemp, except that the 'text' argument is
  19.325 +    not accepted.
  19.326 +
  19.327 +    This function is unsafe and should not be used.  The file name
  19.328 +    refers to a file that did not exist at some point, but by the time
  19.329 +    you get around to creating it, someone else may have beaten you to
  19.330 +    the punch.
  19.331 +    """
  19.332 +
  19.333 +##    from warnings import warn as _warn
  19.334 +##    _warn("mktemp is a potential security risk to your program",
  19.335 +##          RuntimeWarning, stacklevel=2)
  19.336 +
  19.337 +    if dir is None:
  19.338 +        dir = gettempdir()
  19.339 +
  19.340 +    names = _get_candidate_names()
  19.341 +    for seq in xrange(TMP_MAX):
  19.342 +        name = names.next()
  19.343 +        file = _os.path.join(dir, prefix + name + suffix)
  19.344 +        if not _os.path.exists(file):
  19.345 +            return file
  19.346 +
  19.347 +    raise IOError, (_errno.EEXIST, "No usable temporary filename found")
  19.348 +
  19.349 +class _TemporaryFileWrapper:
  19.350 +    """Temporary file wrapper
  19.351 +
  19.352 +    This class provides a wrapper around files opened for
  19.353 +    temporary use.  In particular, it seeks to automatically
  19.354 +    remove the file when it is no longer needed.
  19.355 +    """
  19.356 +
  19.357 +    def __init__(self, file, name):
  19.358 +        self.file = file
  19.359 +        self.name = name
  19.360 +        self.close_called = False
  19.361 +
  19.362 +    def __getattr__(self, name):
  19.363 +        file = self.__dict__['file']
  19.364 +        a = getattr(file, name)
  19.365 +        if type(a) != type(0):
  19.366 +            setattr(self, name, a)
  19.367 +        return a
  19.368 +
  19.369 +    # NT provides delete-on-close as a primitive, so we don't need
  19.370 +    # the wrapper to do anything special.  We still use it so that
  19.371 +    # file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile.
  19.372 +    if _os.name != 'nt':
  19.373 +
  19.374 +        # Cache the unlinker so we don't get spurious errors at
  19.375 +        # shutdown when the module-level "os" is None'd out.  Note
  19.376 +        # that this must be referenced as self.unlink, because the
  19.377 +        # name TemporaryFileWrapper may also get None'd out before
  19.378 +        # __del__ is called.
  19.379 +        unlink = _os.unlink
  19.380 +
  19.381 +        def close(self):
  19.382 +            if not self.close_called:
  19.383 +                self.close_called = True
  19.384 +                self.file.close()
  19.385 +                self.unlink(self.name)
  19.386 +
  19.387 +        def __del__(self):
  19.388 +            self.close()
  19.389 +
  19.390 +def NamedTemporaryFile(mode='w+b', bufsize=-1, suffix="",
  19.391 +                       prefix=template, dir=None):
  19.392 +    """Create and return a temporary file.
  19.393 +    Arguments:
  19.394 +    'prefix', 'suffix', 'dir' -- as for mkstemp.
  19.395 +    'mode' -- the mode argument to os.fdopen (default "w+b").
  19.396 +    'bufsize' -- the buffer size argument to os.fdopen (default -1).
  19.397 +    The file is created as mkstemp() would do it.
  19.398 +
  19.399 +    Returns a file object; the name of the file is accessible as
  19.400 +    file.name.  The file will be automatically deleted when it is
  19.401 +    closed.
  19.402 +    """
  19.403 +
  19.404 +    if dir is None:
  19.405 +        dir = gettempdir()
  19.406 +
  19.407 +    if 'b' in mode:
  19.408 +        flags = _bin_openflags
  19.409 +    else:
  19.410 +        flags = _text_openflags
  19.411 +
  19.412 +    # Setting O_TEMPORARY in the flags causes the OS to delete
  19.413 +    # the file when it is closed.  This is only supported by Windows.
  19.414 +    if _os.name == 'nt':
  19.415 +        flags |= _os.O_TEMPORARY
  19.416 +
  19.417 +    (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
  19.418 +    file = _os.fdopen(fd, mode, bufsize)
  19.419 +    return _TemporaryFileWrapper(file, name)
  19.420 +
  19.421 +if _os.name != 'posix' or _os.sys.platform == 'cygwin':
  19.422 +    # On non-POSIX and Cygwin systems, assume that we cannot unlink a file
  19.423 +    # while it is open.
  19.424 +    TemporaryFile = NamedTemporaryFile
  19.425 +
  19.426 +else:
  19.427 +    def TemporaryFile(mode='w+b', bufsize=-1, suffix="",
  19.428 +                      prefix=template, dir=None):
  19.429 +        """Create and return a temporary file.
  19.430 +        Arguments:
  19.431 +        'prefix', 'suffix', 'directory' -- as for mkstemp.
  19.432 +        'mode' -- the mode argument to os.fdopen (default "w+b").
  19.433 +        'bufsize' -- the buffer size argument to os.fdopen (default -1).
  19.434 +        The file is created as mkstemp() would do it.
  19.435 +
  19.436 +        Returns a file object.  The file has no name, and will cease to
  19.437 +        exist when it is closed.
  19.438 +        """
  19.439 +
  19.440 +        if dir is None:
  19.441 +            dir = gettempdir()
  19.442 +
  19.443 +        if 'b' in mode:
  19.444 +            flags = _bin_openflags
  19.445 +        else:
  19.446 +            flags = _text_openflags
  19.447 +
  19.448 +        (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
  19.449 +        try:
  19.450 +            _os.unlink(name)
  19.451 +            return _os.fdopen(fd, mode, bufsize)
  19.452 +        except:
  19.453 +            _os.close(fd)
  19.454 +            raise
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/tools/xen/lib/xend/Args.py	Mon Jun 28 08:20:16 2004 +0000
    20.3 @@ -0,0 +1,126 @@
    20.4 +import sxp
    20.5 +
    20.6 +class ArgError(StandardError):
    20.7 +    pass
    20.8 +
    20.9 +class Args:
   20.10 +    """Argument encoding support for HTTP.
   20.11 +    """
   20.12 +    
   20.13 +    def __init__(self, paramspec, keyspec):
   20.14 +        self.arg_ord = []
   20.15 +        self.arg_dict = {}
   20.16 +        self.key_ord = []
   20.17 +        self.key_dict = {}
   20.18 +        for (name, type) in paramspec:
   20.19 +                self.arg_ord.append(name)
   20.20 +                self.arg_dict[name] = type
   20.21 +        for (name, type) in keyspec:
   20.22 +                self.key_ord.append(name)
   20.23 +                self.key_dict[name] = type
   20.24 +
   20.25 +    def get_args(self, d, xargs=None):
   20.26 +        args = {}
   20.27 +        keys = {}
   20.28 +        params = []
   20.29 +        if xargs:
   20.30 +            self.split_args(xargs, args, keys)
   20.31 +        self.split_args(d, args, keys)
   20.32 +        for a in self.arg_ord:
   20.33 +            if a in args:
   20.34 +                params.append(args[a])
   20.35 +            else:
   20.36 +                raise ArgError('Missing parameter: %s' % a)
   20.37 +        return (params, keys)
   20.38 +
   20.39 +    def split_args(self, d, args, keys):
   20.40 +        for (k, v) in d.items():
   20.41 +            if k in self.arg_dict:
   20.42 +                type = self.arg_dict[k]
   20.43 +                val = self.coerce(type, v)
   20.44 +                args[k] = val
   20.45 +            elif k in self.key_dict:
   20.46 +                type = self.key_dict[k]
   20.47 +                val = self.coerce(type, v)
   20.48 +                keys[k] = val
   20.49 +            else:
   20.50 +                raise ArgError('Invalid parameter: %s' % k)
   20.51 +
   20.52 +    def get_form_args(self, f, xargs=None):
   20.53 +        d = {}
   20.54 +        for (k, v) in f.items():
   20.55 +            n = len(v)
   20.56 +            if ((k not in self.arg_dict) and
   20.57 +                (k not in self.key_dict)):
   20.58 +                continue
   20.59 +            if n == 0:
   20.60 +                continue
   20.61 +            elif n == 1:
   20.62 +                d[k] = v[0]
   20.63 +            else:
   20.64 +                raise ArgError('Too many values for %s' % k)
   20.65 +        return self.get_args(d, xargs=xargs)
   20.66 +
   20.67 +    def coerce(self, type, v):
   20.68 +        try:
   20.69 +            if type == 'int':
   20.70 +                return int(v)
   20.71 +            if type == 'str':
   20.72 +                return str(v)
   20.73 +            if type == 'sxpr':
   20.74 +                return self.sxpr(v)
   20.75 +        except ArgError:
   20.76 +            raise
   20.77 +        except StandardError, ex:
   20.78 +            raise ArgError(str(ex))
   20.79 +
   20.80 +    def sxpr(self, v):
   20.81 +        if instanceof(v, types.ListType):
   20.82 +            return v
   20.83 +        if instanceof(v, types.File) or hasattr(v, 'readline'):
   20.84 +            return sxpr_file(v)
   20.85 +        if instanceof(v, types.StringType):
   20.86 +            return sxpr_file(StringIO(v))
   20.87 +        return str(v)
   20.88 +
   20.89 +    def sxpr_file(self, fin):
   20.90 +        try:
   20.91 +            vals = sxp.parse(fin)
   20.92 +        except:
   20.93 +            raise ArgError('Coercion to sxpr failed')
   20.94 +        if len(vals) == 1:
   20.95 +            return vals[0]
   20.96 +        else:
   20.97 +            raise ArgError('Too many sxprs')
   20.98 +
   20.99 +    def call_with_args(self, fn, args, xargs=None):
  20.100 +        (params, keys) = self.get_args(args, xargs=xargs)
  20.101 +        fn(*params, **keys)
  20.102 +
  20.103 +    def call_with_form_args(self, fn, fargs, xargs=None):
  20.104 +        (params, keys) = self.get_form_args(fargs, xargs=xargs)
  20.105 +        fn(*params, **keys)
  20.106 +
  20.107 +class ArgFn(Args):
  20.108 +    """Represent a remote HTTP operation as a function.
  20.109 +    Used on the client.
  20.110 +    """
  20.111 +
  20.112 +    def __init__(self, fn, paramspec, keyspec={}):
  20.113 +        Args.__init__(self, paramspec, keyspec)
  20.114 +        self.fn = fn
  20.115 +
  20.116 +    def __call__(self, fargs, xargs=None):
  20.117 +        return self.call_with_args(self.fn, fargs, xargs=xargs)
  20.118 +    
  20.119 +class FormFn(Args):
  20.120 +    """Represent an operation as a function over a form.
  20.121 +    Used in the HTTP server.
  20.122 +    """
  20.123 +
  20.124 +    def __init__(self, fn, paramspec, keyspec={}):
  20.125 +        Args.__init__(self, paramspec, keyspec)
  20.126 +        self.fn = fn
  20.127 +
  20.128 +    def __call__(self, fargs, xargs=None):
  20.129 +        return self.call_with_form_args(self.fn, fargs, xargs=xargs)
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/tools/xen/lib/xend/EventServer.py	Mon Jun 28 08:20:16 2004 +0000
    21.3 @@ -0,0 +1,215 @@
    21.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    21.5 +"""Simple publish/subscribe event server.
    21.6 +
    21.7 +"""
    21.8 +import string
    21.9 +
   21.10 +from twisted.internet import reactor
   21.11 +
   21.12 +# subscribe a.b.c h: map a.b.c -> h
   21.13 +# subscribe a.b.* h: map a.b.* -> h
   21.14 +# subscribe a.b.? h: map a.b.? -> h
   21.15 +#
   21.16 +# for event a.b.c.d:
   21.17 +#
   21.18 +# lookup a.b.c.d, call handlers
   21.19 +#
   21.20 +# lookup a.b.c.?, call handlers
   21.21 +#
   21.22 +# lookup a.b.c.d.*, call handlers
   21.23 +# lookup a.b.c.*, call handlers
   21.24 +# lookup a.b.*, call handlers
   21.25 +# lookup a.*, call handlers
   21.26 +# lookup *, call handlers
   21.27 +
   21.28 +# a.b.c.d = (a b c d)
   21.29 +# a.b.c.? = (a b c _)
   21.30 +# a.b.c.* = (a b c . _)
   21.31 +
   21.32 +class EventServer:
   21.33 +
   21.34 +    DOT = '.'
   21.35 +    QUERY = '?'
   21.36 +    DOT_QUERY = DOT + QUERY
   21.37 +    STAR = '*'
   21.38 +    DOT_STAR = DOT + STAR
   21.39 +
   21.40 +    def __init__(self, run=0):
   21.41 +        self.handlers = {}
   21.42 +        self.run = run
   21.43 +        self.queue = []
   21.44 +
   21.45 +    def start(self):
   21.46 +        """Enable event handling. Sends any queued events.
   21.47 +        """
   21.48 +        self.run = 1
   21.49 +        for (e,v) in self.queue:
   21.50 +            self.inject(e, v)
   21.51 +        self.queue = []
   21.52 +
   21.53 +    def stop(self):
   21.54 +        """Suspend event handling. Events injected while suspended
   21.55 +        are queued until we are started again.
   21.56 +        """
   21.57 +        self.run = 0
   21.58 +
   21.59 +    def subscribe(self, event, handler):
   21.60 +        """Subscribe to an event. For example 'a.b.c.d'.
   21.61 +        A subcription like 'a.b.c.?' ending in '?' matches any value
   21.62 +        for the '?'. A subscription like 'a.b.c.*' ending in '*' matches
   21.63 +        any event type with the same prefix, 'a.b.c' in this case.
   21.64 +
   21.65 +        event	event name
   21.66 +        handler event handler fn(event, val)
   21.67 +        """
   21.68 +        hl = self.handlers.get(event)
   21.69 +        if hl is None:
   21.70 +            self.handlers[event] = [handler]
   21.71 +        else:
   21.72 +            hl.append(handler)
   21.73 +
   21.74 +    def unsubscribe_all(self, event=None):
   21.75 +        """Unsubscribe all handlers for a given event, or all handlers.
   21.76 +
   21.77 +        event	event (optional)
   21.78 +        """
   21.79 +        if event == None:
   21.80 +            self.handlers.clear()
   21.81 +        elif event in self.handlers:
   21.82 +            del self.handlers[event]
   21.83 +        
   21.84 +    def unsubscribe(self, event, handler):
   21.85 +        """Unsubscribe a given event and handler.
   21.86 +
   21.87 +        event	event
   21.88 +        handler handler
   21.89 +        """
   21.90 +        hl = self.handlers.get(event)
   21.91 +        if hl is None:
   21.92 +            return
   21.93 +        if handler in hl:
   21.94 +            hl.remove(handler)
   21.95 +
   21.96 +    def inject(self, event, val, async=1):
   21.97 +        """Inject an event. Handlers for it are called if running, otherwise
   21.98 +        it is queued.
   21.99 +
  21.100 +        event	event type
  21.101 +        val	event value
  21.102 +        """
  21.103 +        if self.run:
  21.104 +            if async:
  21.105 +                reactor.callLater(0, self.call_handlers, event, val)
  21.106 +            else:
  21.107 +                self.notify_handlers(event, val)
  21.108 +        else:
  21.109 +            self.queue.append( (event, val) )
  21.110 +
  21.111 +    def call_handlers(self, event, val):
  21.112 +        """Internal method to call event handlers.
  21.113 +        """
  21.114 +        #print ">event", event, val
  21.115 +        self.call_event_handlers(event, event, val)
  21.116 +        self.call_query_handlers(event, val)
  21.117 +        self.call_star_handlers(event, val)
  21.118 +
  21.119 +    def call_event_handlers(self, key, event, val):
  21.120 +        """Call the handlers for an event.
  21.121 +        It is safe for handlers to subscribe or unsubscribe.
  21.122 +
  21.123 +        key	key for handler list
  21.124 +        event	event type
  21.125 +        val	event value
  21.126 +        """
  21.127 +        hl = self.handlers.get(key)
  21.128 +        if hl is None:
  21.129 +            return
  21.130 +        # Copy the handler list so that handlers can call
  21.131 +        # subscribe/unsubscribe safely - python list iteration
  21.132 +        # is not safe against list modification.
  21.133 +        for h in hl[:]:
  21.134 +            try:
  21.135 +                h(event, val)
  21.136 +            except:
  21.137 +                pass
  21.138 +        
  21.139 +    def call_query_handlers(self, event, val):
  21.140 +        """Call regex handlers for events matching 'event' that end in '?'.
  21.141 +
  21.142 +        event	event type
  21.143 +        val	event value
  21.144 +        """
  21.145 +        dot_idx = event.rfind(self.DOT)
  21.146 +        if dot_idx == -1:
  21.147 +            self.call_event_handlers(self.QUERY, event, val)
  21.148 +        else:
  21.149 +            event_query = event[0:dot_idx] + self.DOT_QUERY
  21.150 +            self.call_event_handlers(event_query, event, val)
  21.151 +
  21.152 +    def call_star_handlers(self, event, val):
  21.153 +        """Call regex handlers for events matching 'event' that end in '*'.
  21.154 +
  21.155 +        event	event type
  21.156 +        val	event value
  21.157 +        """
  21.158 +        etype = string.split(event, self.DOT)
  21.159 +        for i in range(len(etype), 0, -1):
  21.160 +            event_star = self.DOT.join(etype[0:i]) + self.DOT_STAR
  21.161 +            self.call_event_handlers(event_star, event, val)
  21.162 +        self.call_event_handlers(self.STAR, event, val)       
  21.163 +
  21.164 +def instance():
  21.165 +    global inst
  21.166 +    try:
  21.167 +        inst
  21.168 +    except:
  21.169 +        inst = EventServer()
  21.170 +        inst.start()
  21.171 +    return inst
  21.172 +
  21.173 +def main():
  21.174 +    def sys_star(event, val):
  21.175 +        print 'sys_star', event, val
  21.176 +
  21.177 +    def sys_foo(event, val):
  21.178 +        print 'sys_foo', event, val
  21.179 +        s.unsubscribe('sys.foo', sys_foo)
  21.180 +
  21.181 +    def sys_foo2(event, val):
  21.182 +        print 'sys_foo2', event, val
  21.183 +
  21.184 +    def sys_bar(event, val):
  21.185 +        print 'sys_bar', event, val
  21.186 +
  21.187 +    def sys_foo_bar(event, val):
  21.188 +        print 'sys_foo_bar', event, val
  21.189 +
  21.190 +    def foo_bar(event, val):
  21.191 +        print 'foo_bar', event, val
  21.192 +
  21.193 +    s = EventServer()
  21.194 +    s.start()
  21.195 +    s.subscribe('sys.*', sys_star)
  21.196 +    s.subscribe('sys.foo', sys_foo)
  21.197 +    s.subscribe('sys.foo', sys_foo2)
  21.198 +    s.subscribe('sys.bar', sys_bar)
  21.199 +    s.subscribe('sys.foo.bar', sys_foo_bar)
  21.200 +    s.subscribe('foo.bar', foo_bar)
  21.201 +    s.inject('sys.foo', 'hello')
  21.202 +    print
  21.203 +    s.inject('sys.bar', 'hello again')
  21.204 +    print
  21.205 +    s.inject('sys.foo.bar', 'hello again')
  21.206 +    print
  21.207 +    s.inject('foo.bar', 'hello again')
  21.208 +    print
  21.209 +    s.inject('foo', 'hello again')
  21.210 +    print
  21.211 +    s.start()
  21.212 +    s.unsubscribe('sys.*', sys_star)
  21.213 +    s.unsubscribe_all('sys.*')
  21.214 +    s.inject('sys.foo', 'hello')
  21.215 +
  21.216 +if __name__ == "__main__":
  21.217 +    main()
  21.218 +
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/tools/xen/lib/xend/EventTypes.py	Mon Jun 28 08:20:16 2004 +0000
    22.3 @@ -0,0 +1,34 @@
    22.4 +#   Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    22.5 +
    22.6 +## XEND_DOMAIN_CREATE = "xend.domain.create": dom
    22.7 +## create: 
    22.8 +## xend.domain.destroy: dom, reason:died/crashed
    22.9 +## xend.domain.up ?
   22.10 +
   22.11 +## xend.domain.unpause: dom
   22.12 +## xend.domain.pause: dom
   22.13 +## xend.domain.shutdown: dom
   22.14 +## xend.domain.destroy: dom
   22.15 +
   22.16 +## xend.domain.migrate.begin: dom, to
   22.17 +## Begin tells: src host, src domain uri, dst host. Dst id known?
   22.18 +## err: src host, src domain uri, dst host, dst id if known, status (of domain: ok, dead,...), reason
   22.19 +## end: src host, src domain uri, dst host, dst uri
   22.20 +
   22.21 +## Events for both ends of migrate: for exporter and importer?
   22.22 +## Include migrate id so can tie together.
   22.23 +## Have uri /xend/migrate/<id> for migrate info (migrations in progress).
   22.24 +
   22.25 +## (xend.domain.migrate.begin (src <host>) (src.domain <id>)
   22.26 +##                            (dst <host>) (id <migrate id>))
   22.27 + 
   22.28 +## xend.domain.migrate.end:
   22.29 +## (xend.domain.migrate.end (domain <id>) (to <host>)
   22.30 +
   22.31 +## xend.node.up:  xend uri
   22.32 +## xend.node.down: xend uri
   22.33 +
   22.34 +## xend.error ?
   22.35 +
   22.36 +## format:
   22.37 +
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/tools/xen/lib/xend/PrettyPrint.py	Mon Jun 28 08:20:16 2004 +0000
    23.3 @@ -0,0 +1,299 @@
    23.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    23.5 +
    23.6 +"""General pretty-printer, including support for SXP.
    23.7 +
    23.8 +"""
    23.9 +import sys
   23.10 +import types
   23.11 +import StringIO
   23.12 +import sxp
   23.13 +
   23.14 +class PrettyItem:
   23.15 +
   23.16 +    def __init__(self, width):
   23.17 +        self.width = width
   23.18 +
   23.19 +    def insert(self, block):
   23.20 +        block.addtoline(self)
   23.21 +
   23.22 +    def get_width(self):
   23.23 +        return self.width
   23.24 +
   23.25 +    def output(self, out):
   23.26 +        print '***PrettyItem>output>', self
   23.27 +        pass
   23.28 +
   23.29 +    def prettyprint(self, out, width):
   23.30 +        print '***PrettyItem>prettyprint>', self
   23.31 +        return width
   23.32 +
   23.33 +class PrettyString(PrettyItem):
   23.34 +
   23.35 +    def __init__(self, x):
   23.36 +        PrettyItem.__init__(self, len(x))
   23.37 +        self.value = x
   23.38 +
   23.39 +    def output(self, out):
   23.40 +        out.write(self.value)
   23.41 +
   23.42 +    def prettyprint(self, line):
   23.43 +        line.output(self)
   23.44 +
   23.45 +    def show(self, out):
   23.46 +        print >> out, ("(string (width %d) '%s')" % (self.width, self.value))
   23.47 +
   23.48 +class PrettySpace(PrettyItem):
   23.49 +
   23.50 +    def output(self, out):
   23.51 +        out.write(' ' * self.width)
   23.52 +
   23.53 +    def prettyprint(self, line):
   23.54 +        line.output(self)
   23.55 +
   23.56 +    def show(self, out):
   23.57 +        print >> out, ("(space (width %d))" % self.width)
   23.58 +        
   23.59 +class PrettyBreak(PrettyItem):
   23.60 +
   23.61 +    def __init__(self, width, indent):
   23.62 +        PrettyItem.__init__(self, width)
   23.63 +        self.indent = indent
   23.64 +        self.space = 0
   23.65 +        self.active = 0
   23.66 +
   23.67 +    def output(self, out):
   23.68 +        out.write(' ' * self.width)
   23.69 +
   23.70 +    def prettyprint(self, line):
   23.71 +        if line.breaks(self.space):
   23.72 +            self.active = 1
   23.73 +            line.newline(self.indent)
   23.74 +        else:
   23.75 +            line.output(self)
   23.76 +
   23.77 +    def show(self, out):
   23.78 +        print >> out, ("(break (width %d) (indent %d) (space %d) (active %d))"
   23.79 +                       % (self.width, self.indent, self.space, self.lspace, self.active))
   23.80 +
   23.81 +class PrettyNewline(PrettySpace):
   23.82 +
   23.83 +    def __init__(self, indent):
   23.84 +        PrettySpace.__init__(self, indent)
   23.85 +
   23.86 +    def insert(self, block):
   23.87 +        block.newline()
   23.88 +        block.addtoline(self)
   23.89 +
   23.90 +    def output(self, out):
   23.91 +        out.write(' ' * self.width)
   23.92 +
   23.93 +    def prettyprint(self, line):
   23.94 +        line.newline(0)
   23.95 +        line.output(self)
   23.96 +
   23.97 +    def show(self, out):
   23.98 +        print >> out, ("(nl (indent %d))" % self.indent)
   23.99 +
  23.100 +class PrettyLine(PrettyItem):
  23.101 +    def __init__(self):
  23.102 +        PrettyItem.__init__(self, 0)
  23.103 +        self.content = []
  23.104 +
  23.105 +    def write(self, x):
  23.106 +        self.content.append(x)
  23.107 +
  23.108 +    def end(self):
  23.109 +        width = 0
  23.110 +        lastwidth = 0
  23.111 +        lastbreak = None
  23.112 +        for x in self.content:
  23.113 +            if isinstance(x, PrettyBreak):
  23.114 +                if lastbreak:
  23.115 +                    lastbreak.space = (width - lastwidth)
  23.116 +                lastbreak = x
  23.117 +                lastwidth = width
  23.118 +            width += x.get_width()
  23.119 +        if lastbreak:
  23.120 +            lastbreak.space = (width - lastwidth)
  23.121 +        self.width = width
  23.122 + 
  23.123 +    def prettyprint(self, line):
  23.124 +        for x in self.content:
  23.125 +            x.prettyprint(line)
  23.126 +
  23.127 +    def show(self, out):
  23.128 +        print >> out, '(LINE (width %d)' % self.width
  23.129 +        for x in self.content:
  23.130 +            x.show(out)
  23.131 +        print >> out, ')'
  23.132 +
  23.133 +class PrettyBlock(PrettyItem):
  23.134 +
  23.135 +    def __init__(self, all=0, parent=None):
  23.136 +        self.width = 0
  23.137 +        self.lines = []
  23.138 +        self.parent = parent
  23.139 +        self.indent = 0
  23.140 +        self.all = all
  23.141 +        self.broken = 0
  23.142 +        self.newline()
  23.143 +
  23.144 +    def add(self, item):
  23.145 +        item.insert(self)
  23.146 +
  23.147 +    def end(self):
  23.148 +        self.width = 0
  23.149 +        for l in self.lines:
  23.150 +            l.end()
  23.151 +            if self.width < l.width:
  23.152 +                self.width = l.width
  23.153 +
  23.154 +    def breaks(self, n):
  23.155 +        return self.all and self.broken
  23.156 +
  23.157 +    def newline(self):
  23.158 +        self.lines.append(PrettyLine())
  23.159 +
  23.160 +    def addtoline(self, x):
  23.161 +        self.lines[-1].write(x)
  23.162 +
  23.163 +    def prettyprint(self, line):
  23.164 +        self.indent = line.used
  23.165 +        line.block = self
  23.166 +        if not line.fits(self.width):
  23.167 +            self.broken = 1
  23.168 +        for l in self.lines:
  23.169 +            l.prettyprint(line)
  23.170 +        line.block = self.parent
  23.171 +
  23.172 +    def show(self, out):
  23.173 +        print >> out, ('(BLOCK (width %d) (indent %d) (all %d) (broken %d)' %
  23.174 +                       (self.width, self.indent, self.all, self.broken))
  23.175 +        for l in self.lines:
  23.176 +            l.show(out)
  23.177 +        print >> out, ')'
  23.178 +
  23.179 +class Line:
  23.180 +
  23.181 +    def __init__(self, out, width):
  23.182 +        self.out = out
  23.183 +        self.width = width
  23.184 +        self.used = 0
  23.185 +        self.space = self.width
  23.186 +
  23.187 +    def newline(self, indent):
  23.188 +        indent += self.block.indent
  23.189 +        self.out.write('\n')
  23.190 +        self.out.write(' ' * indent)
  23.191 +        self.used = indent
  23.192 +        self.space = self.width - self.used
  23.193 +
  23.194 +    def fits(self, n):
  23.195 +        return self.space - n >= 0
  23.196 +
  23.197 +    def breaks(self, n):
  23.198 +        return self.block.breaks(n) or not self.fits(n)
  23.199 +
  23.200 +    def output(self, x):
  23.201 +        n = x.get_width()
  23.202 +        self.space -= n
  23.203 +        self.used += n
  23.204 +        if self.space < 0:
  23.205 +            self.space = 0
  23.206 +        x.output(self.out)
  23.207 +
  23.208 +class PrettyPrinter:
  23.209 +    """A prettyprinter based on what I remember of Derek Oppen's
  23.210 +    prettyprint algorithm from TOPLAS way back.
  23.211 +    """
  23.212 +
  23.213 +    def __init__(self, width=40):
  23.214 +        self.width = width
  23.215 +        self.block = None
  23.216 +        self.top = None
  23.217 +
  23.218 +    def write(self, x):
  23.219 +        self.block.add(PrettyString(x))
  23.220 +
  23.221 +    def add(self, item):
  23.222 +        self.block.add(item)
  23.223 +
  23.224 +    def addbreak(self, width=1, indent=4):
  23.225 +        self.add(PrettyBreak(width, indent))
  23.226 +
  23.227 +    def addspace(self, width=1):
  23.228 +        self.add(PrettySpace(width))
  23.229 +
  23.230 +    def addnl(self, indent=0):
  23.231 +        self.add(PrettyNewline(indent))
  23.232 +
  23.233 +    def begin(self, all=0):
  23.234 +        block = PrettyBlock(all=all, parent=self.block)
  23.235 +        self.block = block
  23.236 +
  23.237 +    def end(self):
  23.238 +        self.block.end()
  23.239 +        if self.block.parent:
  23.240 +            self.block.parent.add(self.block)
  23.241 +        else:
  23.242 +            self.top = self.block
  23.243 +        self.block = self.block.parent
  23.244 +
  23.245 +    def prettyprint(self, out=sys.stdout):
  23.246 +        line = Line(out, self.width)
  23.247 +        self.top.prettyprint(line)
  23.248 +
  23.249 +class SXPPrettyPrinter(PrettyPrinter):
  23.250 +    """An SXP prettyprinter.
  23.251 +    """
  23.252 +    
  23.253 +    def pstring(self, x):
  23.254 +        io = StringIO.StringIO()
  23.255 +        sxp.show(x, out=io)
  23.256 +        io.seek(0)
  23.257 +        val = io.getvalue()
  23.258 +        io.close()
  23.259 +        return val
  23.260 +
  23.261 +    def pprint(self, l):
  23.262 +        if isinstance(l, types.ListType):
  23.263 +            self.begin(all=1)
  23.264 +            self.write('(')
  23.265 +            i = 0
  23.266 +            for x in l:
  23.267 +                if(i): self.addbreak()
  23.268 +                self.pprint(x)
  23.269 +                i += 1
  23.270 +            self.addbreak(width=0, indent=0)
  23.271 +            self.write(')')
  23.272 +            self.end()
  23.273 +        else:
  23.274 +            self.write(self.pstring(l))
  23.275 +
  23.276 +def prettyprint(sxpr, out=sys.stdout, width=80):
  23.277 +    """Prettyprint an SXP form.
  23.278 +
  23.279 +    sxpr	s-expression
  23.280 +    out		destination
  23.281 +    width	maximum output width
  23.282 +    """
  23.283 +    if isinstance(sxpr, types.ListType):
  23.284 +        pp = SXPPrettyPrinter(width=width)
  23.285 +        pp.pprint(sxpr)
  23.286 +        pp.prettyprint(out=out)
  23.287 +    else:
  23.288 +        sxp.show(sxpr, out=out)
  23.289 +    print >> out
  23.290 +
  23.291 +def main():
  23.292 +    pin = sxp.Parser()
  23.293 +    while 1:
  23.294 +        buf = sys.stdin.read(100)
  23.295 +        pin.input(buf)
  23.296 +        if buf == '': break
  23.297 +    l = pin.get_val()
  23.298 +    prettyprint(l, width=80)
  23.299 +
  23.300 +if __name__ == "__main__":
  23.301 +    main()
  23.302 +    
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/tools/xen/lib/xend/XendBridge.py	Mon Jun 28 08:20:16 2004 +0000
    24.3 @@ -0,0 +1,193 @@
    24.4 +"""Bridge control utilities.
    24.5 +"""
    24.6 +import os
    24.7 +import os.path
    24.8 +import re
    24.9 +import sys
   24.10 +
   24.11 +from xen.xend import XendRoot
   24.12 +xroot = XendRoot.instance()
   24.13 +
   24.14 +os.defpath = os.defpath + ':/sbin:/usr/sbin:/usr/local/sbin'
   24.15 +CMD_IFCONFIG = 'ifconfig'
   24.16 +CMD_ROUTE    = 'route'
   24.17 +CMD_BRCTL    = 'brctl'
   24.18 +CMD_IPTABLES = "iptables"
   24.19 +
   24.20 +DEFAULT_BRIDGE = 'nbe-br'
   24.21 +DEFAULT_INTERFACE = 'eth0'
   24.22 +
   24.23 +opts = None
   24.24 +
   24.25 +class Opts:
   24.26 +
   24.27 +    def __init__(self, defaults):
   24.28 +        for (k, v) in defaults.items():
   24.29 +            setattr(self, k, v)
   24.30 +        pass
   24.31 +
   24.32 +def cmd(p, s):
   24.33 +    """Print and execute command 'p' with args 's'.
   24.34 +    """
   24.35 +    global opts
   24.36 +    c = p + ' ' + s
   24.37 +    if opts.verbose: print c
   24.38 +    if not opts.dryrun:
   24.39 +        os.system(c)
   24.40 +
   24.41 +def default_bridge():
   24.42 +    return xroot.get_config_value('bridge', DEFAULT_BRIDGE)
   24.43 +
   24.44 +def default_interface():
   24.45 +    return xroot.get_config_value('interface', DEFAULT_INTERFACE)
   24.46 +
   24.47 +def vif_dev(dom, vif):
   24.48 +    """Return the name of the network interface for vif on domain dom.
   24.49 +    """
   24.50 +    return "vif%d.%d" % (dom, vif)
   24.51 +
   24.52 +def vif_bridge_add(dom, vif, bridge=None):
   24.53 +    """Add the network interface for vif on dom to a bridge.
   24.54 +    """
   24.55 +    if not bridge: bridge = default_bridge()
   24.56 +    d = { 'bridge': bridge, 'vif': vif_dev(dom, vif) }
   24.57 +    cmd(CMD_BRCTL, 'addif %(bridge)s %(vif)s' % d)
   24.58 +    return bridge
   24.59 +
   24.60 +def vif_bridge_rem(dom, vif, bridge=None):
   24.61 +    """Remove the network interface for vif on dom from a bridge.
   24.62 +    """
   24.63 +    if not bridge: bridge = default_bridge()
   24.64 +    print 'vif_bridge_rem>', dom, vif, bridge
   24.65 +    d = { 'bridge': bridge, 'vif': vif_dev(dom, vif) }
   24.66 +    cmd(CMD_BRCTL, 'delif %(bridge)s %(vif)s' % d)
   24.67 +
   24.68 +def vif_restrict_addr(dom, vif, addr, delete=0):
   24.69 +    d = { 'vif': vif_dev(dom, vif), 'addr': addr}
   24.70 +    if delete:
   24.71 +        d['flag'] = '-D'
   24.72 +    else:
   24.73 +        d['flag'] = '-A'
   24.74 +    cmd(CMD_IPTABLES, '-P FORWARD DROP')
   24.75 +    cmd(CMD_IPTABLES, '%(flag)s FORWARD -m physdev --physdev-in %(vif)s -s %(addr)s -j ACCEPT' % d)
   24.76 +    cmd(CMD_IPTABLES, '%(flag)s FORWARD -m physdev --physdev-out %(vif)s -d %(addr)s -j ACCEPT' % d)
   24.77 +
   24.78 +def bridge_create(bridge=None, **kwd):
   24.79 +    """Create a bridge.
   24.80 +    Defaults hello time to 0, forward delay to 0 and stp off.
   24.81 +    """
   24.82 +    if not bridge: bridge = default_bridge()
   24.83 +    cmd(CMD_BRCTL, 'addbr %s' % bridge)
   24.84 +    if kwd.get('hello', None) is None:
   24.85 +        kwd['hello'] = 0
   24.86 +    if kwd.get('fd', None) is None:
   24.87 +        kwd['fd'] = 0
   24.88 +    if kwd.get('stp', None) is None:
   24.89 +        kwd['stp'] = 'off'
   24.90 +    bridge_set(bridge, **kwd)
   24.91 +
   24.92 +def bridge_set(bridge, hello=None, fd=None, stp=None):
   24.93 +    """Set bridge parameters.
   24.94 +    """
   24.95 +    if hello is not None:
   24.96 +        cmd(CMD_BRCTL, 'sethello %s %d' % (bridge, hello))
   24.97 +    if fd is not None:
   24.98 +        cmd(CMD_BRCTL, 'setfd %s %d' % (bridge, fd))
   24.99 +    if stp is not None:
  24.100 +        cmd(CMD_BRCTL, 'stp %s %s' % (bridge, stp))
  24.101 +
  24.102 +def bridge_del(bridge=None):
  24.103 +    """Delete a bridge.
  24.104 +    """
  24.105 +    if not bridge: bridge = default_bridge()
  24.106 +    cmd(CMD_BRCTL, 'delbr %s' % bridge)
  24.107 +
  24.108 +def routes():
  24.109 +    """Return a list of the routes.
  24.110 +    """
  24.111 +    fin = os.popen(CMD_ROUTE + ' -n', 'r')
  24.112 +    routes = []
  24.113 +    for x in fin:
  24.114 +        if x.startswith('Kernel'): continue
  24.115 +        if x.startswith('Destination'): continue
  24.116 +        x = x.strip()
  24.117 +        y = x.split()
  24.118 +        z = { 'destination': y[0],
  24.119 +              'gateway'    : y[1],
  24.120 +              'mask'       : y[2],
  24.121 +              'flags'      : y[3],
  24.122 +              'metric'     : y[4],
  24.123 +              'ref'        : y[5],
  24.124 +              'use'        : y[6],
  24.125 +              'interface'  : y[7] }
  24.126 +        routes.append(z)
  24.127 +    return routes
  24.128 +
  24.129 +def ifconfig(interface):
  24.130 +    """Return the ip config for an interface,
  24.131 +    """
  24.132 +    fin = os.popen(CMD_IFCONFIG + ' %s' % interface, 'r')
  24.133 +    inetre = re.compile('\s*inet\s*addr:(?P<address>\S*)\s*Bcast:(?P<broadcast>\S*)\s*Mask:(?P<mask>\S*)')
  24.134 +    info = None
  24.135 +    for x in fin:
  24.136 +        m = inetre.match(x)
  24.137 +        if not m: continue
  24.138 +        info = m.groupdict()
  24.139 +        info['interface'] = interface
  24.140 +        break
  24.141 +    return info
  24.142 +
  24.143 +def reconfigure(interface=None, bridge=None):
  24.144 +    """Reconfigure an interface to be attached to a bridge, and give the bridge
  24.145 +    the IP address etc. from interface. Move the default route to the interface
  24.146 +    to the bridge.
  24.147 +
  24.148 +    If opts.create is true, creates the bridge.
  24.149 +    """
  24.150 +    global opts
  24.151 +    if not interface: interface = default_interface()
  24.152 +    if not bridge: bridge = default_bridge()
  24.153 +    intf_info = ifconfig(interface)
  24.154 +    if not intf_info:
  24.155 +        print 'Interface not found:', interface
  24.156 +        return
  24.157 +    if opts.create:
  24.158 +        bridge_create(bridge)
  24.159 +    #bridge_info = ifconfig(bridge)
  24.160 +    #if not bridge_info:
  24.161 +    #    print 'Bridge not found:', bridge
  24.162 +    #    return
  24.163 +    route_info = routes()
  24.164 +    intf_info['bridge'] = bridge
  24.165 +    intf_info['gateway'] = None
  24.166 +    for r in route_info:
  24.167 +        if (r['destination'] == '0.0.0.0' and
  24.168 +            'G' in r['flags'] and
  24.169 +            r['interface'] == interface):
  24.170 +            intf_info['gateway'] = r['gateway']
  24.171 +    if not intf_info['gateway']:
  24.172 +        print 'Gateway not found: ', interface
  24.173 +        return
  24.174 +    cmd(CMD_IFCONFIG,
  24.175 +        '%(bridge)s %(address)s netmask %(mask)s broadcast %(broadcast)s up'
  24.176 +        % intf_info)
  24.177 +    cmd(CMD_ROUTE,
  24.178 +        'add default gateway %(gateway)s dev %(bridge)s'
  24.179 +        % intf_info)
  24.180 +    cmd(CMD_BRCTL, 'addif %(bridge)s %(interface)s' % intf_info)
  24.181 +    cmd(CMD_IFCONFIG, '%(interface)s 0.0.0.0' % intf_info)
  24.182 +
  24.183 +defaults = {
  24.184 +    'interface': default_interface(),
  24.185 +    'bridge'   : default_bridge(),
  24.186 +    'verbose'  : 1,
  24.187 +    'dryrun'   : 0,
  24.188 +    'create'   : 0,
  24.189 +    }
  24.190 +
  24.191 +opts = Opts(defaults)
  24.192 +
  24.193 +def set_opts(val):
  24.194 +    global opts
  24.195 +    opts = val
  24.196 +    return opts
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/tools/xen/lib/xend/XendClient.py	Mon Jun 28 08:20:16 2004 +0000
    25.3 @@ -0,0 +1,311 @@
    25.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    25.5 +"""Client API for the HTTP interface on xend.
    25.6 +Callable as a script - see main().
    25.7 +"""
    25.8 +import sys
    25.9 +import httplib
   25.10 +import types
   25.11 +from StringIO import StringIO
   25.12 +import urlparse
   25.13 +
   25.14 +from encode import *
   25.15 +import sxp
   25.16 +import PrettyPrint
   25.17 +
   25.18 +DEBUG = 0
   25.19 +
   25.20 +class Foo(httplib.HTTPResponse):
   25.21 +
   25.22 +    def begin(self):
   25.23 +        fin = self.fp
   25.24 +        while(1):
   25.25 +            buf = fin.readline()
   25.26 +            print "***", buf
   25.27 +            if buf == '':
   25.28 +                print
   25.29 +                sys.exit()
   25.30 +
   25.31 +
   25.32 +def sxprio(sxpr):
   25.33 +    io = StringIO()
   25.34 +    sxp.show(sxpr, out=io)
   25.35 +    print >> io
   25.36 +    io.seek(0)
   25.37 +    return io
   25.38 +
   25.39 +def fileof(val):
   25.40 +    """Converter for passing configs.
   25.41 +    Handles lists, files directly.
   25.42 +    Assumes a string is a file name and passes its contents.
   25.43 +    """
   25.44 +    if isinstance(val, types.ListType):
   25.45 +        return sxprio(val)
   25.46 +    if isinstance(val, types.StringType):
   25.47 +        return file(val)
   25.48 +    if hasattr(val, 'readlines'):
   25.49 +        return val
   25.50 +
   25.51 +# todo: need to sort of what urls/paths are using for objects.
   25.52 +# e.g. for domains at the moment return '0'.
   25.53 +# should probably return abs path w.r.t. server, e.g. /xend/domain/0.
   25.54 +# As an arg, assume abs path is obj uri, otherwise just id.
   25.55 +
   25.56 +# Function to convert to full url: Xend.uri(path), e.g.
   25.57 +# maps /xend/domain/0 to http://wray-m-3.hpl.hp.com:8000/xend/domain/0
   25.58 +# And should accept urls for ids?
   25.59 +
   25.60 +def urljoin(location, root, prefix='', rest=''):
   25.61 +    prefix = str(prefix)
   25.62 +    rest = str(rest)
   25.63 +    base = 'http://' + location + root + prefix
   25.64 +    url = urlparse.urljoin(base, rest)
   25.65 +    return url
   25.66 +
   25.67 +def nodeurl(location, root, id=''):
   25.68 +    return urljoin(location, root, 'node/', id)
   25.69 +
   25.70 +def domainurl(location, root, id=''):
   25.71 +    return urljoin(location, root, 'domain/', id)
   25.72 +
   25.73 +def consoleurl(location, root, id=''):
   25.74 +    return urljoin(location, root, 'console/', id)
   25.75 +
   25.76 +def deviceurl(location, root, id=''):
   25.77 +    return urljoin(location, root, 'device/', id)
   25.78 +
   25.79 +def vneturl(location, root, id=''):
   25.80 +    return urljoin(location, root, 'vnet/', id)
   25.81 +
   25.82 +def eventurl(location, root, id=''):
   25.83 +    return urljoin(location, root, 'event/', id)
   25.84 +
   25.85 +def xend_request(url, method, data=None):
   25.86 +    urlinfo = urlparse.urlparse(url)
   25.87 +    (uproto, ulocation, upath, uparam, uquery, ufrag) = urlinfo
   25.88 +    if DEBUG: print url, urlinfo
   25.89 +    if uproto != 'http':
   25.90 +        raise StandardError('Invalid protocol: ' + uproto)
   25.91 +    if DEBUG: print '>xend_request', ulocation, upath, method, data
   25.92 +    (hdr, args) = encode_data(data)
   25.93 +    if data and method == 'GET':
   25.94 +        upath += '?' + args
   25.95 +        args = None
   25.96 +    if method == "POST" and upath.endswith('/'):
   25.97 +        upath = upath[:-1]
   25.98 +    if DEBUG: print "ulocation=", ulocation, "upath=", upath, "args=", args
   25.99 +    #hdr['User-Agent'] = 'Mozilla'
  25.100 +    #hdr['Accept'] = 'text/html,text/plain'
  25.101 +    conn = httplib.HTTPConnection(ulocation)
  25.102 +    #conn.response_class = Foo
  25.103 +    if DEBUG: conn.set_debuglevel(1)
  25.104 +    conn.request(method, upath, args, hdr)
  25.105 +    resp = conn.getresponse()
  25.106 +    if DEBUG: print resp.status, resp.reason
  25.107 +    if DEBUG: print resp.msg.headers
  25.108 +    if resp.status in [204, 404]:
  25.109 +        return None
  25.110 +    if resp.status not in [200, 201, 202, 203]:
  25.111 +        raise RuntimeError(resp.reason)
  25.112 +    pin = sxp.Parser()
  25.113 +    data = resp.read()
  25.114 +    if DEBUG: print "***data" , data
  25.115 +    if DEBUG: print "***"
  25.116 +    pin.input(data);
  25.117 +    pin.input_eof()
  25.118 +    conn.close()
  25.119 +    val = pin.get_val()
  25.120 +    #if isinstance(val, types.ListType) and sxp.name(val) == 'val':
  25.121 +    #    val = val[1]
  25.122 +    if isinstance(val, types.ListType) and sxp.name(val) == 'err':
  25.123 +        raise RuntimeError(val[1])
  25.124 +    if DEBUG: print '**val='; sxp.show(val); print
  25.125 +    return val
  25.126 +
  25.127 +def xend_get(url, args=None):
  25.128 +    return xend_request(url, "GET", args)
  25.129 +
  25.130 +def xend_call(url, data):
  25.131 +    return xend_request(url, "POST", data)
  25.132 +
  25.133 +class Xend:
  25.134 +
  25.135 +    SRV_DEFAULT = "localhost:8000"
  25.136 +    ROOT_DEFAULT = "/xend/"
  25.137 +
  25.138 +    def __init__(self, srv=None, root=None):
  25.139 +        self.bind(srv, root)
  25.140 +
  25.141 +    def bind(self, srv=None, root=None):
  25.142 +        if srv is None: srv = self.SRV_DEFAULT
  25.143 +        if root is None: root = self.ROOT_DEFAULT
  25.144 +        if not root.endswith('/'): root += '/'
  25.145 +        self.location = srv
  25.146 +        self.root = root
  25.147 +
  25.148 +    def nodeurl(self, id=''):
  25.149 +        return nodeurl(self.location, self.root, id)
  25.150 +
  25.151 +    def domainurl(self, id=''):
  25.152 +        return domainurl(self.location, self.root, id)
  25.153 +
  25.154 +    def consoleurl(self, id=''):
  25.155 +        return consoleurl(self.location, self.root, id)
  25.156 +
  25.157 +    def deviceurl(self, id=''):
  25.158 +        return deviceurl(self.location, self.root, id)
  25.159 +
  25.160 +    def vneturl(self, id=''):
  25.161 +        return vneturl(self.location, self.root, id)
  25.162 +
  25.163 +    def eventurl(self, id=''):
  25.164 +        return eventurl(self.location, self.root, id)
  25.165 +
  25.166 +    def xend(self):
  25.167 +        return xend_get(urljoin(self.location, self.root))
  25.168 +
  25.169 +    def xend_node(self):
  25.170 +        return xend_get(self.nodeurl())
  25.171 +
  25.172 +    def xend_node_cpu_rrobin_slice_set(self, slice):
  25.173 +        return xend_call(self.nodeurl(),
  25.174 +                         {'op'      : 'cpu_rrobin_slice_set',
  25.175 +                          'slice'   : slice })
  25.176 +    
  25.177 +    def xend_node_cpu_bvt_slice_set(self, slice):
  25.178 +        return xend_call(self.nodeurl(),
  25.179 +                         {'op'      : 'cpu_bvt_slice_set',
  25.180 +                          'slice'   : slice })
  25.181 +
  25.182 +    def xend_domains(self):
  25.183 +        return xend_get(self.domainurl())
  25.184 +
  25.185 +    def xend_domain_create(self, conf):
  25.186 +        return xend_call(self.domainurl(),
  25.187 +                         {'op'      : 'create',
  25.188 +                          'config'  : fileof(conf) })
  25.189 +
  25.190 +    def xend_domain(self, id):
  25.191 +        return xend_get(self.domainurl(id))
  25.192 +
  25.193 +    def xend_domain_unpause(self, id):
  25.194 +        return xend_call(self.domainurl(id),
  25.195 +                         {'op'      : 'unpause'})
  25.196 +
  25.197 +    def xend_domain_pause(self, id):
  25.198 +        return xend_call(self.domainurl(id),
  25.199 +                         {'op'      : 'pause'})
  25.200 +
  25.201 +    def xend_domain_shutdown(self, id):
  25.202 +        return xend_call(self.domainurl(id),
  25.203 +                         {'op'      : 'shutdown'})
  25.204 +
  25.205 +    def xend_domain_destroy(self, id):
  25.206 +        return xend_call(self.domainurl(id),
  25.207 +                         {'op'      : 'destroy'})
  25.208 +
  25.209 +    def xend_domain_save(self, id, filename):
  25.210 +        return xend_call(self.domainurl(id),
  25.211 +                         {'op'      : 'save',
  25.212 +                          'file'    : filename})
  25.213 +
  25.214 +    def xend_domain_restore(self, id, filename):
  25.215 +        return xend_call(self.domainurl(id),
  25.216 +                         {'op'      : 'restore',
  25.217 +                          'file'    : filename })
  25.218 +
  25.219 +    def xend_domain_migrate(self, id, dst):
  25.220 +        return xend_call(self.domainurl(id),
  25.221 +                         {'op'      : 'migrate',
  25.222 +                          'destination': dst})
  25.223 +
  25.224 +    def xend_domain_pincpu(self, id, cpu):
  25.225 +        return xend_call(self.domainurl(id),
  25.226 +                         {'op'      : 'pincpu',
  25.227 +                          'cpu'     : cpu})
  25.228 +
  25.229 +    def xend_domain_cpu_bvt_set(self, id, mcuadv, warp, warpl, warpu):
  25.230 +        return xend_call(self.domainurl(id),
  25.231 +                         {'op'      : 'cpu_bvt_set',
  25.232 +                          'mcuadv'  : mvuadv,
  25.233 +                          'warp'    : warp,
  25.234 +                          'warpl'   : warpl,
  25.235 +                          'warpu'   : warpu })
  25.236 +
  25.237 +    def xend_domain_cpu_atropos_set(self, id, period, slice, latency, xtratime):
  25.238 +        return xend_call(self.domainurl(id),
  25.239 +                         {'op'      : 'cpu_atropos_set',
  25.240 +                          'period'  : period,
  25.241 +                          'slice'   : slice,
  25.242 +                          'latency' : latency,
  25.243 +                          'xtratime': xtratime })
  25.244 +
  25.245 +    def xend_domain_vifs(self, id):
  25.246 +        return xend_get(self.domainurl(id),
  25.247 +                        { 'op'      : 'vifs' })
  25.248 +    
  25.249 +    def xend_domain_vif_ip_add(self, id, vif, ipaddr):
  25.250 +        return xend_call(self.domainurl(id),
  25.251 +                         {'op'      : 'vif_ip_add',
  25.252 +                          'vif'     : vif,
  25.253 +                          'ip'      : ipaddr })
  25.254 +        
  25.255 +    def xend_domain_vbds(self, id):
  25.256 +        return xend_get(self.domainurl(id),
  25.257 +                        {'op'       : 'vbds'})
  25.258 +
  25.259 +    def xend_domain_vbd(self, id, vbd):
  25.260 +        return xend_get(self.domainurl(id),
  25.261 +                        {'op'       : 'vbd',
  25.262 +                         'vbd'      : vbd})
  25.263 +
  25.264 +    def xend_consoles(self):
  25.265 +        return xend_get(self.consoleurl())
  25.266 +
  25.267 +    def xend_console(self, id):
  25.268 +        return xend_get(self.consoleurl(id))
  25.269 +
  25.270 +    def xend_vnets(self):
  25.271 +        return xend_get(self.vneturl())
  25.272 +
  25.273 +    def xend_vnet_create(self, conf):
  25.274 +        return xend_call(self.vneturl(),
  25.275 +                         {'op': 'create', 'config': fileof(conf) })
  25.276 +
  25.277 +    def xend_vnet(self, id):
  25.278 +        return xend_get(self.vneturl(id))
  25.279 +
  25.280 +    def xend_vnet_delete(self, id):
  25.281 +        return xend_call(self.vneturl(id),
  25.282 +                         {'op': 'delete'})
  25.283 +
  25.284 +    def xend_event_inject(self, sxpr):
  25.285 +        val = xend_call(self.eventurl(),
  25.286 +                        {'op': 'inject', 'event': fileof(sxpr) })
  25.287 +    
  25.288 +
  25.289 +def main(argv):
  25.290 +    """Call an API function:
  25.291 +    
  25.292 +    python XendClient.py fn args...
  25.293 +
  25.294 +    The leading 'xend_' on the function can be omitted.
  25.295 +    Example:
  25.296 +
  25.297 +    > python XendClient.py domains
  25.298 +    (domain 0 8)
  25.299 +    > python XendClient.py domain 0
  25.300 +    (domain (id 0) (name Domain-0) (memory 128))
  25.301 +    """
  25.302 +    server = Xend()
  25.303 +    fn = argv[1]
  25.304 +    if not fn.startswith('xend'):
  25.305 +        fn = 'xend_' + fn
  25.306 +    args = argv[2:]
  25.307 +    val = getattr(server, fn)(*args)
  25.308 +    PrettyPrint.prettyprint(val)
  25.309 +    print
  25.310 +
  25.311 +if __name__ == "__main__":
  25.312 +    main(sys.argv)
  25.313 +else:    
  25.314 +    server = Xend()
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/tools/xen/lib/xend/XendConsole.py	Mon Jun 28 08:20:16 2004 +0000
    26.3 @@ -0,0 +1,179 @@
    26.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    26.5 +
    26.6 +import socket
    26.7 +import xen.ext.xc
    26.8 +xc = xen.ext.xc.new()
    26.9 +
   26.10 +import sxp
   26.11 +import XendRoot
   26.12 +xroot = XendRoot.instance()
   26.13 +import XendDB
   26.14 +
   26.15 +import EventServer
   26.16 +eserver = EventServer.instance()
   26.17 +
   26.18 +from xen.xend.server import SrvDaemon
   26.19 +daemon = SrvDaemon.instance()
   26.20 +
   26.21 +class XendConsoleInfo:
   26.22 +    """Console information record.
   26.23 +    """
   26.24 +
   26.25 +    def __init__(self, console, dom1, port1, dom2, port2, conn=None):
   26.26 +        self.console = console
   26.27 +        self.dom1  = int(dom1)
   26.28 +        self.port1 = int(port1)
   26.29 +        self.dom2  = int(dom2)
   26.30 +        self.port2 = int(port2)
   26.31 +        self.conn  = conn
   26.32 +        #self.id = "%d.%d-%d.%d" % (self.dom1, self.port1, self.dom2, self.port2)
   26.33 +        self.id = str(port1)
   26.34 +
   26.35 +    def __str__(self):
   26.36 +        s = "console"
   26.37 +        s += " id=%s" % self.id
   26.38 +        s += " src=%d.%d" % (self.dom1, self.port1)
   26.39 +        s += " dst=%d.%d" % (self.dom2, self.port2)
   26.40 +        s += " port=%s" % self.console
   26.41 +        if self.conn:
   26.42 +            s += " conn=%s:%s" % (self.conn[0], self.conn[1])
   26.43 +        return s
   26.44 +
   26.45 +    def sxpr(self):
   26.46 +        sxpr = ['console',
   26.47 +                ['id', self.id],
   26.48 +                ['src', self.dom1, self.port1],
   26.49 +                ['dst', self.dom2, self.port2],
   26.50 +                ['port', self.console],
   26.51 +                ]
   26.52 +        if self.conn:
   26.53 +            sxpr.append(['connected', self.conn[0], self.conn[1]])
   26.54 +        return sxpr
   26.55 +
   26.56 +    def connection(self):
   26.57 +        return self.conn
   26.58 +
   26.59 +    def update(self, consinfo):
   26.60 +        conn = sxp.child(consinfo, 'connected')
   26.61 +        if conn:
   26.62 +            self.conn = conn[1:]
   26.63 +        else:
   26.64 +            self.conn = None
   26.65 +
   26.66 +    def uri(self):
   26.67 +        """Get the uri to use to connect to the console.
   26.68 +        This will be a telnet: uri.
   26.69 +
   26.70 +        return uri
   26.71 +        """
   26.72 +        host = socket.gethostname()
   26.73 +        return "telnet://%s:%s" % (host, self.console)
   26.74 +
   26.75 +class XendConsole:
   26.76 +
   26.77 +    dbpath = "console"
   26.78 +
   26.79 +    def  __init__(self):
   26.80 +        self.db = XendDB.XendDB(self.dbpath)
   26.81 +        self.console = {}
   26.82 +        self.console_db = self.db.fetchall("")
   26.83 +        if xroot.get_rebooted():
   26.84 +            print 'XendConsole> rebooted: removing all console info'
   26.85 +            self.rm_all()
   26.86 +        eserver.subscribe('xend.domain.died', self.onDomainDied)
   26.87 +        eserver.subscribe('xend.domain.destroy', self.onDomainDied)
   26.88 +
   26.89 +    def rm_all(self):
   26.90 +        """Remove all console info. Used after reboot.
   26.91 +        """
   26.92 +        for (k, v) in self.console_db.items():
   26.93 +            self._delete_console(k)
   26.94 +
   26.95 +    def refresh(self):
   26.96 +        consoles = daemon.consoles()
   26.97 +        cons = {}
   26.98 +        for consinfo in consoles:
   26.99 +            id = str(sxp.child_value(consinfo, 'id'))
  26.100 +            cons[id] = consinfo
  26.101 +            if id not in self.console:
  26.102 +                self._new_console(consinfo)
  26.103 +        for c in self.console.values():
  26.104 +            consinfo = cons.get(c.id)
  26.105 +            if consinfo:
  26.106 +                c.update(consinfo)
  26.107 +            else:
  26.108 +                self._delete_console(c.id)
  26.109 +
  26.110 +    def onDomainDied(self, event, val):
  26.111 +        dom = int(val)
  26.112 +        #print 'XendConsole>onDomainDied', 'event', event, "dom=", dom
  26.113 +        for c in self.consoles():
  26.114 +            #print 'onDomainDied', "dom=", dom, "dom1=", c.dom1, "dom2=", c.dom2
  26.115 +            if (c.dom1 == dom) or (c.dom2 == dom):
  26.116 +                'XendConsole>onDomainDied', 'delete console dom=', dom
  26.117 +                ctrl = daemon.get_domain_console(dom)
  26.118 +                if ctrl:
  26.119 +                    ctrl.close()
  26.120 +                self._delete_console(c.id)
  26.121 +
  26.122 +    def sync(self):
  26.123 +        self.db.saveall("", self.console_db)
  26.124 +
  26.125 +    def sync_console(self, id):
  26.126 +        self.db.save(id, self.console_db[id])
  26.127 +
  26.128 +    def _new_console(self, consinfo):
  26.129 +        # todo: xen needs a call to get current domain id.
  26.130 +        dom1 = 0
  26.131 +        port1 = sxp.child_value(consinfo, 'local_port')
  26.132 +        dom2 = sxp.child_value(consinfo, 'domain')
  26.133 +        port2 = sxp.child_value(consinfo, 'remote_port')
  26.134 +        console = sxp.child_value(consinfo, 'console_port')
  26.135 +        info = XendConsoleInfo(console, dom1, int(port1), int(dom2), int(port2))
  26.136 +        info.update(consinfo)
  26.137 +        self._add_console(info.id, info)
  26.138 +        return info
  26.139 +
  26.140 +    def _add_console(self, id, info):
  26.141 +        self.console[id] = info
  26.142 +        self.console_db[id] = info.sxpr()
  26.143 +        self.sync_console(id)
  26.144 +
  26.145 +    def _delete_console(self, id):
  26.146 +        if id in self.console:
  26.147 +            del self.console[id]
  26.148 +        if id in self.console_db:
  26.149 +            del self.console_db[id]
  26.150 +            self.db.delete(id)
  26.151 +
  26.152 +    def console_ls(self):
  26.153 +        self.refresh()
  26.154 +        return self.console.keys()
  26.155 +
  26.156 +    def consoles(self):
  26.157 +        self.refresh()
  26.158 +        return self.console.values()
  26.159 +    
  26.160 +    def console_create(self, dom):
  26.161 +        consinfo = daemon.console_create(dom)
  26.162 +        info = self._new_console(consinfo)
  26.163 +        return info
  26.164 +    
  26.165 +    def console_get(self, id):
  26.166 +        self.refresh()
  26.167 +        return self.console.get(id)
  26.168 +
  26.169 +    def console_delete(self, id):
  26.170 +        self._delete_console(id)
  26.171 +
  26.172 +    def console_disconnect(self, id):
  26.173 +        id = int(id)
  26.174 +        daemon.console_disconnect(id)
  26.175 +
  26.176 +def instance():
  26.177 +    global inst
  26.178 +    try:
  26.179 +        inst
  26.180 +    except:
  26.181 +        inst = XendConsole()
  26.182 +    return inst
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/tools/xen/lib/xend/XendDB.py	Mon Jun 28 08:20:16 2004 +0000
    27.3 @@ -0,0 +1,91 @@
    27.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    27.5 +
    27.6 +import os
    27.7 +import os.path
    27.8 +import errno
    27.9 +import dircache
   27.10 +import time
   27.11 +
   27.12 +import sxp
   27.13 +import XendRoot
   27.14 +xroot = XendRoot.instance()
   27.15 +
   27.16 +class XendDB:
   27.17 +    """Persistence for Xend. Stores data in files and directories.
   27.18 +    """
   27.19 +
   27.20 +    def __init__(self, path=None):
   27.21 +        self.dbpath = xroot.get_dbroot()
   27.22 +        if path:
   27.23 +            self.dbpath = os.path.join(self.dbpath, path)
   27.24 +        pass
   27.25 +
   27.26 +    def filepath(self, path):
   27.27 +        return os.path.join(self.dbpath, path)
   27.28 +        
   27.29 +    def fetch(self, path):
   27.30 +        fpath = self.filepath(path)
   27.31 +        return self.fetchfile(fpath)
   27.32 +
   27.33 +    def fetchfile(self, fpath):
   27.34 +        pin = sxp.Parser()
   27.35 +        fin = file(fpath, "rb")
   27.36 +        try:
   27.37 +            while 1:
   27.38 +                try:
   27.39 +                    buf = fin.read(1024)
   27.40 +                except IOError, ex:
   27.41 +                    if ex.errno == errno.EINTR:
   27.42 +                        continue
   27.43 +                    else:
   27.44 +                        raise
   27.45 +                pin.input(buf)
   27.46 +                if buf == '':
   27.47 +                    pin.input_eof()
   27.48 +                    break
   27.49 +        finally:
   27.50 +            fin.close()
   27.51 +        return pin.get_val()
   27.52 +
   27.53 +    def save(self, path, sxpr):
   27.54 +        fpath = self.filepath(path)
   27.55 +        return self.savefile(fpath, sxpr)
   27.56 +    
   27.57 +    def savefile(self, fpath, sxpr):
   27.58 +        fdir = os.path.dirname(fpath)
   27.59 +        if not os.path.isdir(fdir):
   27.60 +            os.makedirs(fdir)
   27.61 +        fout = file(fpath, "wb+")
   27.62 +        try:
   27.63 +            t = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
   27.64 +            fout.write("# %s %s\n" % (fpath, t))
   27.65 +            sxp.show(sxpr, out=fout)
   27.66 +        finally:
   27.67 +            fout.close()
   27.68 +
   27.69 +    def fetchall(self, path):
   27.70 +        dpath = self.filepath(path)
   27.71 +        d = {}
   27.72 +        for k in dircache.listdir(dpath):
   27.73 +            try:
   27.74 +                v = self.fetchfile(os.path.join(dpath, k))
   27.75 +                d[k] = v
   27.76 +            except:
   27.77 +                pass
   27.78 +        return d
   27.79 +
   27.80 +    def saveall(self, path, d):
   27.81 +        for (k, v) in d.items():
   27.82 +            self.save(os.path.join(path, k), v)
   27.83 +
   27.84 +    def delete(self, path):
   27.85 +        dpath = self.filepath(path)
   27.86 +        os.unlink(dpath)
   27.87 +
   27.88 +    def ls(self, path):
   27.89 +        dpath = self.filepath(path)
   27.90 +        return dircache.listdir(dpath)
   27.91 +            
   27.92 +        
   27.93 +
   27.94 +        
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/tools/xen/lib/xend/XendDomain.py	Mon Jun 28 08:20:16 2004 +0000
    28.3 @@ -0,0 +1,366 @@
    28.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    28.5 +
    28.6 +"""Handler for domain operations.
    28.7 + Nothing here is persistent (across reboots).
    28.8 + Needs to be persistent for one uptime.
    28.9 +"""
   28.10 +import sys
   28.11 +
   28.12 +from twisted.internet import defer
   28.13 +
   28.14 +import xen.ext.xc; xc = xen.ext.xc.new()
   28.15 +import xenctl.ip
   28.16 +
   28.17 +import sxp
   28.18 +import XendRoot
   28.19 +xroot = XendRoot.instance()
   28.20 +import XendDB
   28.21 +import XendDomainInfo
   28.22 +import XendConsole
   28.23 +import EventServer
   28.24 +
   28.25 +from xen.xend.server import SrvDaemon
   28.26 +xend = SrvDaemon.instance()
   28.27 +
   28.28 +eserver = EventServer.instance()
   28.29 +
   28.30 +__all__ = [ "XendDomain" ]
   28.31 +        
   28.32 +class XendDomain:
   28.33 +    """Index of all domains. Singleton.
   28.34 +    """
   28.35 +    
   28.36 +    dbpath = "domain"
   28.37 +    domain = {}
   28.38 +    
   28.39 +    def __init__(self):
   28.40 +        self.xconsole = XendConsole.instance()
   28.41 +        # Table of domain info indexed by domain id.
   28.42 +        self.db = XendDB.XendDB(self.dbpath)
   28.43 +        #self.domain = {}
   28.44 +        self.domain_db = self.db.fetchall("")
   28.45 +        if xroot.get_rebooted():
   28.46 +            print 'XendDomain> rebooted: removing all domain info'
   28.47 +            self.rm_all()
   28.48 +        eserver.subscribe('xend.virq', self.onVirq)
   28.49 +        self.initial_refresh()
   28.50 +
   28.51 +    def onVirq(self, event, val):
   28.52 +        print 'XendDomain> virq', val
   28.53 +        self.reap()
   28.54 +
   28.55 +    def rm_all(self):
   28.56 +        """Remove all domain info. Used after reboot.
   28.57 +        """
   28.58 +        for (k, v) in self.domain_db.items():
   28.59 +            self._delete_domain(k, notify=0)
   28.60 +            
   28.61 +    def initial_refresh(self):
   28.62 +        """Refresh initial domain info from domain_db.
   28.63 +        """
   28.64 +        print "initial_refresh>"
   28.65 +        for d in self.domain_db.values(): print 'db dom=', d
   28.66 +        domlist = xc.domain_getinfo()
   28.67 +        for d in domlist: print 'xc dom=', d
   28.68 +        doms = {}
   28.69 +        for d in domlist:
   28.70 +            domid = str(d['dom'])
   28.71 +            doms[domid] = d
   28.72 +        dlist = []
   28.73 +        for config in self.domain_db.values():
   28.74 +            domid = str(sxp.child_value(config, 'id'))
   28.75 +            print "dom=", domid, "config=", config
   28.76 +            if domid in doms:
   28.77 +                print "dom=", domid, "new"
   28.78 +                deferred = self._new_domain(config, doms[domid])
   28.79 +                dlist.append(deferred)
   28.80 +            else:
   28.81 +                print "dom=", domid, "del"
   28.82 +                self._delete_domain(domid)
   28.83 +        deferred = defer.DeferredList(dlist, fireOnOneErrback=1)
   28.84 +        def cbok(val):
   28.85 +            #print "doms:"
   28.86 +            #for d in self.domain.values(): print 'dom', d
   28.87 +            self.refresh()
   28.88 +            print "XendDomain>initial_refresh> doms:"
   28.89 +            for d in self.domain.values(): print 'dom', d
   28.90 +        deferred.addCallback(cbok)
   28.91 +
   28.92 +    def sync(self):
   28.93 +        """Sync domain db to disk.
   28.94 +        """
   28.95 +        self.db.saveall("", self.domain_db)
   28.96 +
   28.97 +    def sync_domain(self, dom):
   28.98 +        """Sync info for a domain to disk.
   28.99 +
  28.100 +        dom	domain id (string)
  28.101 +        """
  28.102 +        self.db.save(dom, self.domain_db[dom])
  28.103 +
  28.104 +    def close(self):
  28.105 +        pass
  28.106 +
  28.107 +    def _new_domain(self, savedinfo, info):
  28.108 +        """Create a domain entry from saved info.
  28.109 +        """
  28.110 +##         console = None
  28.111 +##         kernel = None
  28.112 +##         id = sxp.child_value(info, 'id')
  28.113 +##         dom = int(id)
  28.114 +##         name = sxp.child_value(info, 'name')
  28.115 +##         memory = int(sxp.child_value(info, 'memory'))
  28.116 +##         consoleinfo = sxp.child(info, 'console')
  28.117 +##         if consoleinfo:
  28.118 +##             consoleid = sxp.child_value(consoleinfo, 'id')
  28.119 +##             console = self.xconsole.console_get(consoleid)
  28.120 +##         if dom and console is None:
  28.121 +##             # Try to connect a console.
  28.122 +##             console = self.xconsole.console_create(dom)
  28.123 +##         config = sxp.child(info, 'config')
  28.124 +##         if config:
  28.125 +##             image = sxp.child(info, 'image')
  28.126 +##             if image:
  28.127 +##                 image = sxp.child0(image)
  28.128 +##                 kernel = sxp.child_value(image, 'kernel')
  28.129 +##         dominfo = XendDomainInfo.XendDomainInfo(
  28.130 +##             config, dom, name, memory, kernel, console)
  28.131 +        config = sxp.child_value(savedinfo, 'config')
  28.132 +        deferred = XendDomainInfo.vm_recreate(config, info)
  28.133 +        def fn(dominfo):
  28.134 +            self.domain[dominfo.id] = dominfo
  28.135 +        deferred.addCallback(fn)
  28.136 +        return deferred
  28.137 +
  28.138 +    def _add_domain(self, id, info, notify=1):
  28.139 +        self.domain[id] = info
  28.140 +        self.domain_db[id] = info.sxpr()
  28.141 +        self.sync_domain(id)
  28.142 +        if notify: eserver.inject('xend.domain.created', id)
  28.143 +
  28.144 +    def _delete_domain(self, id, notify=1):
  28.145 +        if id in self.domain:
  28.146 +            if notify: eserver.inject('xend.domain.died', id)
  28.147 +            del self.domain[id]
  28.148 +        if id in self.domain_db:
  28.149 +            del self.domain_db[id]
  28.150 +            self.db.delete(id)
  28.151 +
  28.152 +    def reap(self):
  28.153 +        """Go through the domains looking for ones that have crashed or stopped.
  28.154 +        Tidy them up.
  28.155 +        """
  28.156 +        print 'XendDomain>reap>'
  28.157 +        domlist = xc.domain_getinfo()
  28.158 +        casualties = []
  28.159 +        for d in domlist:
  28.160 +            #print 'dom', d
  28.161 +            dead = 0
  28.162 +            dead = dead or (d['crashed'] or d['shutdown'])
  28.163 +            dead = dead or (d['dying'] and
  28.164 +                            not(d['running'] or d['paused'] or d['blocked']))
  28.165 +            if dead:
  28.166 +                casualties.append(d)
  28.167 +        for d in casualties:
  28.168 +            id = str(d['dom'])
  28.169 +            print 'XendDomain>reap> died id=', id, d
  28.170 +            dominfo = self.domain.get(id)
  28.171 +            if not dominfo: continue
  28.172 +            dominfo.died()
  28.173 +            self.domain_destroy(id, refresh=0)
  28.174 +        print 'XendDomain>reap<'
  28.175 +
  28.176 +    def refresh(self):
  28.177 +        """Refresh domain list from Xen.
  28.178 +        """
  28.179 +        domlist = xc.domain_getinfo()
  28.180 +        # Index the domlist by id.
  28.181 +        # Add entries for any domains we don't know about.
  28.182 +        doms = {}
  28.183 +        for d in domlist:
  28.184 +            id = str(d['dom'])
  28.185 +            doms[id] = d
  28.186 +            if id not in self.domain:
  28.187 +                config = None
  28.188 +                #image = None
  28.189 +                #newinfo = XendDomainInfo.XendDomainInfo(
  28.190 +                #    config, d['dom'], d['name'], d['mem_kb']/1024, image=image, info=d)
  28.191 +                deferred = XendDomainInfo.vm_recreate(config, d)
  28.192 +                def fn(dominfo):
  28.193 +                    self._add_domain(dominfo.id, dominfo)
  28.194 +                deferred.addCallback(fn)
  28.195 +        # Remove entries for domains that no longer exist.
  28.196 +        for d in self.domain.values():
  28.197 +            dominfo = doms.get(d.id)
  28.198 +            if dominfo:
  28.199 +                d.update(dominfo)
  28.200 +            else:
  28.201 +                self._delete_domain(d.id)
  28.202 +        self.reap()
  28.203 +
  28.204 +    def refresh_domain(self, id):
  28.205 +        dom = int(id)
  28.206 +        dominfo = xc.domain_getinfo(dom, 1)
  28.207 +        if dominfo == [] or dominfo[0]['dom'] != dom:
  28.208 +            try:
  28.209 +                self._delete_domain(id)
  28.210 +            except:
  28.211 +                print 'refresh_domain: error'
  28.212 +                raise
  28.213 +                pass
  28.214 +        else:
  28.215 +            d = self.domain.get(id)
  28.216 +            if d:
  28.217 +                d.update(dominfo[0])
  28.218 +
  28.219 +    def domain_ls(self):
  28.220 +        # List domains.
  28.221 +        # Update info from kernel first.
  28.222 +        self.refresh()
  28.223 +        return self.domain.keys()
  28.224 +
  28.225 +    def domains(self):
  28.226 +        self.refresh()
  28.227 +        return self.domain.values()
  28.228 +    
  28.229 +    def domain_create(self, config):
  28.230 +        # Create domain, log it.
  28.231 +        deferred = XendDomainInfo.vm_create(config)
  28.232 +        def fn(dominfo):
  28.233 +            self._add_domain(dominfo.id, dominfo)
  28.234 +            return dominfo
  28.235 +        deferred.addCallback(fn)
  28.236 +        return deferred
  28.237 +    
  28.238 +    def domain_get(self, id):
  28.239 +        id = str(id)
  28.240 +        self.refresh_domain(id)
  28.241 +        return self.domain[id]
  28.242 +    
  28.243 +    def domain_unpause(self, id):
  28.244 +        """(Re)start domain running.
  28.245 +        """
  28.246 +        dom = int(id)
  28.247 +        eserver.inject('xend.domain.unpause', id)
  28.248 +        return xc.domain_unpause(dom=dom)
  28.249 +    
  28.250 +    def domain_pause(self, id):
  28.251 +        """Pause domain execution.
  28.252 +        """
  28.253 +        dom = int(id)
  28.254 +        eserver.inject('xend.domain.pause', id)
  28.255 +        return xc.domain_pause(dom=dom)
  28.256 +    
  28.257 +    def domain_shutdown(self, id, reason='poweroff'):
  28.258 +        """Shutdown domain (nicely).
  28.259 +        """
  28.260 +        dom = int(id)
  28.261 +        if dom <= 0:
  28.262 +            return 0
  28.263 +        eserver.inject('xend.domain.shutdown', [id, reason])
  28.264 +        val = xend.domain_shutdown(dom, reason)
  28.265 +        self.refresh()
  28.266 +        return val
  28.267 +    
  28.268 +    def domain_destroy(self, id, refresh=1):
  28.269 +        """Terminate domain immediately.
  28.270 +        """
  28.271 +        dom = int(id)
  28.272 +        if dom <= 0:
  28.273 +            return 0
  28.274 +        eserver.inject('xend.domain.destroy', id)
  28.275 +        val = xc.domain_destroy(dom=dom)
  28.276 +        if refresh: self.refresh()
  28.277 +        return val       
  28.278 +
  28.279 +    def domain_migrate(self, id, dst):
  28.280 +        """Start domain migration.
  28.281 +        """
  28.282 +        # Need a cancel too?
  28.283 +        pass
  28.284 +    
  28.285 +    def domain_save(self, id, dst, progress=0):
  28.286 +        """Save domain state to file, destroy domain.
  28.287 +        """
  28.288 +        dom = int(id)
  28.289 +        self.domain_pause(id)
  28.290 +        eserver.inject('xend.domain.save', id)
  28.291 +        rc = xc.linux_save(dom=dom, state_file=dst, progress=progress)
  28.292 +        if rc == 0:
  28.293 +            self.domain_destroy(id)
  28.294 +        return rc
  28.295 +    
  28.296 +    def domain_restore(self, src, config, progress=0):
  28.297 +        """Restore domain from file.
  28.298 +        """
  28.299 +        dominfo = XendDomainInfo.dom_restore(dom, config)
  28.300 +        self._add_domain(dominfo.id, dominfo)
  28.301 +        return dominfo
  28.302 +    
  28.303 +    #============================================================================
  28.304 +    # Backward compatibility stuff from here on.
  28.305 +
  28.306 +    def domain_pincpu(self, dom, cpu):
  28.307 +        dom = int(dom)
  28.308 +        return xc.domain_pincpu(dom, cpu)
  28.309 +
  28.310 +    def domain_cpu_bvt_set(self, dom, mcuadv, warp, warpl, warpu):
  28.311 +        dom = int(dom)
  28.312 +        return xc.bvtsched_domain_set(dom=dom, mcuadv=mcuadv,
  28.313 +                                      warp=warp, warpl=warpl, warpu=warpu)
  28.314 +
  28.315 +    def domain_cpu_bvt_get(self, dom):
  28.316 +        dom = int(dom)
  28.317 +        return xc.bvtsched_domain_get(dom)
  28.318 +    
  28.319 +    def domain_cpu_atropos_set(self, dom, period, slice, latency, xtratime):
  28.320 +        dom = int(dom)
  28.321 +        return xc.atropos_domain_set(dom, period, slice, latency, xtratime)
  28.322 +
  28.323 +    def domain_cpu_atropos_get(self, dom):
  28.324 +        dom = int(dom)
  28.325 +        return xc.atropos_domain_get(dom)
  28.326 +
  28.327 +    def domain_vif_ls(self, dom):
  28.328 +        dominfo = self.domain_get(dom)
  28.329 +        if not dominfo: return None
  28.330 +        devs = dominfo.get_devices('vif')
  28.331 +        return range(0, len(devs))
  28.332 +
  28.333 +    def domain_vif_get(self, dom, vif):
  28.334 +        dominfo = self.domain_get(dom)
  28.335 +        if not dominfo: return None
  28.336 +        return dominfo.get_device_by_index(vif)
  28.337 +
  28.338 +    def domain_vif_ip_add(self, dom, vif, ip):
  28.339 +        dom = int(dom)
  28.340 +        return xenctl.ip.setup_vfr_rules_for_vif(dom, vif, ip)
  28.341 +
  28.342 +    def domain_vbd_ls(self, dom):
  28.343 +        dominfo = self.domain_get(dom)
  28.344 +        if not dominfo: return []
  28.345 +        devs = dominfo.get_devices('vbd')
  28.346 +        return [ sxp.child_value(v, 'dev') for v in devs ]
  28.347 +
  28.348 +    def domain_vbd_get(self, dom, vbd):
  28.349 +        dominfo = self.domain_get(dom)
  28.350 +        if not dominfo: return None
  28.351 +        devs = dominfo.get_devices('vbd')
  28.352 +        for v in devs:
  28.353 +            if sxp.child_value(v, 'dev') == vbd:
  28.354 +                return v
  28.355 +        return None
  28.356 +
  28.357 +    def domain_shadow_control(self, dom, op):
  28.358 +        dom = int(dom)
  28.359 +        return xc.shadow_control(dom, op)
  28.360 +
  28.361 +    #============================================================================
  28.362 +
  28.363 +def instance():
  28.364 +    global inst
  28.365 +    try:
  28.366 +        inst
  28.367 +    except:
  28.368 +        inst = XendDomain()
  28.369 +    return inst
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/tools/xen/lib/xend/XendDomainConfig.py	Mon Jun 28 08:20:16 2004 +0000
    29.3 @@ -0,0 +1,44 @@
    29.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    29.5 +
    29.6 +"""Handler for persistent domain configs.
    29.7 +
    29.8 +"""
    29.9 +
   29.10 +import sxp
   29.11 +import XendDB
   29.12 +import XendDomain
   29.13 +
   29.14 +__all__ = [ "XendDomainConfig" ]
   29.15 +
   29.16 +class XendDomainConfig:
   29.17 +
   29.18 +    dbpath = 'config'
   29.19 +
   29.20 +    def __init__(self):
   29.21 +        self.db = XendDB.XendDB(self.dbpath)
   29.22 +
   29.23 +    def domain_config_ls(self, path):
   29.24 +        return self.db.ls(path)
   29.25 +
   29.26 +    def domain_config_create(self, path, sxpr):
   29.27 +        self.db.save(path, sxpr)
   29.28 +        pass
   29.29 +
   29.30 +    def domain_config_delete(self, path):
   29.31 +        self.db.delete(path)
   29.32 +
   29.33 +    def domain_config_instance(self, path):
   29.34 +        """Create a domain from a config.
   29.35 +        """
   29.36 +        config = self.db.fetch(path)
   29.37 +        xd = XendDomain.instance()
   29.38 +        newdom = xd.domain_create(config)
   29.39 +        return newdom
   29.40 +
   29.41 +def instance():
   29.42 +    global inst
   29.43 +    try:
   29.44 +        inst
   29.45 +    except:
   29.46 +        inst = XendDomainConfig()
   29.47 +    return inst
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/tools/xen/lib/xend/XendDomainInfo.py	Mon Jun 28 08:20:16 2004 +0000
    30.3 @@ -0,0 +1,911 @@
    30.4 +#!/usr/bin/python
    30.5 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    30.6 +
    30.7 +"""Representation of a single domain.
    30.8 +Includes support for domain construction, using
    30.9 +open-ended configurations.
   30.10 +
   30.11 +Author: Mike Wray <mike.wray@hpl.hp.com>
   30.12 +
   30.13 +"""
   30.14 +
   30.15 +import string
   30.16 +import re
   30.17 +import sys
   30.18 +import os
   30.19 +
   30.20 +from twisted.internet import defer
   30.21 +
   30.22 +import xen.ext.xc; xc = xen.ext.xc.new()
   30.23 +import xenctl.ip
   30.24 +
   30.25 +import sxp
   30.26 +
   30.27 +import XendConsole
   30.28 +xendConsole = XendConsole.instance()
   30.29 +
   30.30 +import XendBridge
   30.31 +
   30.32 +import server.SrvDaemon
   30.33 +xend = server.SrvDaemon.instance()
   30.34 +
   30.35 +SIF_BLK_BE_DOMAIN = (1<<4)
   30.36 +SIF_NET_BE_DOMAIN = (1<<5)
   30.37 +
   30.38 +def readlines(fd):
   30.39 +    """Version of readlines safe against EINTR.
   30.40 +    """
   30.41 +    import errno
   30.42 +    
   30.43 +    lines = []
   30.44 +    while 1:
   30.45 +        try:
   30.46 +            line = fd.readline()
   30.47 +        except IOError, ex:
   30.48 +            if ex.errno == errno.EINTR:
   30.49 +                continue
   30.50 +            else:
   30.51 +                raise
   30.52 +        if line == '': break
   30.53 +        lines.append(line)
   30.54 +    return lines
   30.55 +
   30.56 +class VmError(ValueError):
   30.57 +    """Vm construction error."""
   30.58 +
   30.59 +    def __init__(self, value):
   30.60 +        self.value = value
   30.61 +
   30.62 +    def __str__(self):
   30.63 +        return self.value
   30.64 +
   30.65 +
   30.66 +def blkdev_name_to_number(name):
   30.67 +    """Take the given textual block-device name (e.g., '/dev/sda1',
   30.68 +    'hda') and return the device number used by the OS. """
   30.69 +
   30.70 +    if not re.match( '/dev/', name ):
   30.71 +        name = '/dev/' + name
   30.72 +        
   30.73 +    return os.stat(name).st_rdev
   30.74 +
   30.75 +def lookup_raw_partn(partition):
   30.76 +    """Take the given block-device name (e.g., '/dev/sda1', 'hda')
   30.77 +    and return a dictionary { device, start_sector,
   30.78 +    nr_sectors, type }
   30.79 +        device:       Device number of the given partition
   30.80 +        start_sector: Index of first sector of the partition
   30.81 +        nr_sectors:   Number of sectors comprising this partition
   30.82 +        type:         'Disk' or identifying name for partition type
   30.83 +    """
   30.84 +
   30.85 +    if not re.match( '/dev/', partition ):
   30.86 +        partition = '/dev/' + partition
   30.87 +
   30.88 +    drive = re.split( '[0-9]', partition )[0]
   30.89 +
   30.90 +    if drive == partition:
   30.91 +        fd = os.popen( '/sbin/sfdisk -s ' + drive + ' 2>/dev/null' )
   30.92 +        line = readline(fd)
   30.93 +        if line:
   30.94 +            return [ { 'device' : blkdev_name_to_number(drive),
   30.95 +                       'start_sector' : long(0),
   30.96 +                       'nr_sectors' : long(line) * 2,
   30.97 +                       'type' : 'Disk' } ]
   30.98 +        return None
   30.99 +
  30.100 +    # determine position on disk
  30.101 +    fd = os.popen( '/sbin/sfdisk -d ' + drive + ' 2>/dev/null' )
  30.102 +
  30.103 +    #['/dev/sda3 : start= 16948575, size=16836120, Id=83, bootable\012']
  30.104 +    lines = readlines(fd)
  30.105 +    for line in lines:
  30.106 +        m = re.search( '^' + partition + '\s*: start=\s*([0-9]+), ' +
  30.107 +                       'size=\s*([0-9]+), Id=\s*(\S+).*$', line)
  30.108 +        if m:
  30.109 +            return [ { 'device' : blkdev_name_to_number(drive),
  30.110 +                       'start_sector' : long(m.group(1)),
  30.111 +                       'nr_sectors' : long(m.group(2)),
  30.112 +                       'type' : m.group(3) } ]
  30.113 +    
  30.114 +    return None
  30.115 +
  30.116 +def lookup_disk_uname(uname):
  30.117 +    """Lookup a list of segments for a physical device.
  30.118 +    uname [string]:  name of the device in the format \'phy:dev\' for a physical device
  30.119 +    returns [list of dicts]: list of extents that make up the named device
  30.120 +    """
  30.121 +    ( type, d_name ) = string.split( uname, ':' )
  30.122 +
  30.123 +    if type == "phy":
  30.124 +        segments = lookup_raw_partn( d_name )
  30.125 +    else:
  30.126 +        segments = None
  30.127 +    return segments
  30.128 +
  30.129 +def make_disk(dom, uname, dev, mode, recreate=0):
  30.130 +    """Create a virtual disk device for a domain.
  30.131 +
  30.132 +    @returns Deferred
  30.133 +    """
  30.134 +    segments = lookup_disk_uname(uname)
  30.135 +    if not segments:
  30.136 +        raise VmError("vbd: Segments not found: uname=%s" % uname)
  30.137 +    if len(segments) > 1:
  30.138 +        raise VmError("vbd: Multi-segment vdisk: uname=%s" % uname)
  30.139 +    segment = segments[0]
  30.140 +    vdev = blkdev_name_to_number(dev)
  30.141 +    ctrl = xend.blkif_create(dom, recreate=recreate)
  30.142 +    
  30.143 +    def fn(ctrl):
  30.144 +        return xend.blkif_dev_create(dom, vdev, mode, segment, recreate=recreate)
  30.145 +    ctrl.addCallback(fn)
  30.146 +    return ctrl
  30.147 +        
  30.148 +def make_vif(dom, vif, vmac, recreate=0):
  30.149 +    """Create a virtual network device for a domain.
  30.150 +
  30.151 +    
  30.152 +    @returns Deferred
  30.153 +    """
  30.154 +    xend.netif_create(dom, recreate=recreate)
  30.155 +    d = xend.netif_dev_create(dom, vif, vmac, recreate=recreate)
  30.156 +    return d
  30.157 +
  30.158 +def vif_up(iplist):
  30.159 +    """send an unsolicited ARP reply for all non link-local IP addresses.
  30.160 +
  30.161 +    iplist IP addresses
  30.162 +    """
  30.163 +
  30.164 +    IP_NONLOCAL_BIND = '/proc/sys/net/ipv4/ip_nonlocal_bind'
  30.165 +    
  30.166 +    def get_ip_nonlocal_bind():
  30.167 +        return int(open(IP_NONLOCAL_BIND, 'r').read()[0])
  30.168 +
  30.169 +    def set_ip_nonlocal_bind(v):
  30.170 +        print >> open(IP_NONLOCAL_BIND, 'w'), str(v)
  30.171 +
  30.172 +    def link_local(ip):
  30.173 +        return xenctl.ip.check_subnet(ip, '169.254.0.0', '255.255.0.0')
  30.174 +
  30.175 +    def arping(ip, gw):
  30.176 +        cmd = '/usr/sbin/arping -A -b -I eth0 -c 1 -s %s %s' % (ip, gw)
  30.177 +        print cmd
  30.178 +        os.system(cmd)
  30.179 +        
  30.180 +    gateway = xenctl.ip.get_current_ipgw() or '255.255.255.255'
  30.181 +    nlb = get_ip_nonlocal_bind()
  30.182 +    if not nlb: set_ip_nonlocal_bind(1)
  30.183 +    try:
  30.184 +        for ip in iplist:
  30.185 +            if not link_local(ip):
  30.186 +                arping(ip, gateway)
  30.187 +    finally:
  30.188 +        if not nlb: set_ip_nonlocal_bind(0)
  30.189 +
  30.190 +config_handlers = {}
  30.191 +
  30.192 +def add_config_handler(name, h):
  30.193 +    """Add a handler for a config field.
  30.194 +
  30.195 +    name     field name
  30.196 +    h        handler: fn(vm, config, field, index)
  30.197 +    """
  30.198 +    config_handlers[name] = h
  30.199 +
  30.200 +def get_config_handler(name):
  30.201 +    """Get a handler for a config field.
  30.202 +
  30.203 +    returns handler or None
  30.204 +    """
  30.205 +    return config_handlers.get(name)
  30.206 +
  30.207 +"""Table of handlers for virtual machine images.
  30.208 +Indexed by image type.
  30.209 +"""
  30.210 +image_handlers = {}
  30.211 +
  30.212 +def add_image_handler(name, h):
  30.213 +    """Add a handler for an image type
  30.214 +    name     image type
  30.215 +    h        handler: fn(config, name, memory, image)
  30.216 +    """
  30.217 +    image_handlers[name] = h
  30.218 +
  30.219 +def get_image_handler(name):
  30.220 +    """Get the handler for an image type.
  30.221 +    name     image type
  30.222 +
  30.223 +    returns handler or None
  30.224 +    """
  30.225 +    return image_handlers.get(name)
  30.226 +
  30.227 +"""Table of handlers for devices.
  30.228 +Indexed by device type.
  30.229 +"""
  30.230 +device_handlers = {}
  30.231 +
  30.232 +def add_device_handler(name, h):
  30.233 +    """Add a handler for a device type.
  30.234 +
  30.235 +    name      device type
  30.236 +    h         handler: fn(vm, dev)
  30.237 +    """
  30.238 +    device_handlers[name] = h
  30.239 +
  30.240 +def get_device_handler(name):
  30.241 +    """Get the handler for a device type.
  30.242 +
  30.243 +    name      device type
  30.244 +
  30.245 +    returns handler or None
  30.246 +    """
  30.247 +    return device_handlers.get(name)
  30.248 +
  30.249 +def vm_create(config):
  30.250 +    """Create a VM from a configuration.
  30.251 +    If a vm has been partially created and there is an error it
  30.252 +    is destroyed.
  30.253 +
  30.254 +    config    configuration
  30.255 +
  30.256 +    returns Deferred
  30.257 +    raises VmError for invalid configuration
  30.258 +    """
  30.259 +    print 'vm_create>'
  30.260 +    vm = XendDomainInfo()
  30.261 +    return vm.construct(config)
  30.262 +
  30.263 +def vm_recreate(config, info):
  30.264 +    """Create the VM object for an existing domain.
  30.265 +    """
  30.266 +    vm = XendDomainInfo()
  30.267 +    vm.recreate = 1
  30.268 +    vm.setdom(info['dom'])
  30.269 +    vm.name = info['name']
  30.270 +    vm.memory = info['mem_kb']/1024
  30.271 +    if config:
  30.272 +        d = vm.construct(config)
  30.273 +    else:
  30.274 +        d = defer.Deferred()
  30.275 +        d.callback(vm)
  30.276 +    return d
  30.277 +
  30.278 +def vm_restore(src, config, progress=0):
  30.279 +    """Restore a VM from a disk image.
  30.280 +
  30.281 +    src      saved state to restore
  30.282 +    config   configuration
  30.283 +    progress progress reporting flag
  30.284 +    returns  deferred
  30.285 +    raises   VmError for invalid configuration
  30.286 +    """
  30.287 +    vm = XendDomainInfo()
  30.288 +    vm.config = config
  30.289 +    ostype = "linux" #todo set from config
  30.290 +    restorefn = getattr(xc, "%s_restore" % ostype)
  30.291 +    dom = restorefn(state_file=src, progress=progress)
  30.292 +    if dom < 0:
  30.293 +        raise VMError('restore failed')
  30.294 +    deferred = vm.dom_configure(dom)
  30.295 +    def vifs_cb(val, vm):
  30.296 +        vif_up(vm.ipaddrs)
  30.297 +    deferred.addCallback(vifs_cb, vm)
  30.298 +    return deferred
  30.299 +    
  30.300 +def dom_get(dom):
  30.301 +    domlist = xc.domain_getinfo(dom=dom)
  30.302 +    if domlist and dom == domlist[0]['dom']:
  30.303 +        return domlist[0]
  30.304 +    return None
  30.305 +    
  30.306 +
  30.307 +def append_deferred(dlist, v):
  30.308 +    if isinstance(v, defer.Deferred):
  30.309 +        dlist.append(v)
  30.310 +
  30.311 +def _vm_configure1(val, vm):
  30.312 +    d = vm.create_devices()
  30.313 +    print '_vm_configure1> made devices...'
  30.314 +    def cbok(x):
  30.315 +        print '_vm_configure1> cbok', x
  30.316 +        return x
  30.317 +    d.addCallback(cbok)
  30.318 +    d.addCallback(_vm_configure2, vm)
  30.319 +    print '_vm_configure1<'
  30.320 +    return d
  30.321 +
  30.322 +def _vm_configure2(val, vm):
  30.323 +    print '>callback _vm_configure2...'
  30.324 +    d = vm.configure_fields()
  30.325 +    def cbok(results):
  30.326 +        print '_vm_configure2> cbok', results
  30.327 +        return vm
  30.328 +    def cberr(err):
  30.329 +        print '_vm_configure2> cberr', err
  30.330 +        vm.destroy()
  30.331 +        return err
  30.332 +    d.addCallback(cbok)
  30.333 +    d.addErrback(cberr)
  30.334 +    print '<_vm_configure2'
  30.335 +    return d
  30.336 +
  30.337 +class XendDomainInfo:
  30.338 +    """Virtual machine object."""
  30.339 +
  30.340 +    def __init__(self):
  30.341 +        self.recreate = 0
  30.342 +        self.config = None
  30.343 +        self.id = None
  30.344 +        self.dom = None
  30.345 +        self.name = None
  30.346 +        self.memory = None
  30.347 +        self.image = None
  30.348 +        self.ramdisk = None
  30.349 +        self.cmdline = None
  30.350 +        self.console = None
  30.351 +        self.devices = {}
  30.352 +        self.configs = []
  30.353 +        self.info = None
  30.354 +        self.ipaddrs = []
  30.355 +        self.blkif_backend = 0
  30.356 +        self.netif_backend = 0
  30.357 +        #todo: state: running, suspended
  30.358 +        self.state = 'running'
  30.359 +        #todo: set to migrate info if migrating
  30.360 +        self.migrate = None
  30.361 +
  30.362 +    def setdom(self, dom):
  30.363 +        self.dom = int(dom)
  30.364 +        self.id = str(dom)
  30.365 +        
  30.366 +    def update(self, info):
  30.367 +        """Update with  info from xc.domain_getinfo().
  30.368 +        """
  30.369 +        self.info = info
  30.370 +        self.memory = self.info['mem_kb'] / 1024
  30.371 +
  30.372 +    def __str__(self):
  30.373 +        s = "domain"
  30.374 +        s += " id=" + self.id
  30.375 +        s += " name=" + self.name
  30.376 +        s += " memory=" + str(self.memory)
  30.377 +        if self.console:
  30.378 +            s += " console=" + self.console.id
  30.379 +        if self.image:
  30.380 +            s += " image=" + self.image
  30.381 +        s += ""
  30.382 +        return s
  30.383 +
  30.384 +    __repr__ = __str__
  30.385 +
  30.386 +    def sxpr(self):
  30.387 +        sxpr = ['domain',
  30.388 +                ['id', self.id],
  30.389 +                ['name', self.name],
  30.390 +                ['memory', self.memory] ]
  30.391 +        if self.info:
  30.392 +            run   = (self.info['running'] and 'r') or '-'
  30.393 +            block = (self.info['blocked'] and 'b') or '-'
  30.394 +            stop  = (self.info['paused']  and 'p') or '-'
  30.395 +            susp  = (self.info['shutdown'] and 's') or '-'
  30.396 +            crash = (self.info['crashed'] and 'c') or '-'
  30.397 +            state = run + block + stop + susp + crash
  30.398 +            sxpr.append(['state', state])
  30.399 +            if self.info['shutdown']:
  30.400 +                reasons = ["poweroff", "reboot", "suspend"]
  30.401 +                reason = reasons[self.info['shutdown_reason']]
  30.402 +                sxpr.append(['shutdown_reason', reason])
  30.403 +            sxpr.append(['cpu', self.info['cpu']])
  30.404 +            sxpr.append(['cpu_time', self.info['cpu_time']/1e9])
  30.405 +        if self.console:
  30.406 +            sxpr.append(self.console.sxpr())
  30.407 +        if self.config:
  30.408 +            sxpr.append(['config', self.config])
  30.409 +        return sxpr
  30.410 +
  30.411 +    def construct(self, config):
  30.412 +        # todo - add support for scheduling params?
  30.413 +        self.config = config
  30.414 +        try:
  30.415 +            self.name = sxp.child_value(config, 'name')
  30.416 +            self.memory = int(sxp.child_value(config, 'memory', '128'))
  30.417 +            self.configure_backends()
  30.418 +            image = sxp.child_value(config, 'image')
  30.419 +            image_name = sxp.name(image)
  30.420 +            image_handler = get_image_handler(image_name)
  30.421 +            if image_handler is None:
  30.422 +                raise VmError('unknown image type: ' + image_name)
  30.423 +            image_handler(self, image)
  30.424 +            deferred = self.configure()
  30.425 +        except StandardError, ex:
  30.426 +            # Catch errors, cleanup and re-raise.
  30.427 +            self.destroy()
  30.428 +            raise
  30.429 +        def cbok(x):
  30.430 +            print 'vm_create> cbok', x
  30.431 +            return x
  30.432 +        deferred.addCallback(cbok)
  30.433 +        print 'vm_create<'
  30.434 +        return deferred
  30.435 +
  30.436 +    def config_devices(self, name):
  30.437 +        """Get a list of the 'device' nodes of a given type from the config.
  30.438 +
  30.439 +        name	device type
  30.440 +        return list of device configs
  30.441 +        """
  30.442 +        devices = []
  30.443 +        for d in sxp.children(self.config, 'device'):
  30.444 +            dev = sxp.child0(d)
  30.445 +            if dev is None: continue
  30.446 +            if name == sxp.name(dev):
  30.447 +                devices.append(dev)
  30.448 +        return devices
  30.449 +
  30.450 +    def add_device(self, type, dev):
  30.451 +        """Add a device to a virtual machine.
  30.452 +
  30.453 +        dev      device to add
  30.454 +        """
  30.455 +        dl = self.devices.get(type, [])
  30.456 +        dl.append(dev)
  30.457 +        self.devices[type] = dl
  30.458 +
  30.459 +    def get_devices(self, type):
  30.460 +        val = self.devices.get(type, [])
  30.461 +        return val
  30.462 +
  30.463 +    def get_device_by_id(self, type, id):
  30.464 +        """Get the device with the given id.
  30.465 +
  30.466 +        id       device id
  30.467 +
  30.468 +        returns  device or None
  30.469 +        """
  30.470 +        dl = self.get_devices(type)
  30.471 +        for d in dl:
  30.472 +            if d.getprop('id') == id:
  30.473 +                return d
  30.474 +        return None
  30.475 +
  30.476 +    def get_device_by_index(self, type, idx):
  30.477 +        """Get the device with the given index.
  30.478 +
  30.479 +        idx       device index
  30.480 +
  30.481 +        returns  device or None
  30.482 +        """
  30.483 +        dl = self.get_devices(type)
  30.484 +        if 0 <= idx < len(dl):
  30.485 +            return dl[idx]
  30.486 +        else:
  30.487 +            return None
  30.488 +
  30.489 +    def add_config(self, val):
  30.490 +        """Add configuration data to a virtual machine.
  30.491 +
  30.492 +        val      data to add
  30.493 +        """
  30.494 +        self.configs.append(val)
  30.495 +
  30.496 +    def destroy(self):
  30.497 +        if self.dom <= 0:
  30.498 +            return 0
  30.499 +        return xc.domain_destroy(dom=self.dom)
  30.500 +
  30.501 +    def died(self):
  30.502 +        print 'died>', self.dom
  30.503 +        self.release_devices()
  30.504 +
  30.505 +    def release_devices(self):
  30.506 +        print 'release_devices>', self.dom
  30.507 +        self.release_vifs()
  30.508 +        self.release_vbds()
  30.509 +        self.devices = {}
  30.510 +
  30.511 +    def release_vifs(self):
  30.512 +        print 'release_vifs>', self.dom
  30.513 +        if self.dom is None: return
  30.514 +        ctrl = xend.netif_get(self.dom)
  30.515 +        if ctrl:
  30.516 +            ctrl.destroy()
  30.517 +
  30.518 +    def release_vbds(self):
  30.519 +        print 'release_vbds>', self.dom
  30.520 +        if self.dom is None: return
  30.521 +        ctrl = xend.blkif_get(self.dom)
  30.522 +        if ctrl:
  30.523 +            ctrl.destroy()
  30.524 +
  30.525 +    def show(self):
  30.526 +        """Print virtual machine info.
  30.527 +        """
  30.528 +        print "[VM dom=%d name=%s memory=%d" % (self.dom, self.name, self.memory)
  30.529 +        print "image:"
  30.530 +        sxp.show(self.image)
  30.531 +        print
  30.532 +        for dl in self.devices:
  30.533 +            for dev in dl:
  30.534 +                print "device:"
  30.535 +                sxp.show(dev)
  30.536 +                print
  30.537 +        for val in self.configs:
  30.538 +            print "config:"
  30.539 +            sxp.show(val)
  30.540 +            print
  30.541 +        print "]"
  30.542 +
  30.543 +    def init_domain(self):
  30.544 +        """Initialize the domain memory.
  30.545 +        """
  30.546 +        if self.recreate: return
  30.547 +        memory = self.memory
  30.548 +        name = self.name
  30.549 +        cpu = int(sxp.child_value(self.config, 'cpu', '-1'))
  30.550 +        print 'init_domain>', memory, name, cpu
  30.551 +        dom = xc.domain_create(mem_kb= memory * 1024, name= name, cpu= cpu)
  30.552 +        if dom <= 0:
  30.553 +            raise VmError('Creating domain failed: name=%s memory=%d'
  30.554 +                          % (name, memory))
  30.555 +        self.setdom(dom)
  30.556 +
  30.557 +    def build_domain(self, ostype, kernel, ramdisk, cmdline, vifs_n):
  30.558 +        """Build the domain boot image.
  30.559 +        """
  30.560 +        if self.recreate: return
  30.561 +        if len(cmdline) >= 256:
  30.562 +            print 'Warning: kernel cmdline too long'
  30.563 +        dom = self.dom
  30.564 +        buildfn = getattr(xc, '%s_build' % ostype)
  30.565 +        print 'build_domain>', ostype, dom, kernel, cmdline, ramdisk
  30.566 +        flags = 0
  30.567 +        if self.netif_backend: flags |= SIF_NET_BE_DOMAIN
  30.568 +        if self.blkif_backend: flags |= SIF_BLK_BE_DOMAIN
  30.569 +        err = buildfn(dom            = dom,
  30.570 +                      image          = kernel,
  30.571 +                      control_evtchn = self.console.port2,
  30.572 +                      cmdline        = cmdline,
  30.573 +                      ramdisk        = ramdisk,
  30.574 +                      flags          = flags)
  30.575 +        if err != 0:
  30.576 +            raise VmError('Building domain failed: type=%s dom=%d err=%d'
  30.577 +                          % (ostype, dom, err))
  30.578 +
  30.579 +    def create_domain(self, ostype, kernel, ramdisk, cmdline, vifs_n):
  30.580 +        """Create a domain. Builds the image but does not configure it.
  30.581 +
  30.582 +        ostype  OS type
  30.583 +        kernel  kernel image
  30.584 +        ramdisk kernel ramdisk
  30.585 +        cmdline kernel commandline
  30.586 +        vifs_n  number of network interfaces
  30.587 +        """
  30.588 +        print 'create_domain>', ostype, kernel
  30.589 +        if not self.recreate:
  30.590 +            if not os.path.isfile(kernel):
  30.591 +                raise VmError('Kernel image does not exist: %s' % kernel)
  30.592 +            if ramdisk and not os.path.isfile(ramdisk):
  30.593 +                raise VMError('Kernel ramdisk does not exist: %s' % ramdisk)
  30.594 +        print 'create-domain> init_domain...'
  30.595 +        self.init_domain()
  30.596 +        print 'create_domain>', 'dom=', self.dom
  30.597 +        self.console = xendConsole.console_create(self.dom)
  30.598 +        self.build_domain(ostype, kernel, ramdisk, cmdline, vifs_n)
  30.599 +        self.image = kernel
  30.600 +        self.ramdisk = ramdisk
  30.601 +        self.cmdline = cmdline
  30.602 +
  30.603 +    def create_devices(self):
  30.604 +        """Create the devices for a vm.
  30.605 +
  30.606 +        returns Deferred
  30.607 +        raises VmError for invalid devices
  30.608 +        """
  30.609 +        print '>create_devices'
  30.610 +        dlist = []
  30.611 +        devices = sxp.children(self.config, 'device')
  30.612 +        index = {}
  30.613 +        for d in devices:
  30.614 +            dev = sxp.child0(d)
  30.615 +            if dev is None:
  30.616 +                raise VmError('invalid device')
  30.617 +            dev_name = sxp.name(dev)
  30.618 +            dev_index = index.get(dev_name, 0)
  30.619 +            dev_handler = get_device_handler(dev_name)
  30.620 +            if dev_handler is None:
  30.621 +                raise VmError('unknown device type: ' + dev_name)
  30.622 +            v = dev_handler(self, dev, dev_index)
  30.623 +            append_deferred(dlist, v)
  30.624 +            index[dev_name] = dev_index + 1
  30.625 +        deferred = defer.DeferredList(dlist, fireOnOneErrback=1)
  30.626 +        print '<create_devices'
  30.627 +        return deferred
  30.628 +
  30.629 +    def configure_backends(self):
  30.630 +        """Set configuration flags if the vm is a backend for netif of blkif.
  30.631 +        """
  30.632 +        for c in sxp.children(self.config, 'backend'):
  30.633 +            name = sxp.name(c)
  30.634 +            if name == 'blkif':
  30.635 +                self.blkif_backend = 1
  30.636 +            elif name == 'netif':
  30.637 +                self.netif_backend = 1
  30.638 +            else:
  30.639 +                raise VmError('invalid backend type:' + str(name))
  30.640 +
  30.641 +    def create_backends(self):
  30.642 +        """Setup the netif and blkif backends.
  30.643 +        """
  30.644 +        if self.blkif_backend:
  30.645 +            xend.blkif_set_control_domain(self.dom, recreate=self.recreate)
  30.646 +        if self.netif_backend:
  30.647 +            xend.netif_set_control_domain(self.dom, recreate=self.recreate)
  30.648 +            
  30.649 +    def configure(self):
  30.650 +        """Configure a vm.
  30.651 +
  30.652 +        vm         virtual machine
  30.653 +        config     configuration
  30.654 +
  30.655 +        returns Deferred - calls callback with vm
  30.656 +        """
  30.657 +        if self.blkif_backend:
  30.658 +            d = defer.Deferred()
  30.659 +            d.callback(1)
  30.660 +        else:
  30.661 +            d = xend.blkif_create(self.dom, recreate=self.recreate)
  30.662 +        d.addCallback(_vm_configure1, self)
  30.663 +        return d
  30.664 +
  30.665 +    def dom_configure(self, dom):
  30.666 +        """Configure a domain.
  30.667 +
  30.668 +        dom    domain id
  30.669 +        returns deferred
  30.670 +        """
  30.671 +        d = dom_get(dom)
  30.672 +        if not d:
  30.673 +            raise VMError("Domain not found: %d" % dom)
  30.674 +        try:
  30.675 +            self.setdom(dom)
  30.676 +            self.name = d['name']
  30.677 +            self.memory = d['memory']/1024
  30.678 +            deferred = self.configure()
  30.679 +        except StandardError, ex:
  30.680 +            self.destroy()
  30.681 +            raise
  30.682 +        return deferred
  30.683 +
  30.684 +    def configure_fields(self):
  30.685 +        dlist = []
  30.686 +        index = {}
  30.687 +        for field in sxp.children(self.config):
  30.688 +            field_name = sxp.name(field)
  30.689 +            field_index = index.get(field_name, 0)
  30.690 +            field_handler = get_config_handler(field_name)
  30.691 +            # Ignore unknown fields. Warn?
  30.692 +            if field_handler:
  30.693 +                v = field_handler(self, self.config, field, field_index)
  30.694 +                append_deferred(dlist, v)
  30.695 +            index[field_name] = field_index + 1
  30.696 +        d = defer.DeferredList(dlist, fireOnOneErrback=1)
  30.697 +        return d
  30.698 +
  30.699 +
  30.700 +def vm_image_linux(vm, image):
  30.701 +    """Create a VM for a linux image.
  30.702 +
  30.703 +    name      vm name
  30.704 +    memory    vm memory
  30.705 +    image     image config
  30.706 +
  30.707 +    returns vm
  30.708 +    """
  30.709 +    kernel = sxp.child_value(image, "kernel")
  30.710 +    cmdline = ""
  30.711 +    ip = sxp.child_value(image, "ip", "dhcp")
  30.712 +    if ip:
  30.713 +        cmdline += " ip=" + ip
  30.714 +    root = sxp.child_value(image, "root")
  30.715 +    if root:
  30.716 +        cmdline += " root=" + root
  30.717 +    args = sxp.child_value(image, "args")
  30.718 +    if args:
  30.719 +        cmdline += " " + args
  30.720 +    ramdisk = sxp.child_value(image, "ramdisk", '')
  30.721 +    vifs = vm.config_devices("vif")
  30.722 +    vm.create_domain("linux", kernel, ramdisk, cmdline, len(vifs))
  30.723 +    return vm
  30.724 +
  30.725 +def vm_image_netbsd(vm, image):
  30.726 +    """Create a VM for a bsd image.
  30.727 +
  30.728 +    name      vm name
  30.729 +    memory    vm memory
  30.730 +    image     image config
  30.731 +
  30.732 +    returns vm
  30.733 +    """
  30.734 +    #todo: Same as for linux. Is that right? If so can unify them.
  30.735 +    kernel = sxp.child_value(image, "kernel")
  30.736 +    cmdline = ""
  30.737 +    ip = sxp.child_value(image, "ip", "dhcp")
  30.738 +    if ip:
  30.739 +        cmdline += "ip=" + ip
  30.740 +    root = sxp.child_value(image, "root")
  30.741 +    if root:
  30.742 +        cmdline += "root=" + root
  30.743 +    args = sxp.child_value(image, "args")
  30.744 +    if args:
  30.745 +        cmdline += " " + args
  30.746 +    ramdisk = sxp.child_value(image, "ramdisk")
  30.747 +    vifs = vm.config_devices("vif")
  30.748 +    vm.create_domain("netbsd", kernel, ramdisk, cmdline, len(vifs))
  30.749 +    return vm
  30.750 +
  30.751 +
  30.752 +def vm_dev_vif(vm, val, index):
  30.753 +    """Create a virtual network interface (vif).
  30.754 +
  30.755 +    vm        virtual machine
  30.756 +    val       vif config
  30.757 +    index     vif index
  30.758 +    """
  30.759 +    if vm.netif_backend:
  30.760 +        raise VmError('vif: vif in netif backend domain')
  30.761 +    vif = index #todo
  30.762 +    vmac = sxp.child_value(val, "mac")
  30.763 +    defer = make_vif(vm.dom, vif, vmac, vm.recreate)
  30.764 +    def fn(id):
  30.765 +        dev = xend.netif_dev(vm.dom, vif)
  30.766 +        devid = sxp.attribute(val, 'id')
  30.767 +        if devid:
  30.768 +            dev.setprop('id', devid)
  30.769 +        bridge = sxp.child_value(val, "bridge")
  30.770 +        dev.bridge_add(bridge)
  30.771 +        vm.add_device('vif', dev)
  30.772 +        print 'vm_dev_vif> created', dev
  30.773 +        return id
  30.774 +    defer.addCallback(fn)
  30.775 +    return defer
  30.776 +
  30.777 +def vm_dev_vbd(vm, val, index):
  30.778 +    """Create a virtual block device (vbd).
  30.779 +
  30.780 +    vm        virtual machine
  30.781 +    val       vbd config
  30.782 +    index     vbd index
  30.783 +    """
  30.784 +    if vm.blkif_backend:
  30.785 +        raise VmError('vbd: vbd in blkif backend domain')
  30.786 +    vdev = index
  30.787 +    uname = sxp.child_value(val, 'uname')
  30.788 +    if not uname:
  30.789 +        raise VMError('vbd: Missing uname')
  30.790 +    dev = sxp.child_value(val, 'dev')
  30.791 +    if not dev:
  30.792 +        raise VMError('vbd: Missing dev')
  30.793 +    mode = sxp.child_value(val, 'mode', 'r')
  30.794 +    defer = make_disk(vm.dom, uname, dev, mode, vm.recreate)
  30.795 +    def fn(vbd):
  30.796 +        dev = xend.blkif_dev(vm.dom, vdev)
  30.797 +        vm.add_device('vbd', dev)
  30.798 +        return vbd
  30.799 +    defer.addCallback(fn)
  30.800 +    return defer
  30.801 +
  30.802 +def parse_pci(val):
  30.803 +    if isinstance(val, StringType):
  30.804 +        radix = 10
  30.805 +        if val.startswith('0x') or val.startswith('0X'):
  30.806 +            radix = 16
  30.807 +        v = int(val, radix)
  30.808 +    else:
  30.809 +        v = val
  30.810 +    return v
  30.811 +
  30.812 +def vm_dev_pci(vm, val, index):
  30.813 +    bus = sxp.child_value(val, 'bus')
  30.814 +    if not bus:
  30.815 +        raise VMError('pci: Missing bus')
  30.816 +    dev = sxp.child_value(val, 'dev')
  30.817 +    if not dev:
  30.818 +        raise VMError('pci: Missing dev')
  30.819 +    func = sxp.child_value(val, 'func')
  30.820 +    if not func:
  30.821 +        raise VMError('pci: Missing func')
  30.822 +    try:
  30.823 +        bus = parse_pci(bus)
  30.824 +        dev = parse_pci(dev)
  30.825 +        func = parse_pci(func)
  30.826 +    except:
  30.827 +        raise VMError('pci: invalid parameter')
  30.828 +    rc = xc.physdev_pci_access_modify(dom=vm.dom, bus=bus, dev=dev,
  30.829 +                                      func=func, enable=1)
  30.830 +    if rc < 0:
  30.831 +        #todo non-fatal
  30.832 +        raise VMError('pci: Failed to configure device: bus=%s dev=%s func=%s' %
  30.833 +                      (bus, dev, func))
  30.834 +    return rc
  30.835 +    
  30.836 +
  30.837 +def vm_field_vfr(vm, config, val, index):
  30.838 +    """Handle a vfr field in a config.
  30.839 +
  30.840 +    vm        virtual machine
  30.841 +    config    vm config
  30.842 +    val       vfr field
  30.843 +    """
  30.844 +    # Get the rules and add them.
  30.845 +    # (vfr (vif (id foo) (ip x.x.x.x)) ... ) 
  30.846 +    list = sxp.children(val, 'vif')
  30.847 +    ipaddrs = []
  30.848 +    for v in list:
  30.849 +        id = sxp.child_value(v, 'id')
  30.850 +        if id is None:
  30.851 +            raise VmError('vfr: missing vif id')
  30.852 +        id = int(id)
  30.853 +        dev = vm.get_device_by_index('vif', id)
  30.854 +        if not dev:
  30.855 +            raise VmError('vfr: invalid vif id %d' % id)
  30.856 +        vif = sxp.child_value(dev, 'vif')
  30.857 +        ip = sxp.child_value(v, 'ip')
  30.858 +        if not ip:
  30.859 +            raise VmError('vfr: missing ip address')
  30.860 +        ipaddrs.append(ip);
  30.861 +        #Don't do this in new i/o model.
  30.862 +        #print 'vm_field_vfr> add rule', 'dom=', vm.dom, 'vif=', vif, 'ip=', ip
  30.863 +        #xenctl.ip.setup_vfr_rules_for_vif(vm.dom, vif, ip)
  30.864 +    vm.ipaddrs = ipaddrs
  30.865 +
  30.866 +def vnet_bridge(vnet, vmac, dom, idx):
  30.867 +    """Add the device for the vif to the bridge for its vnet.
  30.868 +    """
  30.869 +    vif = "vif%d.%d" % (dom, idx)
  30.870 +    try:
  30.871 +        cmd = "(vif.conn (vif %s) (vnet %s) (vmac %s))" % (vif, vnet, vmac)
  30.872 +        print "*** vnet_bridge>", cmd
  30.873 +        out = file("/proc/vnet/policy", "wb")
  30.874 +        out.write(cmd)
  30.875 +        err = out.close()
  30.876 +        print "vnet_bridge>", "err=", err
  30.877 +    except IOError, ex:
  30.878 +        print "vnet_bridge>", ex
  30.879 +    
  30.880 +def vm_field_vnet(vm, config, val, index):
  30.881 +    """Handle a vnet field in a config.
  30.882 +
  30.883 +    vm        virtual machine
  30.884 +    config    vm config
  30.885 +    val       vnet field
  30.886 +    index     index
  30.887 +    """
  30.888 +    # Get the vif children. For each vif look up the vif device
  30.889 +    # with the given id and configure its vnet.
  30.890 +    # (vnet (vif (id foo) (vnet 2) (mac x:x:x:x:x:x)) ... )
  30.891 +    vif_vnets = sxp.children(val, 'vif')
  30.892 +    for v in vif_vnets:
  30.893 +        id = sxp.child_value(v, 'id')
  30.894 +        if id is None:
  30.895 +            raise VmError('vnet: missing vif id')
  30.896 +        dev = vm.get_device_by_id('vif', id)
  30.897 +        #vnet = sxp.child_value(v, 'vnet', 1)
  30.898 +        #mac = sxp.child_value(dev, 'mac')
  30.899 +        #vif = sxp.child_value(dev, 'vif')
  30.900 +        #vnet_bridge(vnet, mac, vm.dom, 0)
  30.901 +        #vm.add_config([ 'vif.vnet', ['id', id], ['vnet', vnet], ['mac', mac]])
  30.902 +
  30.903 +# Register image handlers for linux and bsd.
  30.904 +add_image_handler('linux',  vm_image_linux)
  30.905 +add_image_handler('netbsd', vm_image_netbsd)
  30.906 +
  30.907 +# Register device handlers for vifs and vbds.
  30.908 +add_device_handler('vif',  vm_dev_vif)
  30.909 +add_device_handler('vbd',  vm_dev_vbd)
  30.910 +add_device_handler('pci',  vm_dev_pci)
  30.911 +
  30.912 +# Register config handlers for vfr and vnet.
  30.913 +add_config_handler('vfr',  vm_field_vfr)
  30.914 +add_config_handler('vnet', vm_field_vnet)
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/tools/xen/lib/xend/XendMigrate.py	Mon Jun 28 08:20:16 2004 +0000
    31.3 @@ -0,0 +1,103 @@
    31.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    31.5 +
    31.6 +import sys
    31.7 +import socket
    31.8 +
    31.9 +import sxp
   31.10 +import XendDB
   31.11 +import EventServer; eserver = EventServer.instance()
   31.12 +
   31.13 +class XendMigrateInfo:
   31.14 +
   31.15 +    # states: begin, active, failed, succeeded?
   31.16 +
   31.17 +    def __init__(self, id, dom, dst):
   31.18 +        self.id = id
   31.19 +        self.state = 'begin'
   31.20 +        self.src_host = socket.gethostname()
   31.21 +        self.src_dom = dom
   31.22 +        self.dst_host = dst
   31.23 +        self.dst_dom = None
   31.24 +        
   31.25 +    def set_state(self, state):
   31.26 +        self.state = state
   31.27 +
   31.28 +    def get_state(self):
   31.29 +        return self.state
   31.30 +
   31.31 +    def sxpr(self):
   31.32 +        sxpr = ['migrate', ['id', self.id], ['state', self.state] ]
   31.33 +        sxpr_src = ['src', ['host', self.src_host], ['domain', self.src_dom] ]
   31.34 +        sxpr.append(sxpr_src)
   31.35 +        sxpr_dst = ['dst', ['host', self.dst] ]
   31.36 +        if self.dst_dom:
   31.37 +            sxpr_dst.append(['domain', self.dst_dom])
   31.38 +        sxpr.append(sxpr_dst)
   31.39 +        return sxpr
   31.40 +    
   31.41 +
   31.42 +class XendMigrate:
   31.43 +    # Represents migration in progress.
   31.44 +    # Use log for indications of begin/end/errors?
   31.45 +    # Need logging of: domain create/halt, migrate begin/end/fail
   31.46 +    # Log via event server?
   31.47 +
   31.48 +    dbpath = "migrate"
   31.49 +    
   31.50 +    def __init__(self):
   31.51 +        self.db = XendDB.XendDB(self.dbpath)
   31.52 +        self.migrate = {}
   31.53 +        self.migrate_db = self.db.fetchall("")
   31.54 +        self.id = 0
   31.55 +
   31.56 +    def nextid(self):
   31.57 +        self.id += 1
   31.58 +        return "%d" % self.id
   31.59 +
   31.60 +    def sync(self):
   31.61 +        self.db.saveall("", self.migrate_db)
   31.62 +
   31.63 +    def sync_migrate(self, id):
   31.64 +        self.db.save(id, self.migrate_db[id])
   31.65 +
   31.66 +    def close(self):
   31.67 +        pass
   31.68 +
   31.69 +    def _add_migrate(self, id, info):
   31.70 +        self.migrate[id] = info
   31.71 +        self.migrate_db[id] = info.sxpr()
   31.72 +        self.sync_migrate(id)
   31.73 +        #eserver.inject('xend.migrate.begin', info.sxpr())
   31.74 +
   31.75 +    def _delete_migrate(self, id):
   31.76 +        #eserver.inject('xend.migrate.end', id)
   31.77 +        del self.migrate[id]
   31.78 +        del self.migrate_db[id]
   31.79 +        self.db.delete(id)
   31.80 +
   31.81 +    def migrate_ls(self):
   31.82 +        return self.migrate.keys()
   31.83 +
   31.84 +    def migrates(self):
   31.85 +        return self.migrate.values()
   31.86 +
   31.87 +    def migrate_get(self, id):
   31.88 +        return self.migrate.get(id)
   31.89 +    
   31.90 +    def migrate_begin(self, dom, dst):
   31.91 +        # Check dom for existence, not migrating already.
   31.92 +        # Create migrate info, tell xend to migrate it?
   31.93 +        # - or fork migrate command ourselves?
   31.94 +        # Subscribe to migrate notifications (for updating).
   31.95 +        id = self.nextid()
   31.96 +        info = XenMigrateInfo(id, dom, dst)
   31.97 +        self._add_migrate(id, info)
   31.98 +        return id
   31.99 +
  31.100 +def instance():
  31.101 +    global inst
  31.102 +    try:
  31.103 +        inst
  31.104 +    except:
  31.105 +        inst = XendMigrate()
  31.106 +    return inst
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/tools/xen/lib/xend/XendNode.py	Mon Jun 28 08:20:16 2004 +0000
    32.3 @@ -0,0 +1,71 @@
    32.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    32.5 +
    32.6 +"""Handler for node operations.
    32.7 + Has some persistent state:
    32.8 + - logs
    32.9 + - notification urls
   32.10 +
   32.11 +"""
   32.12 +
   32.13 +import os
   32.14 +import xen.ext.xc
   32.15 +
   32.16 +class XendNode:
   32.17 +
   32.18 +    def __init__(self):
   32.19 +        self.xc = xen.ext.xc.new()
   32.20 +
   32.21 +    def shutdown(self):
   32.22 +        return 0
   32.23 +
   32.24 +    def reboot(self):
   32.25 +        return 0
   32.26 +
   32.27 +    def notify(self, uri):
   32.28 +        return 0
   32.29 +    
   32.30 +    def cpu_bvt_slice_set(self, slice):
   32.31 +        ret = 0
   32.32 +        #ret = self.xc.bvtsched_global_set(ctx_allow=slice)
   32.33 +        return ret
   32.34 +
   32.35 +    def cpu_bvt_slice_get(self, slice):
   32.36 +        ret = 0
   32.37 +        #ret = self.xc.bvtsched_global_get()
   32.38 +        return ret
   32.39 +    
   32.40 +    def cpu_rrobin_slice_set(self, slice):
   32.41 +        ret = 0
   32.42 +        #ret = self.xc.rrobin_global_set(slice)
   32.43 +        return ret
   32.44 +
   32.45 +    def info(self):
   32.46 +        return self.nodeinfo() + self.physinfo()
   32.47 +
   32.48 +    def nodeinfo(self):
   32.49 +        (sys, host, rel, ver, mch) = os.uname()
   32.50 +        return [['system',  sys],
   32.51 +                ['host',    host],
   32.52 +                ['release', rel],
   32.53 +                ['version', ver],
   32.54 +                ['machine', mch]]
   32.55 +
   32.56 +    def physinfo(self):
   32.57 +        pinfo = self.xc.physinfo()
   32.58 +        info = [['cores', pinfo['cores']],
   32.59 +                ['hyperthreads_per_core', pinfo['ht_per_core']],
   32.60 +                ['cpu_mhz', pinfo['cpu_khz']/1000],
   32.61 +                ['memory', pinfo['total_pages']/256],
   32.62 +                ['free_memory', pinfo['free_pages']/256]]
   32.63 +        return info
   32.64 +        
   32.65 +        
   32.66 +
   32.67 +def instance():
   32.68 +    global inst
   32.69 +    try:
   32.70 +        inst
   32.71 +    except:
   32.72 +        inst = XendNode()
   32.73 +    return inst
   32.74 +
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/tools/xen/lib/xend/XendRoot.py	Mon Jun 28 08:20:16 2004 +0000
    33.3 @@ -0,0 +1,156 @@
    33.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    33.5 +
    33.6 +"""Xend root class.
    33.7 +Creates the event server and handles configuration.
    33.8 +"""
    33.9 +
   33.10 +import os
   33.11 +import os.path
   33.12 +import sys
   33.13 +import EventServer
   33.14 +
   33.15 +# Initial create of the event server.
   33.16 +eserver = EventServer.instance()
   33.17 +
   33.18 +import sxp
   33.19 +
   33.20 +def reboots():
   33.21 +    """Get a list of system reboots from wtmp.
   33.22 +    """
   33.23 +    out = os.popen('/usr/bin/last reboot', 'r')
   33.24 +    list = [ x.strip() for x in out if x.startswith('reboot') ]
   33.25 +    return list
   33.26 +
   33.27 +def last_reboot():
   33.28 +    """Get the last known system reboot.
   33.29 +    """
   33.30 +    l = reboots()
   33.31 +    return (l and l[-1]) or None
   33.32 +
   33.33 +class XendRoot:
   33.34 +    """Root of the management classes."""
   33.35 +
   33.36 +    lastboot_default = "/var/xen/lastboot"
   33.37 +
   33.38 +    """Default path to the root of the database."""
   33.39 +    dbroot_default = "/var/xen/xend-db"
   33.40 +
   33.41 +    """Default path to the config file."""
   33.42 +    config_default = "/etc/xen/xend-config.sxp"
   33.43 +
   33.44 +    """Environment variable used to override config_default."""
   33.45 +    config_var     = "XEND_CONFIG"
   33.46 +
   33.47 +    def __init__(self):
   33.48 +        self.rebooted = 0
   33.49 +        self.last_reboot = None
   33.50 +        self.dbroot = None
   33.51 +        self.config_path = None
   33.52 +        self.config = None
   33.53 +        self.configure()
   33.54 +        self.check_lastboot()
   33.55 +        eserver.subscribe('xend.*', self.event_handler)
   33.56 +        #eserver.subscribe('xend.domain.created', self.event_handler)
   33.57 +        #eserver.subscribe('xend.domain.died', self.event_handler)
   33.58 +
   33.59 +    def start(self):
   33.60 +        eserver.inject('xend.start', self.rebooted)
   33.61 +
   33.62 +    def event_handler(self, event, val):
   33.63 +        print >> sys.stderr, "EVENT>", event, val
   33.64 +
   33.65 +    def read_lastboot(self):
   33.66 +        try:
   33.67 +            val = file(self.lastboot, 'rb').readlines()[0]
   33.68 +        except StandardError, ex:
   33.69 +            print 'warning: Error reading', self.lastboot, ex
   33.70 +            val = None
   33.71 +        return val
   33.72 +
   33.73 +    def write_lastboot(self, val):
   33.74 +        if not val: return
   33.75 +        try:
   33.76 +            fdir = os.path.dirname(self.lastboot)
   33.77 +            if not os.path.isdir(fdir):
   33.78 +                os.makedirs(fdir)
   33.79 +            out = file(self.lastboot, 'wb+')
   33.80 +            out.write(val)
   33.81 +            out.close()
   33.82 +        except IOError, ex:
   33.83 +            print 'warning: Error writing', self.lastboot, ex
   33.84 +            pass
   33.85 +
   33.86 +    def check_lastboot(self):
   33.87 +        """Check if there has been a system reboot since we saved lastboot.
   33.88 +        """
   33.89 +        last_val = self.read_lastboot()
   33.90 +        this_val = last_reboot()
   33.91 +        if this_val == last_val:
   33.92 +            self.rebooted = 0
   33.93 +        else:
   33.94 +            self.rebooted = 1
   33.95 +            self.write_lastboot(this_val)
   33.96 +        self.last_reboot = this_val
   33.97 +
   33.98 +    def get_last_reboot(self):
   33.99 +        return self.last_reboot
  33.100 +
  33.101 +    def get_rebooted(self):
  33.102 +        return self.rebooted
  33.103 +
  33.104 +    def configure(self):
  33.105 +        self.set_config()
  33.106 +        self.dbroot = self.get_config_value("dbroot", self.dbroot_default)
  33.107 +        self.lastboot = self.get_config_value("lastboot", self.lastboot_default)
  33.108 +
  33.109 +    def get_dbroot(self):
  33.110 +        """Get the path to the database root.
  33.111 +        """
  33.112 +        return self.dbroot
  33.113 +
  33.114 +    def set_config(self):
  33.115 +        """If the config file exists, read it. If not, ignore it.
  33.116 +
  33.117 +        The config file is a sequence of sxp forms.
  33.118 +        """
  33.119 +        self.config_path = os.getenv(self.config_var, self.config_default)
  33.120 +        if os.path.exists(self.config_path):
  33.121 +            fin = file(self.config_path, 'rb')
  33.122 +            try:
  33.123 +                config = sxp.parse(fin)
  33.124 +                config.insert(0, 'config')
  33.125 +                self.config = config
  33.126 +            finally:
  33.127 +                fin.close()
  33.128 +        else:
  33.129 +            self.config = ['config']
  33.130 +
  33.131 +    def get_config(self, name=None):
  33.132 +        """Get the configuration element with the given name, or
  33.133 +        the whole configuration if no name is given.
  33.134 +
  33.135 +        name	element name (optional)
  33.136 +        returns config or none
  33.137 +        """
  33.138 +        if name is None:
  33.139 +            val = self.config
  33.140 +        else:
  33.141 +            val = sxp.child(self.config, name)
  33.142 +        return val
  33.143 +
  33.144 +    def get_config_value(self, name, val=None):
  33.145 +        """Get the value of an atomic configuration element.
  33.146 +
  33.147 +        name	element name
  33.148 +        val	default value (optional, defaults to None)
  33.149 +        returns value
  33.150 +        """
  33.151 +        return sxp.child_value(self.config, name, val=val)
  33.152 +
  33.153 +def instance():
  33.154 +    global inst
  33.155 +    try:
  33.156 +        inst
  33.157 +    except:
  33.158 +        inst = XendRoot()
  33.159 +    return inst
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/tools/xen/lib/xend/XendVnet.py	Mon Jun 28 08:20:16 2004 +0000
    34.3 @@ -0,0 +1,69 @@
    34.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    34.5 +
    34.6 +"""Handler for vnet operations.
    34.7 +"""
    34.8 +
    34.9 +import sxp
   34.10 +import XendDB
   34.11 +
   34.12 +class XendVnet:
   34.13 +    """Index of all vnets. Singleton.
   34.14 +    """
   34.15 +
   34.16 +    dbpath = "vnet"
   34.17 +
   34.18 +    def __init__(self):
   34.19 +        # Table of vnet info indexed by vnet id.
   34.20 +        self.vnet = {}
   34.21 +        self.db = XendDB.XendDB(self.dbpath)
   34.22 +        self.vnet = self.db.fetchall("")
   34.23 +
   34.24 +    def vnet_ls(self):
   34.25 +        """List all vnets.
   34.26 +        """
   34.27 +        return self.vnet.keys()
   34.28 +
   34.29 +    def vnets(self):
   34.30 +        return self.vnet.values()
   34.31 +
   34.32 +    def vnet_get(self, id):
   34.33 +        """Get a vnet.
   34.34 +
   34.35 +        id	vnet id
   34.36 +        """
   34.37 +        return self.vnet.get(id)
   34.38 +
   34.39 +    def vnet_create(self, info):
   34.40 +        """Create a vnet.
   34.41 +
   34.42 +        info	config
   34.43 +        """
   34.44 +        self.vnet_configure(info)
   34.45 +
   34.46 +    def vnet_configure(self, info):
   34.47 +        """Configure a vnet.
   34.48 +        id	vnet id
   34.49 +        info	config
   34.50 +        """
   34.51 +        # Need to configure for real.
   34.52 +        # Only sync if succeeded - otherwise need to back out.
   34.53 +        self.vnet[info.id] = info
   34.54 +        self.db.save(info.id, info)
   34.55 +
   34.56 +    def vnet_delete(self, id):
   34.57 +        """Delete a vnet.
   34.58 +
   34.59 +        id	vnet id
   34.60 +        """
   34.61 +        # Need to delete for real. What if fails?
   34.62 +        if id in self.vnet:
   34.63 +            del self.vnet[id]
   34.64 +            self.db.delete(id)
   34.65 +
   34.66 +def instance():
   34.67 +    global inst
   34.68 +    try:
   34.69 +        inst
   34.70 +    except:
   34.71 +        inst = XendVnet()
   34.72 +    return inst
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/tools/xen/lib/xend/__init__.py	Mon Jun 28 08:20:16 2004 +0000
    35.3 @@ -0,0 +1,1 @@
    35.4 + 
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/tools/xen/lib/xend/encode.py	Mon Jun 28 08:20:16 2004 +0000
    36.3 @@ -0,0 +1,165 @@
    36.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    36.5 +"""Encoding for arguments to HTTP calls.
    36.6 +   Uses the url-encoding with MIME type 'application/x-www-form-urlencoded'
    36.7 +   if the data does not include files. Otherwise it uses the encoding with
    36.8 +   MIME type 'multipart/form-data'. See the HTML4 spec for details.
    36.9 +
   36.10 +   """
   36.11 +import sys
   36.12 +import types
   36.13 +from StringIO import StringIO
   36.14 +
   36.15 +import urllib
   36.16 +import httplib
   36.17 +import random
   36.18 +import md5
   36.19 +
   36.20 +# Extract from HTML4 spec.
   36.21 +## The following example illustrates "multipart/form-data"
   36.22 +## encoding. Suppose we have the following form:
   36.23 +
   36.24 +##  <FORM action="http://server.com/cgi/handle"
   36.25 +##        enctype="multipart/form-data"
   36.26 +##        method="post">
   36.27 +##    <P>
   36.28 +##    What is your name? <INPUT type="text" name="submit-name"><BR>
   36.29 +##    What files are you sending? <INPUT type="file" name="files"><BR>
   36.30 +##    <INPUT type="submit" value="Send"> <INPUT type="reset">
   36.31 +##  </FORM>
   36.32 +
   36.33 +## If the user enters "Larry" in the text input, and selects the text
   36.34 +## file "file1.txt", the user agent might send back the following data:
   36.35 +
   36.36 +##    Content-Type: multipart/form-data; boundary=AaB03x
   36.37 +
   36.38 +##    --AaB03x
   36.39 +##    Content-Disposition: form-data; name="submit-name"
   36.40 +
   36.41 +##    Larry
   36.42 +##    --AaB03x
   36.43 +##    Content-Disposition: form-data; name="files"; filename="file1.txt"
   36.44 +##    Content-Type: text/plain
   36.45 +
   36.46 +##    ... contents of file1.txt ...
   36.47 +##    --AaB03x--
   36.48 +
   36.49 +## If the user selected a second (image) file "file2.gif", the user agent
   36.50 +## might construct the parts as follows:
   36.51 +
   36.52 +##    Content-Type: multipart/form-data; boundary=AaB03x
   36.53 +
   36.54 +##    --AaB03x
   36.55 +##    Content-Disposition: form-data; name="submit-name"
   36.56 +
   36.57 +##    Larry
   36.58 +##    --AaB03x
   36.59 +##    Content-Disposition: form-data; name="files"
   36.60 +##    Content-Type: multipart/mixed; boundary=BbC04y
   36.61 +
   36.62 +##    --BbC04y
   36.63 +##    Content-Disposition: file; filename="file1.txt"
   36.64 +##    Content-Type: text/plain
   36.65 +
   36.66 +##    ... contents of file1.txt ...
   36.67 +##    --BbC04y
   36.68 +##    Content-Disposition: file; filename="file2.gif"
   36.69 +##    Content-Type: image/gif
   36.70 +##    Content-Transfer-Encoding: binary
   36.71 +
   36.72 +##    ...contents of file2.gif...
   36.73 +##    --BbC04y--
   36.74 +##    --AaB03x--
   36.75 +
   36.76 +__all__ = ['encode_data', 'encode_multipart', 'encode_form', 'mime_boundary' ]
   36.77 +
   36.78 +def data_values(d):
   36.79 +    if isinstance(d, types.DictType):
   36.80 +        return d.items()
   36.81 +    else:
   36.82 +        return d
   36.83 +
   36.84 +def encode_data(d):
   36.85 +    """Encode some data for HTTP transport.
   36.86 +    The encoding used is stored in 'Content-Type' in the headers.
   36.87 +
   36.88 +    d	data - sequence of tuples or dictionary
   36.89 +    returns a 2-tuple of the headers and the encoded data
   36.90 +    """
   36.91 +    val = ({}, None)
   36.92 +    if d is None: return val
   36.93 +    multipart = 0
   36.94 +    for (k, v) in data_values(d):
   36.95 +        if encode_isfile(v):
   36.96 +            multipart = 1
   36.97 +            break
   36.98 +    if multipart:
   36.99 +        val = encode_multipart(d)
  36.100 +    else:
  36.101 +        val = encode_form(d)
  36.102 +    return val
  36.103 +
  36.104 +def encode_isfile(v):
  36.105 +    if isinstance(v, types.FileType):
  36.106 +        return 1
  36.107 +    if hasattr(v, 'readlines'):
  36.108 +        return 1
  36.109 +    return 0
  36.110 +
  36.111 +def encode_multipart(d):
  36.112 +    boundary = mime_boundary()
  36.113 +    hdr = { 'Content-Type': 'multipart/form-data; boundary=' + boundary }
  36.114 +    out = StringIO()
  36.115 +    for (k,v) in data_values(d):
  36.116 +        out.write('--')
  36.117 +        out.write(boundary)
  36.118 +        out.write('\r\n')
  36.119 +        if encode_isfile(v):
  36.120 +            out.write('Content-Disposition: form-data; name="')
  36.121 +            out.write(k)
  36.122 +            if hasattr(v, 'name'):
  36.123 +                out.write('"; filename="')
  36.124 +                out.write(v.name)
  36.125 +            out.write('"\r\n')
  36.126 +            out.write('Content-Type: application/octet-stream\r\n')
  36.127 +            out.write('\r\n')
  36.128 +            for l in v.readlines():
  36.129 +               out.write(l)  
  36.130 +        else:
  36.131 +            out.write('Content-Disposition: form-data; name="')
  36.132 +            out.write(k)
  36.133 +            out.write('"\r\n')
  36.134 +            out.write('\r\n')
  36.135 +            out.write(str(v))
  36.136 +            out.write('\r\n')
  36.137 +    out.write('--')
  36.138 +    out.write(boundary)
  36.139 +    out.write('--')
  36.140 +    out.write('\r\n')
  36.141 +    return (hdr, out.getvalue())
  36.142 +
  36.143 +def mime_boundary():
  36.144 +    random.seed()
  36.145 +    m = md5.new()
  36.146 +    for i in range(0, 10):
  36.147 +        c = chr(random.randint(1, 255))
  36.148 +        m.update(c)
  36.149 +    b = m.hexdigest()
  36.150 +    return b[0:16]
  36.151 +
  36.152 +def encode_form(d):
  36.153 +    hdr = { 'Content-Type': 'application/x-www-form-urlencoded' }
  36.154 +    val = urllib.urlencode(d)
  36.155 +    return (hdr, val)
  36.156 +
  36.157 +def main():
  36.158 +    #d = {'a': 1, 'b': 'x y', 'c': file('conf.sxp') }
  36.159 +    #d = {'a': 1, 'b': 'x y' }
  36.160 +    d = [ ('a', 1), ('b', 'x y'), ('c', file('conf.sxp')) ]
  36.161 +    #d = [ ('a', 1), ('b', 'x y')]
  36.162 +    v = encode_data(d)
  36.163 +    print v[0]
  36.164 +    sys.stdout.write(v[1])
  36.165 +    print
  36.166 +
  36.167 +if __name__ == "__main__":
  36.168 +    main()
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/tools/xen/lib/xend/server/SrvBase.py	Mon Jun 28 08:20:16 2004 +0000
    37.3 @@ -0,0 +1,137 @@
    37.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    37.5 +
    37.6 +import cgi
    37.7 +
    37.8 +import os
    37.9 +import sys
   37.10 +import types
   37.11 +import StringIO
   37.12 +
   37.13 +from twisted.internet import defer
   37.14 +from twisted.internet import reactor
   37.15 +from twisted.web import error
   37.16 +from twisted.web import resource
   37.17 +from twisted.web import server
   37.18 +
   37.19 +from xen.xend import sxp
   37.20 +from xen.xend import PrettyPrint
   37.21 +
   37.22 +def uri_pathlist(p):
   37.23 +    """Split a path into a list.
   37.24 +    p		path
   37.25 +    return list of path elements
   37.26 +    """
   37.27 +    l = []
   37.28 +    for x in p.split('/'):
   37.29 +        if x == '': continue
   37.30 +        l.append(x)
   37.31 +    return l
   37.32 +
   37.33 +class SrvBase(resource.Resource):
   37.34 +    """Base class for services.
   37.35 +    """
   37.36 +
   37.37 +    def parse_form(self, req, method):
   37.38 +        """Parse the data for a request, GET using the URL, POST using encoded data.
   37.39 +        Posts should use enctype='multipart/form-data' in the <form> tag,
   37.40 +        rather than 'application/x-www-form-urlencoded'. Only 'multipart/form-data'
   37.41 +        handles file upload.
   37.42 +
   37.43 +        req		request
   37.44 +        returns a cgi.FieldStorage instance
   37.45 +        """
   37.46 +        env = {}
   37.47 +        env['REQUEST_METHOD'] = method
   37.48 +        if self.query:
   37.49 +            env['QUERY_STRING'] = self.query
   37.50 +        val = cgi.FieldStorage(fp=req.rfile, headers=req.headers, environ=env)
   37.51 +        return val
   37.52 +    
   37.53 +    def use_sxp(self, req):
   37.54 +        """Determine whether to send an SXP response to a request.
   37.55 +        Uses SXP if there is no User-Agent, no Accept, or application/sxp is in Accept.
   37.56 +
   37.57 +        req		request
   37.58 +        returns 1 for SXP, 0 otherwise
   37.59 +        """
   37.60 +        ok = 0
   37.61 +        user_agent = req.getHeader('User-Agent')
   37.62 +        accept = req.getHeader('Accept')
   37.63 +        if (not user_agent) or (not accept) or (accept.find(sxp.mime_type) >= 0):
   37.64 +            ok = 1
   37.65 +        return ok
   37.66 +
   37.67 +    def get_op_method(self, op):
   37.68 +        """Get the method for an operation.
   37.69 +        For operation 'foo' looks for 'op_foo'.
   37.70 +
   37.71 +        op	operation name
   37.72 +        returns method or None
   37.73 +        """
   37.74 +        op_method_name = 'op_' + op
   37.75 +        return getattr(self, op_method_name, None)
   37.76 +        
   37.77 +    def perform(self, req):
   37.78 +        """General operation handler for posted operations.
   37.79 +        For operation 'foo' looks for a method op_foo and calls
   37.80 +        it with op_foo(op, req). Replies with code 500 if op_foo
   37.81 +        is not found.
   37.82 +
   37.83 +        The method must return a list when req.use_sxp is true
   37.84 +        and an HTML string otherwise (or list).
   37.85 +        Methods may also return a Deferred (for incomplete processing).
   37.86 +
   37.87 +        req	request
   37.88 +        """
   37.89 +        op = req.args.get('op')
   37.90 +        if op is None or len(op) != 1:
   37.91 +            req.setResponseCode(404, "Invalid")
   37.92 +            return ''
   37.93 +        op = op[0]
   37.94 +        op_method = self.get_op_method(op)
   37.95 +        if op_method is None:
   37.96 +            req.setResponseCode(501, "Not implemented")
   37.97 +            req.setHeader("Content-Type", "text/plain")
   37.98 +            req.write("Not implemented: " + op)
   37.99 +            return ''
  37.100 +        else:
  37.101 +            val = op_method(op, req)
  37.102 +            if isinstance(val, defer.Deferred):
  37.103 +                val.addCallback(self._cb_perform, req, 1)
  37.104 +                return server.NOT_DONE_YET
  37.105 +            else:
  37.106 +                self._cb_perform(val, req, 0)
  37.107 +                return ''
  37.108 +
  37.109 +    def _cb_perform(self, val, req, dfr):
  37.110 +        """Callback to complete the request.
  37.111 +        May be called from a Deferred.
  37.112 +        """
  37.113 +        if isinstance(val, error.ErrorPage):
  37.114 +            req.write(val.render(req))
  37.115 +        elif self.use_sxp(req):
  37.116 +            req.setHeader("Content-Type", sxp.mime_type)
  37.117 +            sxp.show(val, req)
  37.118 +        else:
  37.119 +            req.write('<html><head></head><body>')
  37.120 +            self.print_path(req)
  37.121 +            if isinstance(val, types.ListType):
  37.122 +                req.write('<code><pre>')
  37.123 +                PrettyPrint.prettyprint(val, out=req)
  37.124 +                req.write('</pre></code>')
  37.125 +            else:
  37.126 +                req.write(str(val))
  37.127 +            req.write('</body></html>')
  37.128 +        if dfr:
  37.129 +            req.finish()
  37.130 +
  37.131 +    def print_path(self, req):
  37.132 +        """Print the path with hyperlinks.
  37.133 +        """
  37.134 +        pathlist = [x for x in req.prepath if x != '' ]
  37.135 +        s = "/"
  37.136 +        req.write('<h1><a href="/">/</a>')
  37.137 +        for x in pathlist:
  37.138 +            s += x + "/"
  37.139 +            req.write(' <a href="%s">%s</a>/' % (s, x))
  37.140 +        req.write("</h1>")
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/tools/xen/lib/xend/server/SrvConsole.py	Mon Jun 28 08:20:16 2004 +0000
    38.3 @@ -0,0 +1,42 @@
    38.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    38.5 +
    38.6 +from xen.xend import sxp
    38.7 +from xen.xend import XendConsole
    38.8 +from SrvDir import SrvDir
    38.9 +
   38.10 +class SrvConsole(SrvDir):
   38.11 +    """An individual console.
   38.12 +    """
   38.13 +
   38.14 +    def __init__(self, info):
   38.15 +        SrvDir.__init__(self)
   38.16 +        self.info = info
   38.17 +        self.xc = XendConsole.instance()
   38.18 +
   38.19 +    def op_disconnect(self, op, req):
   38.20 +        val = self.xc.console_disconnect(self.info.id)
   38.21 +        return val
   38.22 +
   38.23 +    def render_POST(self, req):
   38.24 +        return self.perform(req)
   38.25 +        
   38.26 +    def render_GET(self, req):
   38.27 +        if self.use_sxp(req):
   38.28 +            req.setHeader("Content-Type", sxp.mime_type)
   38.29 +            sxp.show(self.info.sxpr(), out=req)
   38.30 +        else:
   38.31 +            req.write('<html><head></head><body>')
   38.32 +            self.print_path(req)
   38.33 +            #self.ls()
   38.34 +            req.write('<p>%s</p>' % self.info)
   38.35 +            req.write('<p><a href="%s">Connect to domain %d</a></p>'
   38.36 +                      % (self.info.uri(), self.info.dom2))
   38.37 +            self.form(req)
   38.38 +            req.write('</body></html>')
   38.39 +        return ''
   38.40 +
   38.41 +    def form(self, req):
   38.42 +        req.write('<form method="post" action="%s">' % req.prePathURL())
   38.43 +        if self.info.connection():
   38.44 +            req.write('<input type="submit" name="op" value="disconnect">')
   38.45 +        req.write('</form>')
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/tools/xen/lib/xend/server/SrvConsoleDir.py	Mon Jun 28 08:20:16 2004 +0000
    39.3 @@ -0,0 +1,59 @@
    39.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    39.5 +
    39.6 +from SrvDir import SrvDir
    39.7 +from SrvConsole import SrvConsole
    39.8 +from xen.xend import XendConsole
    39.9 +from xen.xend import sxp
   39.10 +
   39.11 +class SrvConsoleDir(SrvDir):
   39.12 +    """Console directory.
   39.13 +    """
   39.14 +
   39.15 +    def __init__(self):
   39.16 +        SrvDir.__init__(self)
   39.17 +        self.xconsole = XendConsole.instance()
   39.18 +
   39.19 +    def console(self, x):
   39.20 +        val = None
   39.21 +        try:
   39.22 +            info = self.xconsole.console_get(x)
   39.23 +            val = SrvConsole(info)
   39.24 +        except KeyError, ex:
   39.25 +            print 'SrvConsoleDir>', ex
   39.26 +            pass
   39.27 +        return val
   39.28 +
   39.29 +    def get(self, x):
   39.30 +        v = SrvDir.get(self, x)
   39.31 +        if v is not None:
   39.32 +            return v
   39.33 +        v = self.console(x)
   39.34 +        return v
   39.35 +
   39.36 +    def render_GET(self, req):
   39.37 +        if self.use_sxp(req):
   39.38 +            req.setHeader("Content-Type", sxp.mime_type)
   39.39 +            self.ls_console(req, 1)
   39.40 +        else:
   39.41 +            req.write("<html><head></head><body>")
   39.42 +            self.print_path(req)
   39.43 +            self.ls(req)
   39.44 +            self.ls_console(req)
   39.45 +            #self.form(req.wfile)
   39.46 +            req.write("</body></html>")
   39.47 +        return ''
   39.48 +
   39.49 +    def ls_console(self, req, use_sxp=0):
   39.50 +        url = req.prePathURL()
   39.51 +        if not url.endswith('/'):
   39.52 +            url += '/'
   39.53 +        if use_sxp:
   39.54 +            consoles = self.xconsole.console_ls()
   39.55 +            sxp.show(consoles, out=req)
   39.56 +        else:
   39.57 +            consoles = self.xconsole.consoles()
   39.58 +            consoles.sort(lambda x, y: cmp(x.id, y.id))
   39.59 +            req.write('<ul>')
   39.60 +            for c in consoles:
   39.61 +                req.write('<li><a href="%s%s"> %s</a></li>' % (url, c.id, c))
   39.62 +            req.write('</ul>')
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/tools/xen/lib/xend/server/SrvDaemon.py	Mon Jun 28 08:20:16 2004 +0000
    40.3 @@ -0,0 +1,751 @@
    40.4 +###########################################################
    40.5 +## Xen controller daemon
    40.6 +## Copyright (c) 2004, K A Fraser (University of Cambridge)
    40.7 +## Copyright (C) 2004, Mike Wray <mike.wray@hp.com>
    40.8 +###########################################################
    40.9 +
   40.10 +import os
   40.11 +import os.path
   40.12 +import signal
   40.13 +import sys
   40.14 +import threading
   40.15 +import linecache
   40.16 +import socket
   40.17 +import pwd
   40.18 +import re
   40.19 +import StringIO
   40.20 +
   40.21 +from twisted.internet import pollreactor
   40.22 +pollreactor.install()
   40.23 +
   40.24 +from twisted.internet import reactor
   40.25 +from twisted.internet import protocol
   40.26 +from twisted.internet import abstract
   40.27 +from twisted.internet import defer
   40.28 +
   40.29 +from xen.ext import xu
   40.30 +
   40.31 +from xen.xend import sxp
   40.32 +from xen.xend import PrettyPrint
   40.33 +from xen.xend import EventServer
   40.34 +eserver = EventServer.instance()
   40.35 +
   40.36 +from xen.xend.server import SrvServer
   40.37 +
   40.38 +import channel
   40.39 +import blkif
   40.40 +import netif
   40.41 +import console
   40.42 +import domain
   40.43 +from params import *
   40.44 +
   40.45 +DEBUG = 1
   40.46 +
   40.47 +class MgmtProtocol(protocol.DatagramProtocol):
   40.48 +    """Handler for the management socket (unix-domain).
   40.49 +    """
   40.50 +
   40.51 +    def __init__(self, daemon):
   40.52 +        #protocol.DatagramProtocol.__init__(self)
   40.53 +        self.daemon = daemon
   40.54 +    
   40.55 +    def write(self, data, addr):
   40.56 +        return self.transport.write(data, addr)
   40.57 +
   40.58 +    def datagramReceived(self, data, addr):
   40.59 +        if DEBUG: print 'datagramReceived> addr=', addr, 'data=', data
   40.60 +        io = StringIO.StringIO(data)
   40.61 +        try:
   40.62 +            vals = sxp.parse(io)
   40.63 +            res = self.dispatch(vals[0])
   40.64 +            self.send_result(addr, res)
   40.65 +        except SystemExit:
   40.66 +            raise
   40.67 +        except:
   40.68 +            if DEBUG:
   40.69 +                raise
   40.70 +            else:
   40.71 +                self.send_error(addr)
   40.72 +
   40.73 +    def send_reply(self, addr, sxpr):
   40.74 +        io = StringIO.StringIO()
   40.75 +        sxp.show(sxpr, out=io)
   40.76 +        io.seek(0)
   40.77 +        self.write(io.getvalue(), addr)
   40.78 +
   40.79 +    def send_result(self, addr, res):
   40.80 +        
   40.81 +        def fn(res, self=self, addr=addr):
   40.82 +            self.send_reply(addr, ['ok', res])
   40.83 +            
   40.84 +        if isinstance(res, defer.Deferred):
   40.85 +            res.addCallback(fn)
   40.86 +        else:
   40.87 +            fn(res)
   40.88 +
   40.89 +    def send_error(self, addr):
   40.90 +        (extype, exval) = sys.exc_info()[:2]
   40.91 +        self.send_reply(addr, ['err',
   40.92 +                               ['type',  str(extype) ],
   40.93 +                               ['value', str(exval)  ] ] )
   40.94 +
   40.95 +    def opname(self, name):
   40.96 +        """Get the name of the method for an operation.
   40.97 +        """
   40.98 +        return 'op_' + name.replace('.', '_')
   40.99 +
  40.100 +    def operror(self, name, v):
  40.101 +        """Default operation handler - signals an error.
  40.102 +        """
  40.103 +        raise NotImplementedError('Invalid operation: ' +name)
  40.104 +
  40.105 +    def dispatch(self, req):
  40.106 +        """Dispatch a request to its handler.
  40.107 +        """
  40.108 +        op_name = sxp.name(req)
  40.109 +        op_method_name = self.opname(op_name)
  40.110 +        op_method = getattr(self, op_method_name, self.operror)
  40.111 +        return op_method(op_name, req)
  40.112 +
  40.113 +    def op_console_create(self, name, req):
  40.114 +        """Create a new control interface - console for a domain.
  40.115 +        """
  40.116 +        print name, req
  40.117 +        dom = sxp.child_value(req, 'domain')
  40.118 +        if not dom: raise ValueError('Missing domain')
  40.119 +        dom = int(dom)
  40.120 +        console_port = sxp.child_value(req, 'console_port')
  40.121 +        if console_port:
  40.122 +            console_port = int(console_port)
  40.123 +        resp = self.daemon.console_create(dom, console_port)
  40.124 +        print name, resp
  40.125 +        return resp
  40.126 +
  40.127 +    def op_consoles(self, name, req):
  40.128 +        """Get a list of the consoles.
  40.129 +        """
  40.130 +        return self.daemon.consoles()
  40.131 +
  40.132 +    def op_console_disconnect(self, name, req):
  40.133 +        id = sxp.child_value(req, 'id')
  40.134 +        if not id:
  40.135 +            raise ValueError('Missing console id')
  40.136 +        id = int(id)
  40.137 +        console = self.daemon.get_console(id)
  40.138 +        if not console:
  40.139 +            raise ValueError('Invalid console id')
  40.140 +        if console.conn:
  40.141 +            console.conn.loseConnection()
  40.142 +        return ['ok']
  40.143 +
  40.144 +    def op_blkifs(self, name, req):
  40.145 +        pass
  40.146 +    
  40.147 +    def op_blkif_devs(self, name, req):
  40.148 +        pass
  40.149 +
  40.150 +    def op_blkif_create(self, name, req):
  40.151 +        pass
  40.152 +    
  40.153 +    def op_blkif_dev_create(self, name, req):
  40.154 +        pass
  40.155 +
  40.156 +    def op_netifs(self, name, req):
  40.157 +        pass
  40.158 +
  40.159 +    def op_netif_devs(self, name, req):
  40.160 +        pass
  40.161 +
  40.162 +    def op_netif_create(self, name, req):
  40.163 +        pass
  40.164 +
  40.165 +    def op_netif_dev_create(self, name, req):
  40.166 +        pass
  40.167 +
  40.168 +class NotifierProtocol(protocol.Protocol):
  40.169 +    """Asynchronous handler for i/o on the notifier (event channel).
  40.170 +    """
  40.171 +
  40.172 +    def __init__(self, channelFactory):
  40.173 +        self.channelFactory = channelFactory
  40.174 +
  40.175 +    def notificationReceived(self, idx, type):
  40.176 +        #print 'NotifierProtocol>notificationReceived>', idx, type
  40.177 +        channel = self.channelFactory.getChannel(idx)
  40.178 +        if not channel:
  40.179 +            return
  40.180 +        #print 'NotifierProtocol>notificationReceived> channel', channel
  40.181 +        channel.notificationReceived(type)
  40.182 +
  40.183 +    def connectionLost(self, reason=None):
  40.184 +        pass
  40.185 +
  40.186 +    def doStart(self):
  40.187 +        pass
  40.188 +
  40.189 +    def doStop(self):
  40.190 +        pass
  40.191 +
  40.192 +    def startProtocol(self):
  40.193 +        pass
  40.194 +
  40.195 +    def stopProtocol(self):
  40.196 +        pass
  40.197 +
  40.198 +class NotifierPort(abstract.FileDescriptor):
  40.199 +    """Transport class for the event channel.
  40.200 +    """
  40.201 +
  40.202 +    def __init__(self, daemon, notifier, proto, reactor=None):
  40.203 +        assert isinstance(proto, NotifierProtocol)
  40.204 +        abstract.FileDescriptor.__init__(self, reactor)
  40.205 +        self.daemon = daemon
  40.206 +        self.notifier = notifier
  40.207 +        self.protocol = proto
  40.208 +
  40.209 +    def startListening(self):
  40.210 +        self._bindNotifier()
  40.211 +        self._connectToProtocol()
  40.212 +
  40.213 +    def stopListening(self):
  40.214 +        if self.connected:
  40.215 +            result = self.d = defer.Deferred()
  40.216 +        else:
  40.217 +            result = None
  40.218 +        self.loseConnection()
  40.219 +        return result
  40.220 +
  40.221 +    def fileno(self):
  40.222 +        return self.notifier.fileno()
  40.223 +
  40.224 +    def _bindNotifier(self):
  40.225 +        self.connected = 1
  40.226 +
  40.227 +    def _connectToProtocol(self):
  40.228 +        self.protocol.makeConnection(self)
  40.229 +        self.startReading()
  40.230 +
  40.231 +    def loseConnection(self):
  40.232 +        if self.connected:
  40.233 +            self.stopReading()
  40.234 +            self.disconnecting = 1
  40.235 +            reactor.callLater(0, self.connectionLost)
  40.236 +
  40.237 +    def connectionLost(self, reason=None):
  40.238 +        abstract.FileDescriptor.connectionLost(self, reason)
  40.239 +        if hasattr(self, 'protocol'):
  40.240 +            self.protocol.doStop()
  40.241 +        self.connected = 0
  40.242 +        #self.notifier.close() # Not implemented.
  40.243 +        os.close(self.fileno())
  40.244 +        del self.notifier
  40.245 +        if hasattr(self, 'd'):
  40.246 +            self.d.callback(None)
  40.247 +            del self.d
  40.248 +        
  40.249 +    def doRead(self):
  40.250 +        #print 'NotifierPort>doRead>', self
  40.251 +        count = 0
  40.252 +        while 1:            
  40.253 +            #print 'NotifierPort>doRead>', count
  40.254 +            notification = self.notifier.read()
  40.255 +            if not notification:
  40.256 +                break
  40.257 +            (idx, type) = notification
  40.258 +            self.protocol.notificationReceived(idx, type)
  40.259 +            self.notifier.unmask(idx)
  40.260 +            count += 1
  40.261 +        #print 'NotifierPort>doRead<'
  40.262 +
  40.263 +class EventProtocol(protocol.Protocol):
  40.264 +    """Asynchronous handler for a connected event socket.
  40.265 +    """
  40.266 +
  40.267 +    def __init__(self, daemon):
  40.268 +        #protocol.Protocol.__init__(self)
  40.269 +        self.daemon = daemon
  40.270 +        # Event queue.
  40.271 +        self.queue = []
  40.272 +        # Subscribed events.
  40.273 +        self.events = []
  40.274 +        self.parser = sxp.Parser()
  40.275 +        self.pretty = 0
  40.276 +
  40.277 +        # For debugging subscribe to everything and make output pretty.
  40.278 +        self.subscribe(['*'])
  40.279 +        self.pretty = 1
  40.280 +
  40.281 +    def dataReceived(self, data):
  40.282 +        try:
  40.283 +            self.parser.input(data)
  40.284 +            if self.parser.ready():
  40.285 +                val = self.parser.get_val()
  40.286 +                res = self.dispatch(val)
  40.287 +                self.send_result(res)
  40.288 +            if self.parser.at_eof():
  40.289 +                self.loseConnection()
  40.290 +        except SystemExit:
  40.291 +            raise
  40.292 +        except:
  40.293 +            if DEBUG:
  40.294 +                raise
  40.295 +            else:
  40.296 +                self.send_error()
  40.297 +
  40.298 +    def loseConnection(self):
  40.299 +        if self.transport:
  40.300 +            self.transport.loseConnection()
  40.301 +        if self.connected:
  40.302 +            reactor.callLater(0, self.connectionLost)
  40.303 +
  40.304 +    def connectionLost(self, reason=None):
  40.305 +        self.unsubscribe()
  40.306 +
  40.307 +    def send_reply(self, sxpr):
  40.308 +        io = StringIO.StringIO()
  40.309 +        if self.pretty:
  40.310 +            PrettyPrint.prettyprint(sxpr, out=io)
  40.311 +        else:
  40.312 +            sxp.show(sxpr, out=io)
  40.313 +        print >> io
  40.314 +        io.seek(0)
  40.315 +        return self.transport.write(io.getvalue())
  40.316 +
  40.317 +    def send_result(self, res):
  40.318 +        return self.send_reply(['ok', res])
  40.319 +
  40.320 +    def send_error(self):
  40.321 +        (extype, exval) = sys.exc_info()[:2]
  40.322 +        return self.send_reply(['err',
  40.323 +                                ['type', str(extype)],
  40.324 +                                ['value', str(exval)]])
  40.325 +
  40.326 +    def send_event(self, val):
  40.327 +        return self.send_reply(['event', val[0], val[1]])
  40.328 +
  40.329 +    def unsubscribe(self):
  40.330 +        for event in self.events:
  40.331 +            eserver.unsubscribe(event, self.queue_event)
  40.332 +
  40.333 +    def subscribe(self, events):
  40.334 +        self.unsubscribe()
  40.335 +        for event in events:
  40.336 +            eserver.subscribe(event, self.queue_event)
  40.337 +        self.events = events
  40.338 +
  40.339 +    def queue_event(self, name, v):
  40.340 +        # Despite the name we dont' queue the event here.
  40.341 +        # We send it because the transport will queue it.
  40.342 +        self.send_event([name, v])
  40.343 +        
  40.344 +    def opname(self, name):
  40.345 +         return 'op_' + name.replace('.', '_')
  40.346 +
  40.347 +    def operror(self, name, req):
  40.348 +        raise NotImplementedError('Invalid operation: ' +name)
  40.349 +
  40.350 +    def dispatch(self, req):
  40.351 +        op_name = sxp.name(req)
  40.352 +        op_method_name = self.opname(op_name)
  40.353 +        op_method = getattr(self, op_method_name, self.operror)
  40.354 +        return op_method(op_name, req)
  40.355 +
  40.356 +    def op_help(self, name, req):
  40.357 +        def nameop(x):
  40.358 +            if x.startswith('op_'):
  40.359 +                return x[3:].replace('_', '.')
  40.360 +            else:
  40.361 +                return x
  40.362 +        
  40.363 +        l = [ nameop(k) for k in dir(self) if k.startswith('op_') ]
  40.364 +        return l
  40.365 +
  40.366 +    def op_quit(self, name, req):
  40.367 +        self.loseConnection()
  40.368 +
  40.369 +    def op_exit(self, name, req):
  40.370 +        sys.exit(0)
  40.371 +
  40.372 +    def op_pretty(self, name, req):
  40.373 +        self.pretty = 1
  40.374 +        return ['ok']
  40.375 +
  40.376 +    def op_console_disconnect(self, name, req):
  40.377 +        id = sxp.child_value(req, 'id')
  40.378 +        if not id:
  40.379 +            raise ValueError('Missing console id')
  40.380 +        self.daemon.console_disconnect(id)
  40.381 +        return ['ok']
  40.382 +
  40.383 +    def op_info(self, name, req):
  40.384 +        val = ['info']
  40.385 +        val += self.daemon.consoles()
  40.386 +        val += self.daemon.blkifs()
  40.387 +        val += self.daemon.netifs()
  40.388 +        return val
  40.389 +
  40.390 +    def op_sys_subscribe(self, name, v):
  40.391 +        # (sys.subscribe event*)
  40.392 +        # Subscribe to the events:
  40.393 +        self.subscribe(v[1:])
  40.394 +        return ['ok']
  40.395 +
  40.396 +    def op_sys_inject(self, name, v):
  40.397 +        # (sys.inject event)
  40.398 +        event = v[1]
  40.399 +        eserver.inject(sxp.name(event), event)
  40.400 +        return ['ok']
  40.401 +
  40.402 +
  40.403 +class EventFactory(protocol.Factory):
  40.404 +    """Asynchronous handler for the event server socket.
  40.405 +    """
  40.406 +    protocol = EventProtocol
  40.407 +    service = None
  40.408 +
  40.409 +    def __init__(self, daemon):
  40.410 +        #protocol.Factory.__init__(self)
  40.411 +        self.daemon = daemon
  40.412 +
  40.413 +    def buildProtocol(self, addr):
  40.414 +        proto = self.protocol(self.daemon)
  40.415 +        proto.factory = self
  40.416 +        return proto
  40.417 +
  40.418 +class VirqClient:
  40.419 +    def __init__(self, daemon):
  40.420 +        self.daemon = daemon
  40.421 +
  40.422 +    def virqReceived(self, virq):
  40.423 +        print 'VirqClient.virqReceived>', virq
  40.424 +        eserver.inject('xend.virq', virq)
  40.425 +
  40.426 +    def lostChannel(self, channel):
  40.427 +        print 'VirqClient.lostChannel>', channel
  40.428 +        
  40.429 +class Daemon:
  40.430 +    """The xend daemon.
  40.431 +    """
  40.432 +    def __init__(self):
  40.433 +        self.shutdown = 0
  40.434 +
  40.435 +    def daemon_pids(self):
  40.436 +        pids = []
  40.437 +        pidex = '(?P<pid>\d+)'
  40.438 +        pythonex = '(?P<python>\S*python\S*)'
  40.439 +        cmdex = '(?P<cmd>.*)'
  40.440 +        procre = re.compile('^\s*' + pidex + '\s*' + pythonex + '\s*' + cmdex + '$')
  40.441 +        xendre = re.compile('^/usr/sbin/xend\s*(start|restart)\s*.*$')
  40.442 +        procs = os.popen('ps -e -o pid,args 2>/dev/null')
  40.443 +        for proc in procs:
  40.444 +            pm = procre.match(proc)
  40.445 +            if not pm: continue
  40.446 +            xm = xendre.match(pm.group('cmd'))
  40.447 +            if not xm: continue
  40.448 +            #print 'pid=', pm.group('pid'), 'cmd=', pm.group('cmd')
  40.449 +            pids.append(int(pm.group('pid')))
  40.450 +        return pids
  40.451 +
  40.452 +    def new_cleanup(self, kill=0):
  40.453 +        err = 0
  40.454 +        pids = self.daemon_pids()
  40.455 +        if kill:
  40.456 +            for pid in pids:
  40.457 +                print "Killing daemon pid=%d" % pid
  40.458 +                os.kill(pid, signal.SIGHUP)
  40.459 +        elif pids:
  40.460 +            err = 1
  40.461 +            print "Daemon already running: ", pids
  40.462 +        return err
  40.463 +            
  40.464 +    def cleanup(self, kill=False):
  40.465 +        # No cleanup to do if PID_FILE is empty.
  40.466 +        if not os.path.isfile(PID_FILE) or not os.path.getsize(PID_FILE):
  40.467 +            return 0
  40.468 +        # Read the pid of the previous invocation and search active process list.
  40.469 +        pid = open(PID_FILE, 'r').read()
  40.470 +        lines = os.popen('ps ' + pid + ' 2>/dev/null').readlines()
  40.471 +        for line in lines:
  40.472 +            if re.search('^ *' + pid + '.+xend', line):
  40.473 +                if not kill:
  40.474 +                    print "Daemon is already running (pid %d)" % int(pid)
  40.475 +                    return 1
  40.476 +                # Old daemon is still active: terminate it.
  40.477 +                os.kill(int(pid), 1)
  40.478 +        # Delete the stale PID_FILE.
  40.479 +        os.remove(PID_FILE)
  40.480 +        return 0
  40.481 +
  40.482 +    def install_child_reaper(self):
  40.483 +        #signal.signal(signal.SIGCHLD, self.onSIGCHLD)
  40.484 +        # Ensure that zombie children are automatically reaped.
  40.485 +        xu.autoreap()
  40.486 +
  40.487 +    def onSIGCHLD(self, signum, frame):
  40.488 +        code = 1
  40.489 +        while code > 0:
  40.490 +            code = os.waitpid(-1, os.WNOHANG)
  40.491 +
  40.492 +    def start(self,trace=0):
  40.493 +        if self.cleanup(kill=False):
  40.494 +            return 1
  40.495 +
  40.496 +        # Detach from TTY.
  40.497 +        if not DEBUG:
  40.498 +            os.setsid()
  40.499 +
  40.500 +        if self.set_user():
  40.501 +            return 1
  40.502 +
  40.503 +        self.install_child_reaper()
  40.504 +
  40.505 +        # Fork -- parent writes PID_FILE and exits.
  40.506 +        pid = os.fork()
  40.507 +        if pid:
  40.508 +            # Parent
  40.509 +            pidfile = open(PID_FILE, 'w')
  40.510 +            pidfile.write(str(pid))
  40.511 +            pidfile.close()
  40.512 +            return 0
  40.513 +        # Child
  40.514 +        logfile = self.open_logfile()
  40.515 +        self.redirect_output(logfile)
  40.516 +        if trace:
  40.517 +            self.tracefile = open('/var/log/xend.trace', 'w+', 1)
  40.518 +            self.traceindent = 0
  40.519 +            sys.settrace(self.trace)
  40.520 +            try:
  40.521 +                threading.settrace(self.trace) # Only in Python >= 2.3
  40.522 +            except:
  40.523 +                pass
  40.524 +        self.run()
  40.525 +        return 0
  40.526 +
  40.527 +    def print_trace(self,str):
  40.528 +        for i in range(self.traceindent):
  40.529 +            self.tracefile.write("    ")
  40.530 +        self.tracefile.write(str)
  40.531 +            
  40.532 +    def trace(self, frame, event, arg):
  40.533 +        if event == 'call':
  40.534 +            code = frame.f_code
  40.535 +            filename = code.co_filename
  40.536 +            m = re.search('.*xenmgr/(.*)', code.co_filename)
  40.537 +            if not m:
  40.538 +                return None
  40.539 +            modulename = m.group(1)
  40.540 +            if re.search('sxp.py', modulename):
  40.541 +                return None
  40.542 +            self.traceindent += 1
  40.543 +            self.print_trace("++++ %s:%s\n"
  40.544 +                             % (modulename, code.co_name))
  40.545 +        elif event == 'line':
  40.546 +            filename = frame.f_code.co_filename
  40.547 +            lineno = frame.f_lineno
  40.548 +            self.print_trace("%4d %s" %
  40.549 +                             (lineno, linecache.getline(filename, lineno)))
  40.550 +        elif event == 'return':
  40.551 +            code = frame.f_code
  40.552 +            filename = code.co_filename
  40.553 +            m = re.search('.*xenmgr/(.*)', code.co_filename)
  40.554 +            if not m:
  40.555 +                return None
  40.556 +            modulename = m.group(1)
  40.557 +            self.print_trace("---- %s:%s\n"
  40.558 +                             % (modulename, code.co_name))
  40.559 +            self.traceindent -= 1
  40.560 +        elif event == 'exception':
  40.561 +            pass
  40.562 +        return self.trace
  40.563 +
  40.564 +    def open_logfile(self):
  40.565 +        if not os.path.exists(CONTROL_DIR):
  40.566 +            os.makedirs(CONTROL_DIR)
  40.567 +
  40.568 +        # Open log file. Truncate it if non-empty, and request line buffering.
  40.569 +        if os.path.isfile(LOG_FILE):
  40.570 +            os.rename(LOG_FILE, LOG_FILE+'.old')
  40.571 +        logfile = open(LOG_FILE, 'w+', 1)
  40.572 +        return logfile
  40.573 +
  40.574 +    def set_user(self):
  40.575 +        # Set the UID.
  40.576 +        try:
  40.577 +            os.setuid(pwd.getpwnam(USER)[2])
  40.578 +            return 0
  40.579 +        except KeyError, error:
  40.580 +            print "Error: no such user '%s'" % USER
  40.581 +            return 1
  40.582 +
  40.583 +    def redirect_output(self, logfile):
  40.584 +        if DEBUG: return
  40.585 +        # Close down standard file handles
  40.586 +        try:
  40.587 +            os.close(0) # stdin
  40.588 +            os.close(1) # stdout
  40.589 +            os.close(2) # stderr
  40.590 +        except:
  40.591 +            pass
  40.592 +        # Redirect output to log file.
  40.593 +        sys.stdout = sys.stderr = logfile
  40.594 +
  40.595 +    def stop(self):
  40.596 +        return self.cleanup(kill=True)
  40.597 +
  40.598 +    def run(self):
  40.599 +        self.createFactories()
  40.600 +        self.listenMgmt()
  40.601 +        self.listenEvent()
  40.602 +        self.listenNotifier()
  40.603 +        self.listenVirq()
  40.604 +        SrvServer.create(bridge=1)
  40.605 +        reactor.run()
  40.606 +
  40.607 +    def createFactories(self):
  40.608 +        self.channelF = channel.channelFactory()
  40.609 +        self.domainCF = domain.DomainControllerFactory()
  40.610 +        self.blkifCF = blkif.BlkifControllerFactory()
  40.611 +        self.netifCF = netif.NetifControllerFactory()
  40.612 +        self.consoleCF = console.ConsoleControllerFactory()
  40.613 +
  40.614 +    def listenMgmt(self):
  40.615 +        protocol = MgmtProtocol(self)
  40.616 +        s = os.path.join(CONTROL_DIR, MGMT_SOCK)
  40.617 +        if os.path.exists(s):
  40.618 +            os.unlink(s)
  40.619 +        return reactor.listenUNIXDatagram(s, protocol)
  40.620 +
  40.621 +    def listenEvent(self):
  40.622 +        protocol = EventFactory(self)
  40.623 +        return reactor.listenTCP(EVENT_PORT, protocol)
  40.624 +
  40.625 +    def listenNotifier(self):
  40.626 +        protocol = NotifierProtocol(self.channelF)
  40.627 +        p = NotifierPort(self, self.channelF.notifier, protocol, reactor)
  40.628 +        p.startListening()
  40.629 +        return p
  40.630 +
  40.631 +    def listenVirq(self):
  40.632 +        virqChan = self.channelF.virqChannel(channel.VIRQ_DOM_EXC)
  40.633 +        virqChan.registerClient(VirqClient(self))
  40.634 +
  40.635 +    def exit(self):
  40.636 +        reactor.diconnectAll()
  40.637 +        sys.exit(0)
  40.638 +
  40.639 +    def blkif_set_control_domain(self, dom, recreate=0):
  40.640 +        """Set the block device backend control domain.
  40.641 +        """
  40.642 +        return self.blkifCF.setControlDomain(dom, recreate=recreate)
  40.643 +    
  40.644 +    def blkif_get_control_domain(self, dom):
  40.645 +        """Get the block device backend control domain.
  40.646 +        """
  40.647 +        return self.blkifCF.getControlDomain()
  40.648 +    
  40.649 +    def blkif_create(self, dom, recreate=0):
  40.650 +        """Create a block device interface controller.
  40.651 +        
  40.652 +        Returns Deferred
  40.653 +        """
  40.654 +        d = self.blkifCF.createInstance(dom, recreate=recreate)
  40.655 +        return d
  40.656 +
  40.657 +    def blkifs(self):
  40.658 +        return [ x.sxpr() for x in self.blkifCF.getInstances() ]
  40.659 +
  40.660 +    def blkif_get(self, dom):
  40.661 +        return self.blkifCF.getInstanceByDom(dom)
  40.662 +
  40.663 +    def blkif_dev(self, dom, vdev):
  40.664 +        return self.blkifCF.getDomainDevice(dom, vdev)
  40.665 +
  40.666 +    def blkif_dev_create(self, dom, vdev, mode, segment, recreate=0):
  40.667 +        """Create a block device.
  40.668 +        
  40.669 +        Returns Deferred
  40.670 +        """
  40.671 +        ctrl = self.blkifCF.getInstanceByDom(dom)
  40.672 +        if not ctrl:
  40.673 +            raise ValueError('No blkif controller: %d' % dom)
  40.674 +        print 'blkif_dev_create>', dom, vdev, mode, segment
  40.675 +        d = ctrl.attachDevice(vdev, mode, segment, recreate=recreate)
  40.676 +        return d
  40.677 +
  40.678 +    def netif_set_control_domain(self, dom, recreate=0):
  40.679 +        """Set the network interface backend control domain.
  40.680 +        """
  40.681 +        return self.netifCF.setControlDomain(dom, recreate=recreate)
  40.682 +
  40.683 +    def netif_get_control_domain(self, dom):
  40.684 +        """Get the network interface backend control domain.
  40.685 +        """
  40.686 +        return self.netifCF.getControlDomain()
  40.687 +    
  40.688 +    def netif_create(self, dom, recreate=0):
  40.689 +        """Create a network interface controller.
  40.690 +        
  40.691 +        """
  40.692 +        return self.netifCF.createInstance(dom, recreate=recreate)
  40.693 +
  40.694 +    def netifs(self):
  40.695 +        return [ x.sxpr() for x in self.netifCF.getInstances() ]
  40.696 +
  40.697 +    def netif_get(self, dom):
  40.698 +        return self.netifCF.getInstanceByDom(dom)
  40.699 +
  40.700 +    def netif_dev_create(self, dom, vif, vmac, recreate=0):
  40.701 +        """Create a network device.
  40.702 +
  40.703 +        todo
  40.704 +        """
  40.705 +        ctrl = self.netifCF.getInstanceByDom(dom)
  40.706 +        if not ctrl:
  40.707 +            raise ValueError('No netif controller: %d' % dom)
  40.708 +        d = ctrl.attachDevice(vif, vmac, recreate=recreate)
  40.709 +        return d
  40.710 +
  40.711 +    def netif_dev(self, dom, vif):
  40.712 +        return self.netifCF.getDomainDevice(dom, vif)
  40.713 +
  40.714 +    def console_create(self, dom, console_port=None):
  40.715 +        """Create a console for a domain.
  40.716 +        """
  40.717 +        console = self.consoleCF.getInstanceByDom(dom)
  40.718 +        if console is None:
  40.719 +            console = self.consoleCF.createInstance(dom, console_port)
  40.720 +        return console.sxpr()
  40.721 +
  40.722 +    def consoles(self):
  40.723 +        return [ c.sxpr() for c in self.consoleCF.getInstances() ]
  40.724 +
  40.725 +    def get_console(self, id):
  40.726 +        return self.consoleCF.getInstance(id)
  40.727 +
  40.728 +    def get_domain_console(self, dom):
  40.729 +        return self.consoleCF.getInstanceByDom(dom)
  40.730 +
  40.731 +    def console_disconnect(self, id):
  40.732 +        """Disconnect any connected console client.
  40.733 +        """
  40.734 +        console = self.get_console(id)
  40.735 +        if not console:
  40.736 +            raise ValueError('Invalid console id')
  40.737 +        console.disconnect()
  40.738 +
  40.739 +    def domain_shutdown(self, dom, reason):
  40.740 +        """Shutdown a domain.
  40.741 +        """
  40.742 +        ctrl = self.domainCF.getInstanceByDom(dom)
  40.743 +        if not ctrl:
  40.744 +            raise ValueError('No domain controller: %d' % dom)
  40.745 +        ctrl.shutdown(reason)
  40.746 +        return 0
  40.747 +        
  40.748 +def instance():
  40.749 +    global inst
  40.750 +    try:
  40.751 +        inst
  40.752 +    except:
  40.753 +        inst = Daemon()
  40.754 +    return inst
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/tools/xen/lib/xend/server/SrvDeviceDir.py	Mon Jun 28 08:20:16 2004 +0000
    41.3 @@ -0,0 +1,9 @@
    41.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    41.5 +
    41.6 +from SrvDir import SrvDir
    41.7 +
    41.8 +class SrvDeviceDir(SrvDir):
    41.9 +    """Device directory.
   41.10 +    """
   41.11 +
   41.12 +    pass
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/tools/xen/lib/xend/server/SrvDir.py	Mon Jun 28 08:20:16 2004 +0000
    42.3 @@ -0,0 +1,91 @@
    42.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    42.5 +
    42.6 +from twisted.web import error
    42.7 +from xen.xend import sxp
    42.8 +from SrvBase import SrvBase
    42.9 +
   42.10 +class SrvConstructor:
   42.11 +    """Delayed constructor for sub-servers.
   42.12 +    Does not import the sub-server class or create the object until needed.
   42.13 +    """
   42.14 +    
   42.15 +    def __init__(self, klass):
   42.16 +        """Create a constructor. It is assumed that the class
   42.17 +        should be imported as 'import klass from klass'.
   42.18 +
   42.19 +        klass	name of its class
   42.20 +        """
   42.21 +        self.klass = klass
   42.22 +        self.obj = None
   42.23 +
   42.24 +    def getobj(self):
   42.25 +        """Get the sub-server object, importing its class and instantiating it if
   42.26 +        necessary.
   42.27 +        """
   42.28 +        if not self.obj:
   42.29 +            exec 'from %s import %s' % (self.klass, self.klass)
   42.30 +            klassobj = eval(self.klass)
   42.31 +            self.obj = klassobj()
   42.32 +        return self.obj
   42.33 +
   42.34 +class SrvDir(SrvBase):
   42.35 +    """Base class for directory servlets.
   42.36 +    """
   42.37 +    isLeaf = False
   42.38 +    
   42.39 +    def __init__(self):
   42.40 +        SrvBase.__init__(self)
   42.41 +        self.table = {}
   42.42 +        self.order = []
   42.43 +
   42.44 +    def getChild(self, x, req):
   42.45 +        if x == '': return self
   42.46 +        val = self.get(x)
   42.47 +        if val is None:
   42.48 +            return error.NoResource('Not found')
   42.49 +        else:
   42.50 +            return val
   42.51 +
   42.52 +    def get(self, x):
   42.53 +        val = self.table.get(x)
   42.54 +        if val is not None:
   42.55 +            val = val.getobj()
   42.56 +        return val
   42.57 +
   42.58 +    def add(self, x, xclass = None):
   42.59 +        if xclass is None:
   42.60 +            xclass = 'SrvDir'
   42.61 +        self.table[x] = SrvConstructor(xclass)
   42.62 +        self.order.append(x)
   42.63 +
   42.64 +    def render_GET(self, req):
   42.65 +        if self.use_sxp(req):
   42.66 +            req.setHeader("Content-type", sxp.mime_type)
   42.67 +            self.ls(req, 1)
   42.68 +        else:
   42.69 +            req.write('<html><head></head><body>')
   42.70 +            self.print_path(req)
   42.71 +            self.ls(req)
   42.72 +            self.form(req)
   42.73 +            req.write('</body></html>')
   42.74 +        return ''
   42.75 +            
   42.76 +    def ls(self, req, use_sxp=0):
   42.77 +        url = req.prePathURL()
   42.78 +        if not url.endswith('/'):
   42.79 +            url += '/'
   42.80 +        if use_sxp:
   42.81 +           req.write('(ls ')
   42.82 +           for k in self.order:
   42.83 +               req.write(' ' + k)
   42.84 +           req.write(')')
   42.85 +        else:
   42.86 +            req.write('<ul>')
   42.87 +            for k in self.order:
   42.88 +                v = self.get(k)
   42.89 +                req.write('<li><a href="%s%s">%s</a></li>'
   42.90 +                          % (url, k, k))
   42.91 +            req.write('</ul>')
   42.92 +
   42.93 +    def form(self, req):
   42.94 +        pass
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/tools/xen/lib/xend/server/SrvDomain.py	Mon Jun 28 08:20:16 2004 +0000
    43.3 @@ -0,0 +1,202 @@
    43.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    43.5 +
    43.6 +from xen.xend import sxp
    43.7 +from xen.xend import XendDomain
    43.8 +from xen.xend import XendConsole
    43.9 +from xen.xend import PrettyPrint
   43.10 +from xen.xend.Args import FormFn
   43.11 +
   43.12 +from SrvDir import SrvDir
   43.13 +
   43.14 +class SrvDomain(SrvDir):
   43.15 +    """Service managing a single domain.
   43.16 +    """
   43.17 +
   43.18 +    def __init__(self, dom):
   43.19 +        SrvDir.__init__(self)
   43.20 +        self.dom = dom
   43.21 +        self.xd = XendDomain.instance()
   43.22 +        self.xconsole = XendConsole.instance()
   43.23 +
   43.24 +    def op_unpause(self, op, req):
   43.25 +        val = self.xd.domain_unpause(self.dom.id)
   43.26 +        return val
   43.27 +        
   43.28 +    def op_pause(self, op, req):
   43.29 +        val = self.xd.domain_pause(self.dom.id)
   43.30 +        return val
   43.31 +
   43.32 +    def op_shutdown(self, op, req):
   43.33 +        val = self.xd.domain_shutdown(self.dom.id)
   43.34 +        req.setResponseCode(202)
   43.35 +        req.setHeader("Location", "%s/.." % req.prePathURL())
   43.36 +        return val
   43.37 +
   43.38 +    def op_destroy(self, op, req):
   43.39 +        val = self.xd.domain_destroy(self.dom.id)
   43.40 +        req.setHeader("Location", "%s/.." % req.prePathURL())
   43.41 +        return val
   43.42 +
   43.43 +    def op_save(self, op, req):
   43.44 +        fn = FormFn(self.xd.domain_save,
   43.45 +                    [['dom', 'int'],
   43.46 +                     ['file', 'str']])
   43.47 +        val = fn(req.args, {'dom': self.dom.id})
   43.48 +        return val
   43.49 +
   43.50 +    def op_restore(self, op, req):
   43.51 +        fn = FormFn(self.xd.domain_restore,
   43.52 +                    [['dom', 'int'],
   43.53 +                     ['file', 'str']])
   43.54 +        val = fn(req.args, {'dom': self.dom.id})
   43.55 +        return val
   43.56 +        
   43.57 +    def op_migrate(self, op, req):
   43.58 +        fn = FormFn(self.xd.domain_migrate,
   43.59 +                    [['dom', 'int'],
   43.60 +                     ['destination', 'str']])
   43.61 +        val = fn(req.args, {'dom': self.dom.id})
   43.62 +        val = 0 # Some migrate id.
   43.63 +        req.setResponseCode(202)
   43.64 +        #req.send_header("Location", "%s/.." % self.path) # Some migrate url.
   43.65 +        return val
   43.66 +
   43.67 +    def op_pincpu(self, op, req):
   43.68 +        fn = FormFn(self.xd.domain_migrate,
   43.69 +                    [['dom', 'int'],
   43.70 +                     ['cpu', 'int']])
   43.71 +        val = fn(req.args, {'dom': self.dom.id})
   43.72 +        return val
   43.73 +
   43.74 +    def op_cpu_bvt_set(self, op, req):
   43.75 +        fn = FormFn(self.xd.domain_cpu_bvt_set,
   43.76 +                    [['dom', 'int'],
   43.77 +                     ['mcuadv', 'int'],
   43.78 +                     ['warp', 'int'],
   43.79 +                     ['warpl', 'int'],
   43.80 +                     ['warpu', 'int']])
   43.81 +        val = fn(req.args, {'dom': self.dom.id})
   43.82 +        return val
   43.83 +
   43.84 +    def op_cpu_atropos_set(self, op, req):
   43.85 +        fn = FormFn(self.xd.domain_cpu_atropos_set,
   43.86 +                    [['dom', 'int'],
   43.87 +                     ['period', 'int'],
   43.88 +                     ['slice', 'int'],
   43.89 +                     ['latency', 'int'],
   43.90 +                     ['xtratime', 'int']])
   43.91 +        val = fn(req.args, {'dom': self.dom.id})
   43.92 +        return val
   43.93 +
   43.94 +    def op_vifs(self, op, req):
   43.95 +        return self.xd.domain_vif_ls(self.dom.id)
   43.96 +
   43.97 +    def op_vif(self, op, req):
   43.98 +        fn = FormFn(self.xd.domain_vif_get,
   43.99 +                    [['dom', 'int'],
  43.100 +                     ['vif', 'int']])
  43.101 +        val = fn(req.args, {'dom': self.dom.id})
  43.102 +        return val
  43.103 +
  43.104 +    def op_vif_stats(self, op, req):
  43.105 +        #todo
  43.106 +        fn = FormFn(self.xd.domain_vif_stats,
  43.107 +                    [['dom', 'int'],
  43.108 +                     ['vif', 'int']])
  43.109 +        #val = fn(req.args, {'dom': self.dom.id})
  43.110 +        val = 999
  43.111 +        #return val
  43.112 +        return val
  43.113 +
  43.114 +    def op_vif_ip_add(self, op, req):
  43.115 +        fn = FormFn(self.xd.domain_vif_ip_add,
  43.116 +                    [['dom', 'int'],
  43.117 +                     ['vif', 'int'],
  43.118 +                     ['ip', 'str']])
  43.119 +        val = fn(req.args, {'dom': self.dom.id})
  43.120 +        return val
  43.121 +
  43.122 +    def op_vif_scheduler_set(self, op, req):
  43.123 +        fn = FormFn(self.xd.domain_vif_scheduler_set,
  43.124 +                    [['dom', 'int'],
  43.125 +                     ['vif', 'int'],
  43.126 +                     ['bytes', 'int'],
  43.127 +                     ['usecs', 'int']])
  43.128 +        val = fn(req.args, {'dom': self.dom.id})
  43.129 +        return val
  43.130 +
  43.131 +    def op_vif_scheduler_get(self, op, req):
  43.132 +        fn = FormFn(self.xd.domain_vif_scheduler_set,
  43.133 +                    [['dom', 'int'],
  43.134 +                     ['vif', 'int']])
  43.135 +        val = fn(req.args, {'dom': self.dom.id})
  43.136 +        return val
  43.137 +
  43.138 +    def op_vbds(self, op, req):
  43.139 +        return self.xd.domain_vbd_ls(self.dom.id)
  43.140 +
  43.141 +    def op_vbd(self, op, req):
  43.142 +        fn = FormFn(self.xd.domain_vbd_get,
  43.143 +                    [['dom', 'int'],
  43.144 +                     ['vbd', 'int']])
  43.145 +        val = fn(req.args, {'dom': self.dom.id})
  43.146 +        return val
  43.147 +
  43.148 +    def op_vbd_add(self, op, req):
  43.149 +        fn = FormFn(self.xd.domain_vbd_add,
  43.150 +                    [['dom', 'int'],
  43.151 +                     ['uname', 'str'],
  43.152 +                     ['dev', 'str'],
  43.153 +                     ['mode', 'str']])
  43.154 +        val = fn(req.args, {'dom': self.dom.id})
  43.155 +        return val
  43.156 +
  43.157 +    def op_vbd_remove(self, op, req):
  43.158 +        fn = FormFn(self.xd.domain_vbd_remove,
  43.159 +                    [['dom', 'int'],
  43.160 +                     ['dev', 'str']])
  43.161 +        val = fn(req.args, {'dom': self.dom.id})
  43.162 +        return val
  43.163 +
  43.164 +    def render_POST(self, req):
  43.165 +        return self.perform(req)
  43.166 +        
  43.167 +    def render_GET(self, req):
  43.168 +        op = req.args.get('op')
  43.169 +        if op and op[0] in ['vifs', 'vif', 'vif_stats', 'vbds', 'vbd']:
  43.170 +            return self.perform(req)
  43.171 +        if self.use_sxp(req):
  43.172 +            req.setHeader("Content-Type", sxp.mime_type)
  43.173 +            sxp.show(self.dom.sxpr(), out=req)
  43.174 +        else:
  43.175 +            req.write('<html><head></head><body>')
  43.176 +            self.print_path(req)
  43.177 +            #self.ls()
  43.178 +            req.write('<p>%s</p>' % self.dom)
  43.179 +            if self.dom.console:
  43.180 +                cinfo = self.dom.console
  43.181 +                cid = cinfo.id
  43.182 +                #todo: Local xref: need to know server prefix.
  43.183 +                req.write('<p><a href="/xend/console/%s">Console %s</a></p>'
  43.184 +                          % (cid, cid))
  43.185 +                req.write('<p><a href="%s">Connect to console</a></p>'
  43.186 +                          % cinfo.uri())
  43.187 +            if self.dom.config:
  43.188 +                req.write("<code><pre>")
  43.189 +                PrettyPrint.prettyprint(self.dom.config, out=req)
  43.190 +                req.write("</pre></code>")
  43.191 +            req.write('<a href="%s?op=vif_stats&vif=0">vif 0 stats</a>'
  43.192 +                      % req.prePathURL())
  43.193 +            self.form(req)
  43.194 +            req.write('</body></html>')
  43.195 +        return ''
  43.196 +
  43.197 +    def form(self, req):
  43.198 +        req.write('<form method="post" action="%s">' % req.prePathURL())
  43.199 +        req.write('<input type="submit" name="op" value="unpause">')
  43.200 +        req.write('<input type="submit" name="op" value="pause">')
  43.201 +        req.write('<input type="submit" name="op" value="shutdown">')
  43.202 +        req.write('<input type="submit" name="op" value="destroy">')
  43.203 +        req.write('<br><input type="submit" name="op" value="migrate">')
  43.204 +        req.write('To: <input type="text" name="destination">')
  43.205 +        req.write('</form>')
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/tools/xen/lib/xend/server/SrvDomainDir.py	Mon Jun 28 08:20:16 2004 +0000
    44.3 @@ -0,0 +1,131 @@
    44.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    44.5 +
    44.6 +from StringIO import StringIO
    44.7 +
    44.8 +from twisted.protocols import http
    44.9 +from twisted.web import error
   44.10 +
   44.11 +from xen.xend import sxp
   44.12 +from xen.xend import XendDomain
   44.13 +
   44.14 +from SrvDir import SrvDir
   44.15 +from SrvDomain import SrvDomain
   44.16 +
   44.17 +class SrvDomainDir(SrvDir):
   44.18 +    """Service that manages the domain directory.
   44.19 +    """
   44.20 +
   44.21 +    def __init__(self):
   44.22 +        SrvDir.__init__(self)
   44.23 +        self.xd = XendDomain.instance()
   44.24 +
   44.25 +    def domain(self, x):
   44.26 +        val = None
   44.27 +        try:
   44.28 +            dom = self.xd.domain_get(x)
   44.29 +            val = SrvDomain(dom)
   44.30 +        except KeyError, ex:
   44.31 +            print 'SrvDomainDir>', ex
   44.32 +            pass
   44.33 +        return val
   44.34 +
   44.35 +    def get(self, x):
   44.36 +        v = SrvDir.get(self, x)
   44.37 +        if v is not None:
   44.38 +            return v
   44.39 +        v = self.domain(x)
   44.40 +        return v
   44.41 +
   44.42 +    def op_create(self, op, req):
   44.43 +        ok = 0
   44.44 +        try:
   44.45 +            configstring = req.args.get('config')[0]
   44.46 +            print 'config:', configstring
   44.47 +            pin = sxp.Parser()
   44.48 +            pin.input(configstring)
   44.49 +            pin.input_eof()
   44.50 +            config = pin.get_val()
   44.51 +            ok = 1
   44.52 +        except Exception, ex:
   44.53 +            print 'op_create>', ex
   44.54 +        if not ok:
   44.55 +            req.setResponseCode(http.BAD_REQUEST, "Invalid configuration")
   44.56 +            return "Invalid configuration"
   44.57 +            return error.ErrorPage(http.BAD_REQUEST,
   44.58 +                                   "Invalid",
   44.59 +                                   "Invalid configuration")
   44.60 +        try:
   44.61 +            deferred = self.xd.domain_create(config)
   44.62 +            deferred.addCallback(self._cb_op_create, configstring, req)
   44.63 +            return deferred
   44.64 +        except Exception, ex:
   44.65 +            raise
   44.66 +            #return ['err', str(ex) ]
   44.67 +            #req.setResponseCode(http.BAD_REQUEST, "Error creating domain")
   44.68 +            #return str(ex)
   44.69 +            #return error.ErrorPage(http.BAD_REQUEST,
   44.70 +            #                       "Error creating domain",
   44.71 +            #                       str(ex))
   44.72 +                                   
   44.73 +
   44.74 +    def _cb_op_create(self, dominfo, configstring, req):
   44.75 +        """Callback to handle deferred domain creation.
   44.76 +        """
   44.77 +        dom = dominfo.id
   44.78 +        domurl = "%s/%s" % (req.prePathURL(), dom)
   44.79 +        req.setResponseCode(201, "created")
   44.80 +        req.setHeader("Location", domurl)
   44.81 +        if self.use_sxp(req):
   44.82 +            return dominfo.sxpr()
   44.83 +        else:
   44.84 +            out = StringIO()
   44.85 +            print >> out, ('<p> Created <a href="%s">Domain %s</a></p>'
   44.86 +                           % (domurl, dom))
   44.87 +            print >> out, '<p><pre>'
   44.88 +            print >> out, configstring
   44.89 +            print >> out, '</pre></p>'
   44.90 +            val = out.getvalue()
   44.91 +            out.close()
   44.92 +            return val
   44.93 +
   44.94 +    def render_POST(self, req):
   44.95 +        return self.perform(req)
   44.96 +
   44.97 +    def render_GET(self, req):
   44.98 +        if self.use_sxp(req):
   44.99 +            req.setHeader("Content-Type", sxp.mime_type)
  44.100 +            self.ls_domain(req, 1)
  44.101 +        else:
  44.102 +            req.write("<html><head></head><body>")
  44.103 +            self.print_path(req)
  44.104 +            self.ls(req)
  44.105 +            self.ls_domain(req)
  44.106 +            self.form(req)
  44.107 +            req.write("</body></html>")
  44.108 +        return ''
  44.109 +
  44.110 +    def ls_domain(self, req, use_sxp=0):
  44.111 +        url = req.prePathURL()
  44.112 +        if not url.endswith('/'):
  44.113 +            url += '/'
  44.114 +        if use_sxp:
  44.115 +            domains = self.xd.domain_ls()
  44.116 +            sxp.show(domains, out=req)
  44.117 +        else:
  44.118 +            domains = self.xd.domains()
  44.119 +            domains.sort(lambda x, y: cmp(x.id, y.id))
  44.120 +            req.write('<ul>')
  44.121 +            for d in domains:
  44.122 +               req.write('<li><a href="%s%s"> Domain %s</a>'
  44.123 +                         % (url, d.id, d.id))
  44.124 +               req.write('name=%s' % d.name)
  44.125 +               req.write('memory=%d'% d.memory)
  44.126 +               req.write('</li>')
  44.127 +            req.write('</ul>')
  44.128 +
  44.129 +    def form(self, req):
  44.130 +        req.write('<form method="post" action="%s" enctype="multipart/form-data">'
  44.131 +                  % req.prePathURL())
  44.132 +        req.write('<button type="submit" name="op" value="create">Create Domain</button>')
  44.133 +        req.write('Config <input type="file" name="config"><br>')
  44.134 +        req.write('</form>')
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/tools/xen/lib/xend/server/SrvEventDir.py	Mon Jun 28 08:20:16 2004 +0000
    45.3 @@ -0,0 +1,41 @@
    45.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    45.5 +
    45.6 +from xen.xend import sxp
    45.7 +from xen.xend import EventServer
    45.8 +from SrvDir import SrvDir
    45.9 +
   45.10 +class SrvEventDir(SrvDir):
   45.11 +    """Event directory.
   45.12 +    """
   45.13 +
   45.14 +    def __init__(self):
   45.15 +        SrvDir.__init__(self)
   45.16 +        self.eserver = EventServer.instance()
   45.17 +
   45.18 +    def op_inject(self, op, req):
   45.19 +        eventstring = req.args.get('event')
   45.20 +        pin = sxp.Parser()
   45.21 +        pin.input(eventstring)
   45.22 +        pin.input_eof()
   45.23 +        sxpr = pin.get_val()
   45.24 +        self.eserver.inject(sxp.name(sxpr), sxpr)
   45.25 +        if req.use_sxp:
   45.26 +            sxp.name(sxpr)
   45.27 +        else:
   45.28 +            return '<code>' + eventstring + '</code>'
   45.29 +        
   45.30 +    def render_POST(self, req):
   45.31 +        return self.perform(req)
   45.32 +
   45.33 +    def form(self, req):
   45.34 +        action = req.prePathURL()
   45.35 +        req.write('<form method="post" action="%s" enctype="multipart/form-data">'
   45.36 +                  % action)
   45.37 +        req.write('<button type="submit" name="op" value="inject">Inject</button>')
   45.38 +        req.write('Event <input type="text" name="event" size="40"><br>')
   45.39 +        req.write('</form>')
   45.40 +        req.write('<form method="post" action="%s" enctype="multipart/form-data">'
   45.41 +                  % action)
   45.42 +        req.write('<button type="submit" name="op" value="inject">Inject</button>')
   45.43 +        req.write('Event file<input type="file" name="event"><br>')
   45.44 +        req.write('</form>')
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/tools/xen/lib/xend/server/SrvNode.py	Mon Jun 28 08:20:16 2004 +0000
    46.3 @@ -0,0 +1,54 @@
    46.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    46.5 +
    46.6 +import os
    46.7 +from SrvDir import SrvDir
    46.8 +from xen.xend import sxp
    46.9 +from xen.xend import XendNode
   46.10 +
   46.11 +class SrvNode(SrvDir):
   46.12 +    """Information about the node.
   46.13 +    """
   46.14 +
   46.15 +    def __init__(self):
   46.16 +        SrvDir.__init__(self)
   46.17 +        self.xn = XendNode.instance()
   46.18 +
   46.19 +    def op_shutdown(self, op, req):
   46.20 +        val = self.xn.shutdown()
   46.21 +        return val
   46.22 +
   46.23 +    def op_reboot(self, op, req):
   46.24 +        val = self.xn.reboot()
   46.25 +        return val
   46.26 +
   46.27 +    def op_cpu_rrobin_slice_set(self, op, req):
   46.28 +        fn = FormFn(self.xn.cpu_rrobin_slice_set,
   46.29 +                    [['slice', 'int']])
   46.30 +        val = fn(req.args, {})
   46.31 +        return val
   46.32 +
   46.33 +    def op_cpu_bvt_slice_set(self, op, req):
   46.34 +        fn = FormFn(self.xn.cpu_bvt_slice_set,
   46.35 +                    [['slice', 'int']])
   46.36 +        val = fn(req.args, {})
   46.37 +        return val
   46.38 +
   46.39 +    def render_POST(self, req):
   46.40 +        return self.perform(req)
   46.41 +
   46.42 +    def render_GET(self, req):
   46.43 +        if self.use_sxp(req):
   46.44 +            req.setHeader("Content-Type", sxp.mime_type)
   46.45 +            sxp.show(['node'] + self.info(), out=req)
   46.46 +        else:
   46.47 +            req.write('<html><head></head><body>')
   46.48 +            self.print_path(req)
   46.49 +            req.write('<ul>')
   46.50 +            for d in self.info():
   46.51 +                req.write('<li> %10s: %s' % (d[0], str(d[1])))
   46.52 +            req.write('</ul>')
   46.53 +            req.write('</body></html>')
   46.54 +        return ''
   46.55 +            
   46.56 +    def info(self):
   46.57 +        return self.xn.info()
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/tools/xen/lib/xend/server/SrvRoot.py	Mon Jun 28 08:20:16 2004 +0000
    47.3 @@ -0,0 +1,30 @@
    47.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    47.5 +
    47.6 +from xen.xend import XendRoot
    47.7 +xroot = XendRoot.instance()
    47.8 +from SrvDir import SrvDir
    47.9 +
   47.10 +class SrvRoot(SrvDir):
   47.11 +    """The root of the xend server.
   47.12 +    """
   47.13 +
   47.14 +    """Server sub-components. Each entry is (name, class), where
   47.15 +    'name' is the entry name and  'class' is the name of its class.
   47.16 +    """
   47.17 +    #todo Get this list from the XendRoot config.
   47.18 +    subdirs = [
   47.19 +        ('node',    'SrvNode'       ),
   47.20 +        ('domain',  'SrvDomainDir'  ),
   47.21 +        ('console', 'SrvConsoleDir' ),
   47.22 +        ('event',   'SrvEventDir'   ),
   47.23 +        ('device',  'SrvDeviceDir'  ),
   47.24 +        ('vnet',    'SrvVnetDir'    ),
   47.25 +        ]
   47.26 +
   47.27 +    def __init__(self):
   47.28 +        SrvDir.__init__(self)
   47.29 +        for (name, klass) in self.subdirs:
   47.30 +            self.add(name, klass)
   47.31 +        for (name, klass) in self.subdirs:
   47.32 +            self.get(name)
   47.33 +        xroot.start()
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/tools/xen/lib/xend/server/SrvServer.py	Mon Jun 28 08:20:16 2004 +0000
    48.3 @@ -0,0 +1,60 @@
    48.4 +#!/usr/bin/python2
    48.5 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    48.6 +
    48.7 +"""Example xend HTTP and console server.
    48.8 +
    48.9 +   Can be accessed from a browser or from a program.
   48.10 +   Do 'python SrvServer.py' to run the server.
   48.11 +   Then point a web browser at http://localhost:8000/xend and follow the links.
   48.12 +   Most are stubs, except /domain which has a list of domains and a 'create domain'
   48.13 +   button.
   48.14 +
   48.15 +   You can also access the server from a program.
   48.16 +   Do 'python XendClient.py' to run a few test operations.
   48.17 +
   48.18 +   The data served differs depending on the client (as defined by User-Agent
   48.19 +   and Accept in the HTTP headers). If the client is a browser, data
   48.20 +   is returned in HTML, with interactive forms. If the client is a program,
   48.21 +   data is returned in SXP format, with no forms.
   48.22 +
   48.23 +   The server serves to the world by default. To restrict it to the local host
   48.24 +   change 'interface' in main().
   48.25 +
   48.26 +   Mike Wray <mike.wray@hp.com>
   48.27 +"""
   48.28 +# todo Support security settings etc. in the config file.
   48.29 +# todo Support command-line args.
   48.30 +
   48.31 +from twisted.web import server
   48.32 +from twisted.web import resource
   48.33 +from twisted.internet import reactor
   48.34 +
   48.35 +from xen.xend import XendRoot
   48.36 +xroot = XendRoot.instance()
   48.37 +
   48.38 +from xen.xend import XendBridge
   48.39 +
   48.40 +from SrvRoot import SrvRoot
   48.41 +
   48.42 +def create(port=None, interface=None, bridge=0):
   48.43 +    if port is None: port = 8000
   48.44 +    if interface is None: interface = ''
   48.45 +    if bridge or xroot.rebooted:
   48.46 +        init_bridge()
   48.47 +    root = resource.Resource()
   48.48 +    xend = SrvRoot()
   48.49 +    root.putChild('xend', xend)
   48.50 +    site = server.Site(root)
   48.51 +    reactor.listenTCP(port, site, interface=interface)
   48.52 +
   48.53 +def init_bridge():
   48.54 +    XendBridge.bridge_create()
   48.55 +    XendBridge.reconfigure()
   48.56 +
   48.57 +def main(port=None, interface=None):
   48.58 +    create(port, interface)
   48.59 +    reactor.run()
   48.60 +
   48.61 +
   48.62 +if __name__ == '__main__':
   48.63 +    main()
    49.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2 +++ b/tools/xen/lib/xend/server/SrvVnetDir.py	Mon Jun 28 08:20:16 2004 +0000
    49.3 @@ -0,0 +1,9 @@
    49.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    49.5 +
    49.6 +from SrvDir import SrvDir
    49.7 +
    49.8 +class SrvVnetDir(SrvDir):
    49.9 +    """Vnet directory.
   49.10 +    """
   49.11 +
   49.12 +    pass
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/tools/xen/lib/xend/server/__init__.py	Mon Jun 28 08:20:16 2004 +0000
    50.3 @@ -0,0 +1,1 @@
    50.4 +
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/tools/xen/lib/xend/server/blkif.py	Mon Jun 28 08:20:16 2004 +0000
    51.3 @@ -0,0 +1,341 @@
    51.4 +from twisted.internet import defer
    51.5 +
    51.6 +from xen.xend import sxp
    51.7 +from xen.xend import PrettyPrint
    51.8 +
    51.9 +import channel
   51.10 +import controller
   51.11 +from messages import *
   51.12 +
   51.13 +class BlkifControllerFactory(controller.ControllerFactory):
   51.14 +    """Factory for creating block device interface controllers.
   51.15 +    Also handles the 'back-end' channel to the device driver domain.
   51.16 +    """
   51.17 +
   51.18 +    def __init__(self):
   51.19 +        controller.ControllerFactory.__init__(self)
   51.20 +
   51.21 +        self.majorTypes = [ CMSG_BLKIF_BE ]
   51.22 +
   51.23 +        self.subTypes = {
   51.24 +            CMSG_BLKIF_BE_CREATE     : self.recv_be_create,
   51.25 +            CMSG_BLKIF_BE_CONNECT    : self.recv_be_connect,
   51.26 +            CMSG_BLKIF_BE_VBD_CREATE : self.recv_be_vbd_create,
   51.27 +            CMSG_BLKIF_BE_VBD_GROW   : self.recv_be_vbd_grow,
   51.28 +            CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED: self.recv_be_driver_status_changed,
   51.29 +            }
   51.30 +        self.attached = 1
   51.31 +        self.registerChannel()
   51.32 +
   51.33 +    def createInstance(self, dom, recreate=0):
   51.34 +        d = self.addDeferred()
   51.35 +        blkif = self.getInstanceByDom(dom)
   51.36 +        if blkif:
   51.37 +            self.callDeferred(blkif)
   51.38 +        else:
   51.39 +            blkif = BlkifController(self, dom)
   51.40 +            self.addInstance(blkif)
   51.41 +            if recreate:
   51.42 +                self.callDeferred(blkif)
   51.43 +            else:
   51.44 +                blkif.send_be_create()
   51.45 +        return d
   51.46 +
   51.47 +    def getDomainDevices(self, dom):
   51.48 +        blkif = self.getInstanceByDom(dom)
   51.49 +        return (blkif and blkif.getDevices()) or []
   51.50 +
   51.51 +    def getDomainDevice(self, dom, vdev):
   51.52 +        blkif = self.getInstanceByDom(dom)
   51.53 +        return (blkif and blkif.getDevice(vdev)) or None
   51.54 +
   51.55 +    def setControlDomain(self, dom, recreate=0):
   51.56 +        if self.dom == dom: return
   51.57 +        self.deregisterChannel()
   51.58 +        if not recreate:
   51.59 +            self.attached = 0
   51.60 +        self.dom = dom
   51.61 +        self.registerChannel()
   51.62 +        #
   51.63 +        #if xend.blkif.be_port:
   51.64 +        #    xend.blkif.recovery = True
   51.65 +        #xend.blkif.be_port = xend.main.port_from_dom(dom)
   51.66 +
   51.67 +    def getControlDomain(self):
   51.68 +        return self.dom
   51.69 +
   51.70 +    def reattachDevice(self, dom, vdev):
   51.71 +        blkif = self.getInstanceByDom(dom)
   51.72 +        if blkif:
   51.73 +            blkif.reattachDevice(vdev)
   51.74 +        self.attached = self.devicesAttached()
   51.75 +        if self.attached:
   51.76 +            self.reattached()
   51.77 +
   51.78 +    def devicesAttached(self):
   51.79 +        """Check if all devices are attached.
   51.80 +        """
   51.81 +        attached = 1
   51.82 +        for blkif in self.getInstances():
   51.83 +            if not blkif.attached:
   51.84 +                attached = 0
   51.85 +                break
   51.86 +        return attached
   51.87 +                         
   51.88 +    def reattached(self):
   51.89 +        for blkif in self.getInstances():
   51.90 +            blkif.reattached()
   51.91 +
   51.92 +    def recv_be_create(self, msg, req):
   51.93 +        #print 'recv_be_create>'
   51.94 +        val = unpackMsg('blkif_be_create_t', msg)
   51.95 +        blkif = self.getInstanceByDom(val['domid'])
   51.96 +        self.callDeferred(blkif)
   51.97 +    
   51.98 +    def recv_be_connect(self, msg, req):
   51.99 +        #print 'recv_be_create>'
  51.100 +        val = unpackMsg('blkif_be_connect_t', msg)
  51.101 +        blkif = self.getInstanceByDom(val['domid'])
  51.102 +        if blkif:
  51.103 +            blkif.send_fe_interface_status_changed()
  51.104 +        else:
  51.105 +            pass
  51.106 +    
  51.107 +    def recv_be_vbd_create(self, msg, req):
  51.108 +        #print 'recv_be_vbd_create>'
  51.109 +        val = unpackMsg('blkif_be_vbd_create_t', msg)
  51.110 +        blkif = self.getInstanceByDom(val['domid'])
  51.111 +        if blkif:
  51.112 +            blkif.send_be_vbd_grow(val['vdevice'])
  51.113 +        else:
  51.114 +            pass
  51.115 +    
  51.116 +    def recv_be_vbd_grow(self, msg, req):
  51.117 +        #print 'recv_be_vbd_grow>'
  51.118 +        val = unpackMsg('blkif_be_vbd_grow_t', msg)
  51.119 +        # Check status?
  51.120 +        if self.attached:
  51.121 +            self.callDeferred(0)
  51.122 +        else:
  51.123 +            self.reattachDevice(val['domid'], val['vdevice'])
  51.124 +
  51.125 +    def recv_be_driver_status_changed(self, msg, req):
  51.126 +        val = unpackMsg('blkif_be_driver_status_changed_t', msg)
  51.127 +        status = val['status']
  51.128 +        if status == BLKIF_DRIVER_STATUS_UP and not self.attached:
  51.129 +            for blkif in self.getInstances():
  51.130 +                blkif.detach()
  51.131 +
  51.132 +class BlkDev(controller.Dev):
  51.133 +    """Info record for a block device.
  51.134 +    """
  51.135 +
  51.136 +    def __init__(self, ctrl, vdev, mode, segment):
  51.137 +        controller.Dev.__init__(self, ctrl)
  51.138 +        self.vdev = vdev
  51.139 +        self.mode = mode
  51.140 +        self.device = segment['device']
  51.141 +        self.start_sector = segment['start_sector']
  51.142 +        self.nr_sectors = segment['nr_sectors']
  51.143 +        self.attached = 1
  51.144 +
  51.145 +    def readonly(self):
  51.146 +        return 'w' not in self.mode
  51.147 +
  51.148 +    def sxpr(self):
  51.149 +        val = ['blkdev', ['vdev', self.vdev], ['mode', self.mode] ]
  51.150 +        return val
  51.151 +
  51.152 +    def destroy(self):
  51.153 +        print 'BlkDev>destroy>', self.vdev
  51.154 +        PrettyPrint.prettyprint(self.sxpr())
  51.155 +        self.controller.send_be_vbd_destroy(self.vdev)
  51.156 +        
  51.157 +class BlkifController(controller.Controller):
  51.158 +    """Block device interface controller. Handles all block devices
  51.159 +    for a domain.
  51.160 +    """
  51.161 +    
  51.162 +    def __init__(self, factory, dom):
  51.163 +        #print 'BlkifController> dom=', dom
  51.164 +        controller.Controller.__init__(self, factory, dom)
  51.165 +        self.devices = {}
  51.166 +
  51.167 +        self.majorTypes = [ CMSG_BLKIF_FE ]
  51.168 +
  51.169 +        self.subTypes = {
  51.170 +            CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
  51.171 +                self.recv_fe_driver_status_changed,
  51.172 +            CMSG_BLKIF_FE_INTERFACE_CONNECT    :
  51.173 +                self.recv_fe_interface_connect,
  51.174 +            }
  51.175 +        self.attached = 1
  51.176 +        self.evtchn = None
  51.177 +        self.registerChannel()
  51.178 +        #print 'BlkifController<', 'dom=', self.dom, 'idx=', self.idx
  51.179 +
  51.180 +    def sxpr(self):
  51.181 +        val = ['blkif', ['dom', self.dom]]
  51.182 +        if self.evtchn:
  51.183 +            val.append(['evtchn',
  51.184 +                        self.evtchn['port1'],
  51.185 +                        self.evtchn['port2']])
  51.186 +        return val
  51.187 +
  51.188 +    def lostChannel(self):
  51.189 +        print 'BlkifController>lostChannel>', 'dom=', self.dom
  51.190 +        #self.destroyDevices()
  51.191 +        controller.Controller.lostChannel(self)
  51.192 +
  51.193 +    def getDevices(self):
  51.194 +        return self.devices.values()
  51.195 +
  51.196 +    def getDevice(self, vdev):
  51.197 +        return self.devices.get(vdev)
  51.198 +
  51.199 +    def addDevice(self, vdev, mode, segment):
  51.200 +        if vdev in self.devices: return None
  51.201 +        dev = BlkDev(self, vdev, mode, segment)
  51.202 +        self.devices[vdev] = dev
  51.203 +        return dev
  51.204 +
  51.205 +    def attachDevice(self, vdev, mode, segment, recreate=0):
  51.206 +        """Attach a device to the specified interface.
  51.207 +        """
  51.208 +        #print 'BlkifController>attach_device>', self.dom, vdev, mode, segment
  51.209 +        dev = self.addDevice(vdev, mode, segment)
  51.210 +        if not dev: return -1
  51.211 +        if recreate:
  51.212 +            d = defer.Deferred()
  51.213 +            d.callback(self)
  51.214 +        else:
  51.215 +            self.send_be_vbd_create(vdev)
  51.216 +            d = self.factory.addDeferred()
  51.217 +        return d
  51.218 +
  51.219 +    def destroy(self):
  51.220 +        print 'BlkifController>destroy> dom=', self.dom
  51.221 +        def cb_destroy(val):
  51.222 +            self.send_be_destroy()
  51.223 +        d = self.factory.addDeferred()
  51.224 +        d.addCallback(cb_destroy)
  51.225 +        self.send_be_disconnect()
  51.226 +        #self.destroyDevices()
  51.227 +
  51.228 +    def destroyDevices(self):
  51.229 +        for dev in self.getDevices():
  51.230 +            dev.destroy()
  51.231 +
  51.232 +    def detach(self):
  51.233 +        """Detach all devices, when the back-end control domain has changed.
  51.234 +        """
  51.235 +        self.attached = 0
  51.236 +        for dev in self.devices.values():
  51.237 +            dev.attached = 0
  51.238 +            self.send_be_vbd_create(vdev)
  51.239 +
  51.240 +    def reattachDevice(self, vdev):
  51.241 +        """Reattach a device, when the back-end control domain has changed.
  51.242 +        """
  51.243 +        dev = self.devices[vdev]
  51.244 +        dev.attached = 1
  51.245 +        attached = 1
  51.246 +        for dev in self.devices.values():
  51.247 +            if not dev.attached:
  51.248 +                attached = 0
  51.249 +                break
  51.250 +        self.attached = attached
  51.251 +        return self.attached
  51.252 +
  51.253 +    def reattached(self):
  51.254 +        """All devices have been reattached after the back-end control
  51.255 +        domain has changed.
  51.256 +        """
  51.257 +        msg = packMsg('blkif_fe_interface_status_changed_t',
  51.258 +                      { 'handle' : 0,
  51.259 +                        'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED})
  51.260 +        self.writeRequest(msg)
  51.261 +
  51.262 +    def recv_fe_driver_status_changed(self, msg, req):
  51.263 +        msg = packMsg('blkif_fe_interface_status_changed_t',
  51.264 +                      { 'handle' : 0,
  51.265 +                        'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED,
  51.266 +                        'evtchn' : 0 })
  51.267 +        self.writeRequest(msg)
  51.268 +    
  51.269 +    def recv_fe_interface_connect(self, msg, req):
  51.270 +        val = unpackMsg('blkif_fe_interface_connect_t', msg)
  51.271 +        self.evtchn = channel.eventChannel(0, self.dom)
  51.272 +        print 'recv_fe_interface_connect>'
  51.273 +        PrettyPrint.prettyprint(self.sxpr())
  51.274 +        msg = packMsg('blkif_be_connect_t',
  51.275 +                      { 'domid'        : self.dom,
  51.276 +                        'blkif_handle' : val['handle'],
  51.277 +                        'evtchn'       : self.evtchn['port1'],
  51.278 +                        'shmem_frame'  : val['shmem_frame'] })
  51.279 +        self.factory.writeRequest(msg)
  51.280 +        pass
  51.281 +
  51.282 +    #def recv_fe_interface_status_changed(self, msg, req):
  51.283 +    #    (hnd, status, chan) = unpackMsg('blkif_fe_interface_status_changed_t', msg)
  51.284 +    #    print 'recv_fe_interface_status_changed>', hnd, status, chan
  51.285 +    #   pass
  51.286 +
  51.287 +    def send_fe_interface_status_changed(self):
  51.288 +        msg = packMsg('blkif_fe_interface_status_changed_t',
  51.289 +                      { 'handle' : 0,
  51.290 +                        'status' : BLKIF_INTERFACE_STATUS_CONNECTED,
  51.291 +                        'evtchn' : self.evtchn['port2'] })
  51.292 +        self.writeRequest(msg)
  51.293 +
  51.294 +    def send_be_create(self):
  51.295 +        msg = packMsg('blkif_be_create_t',
  51.296 +                      { 'domid'        : self.dom,
  51.297 +                        'blkif_handle' : 0 })
  51.298 +        self.factory.writeRequest(msg)
  51.299 +
  51.300 +    def send_be_disconnect(self):
  51.301 +        print '>BlkifController>send_be_disconnect>', 'dom=', self.dom
  51.302 +        msg = packMsg('blkif_be_disconnect_t',
  51.303 +                      { 'domid'        : self.dom,
  51.304 +                        'blkif_handle' : 0 })
  51.305 +        self.factory.writeRequest(msg)
  51.306 +
  51.307 +    def send_be_destroy(self):
  51.308 +        print '>BlkifController>send_be_destroy>', 'dom=', self.dom
  51.309 +        msg = packMsg('blkif_be_destroy_t',
  51.310 +                      { 'domid'        : self.dom,
  51.311 +                        'blkif_handle' : 0 })
  51.312 +        self.factory.writeRequest(msg)
  51.313 +
  51.314 +    def send_be_vbd_create(self, vdev):
  51.315 +        dev = self.devices[vdev]
  51.316 +        msg = packMsg('blkif_be_vbd_create_t',
  51.317 +                      { 'domid'        : self.dom,
  51.318 +                        'blkif_handle' : 0,
  51.319 +                        'vdevice'      : dev.vdev,
  51.320 +                        'readonly'     : dev.readonly() })
  51.321 +        self.factory.writeRequest(msg)
  51.322 +        
  51.323 +    def send_be_vbd_grow(self, vdev):
  51.324 +        dev = self.devices[vdev]
  51.325 +        msg = packMsg('blkif_be_vbd_grow_t',
  51.326 +                      { 'domid'                : self.dom,
  51.327 +                        'blkif_handle'         : 0,
  51.328 +                        'vdevice'              : dev.vdev,
  51.329 +                        'extent.device'        : dev.device,
  51.330 +                        'extent.sector_start'  : dev.start_sector,
  51.331 +                        'extent.sector_length' : dev.nr_sectors })
  51.332 +        self.factory.writeRequest(msg)
  51.333 +
  51.334 +    def send_be_vbd_destroy(self, vdev):
  51.335 +        print '>BlkifController>send_be_vbd_destroy>', 'dom=', self.dom, 'vdev=', vdev
  51.336 +        PrettyPrint.prettyprint(self.sxpr())
  51.337 +        dev = self.devices[vdev]
  51.338 +        msg = packMsg('blkif_be_vbd_destroy_t',
  51.339 +                      { 'domid'                : self.dom,
  51.340 +                        'blkif_handle'         : 0,
  51.341 +                        'vdevice'              : dev.vdev })
  51.342 +        del self.devices[vdev]
  51.343 +        self.factory.writeRequest(msg)
  51.344 +    
    52.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.2 +++ b/tools/xen/lib/xend/server/channel.py	Mon Jun 28 08:20:16 2004 +0000
    52.3 @@ -0,0 +1,378 @@
    52.4 +import xen.ext.xc; xc = xen.ext.xc.new()
    52.5 +from xen.ext import xu
    52.6 +from messages import msgTypeName
    52.7 +
    52.8 +VIRQ_MISDIRECT  = 0  # Catch-all interrupt for unbound VIRQs.
    52.9 +VIRQ_TIMER      = 1  # Timebase update, and/or requested timeout.
   52.10 +VIRQ_DEBUG      = 2  # Request guest to dump debug info.
   52.11 +VIRQ_CONSOLE    = 3  # (DOM0) bytes received on emergency console.
   52.12 +VIRQ_DOM_EXC    = 4  # (DOM0) Exceptional event for some domain.
   52.13 +
   52.14 +def eventChannel(dom1, dom2):
   52.15 +    return xc.evtchn_bind_interdomain(dom1=dom1, dom2=dom2)
   52.16 +
   52.17 +class ChannelFactory:
   52.18 +    """Factory for creating channels.
   52.19 +    Maintains a table of channels.
   52.20 +    """
   52.21 +
   52.22 +    """ Channels indexed by index. """
   52.23 +    channels = {}
   52.24 +
   52.25 +    def __init__(self):
   52.26 +        """Constructor - do not use. Use the channelFactory function."""
   52.27 +        self.notifier = xu.notifier()
   52.28 +    
   52.29 +    def addChannel(self, channel):
   52.30 +        """Add a channel.
   52.31 +        """
   52.32 +        idx = channel.idx
   52.33 +        self.channels[idx] = channel
   52.34 +        self.notifier.bind(idx)
   52.35 +        # Try to wake it up
   52.36 +        #self.notifier.unmask(idx)
   52.37 +        #channel.notify()
   52.38 +
   52.39 +    def getChannel(self, idx):
   52.40 +        """Get the channel with the given index (if any).
   52.41 +        """
   52.42 +        return self.channels.get(idx)
   52.43 +
   52.44 +    def delChannel(self, idx):
   52.45 +        """Remove the channel with the given index (if any).
   52.46 +        """
   52.47 +        if idx in self.channels:
   52.48 +            del self.channels[idx]
   52.49 +            self.notifier.unbind(idx)
   52.50 +
   52.51 +    def domChannel(self, dom):
   52.52 +        """Get the channel for the given domain.
   52.53 +        Construct if necessary.
   52.54 +        """
   52.55 +        dom = int(dom)
   52.56 +        for chan in self.channels.values():
   52.57 +            if not isinstance(chan, Channel): continue
   52.58 +            if chan.dom == dom:
   52.59 +                return chan
   52.60 +        chan = Channel(self, dom)
   52.61 +        self.addChannel(chan)
   52.62 +        return chan
   52.63 +
   52.64 +    def virqChannel(self, virq):
   52.65 +        """Get the channel for the given virq.
   52.66 +        Construct if necessary.
   52.67 +        """
   52.68 +        for chan in self.channels.values():
   52.69 +            if not isinstance(chan, VirqChannel): continue
   52.70 +            if chan.virq == virq:
   52.71 +                return chan
   52.72 +        chan = VirqChannel(self, virq)
   52.73 +        self.addChannel(chan)
   52.74 +        return chan
   52.75 +
   52.76 +    def channelClosed(self, channel):
   52.77 +        """The given channel has been closed - remove it.
   52.78 +        """
   52.79 +        self.delChannel(channel.idx)
   52.80 +
   52.81 +    def createPort(self, dom):
   52.82 +        """Create a port for a channel to the given domain.
   52.83 +        """
   52.84 +        return xu.port(dom)
   52.85 +
   52.86 +def channelFactory():
   52.87 +    """Singleton constructor for the channel factory.
   52.88 +    Use this instead of the class constructor.
   52.89 +    """
   52.90 +    global inst
   52.91 +    try:
   52.92 +        inst
   52.93 +    except:
   52.94 +        inst = ChannelFactory()
   52.95 +    return inst
   52.96 +
   52.97 +class BaseChannel:
   52.98 +    """Abstract superclass for channels.
   52.99 +
  52.100 +    The subclass constructor must set idx to the port to use.
  52.101 +    """
  52.102 +
  52.103 +    def __init__(self, factory):
  52.104 +        self.factory = factory
  52.105 +        self.idx = -1
  52.106 +        self.closed = 0
  52.107 +
  52.108 +    def getIndex(self):
  52.109 +        """Get the channel index.
  52.110 +        """
  52.111 +        return self.idx
  52.112 +
  52.113 +    def notificationReceived(self, type):
  52.114 +        """Called when a notification is received.
  52.115 +        Closes the channel on error, otherwise calls
  52.116 +        handleNotification(type), which should be defined
  52.117 +        in a subclass.
  52.118 +        """
  52.119 +        #print 'notificationReceived> type=', type, self
  52.120 +        if self.closed: return
  52.121 +        if type == self.factory.notifier.EXCEPTION:
  52.122 +            print 'notificationReceived> EXCEPTION'
  52.123 +            info = xc.evtchn_status(self.idx)
  52.124 +            if info['status'] == 'unbound':
  52.125 +                print 'notificationReceived> EXCEPTION closing...'
  52.126 +                self.close()
  52.127 +                return
  52.128 +        self.handleNotification(type)
  52.129 +
  52.130 +    def close(self):
  52.131 +        """Close the channel. Calls channelClosed() on the factory.
  52.132 +        Override in subclass.
  52.133 +        """
  52.134 +        self.factory.channelClosed(self)
  52.135 +
  52.136 +    def handleNotification(self, type):
  52.137 +        """Handle notification.
  52.138 +        Define in subclass.
  52.139 +        """
  52.140 +        pass
  52.141 +        
  52.142 +
  52.143 +class VirqChannel(BaseChannel):
  52.144 +    """A channel for handling a virq.
  52.145 +    """
  52.146 +    
  52.147 +    def __init__(self, factory, virq):
  52.148 +        """Create a channel for the given virq using the given factory.
  52.149 +
  52.150 +        Do not call directly, use virqChannel on the factory.
  52.151 +        """
  52.152 +        BaseChannel.__init__(self, factory)
  52.153 +        self.virq = virq
  52.154 +        # Notification port (int).
  52.155 +        self.port = xc.evtchn_bind_virq(virq)
  52.156 +        self.idx = self.port
  52.157 +        # Clients to call when a virq arrives.
  52.158 +        self.clients = []
  52.159 +
  52.160 +    def __repr__(self):
  52.161 +        return ('<VirqChannel virq=%d port=%d>'
  52.162 +                % (self.virq, self.port))
  52.163 +
  52.164 +    def getVirq(self):
  52.165 +        """Get the channel's virq.
  52.166 +        """
  52.167 +        return self.virq
  52.168 +
  52.169 +    def close(self):
  52.170 +        """Close the channel. Calls lostChannel(self) on all its clients and
  52.171 +        channelClosed() on the factory.
  52.172 +        """
  52.173 +        for c in self.clients:
  52.174 +            c.lostChannel(self)
  52.175 +        del self.clients
  52.176 +        BaseChannel.close(self)
  52.177 +
  52.178 +    def registerClient(self, client):
  52.179 +        """Register a client. The client will be called with
  52.180 +        client.virqReceived(virq) when a virq is received.
  52.181 +        The client will be called with client.lostChannel(self) if the
  52.182 +        channel is closed.
  52.183 +        """
  52.184 +        self.clients.append(client)
  52.185 +
  52.186 +    def handleNotification(self, type):
  52.187 +        for c in self.clients:
  52.188 +            c.virqReceived(self.virq)
  52.189 +
  52.190 +    def notify(self):
  52.191 +        xc.evtchn_send(self.port)
  52.192 +
  52.193 +
  52.194 +class Channel(BaseChannel):
  52.195 +    """A control channel to a domain. Messages for the domain device controllers
  52.196 +    are multiplexed over the channel (console, block devs, net devs).
  52.197 +    """
  52.198 +
  52.199 +    def __init__(self, factory, dom):
  52.200 +        """Create a channel to the given domain using the given factory.
  52.201 +
  52.202 +        Do not call directly, use domChannel on the factory.
  52.203 +        """
  52.204 +        BaseChannel.__init__(self, factory)
  52.205 +        # Domain.
  52.206 +        self.dom = int(dom)
  52.207 +        # Domain port (object).
  52.208 +        self.port = self.factory.createPort(dom)
  52.209 +        # Channel port (int).
  52.210 +        self.idx = self.port.local_port
  52.211 +        # Registered devices.
  52.212 +        self.devs = []
  52.213 +        # Devices indexed by the message types they handle.
  52.214 +        self.devs_by_type = {}
  52.215 +        # Output queue.
  52.216 +        self.queue = []
  52.217 +        self.closed = 0
  52.218 +
  52.219 +    def getLocalPort(self):
  52.220 +        """Get the local port.
  52.221 +        """
  52.222 +        return self.port.local_port
  52.223 +
  52.224 +    def getRemotePort(self):
  52.225 +        """Get the remote port.
  52.226 +        """
  52.227 +        return self.port.remote_port
  52.228 +
  52.229 +    def close(self):
  52.230 +        """Close the channel. Calls lostChannel() on all its devices and
  52.231 +        channelClosed() on the factory.
  52.232 +        """
  52.233 +        self.closed = 1
  52.234 +        for d in self.devs:
  52.235 +            d.lostChannel()
  52.236 +        self.factory.channelClosed(self)
  52.237 +        self.devs = []
  52.238 +        self.devs_by_type = {}
  52.239 +
  52.240 +    def registerDevice(self, types, dev):
  52.241 +        """Register a device controller.
  52.242 +
  52.243 +        @param types message types the controller handles
  52.244 +        @param dev   device controller
  52.245 +        """
  52.246 +        if self.closed: return
  52.247 +        self.devs.append(dev)
  52.248 +        for ty in types:
  52.249 +            self.devs_by_type[ty] = dev
  52.250 +
  52.251 +    def deregisterDevice(self, dev):
  52.252 +        """Remove the registration for a device controller.
  52.253 +
  52.254 +        @param dev device controller
  52.255 +        """
  52.256 +        if dev in self.devs:
  52.257 +            self.devs.remove(dev)
  52.258 +        types = [ ty for (ty, d) in self.devs_by_type.items() if d == dev ]
  52.259 +        for ty in types:
  52.260 +            del self.devs_by_type[ty]
  52.261 +
  52.262 +    def getDevice(self, type):
  52.263 +        """Get the device controller handling a message type.
  52.264 +
  52.265 +        @param type message type
  52.266 +        @returns controller or None
  52.267 +        """
  52.268 +        return self.devs_by_type.get(type)
  52.269 +
  52.270 +    def getMessageType(self, msg):
  52.271 +        """Get a 2-tuple of the message type and subtype.
  52.272 +        """
  52.273 +        hdr = msg.get_header()
  52.274 +        return (hdr['type'], hdr.get('subtype'))
  52.275 +
  52.276 +    def __repr__(self):
  52.277 +        return ('<Channel dom=%d ports=%d:%d>'
  52.278 +                % (self.dom,
  52.279 +                   self.port.local_port,
  52.280 +                   self.port.remote_port))
  52.281 +
  52.282 +    def handleNotification(self, type):
  52.283 +        work = 0
  52.284 +        work += self.handleRequests()
  52.285 +        work += self.handleResponses()
  52.286 +        work += self.handleWrites()
  52.287 +        if work:
  52.288 +            self.notify()
  52.289 +
  52.290 +    def notify(self):
  52.291 +        self.port.notify()
  52.292 +
  52.293 +    def handleRequests(self):
  52.294 +        work = 0
  52.295 +        while 1:
  52.296 +            msg = self.readRequest()
  52.297 +            if not msg: break
  52.298 +            self.requestReceived(msg)
  52.299 +            work += 1
  52.300 +        return work
  52.301 +
  52.302 +    def requestReceived(self, msg):
  52.303 +        (ty, subty) = self.getMessageType(msg)
  52.304 +        #todo:  Must respond before writing any more messages.
  52.305 +        #todo:  Should automate this (respond on write)
  52.306 +        self.port.write_response(msg)
  52.307 +        dev = self.getDevice(ty)
  52.308 +        if dev:
  52.309 +            dev.requestReceived(msg, ty, subty)
  52.310 +        else:
  52.311 +            print ("requestReceived> No device: Message type %s %d:%d"
  52.312 +                   % (msgTypeName(ty, subty), ty, subty)), self
  52.313 +
  52.314 +    def handleResponses(self):
  52.315 +        work = 0
  52.316 +        while 1:
  52.317 +            msg = self.readResponse()
  52.318 +            if not msg: break
  52.319 +            self.responseReceived(msg)
  52.320 +            work += 1
  52.321 +        return work
  52.322 +
  52.323 +    def responseReceived(self, msg):
  52.324 +        (ty, subty) = self.getMessageType(msg)
  52.325 +        dev = self.getDevice(ty)
  52.326 +        if dev:
  52.327 +            dev.responseReceived(msg, ty, subty)
  52.328 +        else:
  52.329 +            print ("responseReceived> No device: Message type %d:%d"
  52.330 +                   % (msgTypeName(ty, subty), ty, subty)), self
  52.331 +
  52.332 +    def handleWrites(self):
  52.333 +        work = 0
  52.334 +        # Pull data from producers.
  52.335 +        for dev in self.devs:
  52.336 +            work += dev.produceRequests()
  52.337 +        # Flush the queue.
  52.338 +        while self.queue and self.port.space_to_write_request():
  52.339 +            msg = self.queue.pop(0)
  52.340 +            self.port.write_request(msg)
  52.341 +            work += 1
  52.342 +        return work
  52.343 +
  52.344 +    def writeRequest(self, msg, notify=1):
  52.345 +        if self.closed:
  52.346 +            val = -1
  52.347 +        elif self.writeReady():
  52.348 +            self.port.write_request(msg)
  52.349 +            if notify: self.notify()
  52.350 +            val = 1
  52.351 +        else:
  52.352 +            self.queue.append(msg)
  52.353 +            val = 0
  52.354 +        return val
  52.355 +
  52.356 +    def writeResponse(self, msg):
  52.357 +        if self.closed: return -1
  52.358 +        self.port.write_response(msg)
  52.359 +        return 1
  52.360 +
  52.361 +    def writeReady(self):
  52.362 +        if self.closed or self.queue: return 0
  52.363 +        return self.port.space_to_write_request()
  52.364 +
  52.365 +    def readRequest(self):
  52.366 +        if self.closed:
  52.367 +            return None
  52.368 +        if self.port.request_to_read():
  52.369 +            val = self.port.read_request()
  52.370 +        else:
  52.371 +            val = None
  52.372 +        return val
  52.373 +        
  52.374 +    def readResponse(self):
  52.375 +        if self.closed:
  52.376 +            return None
  52.377 +        if self.port.response_to_read():
  52.378 +            val = self.port.read_response()
  52.379 +        else:
  52.380 +            val = None
  52.381 +        return val
    53.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2 +++ b/tools/xen/lib/xend/server/console.py	Mon Jun 28 08:20:16 2004 +0000
    53.3 @@ -0,0 +1,232 @@
    53.4 +
    53.5 +from twisted.internet import reactor
    53.6 +from twisted.internet import protocol
    53.7 +from twisted.protocols import telnet
    53.8 +
    53.9 +from xen.ext import xu
   53.10 +
   53.11 +from xen.xend import EventServer
   53.12 +eserver = EventServer.instance()
   53.13 +
   53.14 +import controller
   53.15 +from messages import *
   53.16 +from params import *
   53.17 +
   53.18 +"""Telnet binary option."""
   53.19 +TRANSMIT_BINARY = '0'
   53.20 +WILL = chr(251)
   53.21 +IAC = chr(255)
   53.22 +
   53.23 +class ConsoleProtocol(protocol.Protocol):
   53.24 +    """Asynchronous handler for a console TCP socket.
   53.25 +    """
   53.26 +
   53.27 +    def __init__(self, controller, idx):
   53.28 +        self.controller = controller
   53.29 +        self.idx = idx
   53.30 +        self.addr = None
   53.31 +        self.binary = 0
   53.32 +
   53.33 +    def connectionMade(self):
   53.34 +        peer = self.transport.getPeer()
   53.35 +        self.addr = (peer.host, peer.port)
   53.36 +        if self.controller.connect(self.addr, self):
   53.37 +            self.transport.write("Cannot connect to console %d on domain %d\n"
   53.38 +                                 % (self.idx, self.controller.dom))
   53.39 +            self.loseConnection()
   53.40 +            return
   53.41 +        else:
   53.42 +            # KAF: A nice quiet successful connect. Don't bother with telnet
   53.43 +            # control sequence -- telnet is not the appropriate protocol here. 
   53.44 +            #self.transport.write("Connected to console %d on domain %d\n"
   53.45 +            #                     % (self.idx, self.controller.dom))
   53.46 +            #self.setTelnetTransmitBinary()
   53.47 +            eserver.inject('xend.console.connect',
   53.48 +                           [self.idx, self.addr[0], self.addr[1]])
   53.49 +
   53.50 +    def setTelnetTransmitBinary(self):
   53.51 +        """Send the sequence to set the telnet TRANSMIT-BINARY option.
   53.52 +        """
   53.53 +        self.write(IAC + WILL + TRANSMIT_BINARY)
   53.54 +
   53.55 +    def dataReceived(self, data):
   53.56 +        if self.controller.handleInput(self, data):
   53.57 +            self.loseConnection()
   53.58 +
   53.59 +    def write(self, data):
   53.60 +        #if not self.connected: return -1
   53.61 +        self.transport.write(data)
   53.62 +        return len(data)
   53.63 +
   53.64 +    def connectionLost(self, reason=None):
   53.65 +        eserver.inject('xend.console.disconnect',
   53.66 +                       [self.idx, self.addr[0], self.addr[1]])
   53.67 +        self.controller.disconnect()
   53.68 +
   53.69 +    def loseConnection(self):
   53.70 +        self.transport.loseConnection()
   53.71 +
   53.72 +class ConsoleFactory(protocol.ServerFactory):
   53.73 +    """Asynchronous handler for a console server socket.
   53.74 +    """
   53.75 +    protocol = ConsoleProtocol
   53.76 +    
   53.77 +    def __init__(self, controller, idx):
   53.78 +        #protocol.ServerFactory.__init__(self)
   53.79 +        self.controller = controller
   53.80 +        self.idx = idx
   53.81 +
   53.82 +    def buildProtocol(self, addr):
   53.83 +        proto = self.protocol(self.controller, self.idx)
   53.84 +        proto.factory = self
   53.85 +        return proto
   53.86 +
   53.87 +class ConsoleControllerFactory(controller.ControllerFactory):
   53.88 +    """Factory for creating console controllers.
   53.89 +    """
   53.90 +
   53.91 +    def createInstance(self, dom, console_port=None):
   53.92 +        if console_port is None:
   53.93 +            console_port = CONSOLE_PORT_BASE + dom
   53.94 +        console = ConsoleController(self, dom, console_port)
   53.95 +        self.addInstance(console)
   53.96 +        eserver.inject('xend.console.create',
   53.97 +                       [console.idx, console.dom, console.console_port])
   53.98 +        return console
   53.99 +        
  53.100 +    def consoleClosed(self, console):
  53.101 +        eserver.inject('xend.console.close', console.idx)
  53.102 +        self.delInstance(console)
  53.103 +
  53.104 +class ConsoleController(controller.Controller):
  53.105 +    """Console controller for a domain.
  53.106 +    Does not poll for i/o itself, but relies on the notifier to post console
  53.107 +    output and the connected TCP sockets to post console input.
  53.108 +    """
  53.109 +
  53.110 +    def __init__(self, factory, dom, console_port):
  53.111 +        #print 'ConsoleController> dom=', dom, type(dom)
  53.112 +        controller.Controller.__init__(self, factory, dom)
  53.113 +        self.majorTypes = [ CMSG_CONSOLE ]
  53.114 +        self.status = "new"
  53.115 +        self.addr = None
  53.116 +        self.conn = None
  53.117 +        self.rbuf = xu.buffer()
  53.118 +        self.wbuf = xu.buffer()
  53.119 +        self.console_port = console_port
  53.120 +
  53.121 +        self.registerChannel()
  53.122 +        self.listener = None
  53.123 +        self.listen()
  53.124 +        #print 'ConsoleController<', 'dom=', self.dom, 'idx=', self.idx
  53.125 +
  53.126 +    def sxpr(self):
  53.127 +        val =['console',
  53.128 +              ['status',       self.status ],
  53.129 +              ['id',           self.idx ],
  53.130 +              ['domain',       self.dom ],
  53.131 +              ['local_port',   self.channel.getLocalPort() ],
  53.132 +              ['remote_port',  self.channel.getRemotePort() ],
  53.133 +              ['console_port', self.console_port ] ]
  53.134 +        if self.addr:
  53.135 +            val.append(['connected', self.addr[0], self.addr[1]])
  53.136 +        return val
  53.137 +
  53.138 +    def ready(self):
  53.139 +        return not (self.closed() or self.rbuf.empty())
  53.140 +
  53.141 +    def closed(self):
  53.142 +        return self.status == 'closed'
  53.143 +
  53.144 +    def connected(self):
  53.145 +        return self.status == 'connected'
  53.146 +
  53.147 +    def close(self):
  53.148 +        try:
  53.149 +            #print 'ConsoleController> close dom=', self.dom
  53.150 +            self.status = "closed"
  53.151 +            if self.conn:
  53.152 +                self.conn.loseConnection()
  53.153 +            self.listener.stopListening()
  53.154 +            self.deregisterChannel()
  53.155 +            self.lostChannel()
  53.156 +        except Exception, ex:
  53.157 +            print 'ConsoleController>close>', ex
  53.158 +            raise
  53.159 +
  53.160 +    def listen(self):
  53.161 +        """Listen for TCP connections to the console port..
  53.162 +        """
  53.163 +        if self.closed(): return
  53.164 +        self.status = "listening"
  53.165 +        if self.listener:
  53.166 +            #self.listener.startListening()
  53.167 +            pass
  53.168 +        else:
  53.169 +            f = ConsoleFactory(self, self.idx)
  53.170 +            self.listener = reactor.listenTCP(self.console_port, f)
  53.171 +
  53.172 +    def connect(self, addr, conn):
  53.173 +        if self.closed(): return -1
  53.174 +        if self.connected(): return -1
  53.175 +        self.addr = addr
  53.176 +        self.conn = conn
  53.177 +        self.status = "connected"
  53.178 +        self.handleOutput()
  53.179 +        return 0
  53.180 +
  53.181 +    def disconnect(self):
  53.182 +        if self.conn:
  53.183 +            self.conn.loseConnection()
  53.184 +        self.addr = None
  53.185 +        self.conn = None
  53.186 +        self.listen()
  53.187 +
  53.188 +    def requestReceived(self, msg, type, subtype):
  53.189 +        #print '***Console', self.dom, msg.get_payload()
  53.190 +        self.rbuf.write(msg.get_payload())
  53.191 +        self.handleOutput()
  53.192 +        
  53.193 +    def responseReceived(self, msg, type, subtype):
  53.194 +        pass
  53.195 +
  53.196 +    def produceRequests(self):
  53.197 +        # Send as much pending console data as there is room for.
  53.198 +        work = 0
  53.199 +        while not self.wbuf.empty() and self.channel.writeReady():
  53.200 +            msg = xu.message(CMSG_CONSOLE, 0, 0)
  53.201 +            msg.append_payload(self.wbuf.read(msg.MAX_PAYLOAD))
  53.202 +            work += self.channel.writeRequest(msg, notify=0)
  53.203 +        return work
  53.204 +
  53.205 +    def handleInput(self, conn, data):
  53.206 +        """Handle some external input aimed at the console.
  53.207 +        Called from a TCP connection (conn).
  53.208 +        """
  53.209 +        if self.closed(): return -1
  53.210 +        if conn != self.conn: return 0
  53.211 +        self.wbuf.write(data)
  53.212 +        if self.produceRequests():
  53.213 +            self.channel.notify()
  53.214 +        return 0
  53.215 +
  53.216 +    def handleOutput(self):
  53.217 +        """Handle buffered output from the console.
  53.218 +        Sends it to the connected console (if any).
  53.219 +        """
  53.220 +        if self.closed():
  53.221 +            #print 'Console>handleOutput> closed'
  53.222 +            return -1
  53.223 +        if not self.conn:
  53.224 +            #print 'Console>handleOutput> not connected'
  53.225 +            return 0
  53.226 +        while not self.rbuf.empty():
  53.227 +            try:
  53.228 +                #print 'Console>handleOutput> writing...'
  53.229 +                bytes = self.conn.write(self.rbuf.peek())
  53.230 +                if bytes > 0:
  53.231 +                    self.rbuf.discard(bytes)
  53.232 +            except socket.error, error:
  53.233 +                pass
  53.234 +        #print 'Console>handleOutput<'
  53.235 +        return 0
    54.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.2 +++ b/tools/xen/lib/xend/server/controller.py	Mon Jun 28 08:20:16 2004 +0000
    54.3 @@ -0,0 +1,169 @@
    54.4 +from twisted.internet import defer
    54.5 +
    54.6 +import channel
    54.7 +from messages import msgTypeName
    54.8 +
    54.9 +class CtrlMsgRcvr:
   54.10 +    """Abstract class for things that deal with a control interface to a domain.
   54.11 +    """
   54.12 +
   54.13 +
   54.14 +    def __init__(self):
   54.15 +        self.channelFactory = channel.channelFactory()
   54.16 +        self.majorTypes = [ ]
   54.17 +        self.subTypes = {}
   54.18 +        self.dom = None
   54.19 +        self.channel = None
   54.20 +        self.idx = None
   54.21 +
   54.22 +    def requestReceived(self, msg, type, subtype):
   54.23 +        method = self.subTypes.get(subtype)
   54.24 +        if method:
   54.25 +            method(msg, 1)
   54.26 +        else:
   54.27 +            print ('requestReceived> No handler: Message type %s %d:%d'
   54.28 +                   % (msgTypeName(type, subtype), type, subtype)), self
   54.29 +        
   54.30 +    def responseReceived(self, msg, type, subtype):
   54.31 +        method = self.subTypes.get(subtype)
   54.32 +        if method:
   54.33 +            method(msg, 0)
   54.34 +        else:
   54.35 +            print ('responseReceived> No handler: Message type %s %d:%d'
   54.36 +                   % (msgTypeName(type, subtype), type, subtype)), self
   54.37 +
   54.38 +    def lostChannel(self):
   54.39 +        pass
   54.40 +    
   54.41 +    def registerChannel(self):
   54.42 +        #print 'CtrlMsgRcvr>registerChannel>', self
   54.43 +        self.channel = self.channelFactory.domChannel(self.dom)
   54.44 +        self.idx = self.channel.getIndex()
   54.45 +        if self.majorTypes:
   54.46 +            self.channel.registerDevice(self.majorTypes, self)
   54.47 +        
   54.48 +    def deregisterChannel(self):
   54.49 +        #print 'CtrlMsgRcvr>deregisterChannel>', self
   54.50 +        if self.channel:
   54.51 +            self.channel.deregisterDevice(self)
   54.52 +            del self.channel
   54.53 +
   54.54 +    def produceRequests(self):
   54.55 +        return 0
   54.56 +
   54.57 +    def writeRequest(self, msg):
   54.58 +        if self.channel:
   54.59 +            self.channel.writeRequest(msg)
   54.60 +        else:
   54.61 +            print 'CtrlMsgRcvr>writeRequest>', 'no channel!', self
   54.62 +
   54.63 +    def writeResponse(self, msg):
   54.64 +        if self.channel:
   54.65 +            self.channel.writeResponse(msg)
   54.66 +        else:
   54.67 +            print 'CtrlMsgRcvr>writeResponse>', 'no channel!', self
   54.68 +            
   54.69 +class ControllerFactory(CtrlMsgRcvr):
   54.70 +    """Abstract class for factories creating controllers.
   54.71 +    Maintains a table of instances.
   54.72 +    """
   54.73 +
   54.74 +    def __init__(self):
   54.75 +        CtrlMsgRcvr.__init__(self)
   54.76 +        self.instances = {}
   54.77 +        self.dlist = []
   54.78 +        self.dom = 0
   54.79 +        # Timeout (in seconds) for deferreds.
   54.80 +        self.timeout = 10
   54.81 +        
   54.82 +    def addInstance(self, instance):
   54.83 +        self.instances[instance.idx] = instance
   54.84 +
   54.85 +    def getInstance(self, idx):
   54.86 +        return self.instances.get(idx)
   54.87 +
   54.88 +    def getInstances(self):
   54.89 +        return self.instances.values()
   54.90 +
   54.91 +    def getInstanceByDom(self, dom):
   54.92 +        for inst in self.instances.values():
   54.93 +            if inst.dom == dom:
   54.94 +                return inst
   54.95 +        return None
   54.96 +
   54.97 +    def delInstance(self, instance):
   54.98 +        #print 'ControllerFactory>delInstance>', instance.idx
   54.99 +        if instance.idx in self.instances:
  54.100 +            #print 'ControllerFactory>delInstance> remove', instance.idx
  54.101 +            del self.instances[instance.idx]
  54.102 +
  54.103 +    def createInstance(self, dom, recreate=0):
  54.104 +        raise NotImplementedError()
  54.105 +
  54.106 +    def instanceClosed(self, instance):
  54.107 +        #print 'ControllerFactory>instanceClosed>', instance.idx, instance
  54.108 +        self.delInstance(instance)
  54.109 +
  54.110 +    def addDeferred(self):
  54.111 +        d = defer.Deferred()
  54.112 +        if self.timeout > 0:
  54.113 +            # The deferred will error if not called before timeout.
  54.114 +            d.setTimeout(self.timeout)
  54.115 +        self.dlist.append(d)
  54.116 +        return d
  54.117 +
  54.118 +    def callDeferred(self, *args):
  54.119 +        if self.dlist:
  54.120 +            d = self.dlist.pop(0)
  54.121 +            d.callback(*args)
  54.122 +
  54.123 +    def errDeferred(self, *args):
  54.124 +        if self.dlist:
  54.125 +            d = self.dlist.pop(0)
  54.126 +            d.errback(*args)
  54.127 +
  54.128 +class Controller(CtrlMsgRcvr):
  54.129 +    """Abstract class for a device controller attached to a domain.
  54.130 +    """
  54.131 +
  54.132 +    def __init__(self, factory, dom):
  54.133 +        CtrlMsgRcvr.__init__(self)
  54.134 +        self.factory = factory
  54.135 +        self.dom = int(dom)
  54.136 +        self.channel = None
  54.137 +        self.idx = None
  54.138 +
  54.139 +    def close(self):
  54.140 +        self.deregisterChannel()
  54.141 +        self.lostChannel()
  54.142 +
  54.143 +    def lostChannel(self):
  54.144 +        #print 'Controller>lostChannel>', self, self.factory
  54.145 +        self.factory.instanceClosed(self)
  54.146 +
  54.147 +class Dev:
  54.148 +
  54.149 +    def __init__(self, controller):
  54.150 +        self.controller = controller
  54.151 +        self.props = {}
  54.152 +
  54.153 +    def setprop(self, k, v):
  54.154 +        self.props[k] = v
  54.155 +
  54.156 +    def getprop(self, k, v=None):
  54.157 +        return self.props.get(k, v)
  54.158 +
  54.159 +    def hasprop(self, k):
  54.160 +        return k in self.props
  54.161 +
  54.162 +    def delprop(self, k):
  54.163 +        if k in self.props:
  54.164 +            del self.props[k]
  54.165 +
  54.166 +    #def __repr__(self):
  54.167 +    #    return str(self.sxpr())
  54.168 +
  54.169 +    def sxpr(self):
  54.170 +        raise NotImplementedError()
  54.171 +
  54.172 +    
    55.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.2 +++ b/tools/xen/lib/xend/server/cstruct.py	Mon Jun 28 08:20:16 2004 +0000
    55.3 @@ -0,0 +1,269 @@
    55.4 +import struct
    55.5 +
    55.6 +class Struct:
    55.7 +
    55.8 +    maxDepth = 10
    55.9 +
   55.10 +    base = ['x', 'B', 'H', 'I', 'L', 'Q', 'c', 'h', 'i', 'l', 'q', ]
   55.11 +
   55.12 +    sizes = {'B': 1,
   55.13 +            'H': 2,
   55.14 +            'I': 4,
   55.15 +            'L': 4,
   55.16 +            'Q': 8,
   55.17 +            'c': 1,
   55.18 +            'h': 2,
   55.19 +            'i': 4,
   55.20 +            'l': 4,
   55.21 +            'q': 8,
   55.22 +            'x': 1,
   55.23 +            }
   55.24 +
   55.25 +    formats = {
   55.26 +        'int8'          : 'B',
   55.27 +        'int16'         : 'H',
   55.28 +        'int32'         : 'I',
   55.29 +        'int64'         : 'Q',
   55.30 +        'u8'            : 'B',
   55.31 +        'u16'           : 'H',
   55.32 +        'u32'           : 'I',
   55.33 +        'u64'           : 'Q'
   55.34 +        }
   55.35 +
   55.36 +    def typedef(self, name, val):
   55.37 +        self.formats[name] = val
   55.38 +
   55.39 +    def struct(self, name, *f):
   55.40 +        self.typedef(name, StructInfo(self, f))
   55.41 +        
   55.42 +    def getType(self, name):
   55.43 +        return self.formats[name]
   55.44 +
   55.45 +    def format(self, ty):
   55.46 +        d = 0
   55.47 +        f = ty
   55.48 +        while d < self.maxDepth:
   55.49 +            d += 1
   55.50 +            f = self.formats[f]
   55.51 +            if isinstance(f, StructInfo):
   55.52 +                return f.format()
   55.53 +            if f in self.base:
   55.54 +                return f
   55.55 +        return -1
   55.56 +
   55.57 +    def alignedformat(self, ty):
   55.58 +        fmt = self.format(ty)
   55.59 +        #print 'alignedformat> %s |%s|' %(ty, fmt)
   55.60 +        afmt = self.align(fmt)
   55.61 +        #print 'alignedformat< %s |%s| |%s|' % (ty, fmt, afmt)
   55.62 +        return afmt
   55.63 +
   55.64 +    def align(self, fmt):
   55.65 +        n1 = 0
   55.66 +        afmt = ''
   55.67 +        for a in fmt:
   55.68 +            n2 = self.getSize(a)
   55.69 +            m = n1 % n2
   55.70 +            if m:
   55.71 +                d = (n2 - m)
   55.72 +                afmt += 'x' * d
   55.73 +                n1 += d
   55.74 +            afmt += a
   55.75 +            n1 += n2
   55.76 +        return afmt
   55.77 +
   55.78 +    def fmtsize(self, fmt):
   55.79 +        s = 0
   55.80 +        for f in fmt:
   55.81 +            s += self.getSize(f)
   55.82 +        return s
   55.83 +
   55.84 +    def getSize(self, f):
   55.85 +        return self.sizes[f]
   55.86 +
   55.87 +    def pack(self, ty, data):
   55.88 +        return self.getType(ty).pack(data)
   55.89 +
   55.90 +    def unpack(self, ty, data):
   55.91 +        return self.getType(ty).unpack(data)
   55.92 +
   55.93 +    def show(self):
   55.94 +        l = self.formats.keys()
   55.95 +        l.sort()
   55.96 +        for v in l:
   55.97 +            print "%-35s %-10s %s" % (v, self.format(v), self.alignedformat(v))
   55.98 +
   55.99 +
  55.100 +class StructInfo:
  55.101 +
  55.102 +    def __init__(self, s, f):
  55.103 +        self.fmt = None
  55.104 +        self.structs = s
  55.105 +        self.fields = f
  55.106 +
  55.107 +    def alignedformat(self):
  55.108 +        if self.afmt: return self.afmt
  55.109 +        self.afmt = self.structs.align(self.format())
  55.110 +        return self.afmt
  55.111 +    
  55.112 +    def format(self):
  55.113 +        if self.fmt: return self.fmt
  55.114 +        fmt = ""
  55.115 +        for (ty, name) in self.fields:
  55.116 +            fmt += self.formatString(ty)
  55.117 +        self.fmt = fmt
  55.118 +        return fmt
  55.119 +
  55.120 +    def formatString(self, ty):
  55.121 +        if ty in self.fields:
  55.122 +            ty = self.fields[ty]
  55.123 +        return self.structs.format(ty)
  55.124 +
  55.125 +    def pack(self, *args):
  55.126 +        return struct.pack(self.alignedformat(), *args)
  55.127 +
  55.128 +    def unpack(self, data):
  55.129 +        return struct.unpack(self.alignedformat(), data)
  55.130 +
  55.131 +types = Struct()
  55.132 +
  55.133 +types.typedef('short'         , 'h')
  55.134 +types.typedef('int'           , 'i')
  55.135 +types.typedef('long'          , 'l')
  55.136 +types.typedef('unsigned short', 'H')
  55.137 +types.typedef('unsigned int'  , 'I')
  55.138 +types.typedef('unsigned long' , 'L')
  55.139 +types.typedef('domid_t'       , 'u64')
  55.140 +types.typedef('blkif_vdev_t'  , 'u16')
  55.141 +types.typedef('blkif_pdev_t'  , 'u16')
  55.142 +types.typedef('blkif_sector_t', 'u64')
  55.143 +
  55.144 +types.struct('u8[6]',
  55.145 +             ('u8', 'a1'),
  55.146 +             ('u8', 'a2'),
  55.147 +             ('u8', 'a3'),
  55.148 +             ('u8', 'a4'),
  55.149 +             ('u8', 'a5'),
  55.150 +             ('u8', 'a6'))
  55.151 +             
  55.152 +types.struct('blkif_fe_interface_status_changed_t',
  55.153 +    ('unsigned int',    'handle'),
  55.154 +    ('unsigned int',    'status'),
  55.155 +    ('unsigned int',    'evtchn'))
  55.156 +
  55.157 +types.struct('blkif_fe_driver_status_changed_t',
  55.158 +    ('unsigned int',    'status'),
  55.159 +    ('unsigned int',    'nr_interfaces'))
  55.160 +
  55.161 +types.struct('blkif_fe_interface_connect_t',
  55.162 +    ('unsigned int' ,   'handle'),
  55.163 +    ('unsigned long',   'shmem_frame'))
  55.164 +
  55.165 +types.struct('blkif_fe_interface_disconnect_t',
  55.166 +    ('unsigned int',   'handle'))
  55.167 +
  55.168 +types.struct('blkif_extent_t',
  55.169 +    ('blkif_pdev_t'  , 'device'),
  55.170 +    ('blkif_sector_t', 'sector_start'),
  55.171 +    ('blkif_sector_t', 'sector_length'))
  55.172 +
  55.173 +types.struct('blkif_be_create_t', 
  55.174 +    ('domid_t'     ,   'domid'),
  55.175 +    ('unsigned int',   'blkif_handle'),
  55.176 +    ('unsigned int',   'status'))
  55.177 +             
  55.178 +types.struct('blkif_be_destroy_t',
  55.179 +    ('domid_t'     ,   'domid'),
  55.180 +    ('unsigned int',   'blkif_handle'),
  55.181 +    ('unsigned int',   'status'))
  55.182 +
  55.183 +types.struct('blkif_be_connect_t',
  55.184 +    ('domid_t'      ,  'domid'),
  55.185 +    ('unsigned int' ,  'blkif_handle'),
  55.186 +    ('unsigned int' ,  'evtchn'),
  55.187 +    ('unsigned long',  'shmem_frame'),
  55.188 +    ('unsigned int' ,  'status'))
  55.189 +
  55.190 +types.struct('blkif_be_disconnect_t',
  55.191 +    ('domid_t'     ,   'domid'),
  55.192 +    ('unsigned int',   'blkif_handle'),
  55.193 +    ('unsigned int',   'status'))
  55.194 +
  55.195 +types.struct('blkif_be_vbd_create_t', 
  55.196 +    ('domid_t'     ,   'domid'),         #Q
  55.197 +    ('unsigned int',   'blkif_handle'),  #I
  55.198 +    ('blkif_vdev_t',   'vdevice'),       #H
  55.199 +    ('int'         ,   'readonly'),      #i
  55.200 +    ('unsigned int',   'status'))        #I
  55.201 +
  55.202 +types.struct('blkif_be_vbd_destroy_t', 
  55.203 +    ('domid_t'     ,   'domid'),
  55.204 +    ('unsigned int',   'blkif_handle'),
  55.205 +    ('blkif_vdev_t',   'vdevice'),
  55.206 +    ('unsigned int',   'status'))
  55.207 +
  55.208 +types.struct('blkif_be_vbd_grow_t', 
  55.209 +    ('domid_t'       , 'domid'),         #Q
  55.210 +    ('unsigned int'  , 'blkif_handle'),  #I
  55.211 +    ('blkif_vdev_t'  , 'vdevice'),       #H   
  55.212 +    ('blkif_extent_t', 'extent'),        #HQQ
  55.213 +    ('unsigned int'  , 'status'))        #I
  55.214 +
  55.215 +types.struct('blkif_be_vbd_shrink_t', 
  55.216 +    ('domid_t'     ,   'domid'),
  55.217 +    ('unsigned int',   'blkif_handle'),
  55.218 +    ('blkif_vdev_t',   'vdevice'),
  55.219 +    ('unsigned int',   'status'))
  55.220 +
  55.221 +types.struct('blkif_be_driver_status_changed_t',
  55.222 +    ('unsigned int',   'status'),
  55.223 +    ('unsigned int',   'nr_interfaces'))
  55.224 +
  55.225 +types.struct('netif_fe_interface_status_changed_t',
  55.226 +    ('unsigned int',   'handle'),
  55.227 +    ('unsigned int',   'status'),
  55.228 +    ('unsigned int',   'evtchn'),
  55.229 +    ('u8[6]',          'mac'))
  55.230 +
  55.231 +types.struct('netif_fe_driver_status_changed_t',
  55.232 +    ('unsigned int',   'status'),
  55.233 +    ('unsigned int',   'nr_interfaces'))
  55.234 +
  55.235 +types.struct('netif_fe_interface_connect_t',
  55.236 +    ('unsigned int',   'handle'),
  55.237 +    ('unsigned long',  'tx_shmem_frame'),
  55.238 +    ('unsigned long',  'rx_shmem_frame'))
  55.239 +
  55.240 +types.struct('netif_fe_interface_disconnect_t',
  55.241 +    ('unsigned int',   'handle'))
  55.242 +
  55.243 +types.struct('netif_be_create_t', 
  55.244 +    ('domid_t'     ,   'domid'),
  55.245 +    ('unsigned int',   'netif_handle'),
  55.246 +    ('u8[6]'       ,   'mac'),
  55.247 +    ('unsigned int',   'status'))
  55.248 +
  55.249 +types.struct('netif_be_destroy_t',
  55.250 +    ('domid_t'     ,   'domid'),
  55.251 +    ('unsigned int',   'netif_handle'),
  55.252 +    ('unsigned int',   'status'))
  55.253 +
  55.254 +types.struct('netif_be_connect_t', 
  55.255 +    ('domid_t'      ,  'domid'),
  55.256 +    ('unsigned int' ,  'netif_handle'),
  55.257 +    ('unsigned int' ,  'evtchn'),
  55.258 +    ('unsigned long',  'tx_shmem_frame'),
  55.259 +    ('unsigned long',  'rx_shmem_frame'),
  55.260 +    ('unsigned int' ,  'status'))
  55.261 +
  55.262 +types.struct('netif_be_disconnect_t',
  55.263 +    ('domid_t'     ,   'domid'),
  55.264 +    ('unsigned int',   'netif_handle'),
  55.265 +    ('unsigned int',   'status'))
  55.266 +
  55.267 +types.struct('netif_be_driver_status_changed_t',
  55.268 +    ('unsigned int',   'status'),
  55.269 +    ('unsigned int',   'nr_interfaces'))
  55.270 +
  55.271 +if 1 or __name__ == "__main__":
  55.272 +    types.show()
    56.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.2 +++ b/tools/xen/lib/xend/server/domain.py	Mon Jun 28 08:20:16 2004 +0000
    56.3 @@ -0,0 +1,41 @@
    56.4 +import channel
    56.5 +import controller
    56.6 +from messages import *
    56.7 +
    56.8 +class DomainControllerFactory(controller.ControllerFactory):
    56.9 +    """Factory for creating domain controllers.
   56.10 +    """
   56.11 +
   56.12 +    def createInstance(self, dom):
   56.13 +        d = DomainController(self, dom)
   56.14 +        self.addInstance(d)
   56.15 +        return d
   56.16 +    
   56.17 +    def getInstanceByDom(self, dom):
   56.18 +        for inst in self.instances.values():
   56.19 +            if inst.dom == dom:
   56.20 +                return inst
   56.21 +        inst = self.createInstance(dom)
   56.22 +        return inst
   56.23 +
   56.24 +
   56.25 +class DomainController(controller.Controller):
   56.26 +    """Generic controller for a domain.
   56.27 +    """
   56.28 +
   56.29 +    reasons = {'poweroff' : 'shutdown_poweroff_t',
   56.30 +               'reboot'   : 'shutdown_reboot_t',
   56.31 +               'suspend'  : 'shutdown_suspend_t' }
   56.32 +
   56.33 +    def __init__(self, factory, dom):
   56.34 +        controller.Controller.__init__(self, factory, dom)
   56.35 +        self.majorTypes = [ CMSG_SHUTDOWN ]
   56.36 +        self.registerChannel()
   56.37 +        print 'DomainController>', self, self.channel, self.idx
   56.38 +
   56.39 +    def shutdown(self, reason):
   56.40 +        msgtype = self.reasons.get(reason)
   56.41 +        if not msgtype:
   56.42 +            raise ValueError('invalid reason:' + reason)
   56.43 +        msg = packMsg(msgtype, {})
   56.44 +        self.writeRequest(msg)
    57.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.2 +++ b/tools/xen/lib/xend/server/messages.py	Mon Jun 28 08:20:16 2004 +0000
    57.3 @@ -0,0 +1,219 @@
    57.4 +import struct
    57.5 +
    57.6 +from xen.ext import xu
    57.7 +
    57.8 +DEBUG = 0
    57.9 +
   57.10 +""" All message formats.
   57.11 +Added to incrementally for the various message types.
   57.12 +See below.
   57.13 +"""
   57.14 +msg_formats = {}
   57.15 +
   57.16 +#============================================================================
   57.17 +# Console message types.
   57.18 +#============================================================================
   57.19 +
   57.20 +CMSG_CONSOLE  = 0
   57.21 +
   57.22 +console_formats = { 'console_data': (CMSG_CONSOLE, 0) }
   57.23 +
   57.24 +msg_formats.update(console_formats)
   57.25 +
   57.26 +#============================================================================
   57.27 +# Block interface message types.
   57.28 +#============================================================================
   57.29 +
   57.30 +CMSG_BLKIF_BE = 1
   57.31 +CMSG_BLKIF_FE = 2
   57.32 +
   57.33 +CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED =  0
   57.34 +CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED    = 32
   57.35 +CMSG_BLKIF_FE_INTERFACE_CONNECT        = 33
   57.36 +CMSG_BLKIF_FE_INTERFACE_DISCONNECT     = 34
   57.37 +
   57.38 +CMSG_BLKIF_BE_CREATE      = 0
   57.39 +CMSG_BLKIF_BE_DESTROY     = 1
   57.40 +CMSG_BLKIF_BE_CONNECT     = 2
   57.41 +CMSG_BLKIF_BE_DISCONNECT  = 3
   57.42 +CMSG_BLKIF_BE_VBD_CREATE  = 4
   57.43 +CMSG_BLKIF_BE_VBD_DESTROY = 5
   57.44 +CMSG_BLKIF_BE_VBD_GROW    = 6
   57.45 +CMSG_BLKIF_BE_VBD_SHRINK  = 7
   57.46 +CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED    = 32
   57.47 +
   57.48 +BLKIF_DRIVER_STATUS_DOWN  = 0
   57.49 +BLKIF_DRIVER_STATUS_UP    = 1
   57.50 +
   57.51 +BLKIF_INTERFACE_STATUS_DESTROYED    = 0 #/* Interface doesn't exist.    */
   57.52 +BLKIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */
   57.53 +BLKIF_INTERFACE_STATUS_CONNECTED    = 2 #/* Exists and is connected.    */
   57.54 +
   57.55 +BLKIF_BE_STATUS_OKAY                = 0
   57.56 +BLKIF_BE_STATUS_ERROR               = 1
   57.57 +BLKIF_BE_STATUS_INTERFACE_EXISTS    = 2
   57.58 +BLKIF_BE_STATUS_INTERFACE_NOT_FOUND = 3
   57.59 +BLKIF_BE_STATUS_INTERFACE_CONNECTED = 4
   57.60 +BLKIF_BE_STATUS_VBD_EXISTS          = 5
   57.61 +BLKIF_BE_STATUS_VBD_NOT_FOUND       = 6
   57.62 +BLKIF_BE_STATUS_OUT_OF_MEMORY       = 7
   57.63 +BLKIF_BE_STATUS_EXTENT_NOT_FOUND    = 8
   57.64 +BLKIF_BE_STATUS_MAPPING_ERROR       = 9
   57.65 +
   57.66 +blkif_formats = {
   57.67 +    'blkif_be_connect_t':
   57.68 +    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT),
   57.69 +
   57.70 +    'blkif_be_create_t':
   57.71 +    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE),
   57.72 +
   57.73 +    'blkif_be_disconnect_t':
   57.74 +    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT),
   57.75 +
   57.76 +    'blkif_be_destroy_t':
   57.77 +    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY),
   57.78 +
   57.79 +    'blkif_be_vbd_create_t':
   57.80 +    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE),
   57.81 +
   57.82 +    'blkif_be_vbd_grow_t':
   57.83 +    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW),
   57.84 +
   57.85 +    'blkif_be_vbd_destroy_t':
   57.86 +    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY),
   57.87 +
   57.88 +    'blkif_fe_interface_status_changed_t':
   57.89 +    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED),
   57.90 +
   57.91 +    'blkif_fe_driver_status_changed_t':
   57.92 +    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED),
   57.93 +
   57.94 +    'blkif_fe_interface_connect_t':
   57.95 +    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT),
   57.96 +}
   57.97 +
   57.98 +msg_formats.update(blkif_formats)
   57.99 +
  57.100 +#============================================================================
  57.101 +# Network interface message types.
  57.102 +#============================================================================
  57.103 +
  57.104 +CMSG_NETIF_BE = 3
  57.105 +CMSG_NETIF_FE = 4
  57.106 +
  57.107 +CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED =  0
  57.108 +CMSG_NETIF_FE_DRIVER_STATUS_CHANGED    = 32
  57.109 +CMSG_NETIF_FE_INTERFACE_CONNECT        = 33
  57.110 +CMSG_NETIF_FE_INTERFACE_DISCONNECT     = 34
  57.111 +
  57.112 +CMSG_NETIF_BE_CREATE      = 0
  57.113 +CMSG_NETIF_BE_DESTROY     = 1
  57.114 +CMSG_NETIF_BE_CONNECT     = 2
  57.115 +CMSG_NETIF_BE_DISCONNECT  = 3
  57.116 +CMSG_NETIF_BE_DRIVER_STATUS_CHANGED    = 32
  57.117 +
  57.118 +NETIF_INTERFACE_STATUS_DESTROYED    = 0 #/* Interface doesn't exist.    */
  57.119 +NETIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */
  57.120 +NETIF_INTERFACE_STATUS_CONNECTED    = 2 #/* Exists and is connected.    */
  57.121 +
  57.122 +NETIF_DRIVER_STATUS_DOWN   = 0
  57.123 +NETIF_DRIVER_STATUS_UP     = 1
  57.124 +
  57.125 +netif_formats = {
  57.126 +    'netif_be_connect_t':
  57.127 +    (CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT),
  57.128 +
  57.129 +    'netif_be_create_t':
  57.130 +    (CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE),
  57.131 +
  57.132 +    'netif_be_disconnect_t':
  57.133 +    (CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT),
  57.134 +
  57.135 +    'netif_be_destroy_t':
  57.136 +    (CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY),
  57.137 +
  57.138 +    'netif_be_driver_status_changed_t':
  57.139 +    (CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS_CHANGED),
  57.140 +
  57.141 +    'netif_fe_driver_status_changed_t':
  57.142 +    (CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED),
  57.143 +
  57.144 +    'netif_fe_interface_connect_t':
  57.145 +    (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT),
  57.146 +
  57.147 +    'netif_fe_interface_status_changed_t':
  57.148 +    (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED),
  57.149 +    }
  57.150 +
  57.151 +msg_formats.update(netif_formats)
  57.152 +
  57.153 +#============================================================================
  57.154 +CMSG_SHUTDOWN = 6
  57.155 +
  57.156 +CMSG_SHUTDOWN_POWEROFF  = 0
  57.157 +CMSG_SHUTDOWN_REBOOT    = 1
  57.158 +CMSG_SHUTDOWN_SUSPEND   = 2
  57.159 +
  57.160 +STOPCODE_shutdown       = 0
  57.161 +STOPCODE_reboot         = 1
  57.162 +STOPCODE_suspend        = 2
  57.163 +
  57.164 +shutdown_formats = {
  57.165 +    'shutdown_poweroff_t':
  57.166 +    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_POWEROFF),
  57.167 +    
  57.168 +    'shutdown_reboot_t':
  57.169 +    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_REBOOT),
  57.170 +
  57.171 +    'shutdown_suspend_t':
  57.172 +    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_SUSPEND),
  57.173 +    }
  57.174 +
  57.175 +msg_formats.update(shutdown_formats)
  57.176 +
  57.177 +#============================================================================
  57.178 +
  57.179 +class Msg:
  57.180 +    pass
  57.181 +
  57.182 +def packMsg(ty, params):
  57.183 +    if DEBUG: print '>packMsg', ty, params
  57.184 +    (major, minor) = msg_formats[ty]
  57.185 +    args = {}
  57.186 +    for (k, v) in params.items():
  57.187 +        if k == 'mac':
  57.188 +            for i in range(0, 6):
  57.189 +                args['mac[%d]' % i] = v[i]
  57.190 +        else:
  57.191 +            args[k] = v
  57.192 +    if DEBUG:
  57.193 +        for (k, v) in args.items():
  57.194 +            print 'packMsg>', k, v, type(v)
  57.195 +    msgid = 0
  57.196 +    msg = xu.message(major, minor, msgid, args)
  57.197 +    return msg
  57.198 +
  57.199 +def unpackMsg(ty, msg):
  57.200 +    args = msg.get_payload()
  57.201 +    mac = [0, 0, 0, 0, 0, 0]
  57.202 +    macs = []
  57.203 +    for (k, v) in args.items():
  57.204 +        if k.startswith('mac['):
  57.205 +            macs += k
  57.206 +            i = int(k[4:5])
  57.207 +            mac[i] = v
  57.208 +        else:
  57.209 +            pass
  57.210 +    if macs:
  57.211 +        args['mac'] = mac
  57.212 +        for k in macs:
  57.213 +            del args[k]
  57.214 +    if DEBUG: print '<unpackMsg', ty, args
  57.215 +    return args
  57.216 +
  57.217 +def msgTypeName(ty, subty):
  57.218 +    for (name, info) in msg_formats.items():
  57.219 +        if info[0] == ty and info[1] == subty:
  57.220 +            return name
  57.221 +    return None
  57.222 +
    58.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.2 +++ b/tools/xen/lib/xend/server/netif.py	Mon Jun 28 08:20:16 2004 +0000
    58.3 @@ -0,0 +1,304 @@
    58.4 +import random
    58.5 +
    58.6 +from twisted.internet import defer
    58.7 +
    58.8 +from xen.xend import sxp
    58.9 +from xen.xend import PrettyPrint
   58.10 +from xen.xend import XendBridge
   58.11 +
   58.12 +import channel
   58.13 +import controller
   58.14 +from messages import *
   58.15 +
   58.16 +class NetifControllerFactory(controller.ControllerFactory):
   58.17 +    """Factory for creating network interface controllers.
   58.18 +    Also handles the 'back-end' channel to the device driver domain.
   58.19 +    """
   58.20 +
   58.21 +    def __init__(self):
   58.22 +        controller.ControllerFactory.__init__(self)
   58.23 +
   58.24 +        self.majorTypes = [ CMSG_NETIF_BE ]
   58.25 +
   58.26 +        self.subTypes = {
   58.27 +            CMSG_NETIF_BE_CREATE : self.recv_be_create,
   58.28 +            CMSG_NETIF_BE_CONNECT: self.recv_be_connect,
   58.29 +            CMSG_NETIF_BE_DRIVER_STATUS_CHANGED: self.recv_be_driver_status_changed,
   58.30 +            }
   58.31 +        self.attached = 1
   58.32 +        self.registerChannel()
   58.33 +
   58.34 +    def createInstance(self, dom, recreate=0):
   58.35 +        """Create or find the network interface controller for a domain.
   58.36 +        """
   58.37 +        #print 'netif>createInstance> dom=', dom
   58.38 +        netif = self.getInstanceByDom(dom)
   58.39 +        if netif is None:
   58.40 +            netif = NetifController(self, dom)
   58.41 +            self.addInstance(netif)
   58.42 +        return netif
   58.43 +
   58.44 +    def getDomainDevices(self, dom):
   58.45 +        netif = self.getInstanceByDom(dom)
   58.46 +        return (netif and netif.getDevices()) or []
   58.47 +
   58.48 +    def getDomainDevice(self, dom, vif):
   58.49 +        netif = self.getInstanceByDom(dom)
   58.50 +        return (netif and netif.getDevice(vif)) or None
   58.51 +        
   58.52 +    def setControlDomain(self, dom, recreate=0):
   58.53 +        """Set the 'back-end' device driver domain.
   58.54 +        """
   58.55 +        if self.dom == dom: return
   58.56 +        self.deregisterChannel()
   58.57 +        if not recreate:
   58.58 +            self.attached = 0
   58.59 +        self.dom = dom
   58.60 +        self.registerChannel()
   58.61 +        #
   58.62 +        #if xend.netif.be_port.remote_dom != 0:
   58.63 +        #    xend.netif.recovery = True
   58.64 +        #    xend.netif.be_port = xend.main.port_from_dom(dom)
   58.65 +        #
   58.66 +
   58.67 +    def getControlDomain(self):
   58.68 +        return self.dom
   58.69 +
   58.70 +    def recv_be_create(self, msg, req):
   58.71 +        self.callDeferred(0)
   58.72 +    
   58.73 +    def recv_be_connect(self, msg, req):
   58.74 +        val = unpackMsg('netif_be_connect_t', msg)
   58.75 +        dom = val['domid']
   58.76 +        vif = val['netif_handle']
   58.77 +        netif = self.getInstanceByDom(dom)
   58.78 +        if netif:
   58.79 +            netif.send_interface_connected(vif)
   58.80 +        else:
   58.81 +            print "recv_be_connect> unknown vif=", vif
   58.82 +            pass
   58.83 +
   58.84 +    def recv_be_driver_status_changed(self, msg, req):
   58.85 +        val = unpackMsg('netif_be_driver_status_changed_t', msg)
   58.86 +        status = val['status']
   58.87 +        if status == NETIF_DRIVER_STATUS_UP and not self.attached:
   58.88 +            # If we are not attached the driver domain was changed, and
   58.89 +            # this signals the new driver domain is ready.
   58.90 +            for netif in self.getInstances():
   58.91 +                netif.reattach_devices()
   58.92 +            self.attached = 1
   58.93 +
   58.94 +##         pl = msg.get_payload()
   58.95 +##         status = pl['status']
   58.96 +##         if status == NETIF_DRIVER_STATUS_UP:
   58.97 +##             if xend.netif.recovery:
   58.98 +##                 print "New netif backend now UP, notifying guests:"
   58.99 +##                 for netif_key in interface.list.keys():
  58.100 +##                     netif = interface.list[netif_key]
  58.101 +##                     netif.create()
  58.102 +##                     print "  Notifying %d" % netif.dom
  58.103 +##                     msg = xu.message(
  58.104 +##                         CMSG_NETIF_FE,
  58.105 +##                         CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED, 0,
  58.106 +##                         { 'handle' : 0, 'status' : 1 })
  58.107 +##                     netif.ctrlif_tx_req(xend.main.port_from_dom(netif.dom),msg)
  58.108 +##                 print "Done notifying guests"
  58.109 +##                 recovery = False
  58.110 +                
  58.111 +class NetDev(controller.Dev):
  58.112 +    """Info record for a network device.
  58.113 +    """
  58.114 +
  58.115 +    def __init__(self, ctrl, vif, mac):
  58.116 +        controller.Dev.__init__(self, ctrl)
  58.117 +        self.vif = vif
  58.118 +        self.mac = mac
  58.119 +        self.evtchn = None
  58.120 +        self.bridge = None
  58.121 +
  58.122 +    def sxpr(self):
  58.123 +        vif = str(self.vif)
  58.124 +        mac = ':'.join(map(lambda x: "%x" % x, self.mac))
  58.125 +        val = ['netdev', ['vif', vif], ['mac', mac]]
  58.126 +        if self.bridge:
  58.127 +            val.append(['bridge', self.bridge])
  58.128 +        if self.evtchn:
  58.129 +            val.append(['evtchn',
  58.130 +                        self.evtchn['port1'],
  58.131 +                        self.evtchn['port2']])
  58.132 +        return val
  58.133 +
  58.134 +    def bridge_add(self, bridge):
  58.135 +        self.bridge = XendBridge.vif_bridge_add(self.controller.dom, self.vif, bridge)
  58.136 +
  58.137 +    def bridge_rem(self):
  58.138 +        if not self.bridge: return
  58.139 +        XendBridge.vif_bridge_rem(self.controller.dom, self.vif, self.bridge)
  58.140 +        self.bridge = None
  58.141 +
  58.142 +    def destroy(self):
  58.143 +        def cb_destroy(val):
  58.144 +            self.controller.send_be_destroy(self.vif)
  58.145 +        print 'NetDev>destroy>', 'vif=', self.vif
  58.146 +        PrettyPrint.prettyprint(self.sxpr())
  58.147 +        self.bridge_rem()
  58.148 +        d = self.controller.factory.addDeferred()
  58.149 +        d.addCallback(cb_destroy)
  58.150 +        self.controller.send_be_disconnect(self.vif)
  58.151 +        #self.controller.send_be_destroy(self.vif)
  58.152 +        
  58.153 +
  58.154 +class NetifController(controller.Controller):
  58.155 +    """Network interface controller. Handles all network devices for a domain.
  58.156 +    """
  58.157 +    
  58.158 +    def __init__(self, factory, dom):
  58.159 +        #print 'NetifController> dom=', dom
  58.160 +        controller.Controller.__init__(self, factory, dom)
  58.161 +        self.devices = {}
  58.162 +        
  58.163 +        self.majorTypes = [ CMSG_NETIF_FE ]
  58.164 +
  58.165 +        self.subTypes = {
  58.166 +            CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
  58.167 +                self.recv_fe_driver_status_changed,
  58.168 +            CMSG_NETIF_FE_INTERFACE_CONNECT    :
  58.169 +                self.recv_fe_interface_connect,
  58.170 +            }
  58.171 +        self.registerChannel()
  58.172 +        #print 'NetifController<', 'dom=', self.dom, 'idx=', self.idx
  58.173 +
  58.174 +    def sxpr(self):
  58.175 +        val = ['netif', ['dom', self.dom]]
  58.176 +        return val
  58.177 +    
  58.178 +    def randomMAC(self):
  58.179 +        # VIFs get a random MAC address with a "special" vendor id.
  58.180 +        # 
  58.181 +        # NB. The vendor is currently an "obsolete" one that used to belong
  58.182 +        # to DEC (AA-00-00). Using it is probably a bit rude :-)
  58.183 +        # 
  58.184 +        # NB2. The first bit of the first random octet is set to zero for
  58.185 +        # all dynamic MAC addresses. This may allow us to manually specify
  58.186 +        # MAC addresses for some VIFs with no fear of clashes.
  58.187 +        mac = [ 0xaa, 0x00, 0x00,
  58.188 +                random.randint(0x00, 0x7f),
  58.189 +                random.randint(0x00, 0xff),
  58.190 +                random.randint(0x00, 0xff) ]
  58.191 +        return mac
  58.192 +
  58.193 +    def lostChannel(self):
  58.194 +        print 'NetifController>lostChannel>', 'dom=', self.dom
  58.195 +        #self.destroyDevices()
  58.196 +        controller.Controller.lostChannel(self)
  58.197 +
  58.198 +    def getDevices(self):
  58.199 +        return self.devices.values()
  58.200 +
  58.201 +    def getDevice(self, vif):
  58.202 +        return self.devices.get(vif)
  58.203 +
  58.204 +    def addDevice(self, vif, vmac):
  58.205 +        if vmac is None:
  58.206 +            mac = self.randomMAC()
  58.207 +        else:
  58.208 +            mac = [ int(x, 16) for x in vmac.split(':') ]
  58.209 +        if len(mac) != 6: raise ValueError("invalid mac")
  58.210 +        #print "attach_device>", "vif=", vif, "mac=", mac
  58.211 +        dev = NetDev(self, vif, mac)
  58.212 +        self.devices[vif] = dev
  58.213 +        return dev
  58.214 +
  58.215 +    def destroy(self):
  58.216 +        print 'NetifController>destroy>', 'dom=', self.dom
  58.217 +        self.destroyDevices()
  58.218 +        
  58.219 +    def destroyDevices(self):
  58.220 +        for dev in self.getDevices():
  58.221 +            dev.destroy()
  58.222 +
  58.223 +    def attachDevice(self, vif, vmac, recreate=0):
  58.224 +        """Attach a network device.
  58.225 +        If vmac is None a random mac address is assigned.
  58.226 +
  58.227 +        @param vif interface index
  58.228 +        @param vmac mac address (string)
  58.229 +        """
  58.230 +        self.addDevice(vif, vmac)
  58.231 +        if recreate:
  58.232 +            d = defer.Deferred()
  58.233 +            d.callback(self)
  58.234 +        else:
  58.235 +            d = self.factory.addDeferred()
  58.236 +            self.send_be_create(vif)
  58.237 +        return d
  58.238 +
  58.239 +    def reattach_devices(self):
  58.240 +        """Reattach all devices when the back-end control domain has changed.
  58.241 +        """
  58.242 +        d = self.factory.addDeferred()
  58.243 +        self.send_be_create(vif)
  58.244 +        self.attach_fe_devices(0)
  58.245 +
  58.246 +    def attach_fe_devices(self):
  58.247 +        for dev in self.devices.values():
  58.248 +            msg = packMsg('netif_fe_interface_status_changed_t',
  58.249 +                          { 'handle' : dev.vif,
  58.250 +                            'status' : NETIF_INTERFACE_STATUS_DISCONNECTED,
  58.251 +                            'evtchn' : 0,
  58.252 +                            'mac'    : dev.mac })
  58.253 +            self.writeRequest(msg)
  58.254 +    
  58.255 +    def recv_fe_driver_status_changed(self, msg, req):
  58.256 +        if not req: return
  58.257 +        msg = packMsg('netif_fe_driver_status_changed_t',
  58.258 +                      { 'status'        : NETIF_DRIVER_STATUS_UP,
  58.259 +                        'nr_interfaces' : len(self.devices) })
  58.260 +        self.writeRequest(msg)
  58.261 +        self.attach_fe_devices()
  58.262 +
  58.263 +    def recv_fe_interface_connect(self, msg, req):
  58.264 +        val = unpackMsg('netif_fe_interface_connect_t', msg)
  58.265 +        dev = self.devices[val['handle']]
  58.266 +        dev.evtchn = channel.eventChannel(0, self.dom)
  58.267 +        msg = packMsg('netif_be_connect_t',
  58.268 +                      { 'domid'          : self.dom,
  58.269 +                        'netif_handle'   : dev.vif,
  58.270 +                        'evtchn'         : dev.evtchn['port1'],
  58.271 +                        'tx_shmem_frame' : val['tx_shmem_frame'],
  58.272 +                        'rx_shmem_frame' : val['rx_shmem_frame'] })
  58.273 +        self.factory.writeRequest(msg)
  58.274 +
  58.275 +    def send_interface_connected(self, vif):
  58.276 +        dev = self.devices[vif]
  58.277 +        msg = packMsg('netif_fe_interface_status_changed_t',
  58.278 +                      { 'handle' : dev.vif,
  58.279 +                        'status' : NETIF_INTERFACE_STATUS_CONNECTED,
  58.280 +                        'evtchn' : dev.evtchn['port2'],
  58.281 +                        'mac'    : dev.mac })
  58.282 +        self.writeRequest(msg)
  58.283 +
  58.284 +    def send_be_create(self, vif):
  58.285 +        dev = self.devices[vif]
  58.286 +        msg = packMsg('netif_be_create_t',
  58.287 +                      { 'domid'        : self.dom,
  58.288 +                        'netif_handle' : dev.vif,
  58.289 +                        'mac'          : dev.mac })
  58.290 +        self.factory.writeRequest(msg)
  58.291 +
  58.292 +    def send_be_disconnect(self, vif):
  58.293 +        dev = self.devices[vif]
  58.294 +        msg = packMsg('netif_be_disconnect_t',
  58.295 +                      { 'domid'        : self.dom,
  58.296 +                        'netif_handle' : dev.vif })
  58.297 +        self.factory.writeRequest(msg)
  58.298 +
  58.299 +    def send_be_destroy(self, vif):
  58.300 +        print 'NetifController>send_be_destroy>', 'dom=', self.dom, 'vif=', vif
  58.301 +        PrettyPrint.prettyprint(self.sxpr())
  58.302 +        dev = self.devices[vif]
  58.303 +        del self.devices[vif]
  58.304 +        msg = packMsg('netif_be_destroy_t',
  58.305 +                      { 'domid'        : self.dom,
  58.306 +                        'netif_handle' : vif })
  58.307 +        self.factory.writeRequest(msg)
    59.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.2 +++ b/tools/xen/lib/xend/server/params.py	Mon Jun 28 08:20:16 2004 +0000
    59.3 @@ -0,0 +1,10 @@
    59.4 +# The following parameters could be placed in a configuration file.
    59.5 +PID_FILE  = '/var/run/xend.pid'
    59.6 +LOG_FILE  = '/var/log/xend.log'
    59.7 +USER = 'root'
    59.8 +CONTROL_DIR  = '/var/run/xend'
    59.9 +MGMT_SOCK    = 'xendsock' # relative to CONTROL_DIR
   59.10 +EVENT_PORT = 8001
   59.11 +
   59.12 +CONSOLE_PORT_BASE = 9600
   59.13 +
    60.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.2 +++ b/tools/xen/lib/xend/sxp.py	Mon Jun 28 08:20:16 2004 +0000
    60.3 @@ -0,0 +1,557 @@
    60.4 +#!/usr/bin/python2
    60.5 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    60.6 +"""
    60.7 +Input-driven parsing for s-expression (sxp) format.
    60.8 +Create a parser: pin = Parser();
    60.9 +Then call pin.input(buf) with your input.
   60.10 +Call pin.input_eof() when done.
   60.11 +Use pin.read() to see if a value has been parsed, pin.get_val()
   60.12 +to get a parsed value. You can call ready and get_val at any time -
   60.13 +you don't have to wait until after calling input_eof.
   60.14 +
   60.15 +"""
   60.16 +from __future__ import generators
   60.17 +
   60.18 +import sys
   60.19 +import types
   60.20 +import errno
   60.21 +import string
   60.22 +
   60.23 +__all__ = [
   60.24 +    "mime_type", 
   60.25 +    "ParseError", 
   60.26 +    "Parser", 
   60.27 +    "atomp", 
   60.28 +    "show", 
   60.29 +    "show_xml", 
   60.30 +    "elementp", 
   60.31 +    "name", 
   60.32 +    "attributes", 
   60.33 +    "attribute", 
   60.34 +    "children", 
   60.35 +    "child", 
   60.36 +    "child_at", 
   60.37 +    "child0", 
   60.38 +    "child1", 
   60.39 +    "child2", 
   60.40 +    "child3", 
   60.41 +    "child4", 
   60.42 +    "child_value", 
   60.43 +    "has_id", 
   60.44 +    "with_id", 
   60.45 +    "child_with_id", 
   60.46 +    "elements", 
   60.47 +    "parse", 
   60.48 +    ]
   60.49 +
   60.50 +mime_type = "application/sxp"
   60.51 +
   60.52 +escapes = {
   60.53 +    'a': '\a',
   60.54 +    'b': '\b',
   60.55 +    't': '\t',
   60.56 +    'n': '\n',
   60.57 +    'v': '\v',
   60.58 +    'f': '\f',
   60.59 +    'r': '\r',
   60.60 +    '\\': '\\',
   60.61 +    '\'': '\'',
   60.62 +    '\"': '\"'}
   60.63 +
   60.64 +k_list_open  = "("
   60.65 +k_list_close = ")"
   60.66 +k_attr_open  = "@"
   60.67 +k_eval       = "!"
   60.68 +
   60.69 +escapes_rev = {}
   60.70 +for k in escapes:
   60.71 +    escapes_rev[escapes[k]] = k
   60.72 +
   60.73 +class ParseError(StandardError):
   60.74 +
   60.75 +    def __init__(self, parser, value):
   60.76 +        self.parser = parser
   60.77 +        self.value = value
   60.78 +
   60.79 +    def __str__(self):
   60.80 +        return self.value
   60.81 +
   60.82 +class ParserState:
   60.83 +
   60.84 +    def __init__(self, fn, parent=None):
   60.85 +        self.parent = parent
   60.86 +        self.buf = ''
   60.87 +        self.val = []
   60.88 +        self.delim = None
   60.89 +        self.fn = fn
   60.90 +
   60.91 +    def push(self, fn):
   60.92 +        return ParserState(fn, parent=self)
   60.93 +    
   60.94 +class Parser:
   60.95 +
   60.96 +    def __init__(self):
   60.97 +        self.error = sys.stderr
   60.98 +        self.reset()
   60.99 +
  60.100 +    def reset(self):
  60.101 +        self.val = []
  60.102 +        self.eof = 0
  60.103 +        self.err = 0
  60.104 +        self.line_no = 0
  60.105 +        self.char_no = 0
  60.106 +        self.state = None
  60.107 +
  60.108 +    def push_state(self, fn):
  60.109 +        self.state = self.state.push(fn)
  60.110 +
  60.111 +    def pop_state(self):
  60.112 +        val = self.state
  60.113 +        self.state = self.state.parent
  60.114 +        if self.state and self.state.fn == self.state_start:
  60.115 +            # Return to start state - produce the value.
  60.116 +            self.val += self.state.val
  60.117 +            self.state.val = []
  60.118 +        return val
  60.119 +
  60.120 +    def in_class(self, c, s):
  60.121 +        return s.find(c) >= 0
  60.122 +        
  60.123 +    def in_space_class(self, c):
  60.124 +        return self.in_class(c, ' \t\n\v\f\r')
  60.125 +
  60.126 +    def is_separator(self, c):
  60.127 +        return self.in_class(c, '{}()<>[]!;')
  60.128 +
  60.129 +    def in_comment_class(self, c):
  60.130 +        return self.in_class(c, '#')
  60.131 +
  60.132 +    def in_string_quote_class(self, c):
  60.133 +        return self.in_class(c, '"\'')
  60.134 +
  60.135 +    def in_printable_class(self, c):
  60.136 +        return self.in_class(c, string.printable)
  60.137 +
  60.138 +    def set_error_stream(self, error):
  60.139 +        self.error = error
  60.140 +
  60.141 +    def has_error(self):
  60.142 +        return self.err > 0
  60.143 +
  60.144 +    def at_eof(self):
  60.145 +        return self.eof
  60.146 +
  60.147 +    def input_eof(self):
  60.148 +        self.eof = 1
  60.149 +        self.input_char(-1)
  60.150 +
  60.151 +    def input(self, buf):
  60.152 +        if not buf or len(buf) == 0:
  60.153 +            self.input_eof()
  60.154 +        else:
  60.155 +            for c in buf:
  60.156 +                self.input_char(c)
  60.157 +
  60.158 +    def input_char(self, c):
  60.159 +        if self.at_eof():
  60.160 +            pass
  60.161 +        elif c == '\n':
  60.162 +            self.line_no += 1
  60.163 +            self.char_no = 0
  60.164 +        else:
  60.165 +           self.char_no += 1 
  60.166 +
  60.167 +        if self.state is None:
  60.168 +            self.begin_start(None)
  60.169 +        self.state.fn(c)
  60.170 +
  60.171 +    def ready(self):
  60.172 +        return len(self.val) > 0
  60.173 +
  60.174 +    def get_val(self):
  60.175 +        v = self.val[0]
  60.176 +        self.val = self.val[1:]
  60.177 +        return v
  60.178 +
  60.179 +    def get_all(self):
  60.180 +        return self.val
  60.181 +
  60.182 +    def begin_start(self, c):
  60.183 +        self.state = ParserState(self.state_start)
  60.184 +
  60.185 +    def end_start(self):
  60.186 +        self.val += self.state.val
  60.187 +        self.pop_state()
  60.188 +    
  60.189 +    def state_start(self, c):
  60.190 +        if self.at_eof():
  60.191 +            self.end_start()
  60.192 +        elif self.in_space_class(c):
  60.193 +            pass
  60.194 +        elif self.in_comment_class(c):
  60.195 +            self.begin_comment(c)
  60.196 +        elif c == k_list_open:
  60.197 +            self.begin_list(c)
  60.198 +        elif c == k_list_close:
  60.199 +            raise ParseError(self, "syntax error: "+c)
  60.200 +        elif self.in_string_quote_class(c):
  60.201 +            self.begin_string(c)
  60.202 +        elif self.in_printable_class(c):
  60.203 +            self.begin_atom(c)
  60.204 +        elif c == chr(4):
  60.205 +            # ctrl-D, EOT: end-of-text.
  60.206 +            self.input_eof()
  60.207 +        else:
  60.208 +            raise ParseError(self, "invalid character: code %d" % ord(c))
  60.209 +
  60.210 +    def begin_comment(self, c):
  60.211 +        self.push_state(self.state_comment)
  60.212 +        self.state.buf += c
  60.213 +
  60.214 +    def end_comment(self):
  60.215 +        self.pop_state()
  60.216 +    
  60.217 +    def state_comment(self, c):
  60.218 +        if c == '\n' or self.at_eof():
  60.219 +            self.end_comment()
  60.220 +        else:
  60.221 +            self.state.buf += c
  60.222 +
  60.223 +    def begin_string(self, c):
  60.224 +        self.push_state(self.state_string)
  60.225 +        self.state.delim = c
  60.226 +
  60.227 +    def end_string(self):
  60.228 +        val = self.state.buf
  60.229 +        self.state.parent.val.append(val)
  60.230 +        self.pop_state()
  60.231 +        
  60.232 +    def state_string(self, c):
  60.233 +        if self.at_eof():
  60.234 +            raise ParseError(self, "unexpected EOF")
  60.235 +        elif c == self.state.delim:
  60.236 +            self.end_string()
  60.237 +        elif c == '\\':
  60.238 +            self.push_state(self.state_escape)
  60.239 +        else:
  60.240 +            self.state.buf += c
  60.241 +
  60.242 +    def state_escape(self, c):
  60.243 +        if self.at_eof():
  60.244 +            raise ParseError(self, "unexpected EOF")
  60.245 +        d = escapes.get(c)
  60.246 +        if d:
  60.247 +            self.state.parent.buf += d
  60.248 +            self.pop_state()
  60.249 +        elif c == 'x':
  60.250 +            self.state.fn = self.state_hex
  60.251 +            self.state.val = 0
  60.252 +        else:
  60.253 +            self.state.fn = self.state_octal
  60.254 +            self.state.val = 0
  60.255 +            self.input_char(c)
  60.256 +
  60.257 +    def state_octal(self, c):
  60.258 +        def octaldigit(c):
  60.259 +            self.state.val *= 8
  60.260 +            self.state.val += ord(c) - ord('0')
  60.261 +            self.state.buf += c
  60.262 +            if self.state.val < 0 or self.state.val > 0xff:
  60.263 +                raise ParseError(self, "invalid octal escape: out of range " + self.state.buf)
  60.264 +            if len(self.state.buf) == 3:
  60.265 +               octaldone()
  60.266 +               
  60.267 +        def octaldone():
  60.268 +            d = chr(self.state.val)
  60.269 +            self.state.parent.buf += d
  60.270 +            self.pop_state()
  60.271 +            
  60.272 +        if self.at_eof():
  60.273 +            raise ParseError(self, "unexpected EOF")
  60.274 +        elif '0' <= c <= '7':
  60.275 +            octaldigit(c)
  60.276 +        elif len(self.buf):
  60.277 +            octaldone()
  60.278 +            self.input_char(c)
  60.279 +
  60.280 +    def state_hex(self, c):
  60.281 +        def hexdone():
  60.282 +            d = chr(self.state.val)
  60.283 +            self.state.parent.buf += d
  60.284 +            self.pop_state()
  60.285 +            
  60.286 +        def hexdigit(c, d):
  60.287 +            self.state.val *= 16
  60.288 +            self.state.val += ord(c) - ord(d)
  60.289 +            self.state.buf += c
  60.290 +            if self.state.val < 0 or self.state.val > 0xff:
  60.291 +                raise ParseError(self, "invalid hex escape: out of range " + self.state.buf)
  60.292 +            if len(self.state.buf) == 2:
  60.293 +                hexdone()
  60.294 +            
  60.295 +        if self.at_eof():
  60.296 +            raise ParseError(self, "unexpected EOF")
  60.297 +        elif '0' <= c <= '9':
  60.298 +            hexdigit(c, '0')
  60.299 +        elif 'A' <= c <= 'F':
  60.300 +            hexdigit(c, 'A')
  60.301 +        elif 'a' <= c <= 'f':
  60.302 +            hexdigit(c, 'a')
  60.303 +        elif len(buf):
  60.304 +            hexdone()
  60.305 +            self.input_char(c)
  60.306 +
  60.307 +    def begin_atom(self, c):
  60.308 +        self.push_state(self.state_atom)
  60.309 +        self.state.buf = c
  60.310 +
  60.311 +    def end_atom(self):
  60.312 +        val = self.state.buf
  60.313 +        self.state.parent.val.append(val)
  60.314 +        self.pop_state()
  60.315 +    
  60.316 +    def state_atom(self, c):
  60.317 +        if self.at_eof():
  60.318 +            self.end_atom()
  60.319 +        elif (self.is_separator(c) or
  60.320 +              self.in_space_class(c) or
  60.321 +              self.in_comment_class(c)):
  60.322 +            self.end_atom()
  60.323 +            self.input_char(c)
  60.324 +        else:
  60.325 +            self.state.buf += c
  60.326 +
  60.327 +    def begin_list(self, c):
  60.328 +        self.push_state(self.state_list)
  60.329 +
  60.330 +    def end_list(self):
  60.331 +        val = self.state.val
  60.332 +        self.state.parent.val.append(val)
  60.333 +        self.pop_state()
  60.334 +
  60.335 +    def state_list(self, c):
  60.336 +        if self.at_eof():
  60.337 +            raise ParseError(self, "unexpected EOF")
  60.338 +        elif c == k_list_close:
  60.339 +            self.end_list()
  60.340 +        else:
  60.341 +            self.state_start(c)
  60.342 +
  60.343 +def atomp(sxpr):
  60.344 +    if sxpr.isalnum() or sxpr == '@':
  60.345 +        return 1
  60.346 +    for c in sxpr:
  60.347 +        if c in string.whitespace: return 0
  60.348 +        if c in '"\'\\(){}[]<>$#&%^': return 0
  60.349 +        if c in string.ascii_letters: continue
  60.350 +        if c in string.digits: continue
  60.351 +        if c in '.-_:/~': continue
  60.352 +        return 0
  60.353 +    return 1
  60.354 +    
  60.355 +def show(sxpr, out=sys.stdout):
  60.356 +    if isinstance(sxpr, types.ListType):
  60.357 +        out.write(k_list_open)
  60.358 +        i = 0
  60.359 +        for x in sxpr:
  60.360 +            if i: out.write(' ')
  60.361 +            show(x, out)
  60.362 +            i += 1
  60.363 +        out.write(k_list_close)
  60.364 +    elif isinstance(sxpr, types.StringType) and atomp(sxpr):
  60.365 +        out.write(sxpr)
  60.366 +    else:
  60.367 +        #out.write("'" + str(sxpr) + "'")
  60.368 +        out.write(repr(str(sxpr)))
  60.369 +
  60.370 +def show_xml(sxpr, out=sys.stdout):
  60.371 +    if isinstance(sxpr, types.ListType):
  60.372 +        element = name(sxpr)
  60.373 +        out.write('<%s' % element)
  60.374 +        for attr in attributes(sxpr):
  60.375 +            out.write(' %s=%s' % (attr[0], attr[1]))
  60.376 +        out.write('>')
  60.377 +        i = 0
  60.378 +        for x in children(sxpr):
  60.379 +            if i: out.write(' ')
  60.380 +            show_xml(x, out)
  60.381 +            i += 1
  60.382 +        out.write('</%s>' % element)
  60.383 +    elif isinstance(sxpr, types.StringType) and atomp(sxpr):
  60.384 +        out.write(sxpr)
  60.385 +    else:
  60.386 +        out.write(str(sxpr))
  60.387 +
  60.388 +def elementp(sxpr, elt=None):
  60.389 +    return (isinstance(sxpr, types.ListType)
  60.390 +            and len(sxpr)
  60.391 +            and (None == elt or sxpr[0] == elt))
  60.392 +
  60.393 +def name(sxpr):
  60.394 +    val = None
  60.395 +    if isinstance(sxpr, types.StringType):
  60.396 +        val = sxpr
  60.397 +    elif isinstance(sxpr, types.ListType) and len(sxpr):
  60.398 +        val = sxpr[0]
  60.399 +    return val
  60.400 +
  60.401 +def attributes(sxpr):
  60.402 +    val = []
  60.403 +    if isinstance(sxpr, types.ListType) and len(sxpr) > 1:
  60.404 +        attr = sxpr[1]
  60.405 +        if elementp(attr, k_attr_open):
  60.406 +            val = attr[1:]
  60.407 +    return val
  60.408 +
  60.409 +def attribute(sxpr, key, val=None):
  60.410 +    for x in attributes(sxpr):
  60.411 +        if x[0] == key:
  60.412 +            val = x[1]
  60.413 +            break
  60.414 +    return val
  60.415 +
  60.416 +def children(sxpr, elt=None):
  60.417 +    val = []
  60.418 +    if isinstance(sxpr, types.ListType) and len(sxpr) > 1:
  60.419 +        i = 1
  60.420 +        x = sxpr[i]
  60.421 +        if elementp(x, k_attr_open):
  60.422 +            i += 1
  60.423 +        val = sxpr[i : ]
  60.424 +    if elt:
  60.425 +        def iselt(x):
  60.426 +            return elementp(x, elt)
  60.427 +        val = filter(iselt, val)
  60.428 +    return val
  60.429 +
  60.430 +def child(sxpr, elt, val=None):
  60.431 +    for x in children(sxpr):
  60.432 +        if elementp(x, elt):
  60.433 +            val = x
  60.434 +            break
  60.435 +    return val
  60.436 +
  60.437 +def child_at(sxpr, index, val=None):
  60.438 +    kids = children(sxpr)
  60.439 +    if len(kids) > index:
  60.440 +        val = kids[index]
  60.441 +    return val
  60.442 +
  60.443 +def child0(sxpr, val=None):
  60.444 +    return child_at(sxpr, 0, val)
  60.445 +
  60.446 +def child1(sxpr, val=None):
  60.447 +    return child_at(sxpr, 1, val)
  60.448 +
  60.449 +def child2(sxpr, val=None):
  60.450 +    return child_at(sxpr, 2, val)
  60.451 +
  60.452 +def child3(sxpr, val=None):
  60.453 +    return child_at(sxpr, 3, val)
  60.454 +
  60.455 +def child4(sxpr, val=None):
  60.456 +    return child_at(sxpr, 4, val)
  60.457 +
  60.458 +def child_value(sxpr, elt, val=None):
  60.459 +    kid = child(sxpr, elt)
  60.460 +    if kid:
  60.461 +        val = child_at(kid, 0, val)
  60.462 +    return val
  60.463 +
  60.464 +def has_id(sxpr, id):
  60.465 +    """Test if an s-expression has a given id.
  60.466 +    """
  60.467 +    return attribute(sxpr, 'id') == id
  60.468 +
  60.469 +def with_id(sxpr, id, val=None):
  60.470 +    """Find the first s-expression with a given id, at any depth.
  60.471 +
  60.472 +    sxpr   s-exp or list
  60.473 +    id     id
  60.474 +    val    value if not found (default None)
  60.475 +
  60.476 +    return s-exp or val
  60.477 +    """
  60.478 +    if isinstance(sxpr, types.ListType):
  60.479 +        for n in sxpr:
  60.480 +            if has_id(n, id):
  60.481 +                val = n
  60.482 +                break
  60.483 +            v = with_id(n, id)
  60.484 +            if v is None: continue
  60.485 +            val = v
  60.486 +            break
  60.487 +    return val
  60.488 +
  60.489 +def child_with_id(sxpr, id, val=None):
  60.490 +    """Find the first child with a given id.
  60.491 +
  60.492 +    sxpr   s-exp or list
  60.493 +    id     id
  60.494 +    val    value if not found (default None)
  60.495 +
  60.496 +    return s-exp or val
  60.497 +    """
  60.498 +    if isinstance(sxpr, types.ListType):
  60.499 +        for n in sxpr:
  60.500 +            if has_id(n, id):
  60.501 +                val = n
  60.502 +                break
  60.503 +    return val
  60.504 +
  60.505 +def elements(sxpr, ctxt=None):
  60.506 +    """Generate elements (at any depth).
  60.507 +    Visit elements in pre-order.
  60.508 +    Values generated are (node, context)
  60.509 +    The context is None if there is no parent, otherwise
  60.510 +    (index, parent, context) where index is the node's index w.r.t its parent,
  60.511 +    and context is the parent's context.
  60.512 +
  60.513 +    sxpr   s-exp
  60.514 +
  60.515 +    returns generator
  60.516 +    """
  60.517 +    yield (sxpr, ctxt)
  60.518 +    i = 0
  60.519 +    for n in children(sxpr):
  60.520 +        if isinstance(n, types.ListType):
  60.521 +            # Calling elements() recursively does not generate recursively,
  60.522 +            # it just returns a generator object. So we must iterate over it.
  60.523 +            for v in elements(n, (i, sxpr, ctxt)):
  60.524 +                yield v
  60.525 +        i += 1
  60.526 +
  60.527 +def parse(io):
  60.528 +    """Completely parse all input from 'io'.
  60.529 +
  60.530 +    io	input file object
  60.531 +    returns list of values, None if incomplete
  60.532 +    raises ParseError on parse error
  60.533 +    """
  60.534 +    pin = Parser()
  60.535 +    while 1:
  60.536 +        buf = io.readline()
  60.537 +        pin.input(buf)
  60.538 +        if len(buf) == 0:
  60.539 +            break
  60.540 +    if pin.ready():
  60.541 +        val = pin.get_all()
  60.542 +    else:
  60.543 +        val = None
  60.544 +    return val
  60.545 +   
  60.546 +
  60.547 +if __name__ == '__main__':
  60.548 +    print ">main"
  60.549 +    pin = Parser()
  60.550 +    while 1:
  60.551 +        buf = sys.stdin.read(1024)
  60.552 +        #buf = sys.stdin.readline()
  60.553 +        pin.input(buf)
  60.554 +        while pin.ready():
  60.555 +            val = pin.get_val()
  60.556 +            print
  60.557 +            print '****** val=', val
  60.558 +        if len(buf) == 0:
  60.559 +            break
  60.560 +
    62.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.2 +++ b/tools/xen/lib/xm/create.py	Mon Jun 28 08:20:16 2004 +0000
    62.3 @@ -0,0 +1,366 @@
    62.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    62.5 +"""Domain creation.
    62.6 +"""
    62.7 +import string
    62.8 +import sys
    62.9 +
   62.10 +from xen.xend import sxp
   62.11 +from xen.xend import PrettyPrint
   62.12 +from xen.xend.XendClient import server
   62.13 +
   62.14 +from xen.xend.xm.opts import *
   62.15 +
   62.16 +gopts = Opts(use="""[options]
   62.17 +
   62.18 +Create a domain.
   62.19 +""")
   62.20 +
   62.21 +gopts.opt('help', short='h',
   62.22 +         fn=set_true, default=0,
   62.23 +         use="Print this help.")
   62.24 +
   62.25 +gopts.opt('quiet', short='q',
   62.26 +         fn=set_true, default=0,
   62.27 +         use="Quiet.")
   62.28 +
   62.29 +gopts.opt('path', val='PATH',
   62.30 +         fn=set_value, default='.:/etc/xen',
   62.31 +         use="Search path for default scripts.")
   62.32 +
   62.33 +gopts.opt('defaults', short='f', val='FILE',
   62.34 +         fn=set_value, default='xmdefaults',
   62.35 +         use="Use the given default script.")
   62.36 +
   62.37 +gopts.opt('config', short='F', val='FILE',
   62.38 +         fn=set_value, default=None,
   62.39 +         use='Domain configuration to use (SXP).')
   62.40 +
   62.41 +gopts.opt('load', short='L', val='FILE',
   62.42 +          fn=set_value, default=None,
   62.43 +          use='Domain saved state to load.')
   62.44 +
   62.45 +gopts.opt('define', short='D', val='VAR=VAL',
   62.46 +         fn=set_var, default=None,
   62.47 +         use="""Set a variable before loading defaults, e.g. '-D vmid=3'
   62.48 +         to set vmid. May be repeated to set more thanone variable.""")
   62.49 +
   62.50 +gopts.opt('dryrun', short='n',
   62.51 +         fn=set_true, default=0,
   62.52 +         use="Dry run - print the config but don't create the domain.")
   62.53 +
   62.54 +gopts.opt('name', short='N', val='NAME',
   62.55 +          fn=set_value, default=None,
   62.56 +          use="Domain name.")
   62.57 +
   62.58 +gopts.opt('console', short='c',
   62.59 +         fn=set_true, default=0,
   62.60 +         use="Connect to console after domain is created.")
   62.61 +
   62.62 +gopts.opt('kernel', short='k', val='FILE',
   62.63 +         fn=set_value, default=None,
   62.64 +         use="Path to kernel image.")
   62.65 +
   62.66 +gopts.opt('ramdisk', short='r', val='FILE',
   62.67 +         fn=set_value, default='',
   62.68 +         use="Path to ramdisk.")
   62.69 +
   62.70 +gopts.opt('builder', short='b', val='FUNCTION',
   62.71 +         fn=set_value, default='linux',
   62.72 +         use="Function to use to build the domain.")
   62.73 +
   62.74 +gopts.opt('memory', short='m', val='MEMORY',
   62.75 +         fn=set_value, default=128,
   62.76 +         use="Domain memory in MB.")
   62.77 +
   62.78 +gopts.opt('blkif',
   62.79 +          fn=set_true, default=0,
   62.80 +          use="Make the domain a block device backend.")
   62.81 +
   62.82 +gopts.opt('netif',
   62.83 +          fn=set_true, default=0,
   62.84 +          use="Make the domain a network interface backend.")
   62.85 +
   62.86 +gopts.opt('disk', short='d', val='phy:DEV,VDEV,MODE',
   62.87 +         fn=append_value, default=[],
   62.88 +         use="""Add a disk device to a domain. The physical device is DEV, which
   62.89 +         is exported to the domain as VDEV. The disk is read-only if MODE
   62.90 +         is 'r', read-write if MODE is 'w'.
   62.91 +         The option may be repeated to add more than one disk.
   62.92 +         """)
   62.93 +
   62.94 +gopts.opt('pci', val='BUS,DEV,FUNC',
   62.95 +         fn=append_value, default=[],
   62.96 +         use="""Add a PCI device to a domain, using given params (in hex).
   62.97 +         For example '-pci c0,02,1a'.
   62.98 +         The option may be repeated to add more than one pci device.
   62.99 +         """)
  62.100 +
  62.101 +gopts.opt('ipaddr', short='i', val="IPADDR",
  62.102 +         fn=append_value, default=[],
  62.103 +         use="Add an IP address to the domain.")
  62.104 +
  62.105 +gopts.opt('vif', val="mac=MAC,bridge=BRIDGE",
  62.106 +         fn=append_value, default=[],
  62.107 +         use="""Add a network interface with the given MAC address and bridge.
  62.108 +         If mac is not specified a random MAC address is used.
  62.109 +         If bridge is not specified the default bridge is used.
  62.110 +         This option may be repeated to add more than one vif.
  62.111 +         Specifying vifs will increase the number of interfaces as needed.
  62.112 +         """)
  62.113 +
  62.114 +gopts.opt('nics', val="NUM",
  62.115 +         fn=set_int, default=1,
  62.116 +         use="""Set the number of network interfaces.
  62.117 +         Use the vif option to define interface parameters, otherwise
  62.118 +         defaults are used. Specifying vifs will increase the
  62.119 +         number of interfaces as needed.
  62.120 +         """)
  62.121 +
  62.122 +gopts.opt('root', short='R', val='DEVICE',
  62.123 +         fn=set_value, default='',
  62.124 +         use="""Set the root= parameter on the kernel command line.
  62.125 +         Use a device, e.g. /dev/sda1, or /dev/nfs for NFS root.""")
  62.126 +
  62.127 +gopts.opt('extra', short='E', val="ARGS",
  62.128 +         fn=set_value, default='',
  62.129 +         use="Set extra arguments to append to the kernel command line.")
  62.130 +
  62.131 +gopts.opt('ip', short='I', val='IPADDR',
  62.132 +         fn=set_value, default='',
  62.133 +         use="Set the kernel IP interface address.")
  62.134 +
  62.135 +gopts.opt('gateway', val="IPADDR",
  62.136 +         fn=set_value, default='',
  62.137 +         use="Set the kernel IP gateway.")
  62.138 +
  62.139 +gopts.opt('netmask', val="MASK",
  62.140 +         fn=set_value, default = '',
  62.141 +         use="Set the kernel IP netmask.")
  62.142 +
  62.143 +gopts.opt('hostname', val="NAME",
  62.144 +         fn=set_value, default='',
  62.145 +         use="Set the kernel IP hostname.")
  62.146 +
  62.147 +gopts.opt('interface', val="INTF",
  62.148 +         fn=set_value, default="eth0",
  62.149 +         use="Set the kernel IP interface name.")
  62.150 +
  62.151 +gopts.opt('dhcp', val="off|dhcp",
  62.152 +         fn=set_value, default='off',
  62.153 +         use="Set the kernel dhcp option.")
  62.154 +
  62.155 +gopts.opt('nfs_server', val="IPADDR",
  62.156 +         fn=set_value, default=None,
  62.157 +         use="Set the address of the NFS server for NFS root.")
  62.158 +
  62.159 +gopts.opt('nfs_root', val="PATH",
  62.160 +         fn=set_value, default=None,
  62.161 +         use="Set the path of the root NFS directory.")
  62.162 +
  62.163 +def strip(pre, s):
  62.164 +    """Strip prefix 'pre' if present.
  62.165 +    """
  62.166 +    if s.startswith(pre):
  62.167 +        return s[len(pre):]
  62.168 +    else:
  62.169 +        return s
  62.170 +
  62.171 +def configure_image(config, opts):
  62.172 +    """Create the image config.
  62.173 +    """
  62.174 +    config_image = [ opts.builder ]
  62.175 +    config_image.append([ 'kernel', os.path.abspath(opts.kernel) ])
  62.176 +    if opts.ramdisk:
  62.177 +        config_image.append([ 'ramdisk', os.path.abspath(opts.ramdisk) ])
  62.178 +    if opts.cmdline_ip:
  62.179 +        cmdline_ip = strip('ip=', opts.cmdline_ip)
  62.180 +        config_image.append(['ip', cmdline_ip])
  62.181 +    if opts.root:
  62.182 +        cmdline_root = strip('root=', opts.root)
  62.183 +        config_image.append(['root', cmdline_root])
  62.184 +    if opts.extra:
  62.185 +        config_image.append(['args', opts.extra])
  62.186 +    config.append(['image', config_image ])
  62.187 +    
  62.188 +def configure_disks(config_devs, opts):
  62.189 +    """Create the config for disks (virtual block devices).
  62.190 +    """
  62.191 +    for (uname, dev, mode) in opts.disk:
  62.192 +        config_vbd = ['vbd',
  62.193 +                      ['uname', uname],
  62.194 +                      ['dev', dev ],
  62.195 +                      ['mode', mode ] ]
  62.196 +        config_devs.append(['device', config_vbd])
  62.197 +
  62.198 +def configure_pci(config_devs, opts):
  62.199 +    """Create the config for pci devices.
  62.200 +    """
  62.201 +    for (bus, dev, func) in opts.pci:
  62.202 +        config_pci = ['pci', ['bus', bus], ['dev', dev], ['func', func]]
  62.203 +        config_devs.append(['device', config_pci])
  62.204 +
  62.205 +def configure_vifs(config_devs, opts):
  62.206 +    """Create the config for virtual network interfaces.
  62.207 +    """
  62.208 +    vifs = opts.vif
  62.209 +    vifs_n = max(opts.nics, len(vifs))
  62.210 +
  62.211 +    for idx in range(0, vifs_n):
  62.212 +        if idx < len(vifs):
  62.213 +            d = vifs[idx]
  62.214 +            mac = d.get('mac')
  62.215 +            bridge = d.get('bridge')
  62.216 +        else:
  62.217 +            mac = None
  62.218 +            bridge = None
  62.219 +        config_vif = ['vif']
  62.220 +        if mac:
  62.221 +            config_vif.append(['mac', mac])
  62.222 +        if bridge:
  62.223 +            config_vif.append(['bridge', bridge])
  62.224 +        config_devs.append(['device', config_vif])
  62.225 +
  62.226 +def configure_vfr(config, opts):
  62.227 +     if not opts.ipaddr: return
  62.228 +     config_vfr = ['vfr']
  62.229 +     idx = 0 # No way of saying which IP is for which vif?
  62.230 +     for ip in opts.ipaddr:
  62.231 +         config_vfr.append(['vif', ['id', idx], ['ip', ip]])
  62.232 +     config.append(config_vfr)
  62.233 +
  62.234 +
  62.235 +def make_config(opts):
  62.236 +    """Create the domain configuration.
  62.237 +    """
  62.238 +    
  62.239 +    config = ['vm',
  62.240 +              ['name', opts.name ],
  62.241 +              ['memory', opts.memory ] ]
  62.242 +    if opts.cpu:
  62.243 +        config.append(['cpu', opts.cpu])
  62.244 +    if opts.blkif:
  62.245 +        config.append(['backend', ['blkif']])
  62.246 +    if opts.netif:
  62.247 +        config.append(['backend', ['netif']])
  62.248 +    
  62.249 +    configure_image(config, opts)
  62.250 +    config_devs = []
  62.251 +    configure_disks(config_devs, opts)
  62.252 +    configure_pci(config_devs, opts)
  62.253 +    configure_vifs(config_devs, opts)
  62.254 +    config += config_devs
  62.255 +    return config
  62.256 +
  62.257 +def preprocess_disk(opts):
  62.258 +    if not opts.disk: return
  62.259 +    disk = []
  62.260 +    for v in opts.disk:
  62.261 +        d = v.split(',')
  62.262 +        if len(d) != 3:
  62.263 +            opts.err('Invalid disk specifier: ' + v)
  62.264 +        disk.append(d)
  62.265 +    opts.disk = disk
  62.266 +
  62.267 +def preprocess_pci(opts):
  62.268 +    if not opts.pci: return
  62.269 +    pci = []
  62.270 +    for v in opts.pci:
  62.271 +        d = v.split(',')
  62.272 +        if len(d) != 3:
  62.273 +            opts.err('Invalid pci specifier: ' + v)
  62.274 +        # Components are in hex: add hex specifier.
  62.275 +        hexd = map(lambda v: '0x'+v, d)
  62.276 +        pci.append(hexd)
  62.277 +    opts.pci = pci
  62.278 +
  62.279 +def preprocess_vifs(opts):
  62.280 +    if not opts.vif: return
  62.281 +    vifs = []
  62.282 +    for vif in opts.vif:
  62.283 +        d = {}
  62.284 +        a = vif.split(',')
  62.285 +        for b in a:
  62.286 +            (k, v) = b.strip().split('=')
  62.287 +            k = k.strip()
  62.288 +            v = v.strip()
  62.289 +            if k not in ['mac', 'bridge']:
  62.290 +                opts.err('Invalid vif specifier: ' + vif)
  62.291 +            d[k] = v
  62.292 +        vifs.append(d)
  62.293 +    opts.vif = vifs
  62.294 +
  62.295 +def preprocess_ip(opts):
  62.296 +    setip = (opts.hostname or opts.netmask
  62.297 +             or opts.gateway or opts.dhcp or opts.interface)
  62.298 +    if not setip: return
  62.299 +    #if not opts
  62.300 +    ip = (opts.ip
  62.301 +          + ':'
  62.302 +          + ':' + opts.gateway
  62.303 +          + ':' + opts.netmask
  62.304 +          + ':' + opts.hostname
  62.305 +          + ':' + opts.interface
  62.306 +          + ':' + opts.dhcp)
  62.307 +    opts.cmdline_ip = ip
  62.308 +
  62.309 +def preprocess_nfs(opts):
  62.310 +    if (opts.nfs_root or opts.nfs_server):
  62.311 +        if (not opts.nfs_root) or (not opts.nfs_server):
  62.312 +            opts.err('Must set nfs root and nfs server')
  62.313 +    else:
  62.314 +        return
  62.315 +    nfs = 'nfsroot=' + opts.nfs_server + ':' + opts.nfs_root
  62.316 +    opts.extra = nfs + ' ' + opts.extra
  62.317 +    
  62.318 +def preprocess(opts):
  62.319 +    if not opts.kernel:
  62.320 +        opts.err("No kernel specified")
  62.321 +    preprocess_disk(opts)
  62.322 +    preprocess_pci(opts)
  62.323 +    preprocess_vifs(opts)
  62.324 +    preprocess_ip(opts)
  62.325 +    preprocess_nfs(opts)
  62.326 +         
  62.327 +def make_domain(opts, config):
  62.328 +    """Create, build and start a domain.
  62.329 +    Returns: [int] the ID of the new domain.
  62.330 +    """
  62.331 +    if opts.vals.load:
  62.332 +        filename = os.path.abspath(opts.vals.load)
  62.333 +        dominfo = server.xend_domain_restore(filename, config)
  62.334 +    else:
  62.335 +        dominfo = server.xend_domain_create(config)
  62.336 +
  62.337 +    dom = int(sxp.child_value(dominfo, 'id'))
  62.338 +    console_info = sxp.child(dominfo, 'console')
  62.339 +    if console_info:
  62.340 +        console_port = int(sxp.child_value(console_info, 'port'))
  62.341 +    else:
  62.342 +        console_port = None
  62.343 +    
  62.344 +    if server.xend_domain_unpause(dom) < 0:
  62.345 +        server.xend_domain_destroy(dom)
  62.346 +        opts.err("Failed to start domain %d" % dom)
  62.347 +    opts.info("Started domain %d, console on port %d"
  62.348 +              % (dom, console_port))
  62.349 +    return (dom, console_port)
  62.350 +
  62.351 +def main(argv):
  62.352 +    opts = gopts
  62.353 +    args = opts.parse(argv)
  62.354 +    if opts.vals.help:
  62.355 +        opts.usage()
  62.356 +        return
  62.357 +    if opts.vals.config:
  62.358 +        pass
  62.359 +    else:
  62.360 +        opts.load_defaults()
  62.361 +    preprocess(opts.vals)
  62.362 +    config = make_config(opts.vals)
  62.363 +    if opts.vals.dryrun:
  62.364 +        PrettyPrint.prettyprint(config)
  62.365 +    else:
  62.366 +        make_domain(opts, config)
  62.367 +        
  62.368 +if __name__ == '__main__':
  62.369 +    main(sys.argv)
    63.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.2 +++ b/tools/xen/lib/xm/main.py	Mon Jun 28 08:20:16 2004 +0000
    63.3 @@ -0,0 +1,448 @@
    63.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    63.5 +"""Grand unified management application for Xen.
    63.6 +"""
    63.7 +import os
    63.8 +import os.path
    63.9 +import sys
   63.10 +from getopt import getopt
   63.11 +
   63.12 +from xen.xend import PrettyPrint
   63.13 +from xen.xend import sxp
   63.14 +from xen.xend.XendClient import server
   63.15 +from xen.xend.xm import create, shutdown
   63.16 +
   63.17 +class Prog:
   63.18 +    """Base class for sub-programs.
   63.19 +    """
   63.20 +
   63.21 +    """Program group it belongs to"""
   63.22 +    group = 'all'
   63.23 +    """Program name."""
   63.24 +    name = '??'
   63.25 +    """Short program info."""
   63.26 +    info = ''
   63.27 +
   63.28 +    def __init__(self, xm):
   63.29 +        self.xm = xm
   63.30 +
   63.31 +    def err(self, msg):
   63.32 +        self.xm.err(msg)
   63.33 +
   63.34 +    def help(self, args):
   63.35 +        self.shortHelp(args)
   63.36 +
   63.37 +    def shortHelp(self, args):
   63.38 +        print "%-14s %s" % (self.name, self.info)
   63.39 +
   63.40 +    def main(self, args):
   63.41 +        """Program main entry point.
   63.42 +        """
   63.43 +        pass
   63.44 +
   63.45 +
   63.46 +class ProgUnknown(Prog):
   63.47 +
   63.48 +    name = 'unknown'
   63.49 +    info = ''
   63.50 +    
   63.51 +    def help(self, args):
   63.52 +        self.xm.err("Unknown command: %s\nTry '%s help' for more information."
   63.53 +                    % (args[0], self.xm.name))
   63.54 +
   63.55 +    main = help
   63.56 +
   63.57 +class Xm:
   63.58 +    """Main application.
   63.59 +    """
   63.60 +
   63.61 +    def __init__(self):
   63.62 +        self.name = 'xm'
   63.63 +        self.unknown = ProgUnknown(self)
   63.64 +        self.progs = {}
   63.65 +
   63.66 +    def err(self, msg):
   63.67 +        print >>sys.stderr, "Error:", msg
   63.68 +        sys.exit(1)
   63.69 +
   63.70 +    def main(self, args):
   63.71 +        """Main entry point. Dispatches to the progs.
   63.72 +        """
   63.73 +        self.name = args[0]
   63.74 +        if len(args) < 2:
   63.75 +            self.err("Missing command\nTry '%s help' for more information."
   63.76 +                     % self.name)
   63.77 +        help = self.helparg(args)
   63.78 +        p = self.getprog(args[1], self.unknown)
   63.79 +        if help:
   63.80 +            p.help(args[1:])
   63.81 +        else:
   63.82 +            p.main(args[1:])
   63.83 +
   63.84 +    def helparg(self, args):
   63.85 +        for a in args:
   63.86 +            if a in ['-h', '--help']:
   63.87 +                return 1
   63.88 +        return 0
   63.89 +
   63.90 +    def prog(self, pklass):
   63.91 +        """Add a sub-program.
   63.92 +
   63.93 +        pklass  program class (Prog subclass)
   63.94 +        """
   63.95 +        p = pklass(self)
   63.96 +        self.progs[p.name] = p
   63.97 +        return p
   63.98 +
   63.99 +    def getprog(self, name, val=None):
  63.100 +        """Get a sub-program.
  63.101 +        """
  63.102 +        return self.progs.get(name, val)
  63.103 +
  63.104 +    def proglist(self):
  63.105 +        """Get a list of sub-programs, ordered by group.
  63.106 +        """
  63.107 +        groups = {}
  63.108 +        for p in self.progs.values():
  63.109 +            l = groups.get(p.group, [])
  63.110 +            l.append(p)
  63.111 +            groups[p.group] = l
  63.112 +        kl = groups.keys()
  63.113 +        kl.sort()
  63.114 +        pl = []
  63.115 +        for k in kl:
  63.116 +            l = groups[k]