ia64/xen-unstable

changeset 1585:cb0967db88bc

bitkeeper revision 1.1010.1.9 (40dc4078vvvprFxMFMTOULzuaeEQoQ)

Renaming 'xenmgr' to 'xen.xend'.
author mjw@wray-m-3.hpl.hp.com
date Fri Jun 25 15:10:48 2004 +0000 (2004-06-25)
parents 07af9a3715e2
children c8e677f40f9d
files .rootkeys extras/mini-os/h/hypervisor.h linux-2.4.26-xen-sparse/mkbuildtree tools/Makefile 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/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/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/lib/__init__.py tools/xu/lib/domain_controller.h tools/xu/lib/xu.c tools/xu/setup.py
line diff
     1.1 --- a/.rootkeys	Fri Jun 25 13:44:22 2004 +0000
     1.2 +++ b/.rootkeys	Fri Jun 25 15:10:48 2004 +0000
     1.3 @@ -198,6 +198,58 @@ 40589968UQFnJeOMn8UIFLbXBuwXjw tools/xc/
     1.4  3fbd0a3dTwnDcfdw0-v46dPbX98zDw tools/xc/py/Makefile
     1.5  3fbd0a42l40lM0IICw2jXbQBVZSdZg tools/xc/py/Xc.c
     1.6  3fbd0a40yT6G3M9hMpaz5xTUdl0E4g tools/xc/py/setup.py
     1.7 +40c9c468icGyC5RAF1bRKsCXPDCvsA tools/xen/Makefile
     1.8 +40dc4076hGpwa8-sWRN0jtXZeQJuKg tools/xen/lib/__init__.py
     1.9 +40c9c468SNuObE_YWARyS0hzTPSzKg tools/xen/lib/xend/Args.py
    1.10 +40c9c468Um_qc66OQeLEceIz1pgD5g tools/xen/lib/xend/EventServer.py
    1.11 +40c9c468U8EVl0d3G--8YXVg6VJD3g tools/xen/lib/xend/EventTypes.py
    1.12 +40c9c468QJTEuk9g4qHxGpmIi70PEQ tools/xen/lib/xend/PrettyPrint.py
    1.13 +40d8915cyoVA0hJxiBFNymL7YvDaRg tools/xen/lib/xend/XendBridge.py
    1.14 +40c9c4688m3eqnC8fhLu1APm36VOVA tools/xen/lib/xend/XendClient.py
    1.15 +40c9c468t6iIKTjwuYoe-UMCikDcOQ tools/xen/lib/xend/XendConsole.py
    1.16 +40c9c468WnXs6eOUSff23IIGI4kMfQ tools/xen/lib/xend/XendDB.py
    1.17 +40c9c468fSl3H3IypyT0ppkbb0ZT9A tools/xen/lib/xend/XendDomain.py
    1.18 +40c9c468bbKq3uC7_fuNUkiMMjArdw tools/xen/lib/xend/XendDomainConfig.py
    1.19 +40c9c4685ykq87_n1kVUbMr9flx9fg tools/xen/lib/xend/XendDomainInfo.py
    1.20 +40c9c46854nsHmuxHQHncKk5rAs5NA tools/xen/lib/xend/XendMigrate.py
    1.21 +40c9c468M96gA1EYDvNa5w5kQNYLFA tools/xen/lib/xend/XendNode.py
    1.22 +40c9c4686jruMyZIqiaZRMiMoqMJtg tools/xen/lib/xend/XendRoot.py
    1.23 +40c9c468xzANp6o2D_MeCYwNmOIUsQ tools/xen/lib/xend/XendVnet.py
    1.24 +40c9c468x191zetrVlMnExfsQWHxIQ tools/xen/lib/xend/__init__.py
    1.25 +40c9c468S2YnCEKmk4ey8XQIST7INg tools/xen/lib/xend/encode.py
    1.26 +40c9c468DCpMe542varOolW1Xc68ew tools/xen/lib/xend/server/SrvBase.py
    1.27 +40c9c468IxQabrKJSWs0aEjl-27mRQ tools/xen/lib/xend/server/SrvConsole.py
    1.28 +40c9c4689Io5bxfbYIfRiUvsiLX0EQ tools/xen/lib/xend/server/SrvConsoleDir.py
    1.29 +40c9c468woSmBByfeXA4o_jGf2gCgA tools/xen/lib/xend/server/SrvDaemon.py
    1.30 +40c9c468kACsmkqjxBWKHRo071L26w tools/xen/lib/xend/server/SrvDeviceDir.py
    1.31 +40c9c468EQZJVkCLds-OhesJVVyZbQ tools/xen/lib/xend/server/SrvDir.py
    1.32 +40c9c468TyHZUq8sk0FF_vxM6Sozrg tools/xen/lib/xend/server/SrvDomain.py
    1.33 +40c9c469WzajDjutou3X7FmL9hMf3g tools/xen/lib/xend/server/SrvDomainDir.py
    1.34 +40c9c469-8mYEJJTAR6w_ClrJRAfwQ tools/xen/lib/xend/server/SrvEventDir.py
    1.35 +40c9c4694eu5759Dehr4Uhakei0EMg tools/xen/lib/xend/server/SrvNode.py
    1.36 +40c9c469TaZ83ypsrktmPSHLEZiP5w tools/xen/lib/xend/server/SrvRoot.py
    1.37 +40c9c469W3sgDMbBJYQdz5wbQweL0Q tools/xen/lib/xend/server/SrvServer.py
    1.38 +40c9c469aq7oXrE1Ngqf3_lBqL0RoQ tools/xen/lib/xend/server/SrvVnetDir.py
    1.39 +40c9c469Y_aimoOFfUZoS-4eV8gEKg tools/xen/lib/xend/server/__init__.py
    1.40 +40c9c4692hckPol_EK0EGB16ZyDsyQ tools/xen/lib/xend/server/blkif.py
    1.41 +40c9c469N2-b3GqpLHHHPZykJPLVvA tools/xen/lib/xend/server/channel.py
    1.42 +40c9c469hJ_IlatRne-9QEa0-wlquw tools/xen/lib/xend/server/console.py
    1.43 +40c9c469UcNJh_NuLU0ytorM0Lk5Ow tools/xen/lib/xend/server/controller.py
    1.44 +40c9c469vHh-qLiiubdbKEQbJf18Zw tools/xen/lib/xend/server/cstruct.py
    1.45 +40d83983OXjt-y3HjSCcuoPp9rzvmw tools/xen/lib/xend/server/domain.py
    1.46 +40c9c469yrm31i60pGKslTi2Zgpotg tools/xen/lib/xend/server/messages.py
    1.47 +40c9c46925x-Rjb0Cv2f1-l2jZrPYg tools/xen/lib/xend/server/netif.py
    1.48 +40c9c469ZqILEQ8x6yWy0_51jopiCg tools/xen/lib/xend/server/params.py
    1.49 +40c9c469LNxLVizOUpOjEaTKKCm8Aw tools/xen/lib/xend/sxp.py
    1.50 +40d05079aFRp6NQdo5wIh5Ly31c0cg tools/xen/lib/xm/__init__.py
    1.51 +40cf2937gKQcATgXKGtNeWb1PDH5nA tools/xen/lib/xm/create.py
    1.52 +40cf2937isyS250zyd0Q2GuEDoNXfQ tools/xen/lib/xm/main.py
    1.53 +40cf2937PSslwBliN1g7ofDy2H_RhA tools/xen/lib/xm/opts.py
    1.54 +40cf2937Z8WCNOnO2FcWdubvEAF9QQ tools/xen/lib/xm/shutdown.py
    1.55 +40c9c469kT0H9COWzA4XzPBjWK0WsA tools/xen/netfix
    1.56 +40c9c469n2RRwCmjWdjdyyVRWKmgWg tools/xen/setup.py
    1.57 +40c9c4697z76HDfkCLdMhmaEwzFoNQ tools/xen/xend
    1.58 +40cf2937dqM1jWW87O5OoOYND8leuA tools/xen/xm
    1.59  4055ee41IfFazrwadCH2J72nz-A9YA tools/xenctl/Makefile
    1.60  4055ee4b_4Rvns_KzE12csI14EKK6Q tools/xenctl/lib/__init__.py
    1.61  4055ee4dwy4l0MghZosxoiu6zmhc9Q tools/xenctl/lib/console_client.py
    1.62 @@ -205,75 +257,27 @@ 40c9c468IienauFHQ_xJIcqnPJ8giQ tools/xen
    1.63  4059c6a0pnxhG8hwSOivXybbGOwuXw tools/xenctl/lib/tempfile.py
    1.64  3fbd4bd6GtGwZGxYUJPOheYIR7bPaA tools/xenctl/lib/utils.py
    1.65  4055ee44Bu6oP7U0WxxXypbUt4dNPQ tools/xenctl/setup.py
    1.66 -40431ac64Hj4ixUnKmlugZKhXPFE_Q tools/xend/Makefile
    1.67 -4055ad95Se-FqttgxollqOAAHB94zA tools/xend/lib/__init__.py
    1.68 -4092738fMRGC9fFBcPRCWaJaj9U3ag tools/xend/lib/blkif.py
    1.69 -4055ad97wMLUj0BZT0e_T0EwQN0Bvw tools/xend/lib/console.py
    1.70 -4048c0ddsF0WrU7HUzTvg1MJoCIfWg tools/xend/lib/domain_controller.h
    1.71 -4054a301VEag2GwrBrFBna5U1BGlLA tools/xend/lib/main.py
    1.72 -4055ad9ah9IuC3sJT2c_gYIFY5Tw_g tools/xend/lib/manager.py
    1.73 -409ba2e729HhE7fEra4B5EqX-F8Xzw tools/xend/lib/netif.py
    1.74 -40431ac8wrUEj-XM7B8smFtx_HA7lQ tools/xend/lib/utils.c
    1.75 -4054a2fdkdATEnRw-U7AUlgu-6JiUA tools/xend/setup.py
    1.76 -4056cd26Qyp09iNoOjrvzg8KYzSqOw tools/xend/xend
    1.77 -40c9c468icGyC5RAF1bRKsCXPDCvsA tools/xenmgr/Makefile
    1.78 -40c9c468SNuObE_YWARyS0hzTPSzKg tools/xenmgr/lib/Args.py
    1.79 -40c9c468Um_qc66OQeLEceIz1pgD5g tools/xenmgr/lib/EventServer.py
    1.80 -40c9c468U8EVl0d3G--8YXVg6VJD3g tools/xenmgr/lib/EventTypes.py
    1.81 -40c9c468QJTEuk9g4qHxGpmIi70PEQ tools/xenmgr/lib/PrettyPrint.py
    1.82 -40d8915cyoVA0hJxiBFNymL7YvDaRg tools/xenmgr/lib/XendBridge.py
    1.83 -40c9c4688m3eqnC8fhLu1APm36VOVA tools/xenmgr/lib/XendClient.py
    1.84 -40c9c468t6iIKTjwuYoe-UMCikDcOQ tools/xenmgr/lib/XendConsole.py
    1.85 -40c9c468WnXs6eOUSff23IIGI4kMfQ tools/xenmgr/lib/XendDB.py
    1.86 -40c9c468fSl3H3IypyT0ppkbb0ZT9A tools/xenmgr/lib/XendDomain.py
    1.87 -40c9c468bbKq3uC7_fuNUkiMMjArdw tools/xenmgr/lib/XendDomainConfig.py
    1.88 -40c9c4685ykq87_n1kVUbMr9flx9fg tools/xenmgr/lib/XendDomainInfo.py
    1.89 -40c9c46854nsHmuxHQHncKk5rAs5NA tools/xenmgr/lib/XendMigrate.py
    1.90 -40c9c468M96gA1EYDvNa5w5kQNYLFA tools/xenmgr/lib/XendNode.py
    1.91 -40c9c4686jruMyZIqiaZRMiMoqMJtg tools/xenmgr/lib/XendRoot.py
    1.92 -40c9c468xzANp6o2D_MeCYwNmOIUsQ tools/xenmgr/lib/XendVnet.py
    1.93 -40c9c468x191zetrVlMnExfsQWHxIQ tools/xenmgr/lib/__init__.py
    1.94 -40c9c468S2YnCEKmk4ey8XQIST7INg tools/xenmgr/lib/encode.py
    1.95 -40c9c468DCpMe542varOolW1Xc68ew tools/xenmgr/lib/server/SrvBase.py
    1.96 -40c9c468IxQabrKJSWs0aEjl-27mRQ tools/xenmgr/lib/server/SrvConsole.py
    1.97 -40c9c4689Io5bxfbYIfRiUvsiLX0EQ tools/xenmgr/lib/server/SrvConsoleDir.py
    1.98 -40c9c468woSmBByfeXA4o_jGf2gCgA tools/xenmgr/lib/server/SrvConsoleServer.py
    1.99 -40c9c468kACsmkqjxBWKHRo071L26w tools/xenmgr/lib/server/SrvDeviceDir.py
   1.100 -40c9c468EQZJVkCLds-OhesJVVyZbQ tools/xenmgr/lib/server/SrvDir.py
   1.101 -40c9c468TyHZUq8sk0FF_vxM6Sozrg tools/xenmgr/lib/server/SrvDomain.py
   1.102 -40c9c469WzajDjutou3X7FmL9hMf3g tools/xenmgr/lib/server/SrvDomainDir.py
   1.103 -40c9c469-8mYEJJTAR6w_ClrJRAfwQ tools/xenmgr/lib/server/SrvEventDir.py
   1.104 -40c9c4694eu5759Dehr4Uhakei0EMg tools/xenmgr/lib/server/SrvNode.py
   1.105 -40c9c469TaZ83ypsrktmPSHLEZiP5w tools/xenmgr/lib/server/SrvRoot.py
   1.106 -40c9c469W3sgDMbBJYQdz5wbQweL0Q tools/xenmgr/lib/server/SrvServer.py
   1.107 -40c9c469aq7oXrE1Ngqf3_lBqL0RoQ tools/xenmgr/lib/server/SrvVnetDir.py
   1.108 -40c9c469Y_aimoOFfUZoS-4eV8gEKg tools/xenmgr/lib/server/__init__.py
   1.109 -40c9c4692hckPol_EK0EGB16ZyDsyQ tools/xenmgr/lib/server/blkif.py
   1.110 -40c9c469N2-b3GqpLHHHPZykJPLVvA tools/xenmgr/lib/server/channel.py
   1.111 -40c9c469hJ_IlatRne-9QEa0-wlquw tools/xenmgr/lib/server/console.py
   1.112 -40c9c469UcNJh_NuLU0ytorM0Lk5Ow tools/xenmgr/lib/server/controller.py
   1.113 -40c9c469vHh-qLiiubdbKEQbJf18Zw tools/xenmgr/lib/server/cstruct.py
   1.114 -40d83983OXjt-y3HjSCcuoPp9rzvmw tools/xenmgr/lib/server/domain.py
   1.115 -40c9c469yrm31i60pGKslTi2Zgpotg tools/xenmgr/lib/server/messages.py
   1.116 -40c9c46925x-Rjb0Cv2f1-l2jZrPYg tools/xenmgr/lib/server/netif.py
   1.117 -40c9c469ZqILEQ8x6yWy0_51jopiCg tools/xenmgr/lib/server/params.py
   1.118 -40c9c469LNxLVizOUpOjEaTKKCm8Aw tools/xenmgr/lib/sxp.py
   1.119 -40d05079aFRp6NQdo5wIh5Ly31c0cg tools/xenmgr/lib/xm/__init__.py
   1.120 -40cf2937gKQcATgXKGtNeWb1PDH5nA tools/xenmgr/lib/xm/create.py
   1.121 -40cf2937isyS250zyd0Q2GuEDoNXfQ tools/xenmgr/lib/xm/main.py
   1.122 -40cf2937PSslwBliN1g7ofDy2H_RhA tools/xenmgr/lib/xm/opts.py
   1.123 -40cf2937Z8WCNOnO2FcWdubvEAF9QQ tools/xenmgr/lib/xm/shutdown.py
   1.124 -40c9c469kT0H9COWzA4XzPBjWK0WsA tools/xenmgr/netfix
   1.125 -40c9c469n2RRwCmjWdjdyyVRWKmgWg tools/xenmgr/setup.py
   1.126 -40c9c4697z76HDfkCLdMhmaEwzFoNQ tools/xenmgr/xend
   1.127 -40c9c469JkN47d1oXi-e0RjAP-C6uQ tools/xenmgr/xenmgrd
   1.128 -40cf2937dqM1jWW87O5OoOYND8leuA tools/xenmgr/xm
   1.129 +40431ac64Hj4ixUnKmlugZKhXPFE_Q tools/xend-old/Makefile
   1.130 +4055ad95Se-FqttgxollqOAAHB94zA tools/xend-old/lib/__init__.py
   1.131 +4092738fMRGC9fFBcPRCWaJaj9U3ag tools/xend-old/lib/blkif.py
   1.132 +4055ad97wMLUj0BZT0e_T0EwQN0Bvw tools/xend-old/lib/console.py
   1.133 +4048c0ddsF0WrU7HUzTvg1MJoCIfWg tools/xend-old/lib/domain_controller.h
   1.134 +4054a301VEag2GwrBrFBna5U1BGlLA tools/xend-old/lib/main.py
   1.135 +4055ad9ah9IuC3sJT2c_gYIFY5Tw_g tools/xend-old/lib/manager.py
   1.136 +409ba2e729HhE7fEra4B5EqX-F8Xzw tools/xend-old/lib/netif.py
   1.137 +40431ac8wrUEj-XM7B8smFtx_HA7lQ tools/xend-old/lib/utils.c
   1.138 +4054a2fdkdATEnRw-U7AUlgu-6JiUA tools/xend-old/setup.py
   1.139 +4056cd26Qyp09iNoOjrvzg8KYzSqOw tools/xend-old/xend
   1.140  403a3edbrr8RE34gkbR40zep98SXbg tools/xentrace/Makefile
   1.141  40a107afN60pFdURgBv9KwEzgRl5mQ tools/xentrace/formats
   1.142  4050c413PhhLNAYk3TEwP37i_iLw9Q tools/xentrace/xentrace.8
   1.143  403a3edbVpV2E_wq1zeEkJ_n4Uu2eg tools/xentrace/xentrace.c
   1.144  403a3edblCUrzSj0mmKhO5HOPrOrSQ tools/xentrace/xentrace_format
   1.145  4050c413NtuyIq5lsYJV4P7KIjujXw tools/xentrace/xentrace_format.1
   1.146 +40dc4076St6AmPTmQPrtQ6LGHPxGmw tools/xu/lib/__init__.py
   1.147 +40dc4076pVeE1kEEWzcUaNZin65kCA tools/xu/lib/domain_controller.h
   1.148 +40dc4076CwBYRTUQDdbdU1L6KcLgSw tools/xu/lib/xu.c
   1.149 +40dc4076FyWUYS2nX9YufgglUzKX2A tools/xu/setup.py
   1.150  3f72f1bdJPsV3JCnBqs9ddL9tr6D2g xen/COPYING
   1.151  3ddb79bcbOVHh38VJzc97-JEGD4dJQ xen/Makefile
   1.152  3ddb79bcWnTwYsQRWl_PaneJfa6p0w xen/Rules.mk
     2.1 --- a/extras/mini-os/h/hypervisor.h	Fri Jun 25 13:44:22 2004 +0000
     2.2 +++ b/extras/mini-os/h/hypervisor.h	Fri Jun 25 15:10:48 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	Fri Jun 25 13:44:22 2004 +0000
     3.2 +++ b/linux-2.4.26-xen-sparse/mkbuildtree	Fri Jun 25 15:10:48 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	Fri Jun 25 13:44:22 2004 +0000
     4.2 +++ b/tools/Makefile	Fri Jun 25 15:10:48 2004 +0000
     4.3 @@ -1,21 +1,22 @@
     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 xenctl install
    4.21  	$(MAKE) -C examples install
    4.22  	$(MAKE) -C xentrace install
    4.23  	$(MAKE) -C xenctl install
    4.24 -	$(MAKE) -C xend install
    4.25 -	$(MAKE) -C xenmgr install
    4.26 +	$(MAKE) -C xen install
    4.27  
    4.28  dist: $(TARGET)
    4.29  	$(MAKE) prefix=`pwd`/../../install dist=yes install
    4.30 @@ -23,10 +24,10 @@ dist: $(TARGET)
    4.31  
    4.32  clean:
    4.33  	$(MAKE) -C xc clean
    4.34 +	$(MAKE) -C xu clean
    4.35  	$(MAKE) -C misc clean
    4.36  	$(MAKE) -C examples clean
    4.37  	$(MAKE) -C xentrace clean
    4.38  	$(MAKE) -C xenctl clean
    4.39 -	$(MAKE) -C xend clean
    4.40 -	$(MAKE) -C xenmgr clean
    4.41 +	$(MAKE) -C xen clean
    4.42  
     5.1 --- a/tools/misc/Makefile	Fri Jun 25 13:44:22 2004 +0000
     5.2 +++ b/tools/misc/Makefile	Fri Jun 25 15:10:48 2004 +0000
     5.3 @@ -3,7 +3,7 @@ CC         = gcc
     5.4  CFLAGS     = -Wall -O3 
     5.5  EXTRA_INC  = -I../../xen/include/hypervisor-ifs
     5.6  EXTRA_INC += -I../../linux-xen-sparse/include -I../xc/lib
     5.7 -EXTRA_INC += -I../xend/lib
     5.8 +EXTRA_INC += -I../xu/lib
     5.9  
    5.10  HDRS     = $(wildcard *.h)
    5.11  SRCS     = $(wildcard *.c)
     6.1 --- a/tools/xc/lib/Makefile	Fri Jun 25 13:44:22 2004 +0000
     6.2 +++ b/tools/xc/lib/Makefile	Fri Jun 25 15:10:48 2004 +0000
     6.3 @@ -6,7 +6,7 @@ SONAME   = libxc.so.$(MAJOR)
     6.4  CC       = gcc
     6.5  CFLAGS   = -c -Werror -O3 -fno-strict-aliasing
     6.6  CFLAGS  += -I../../../xen/include/hypervisor-ifs
     6.7 -CFLAGS  += -I../../xend/lib
     6.8 +CFLAGS  += -I../../xu/lib
     6.9  CFLAGS  += -I../../../linux-xen-sparse/include
    6.10  
    6.11  HDRS     = $(wildcard *.h)
     7.1 --- a/tools/xc/py/Xc.c	Fri Jun 25 13:44:22 2004 +0000
     7.2 +++ b/tools/xc/py/Xc.c	Fri Jun 25 15:10:48 2004 +0000
     7.3 @@ -20,6 +20,8 @@
     7.4  #define PyMODINIT_FUNC DL_EXPORT(void)
     7.5  #endif
     7.6  
     7.7 +#define XENPKG "xen.ext.xc"
     7.8 +
     7.9  static PyObject *xc_error, *zero;
    7.10  
    7.11  typedef struct {
    7.12 @@ -187,112 +189,73 @@ static PyObject *pyxc_domain_getinfo(PyO
    7.13      return list;
    7.14  }
    7.15  
    7.16 -static PyObject *pyxc_linux_save(PyObject *self,
    7.17 -                                 PyObject *args,
    7.18 -                                 PyObject *kwds)
    7.19 -{
    7.20 -    XcObject *xc = (XcObject *)self;
    7.21 -
    7.22 -    u32   dom;
    7.23 -    char *state_file;
    7.24 -    int   progress = 1, live = -1, debug = 0;
    7.25 -    unsigned int flags = 0;
    7.26 -
    7.27 -    static char *kwd_list[] = { "dom", "state_file", "progress", 
    7.28 -                                "live", "debug", NULL };
    7.29 -
    7.30 -    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|iii", kwd_list, 
    7.31 -                                      &dom, &state_file, &progress, 
    7.32 -                                      &live, &debug) )
    7.33 -        return NULL;
    7.34 -
    7.35 -    if (progress)  flags |= XCFLAGS_VERBOSE;
    7.36 -    if (live == 1) flags |= XCFLAGS_LIVE;
    7.37 -    if (debug)     flags |= XCFLAGS_DEBUG;
    7.38 -
    7.39 -    if ( strncmp(state_file,"tcp:", strlen("tcp:")) == 0 )
    7.40 -    {
    7.41 +static PyObject *tcp_save(XcObject *xc, u32 dom, char *url, unsigned flags){
    7.42  #define max_namelen 64
    7.43 -        char server[max_namelen];
    7.44 -        char *port_s;
    7.45 -        int port=777;
    7.46 -        int sd = -1;
    7.47 -        struct hostent *h;
    7.48 -        struct sockaddr_in s;
    7.49 -        int sockbufsize;
    7.50 -        int rc = -1;
    7.51 +    char server[max_namelen];
    7.52 +    char *port_s;
    7.53 +    int port=777;
    7.54 +    int sd = -1;
    7.55 +    struct hostent *h;
    7.56 +    struct sockaddr_in s;
    7.57 +    int sockbufsize;
    7.58 +    int rc = -1;
    7.59 +    
    7.60 +    int writerfn(void *fd, const void *buf, size_t count) {
    7.61 +        int tot = 0, rc;
    7.62 +        do {
    7.63 +            rc = write( (int) fd, ((char*)buf)+tot, count-tot );
    7.64 +            if ( rc < 0 ) { perror("WRITE"); return rc; };
    7.65 +            tot += rc;
    7.66 +        }
    7.67 +        while ( tot < count );
    7.68 +        return 0;
    7.69 +    }
    7.70 +    
    7.71 +    strncpy( server, url+strlen("tcp://"), max_namelen);
    7.72 +    server[max_namelen-1]='\0';
    7.73 +    if ( (port_s = strchr(server,':')) != NULL ) {
    7.74 +        *port_s = '\0';
    7.75 +        port = atoi(port_s+1);
    7.76 +    }
    7.77 +    printf("X server=%s port=%d\n",server,port);
    7.78 +    h = gethostbyname(server);
    7.79 +    sd = socket(AF_INET, SOCK_STREAM,0);
    7.80 +    if (sd < 0) goto serr;
    7.81 +    s.sin_family = AF_INET;
    7.82 +    bcopy ( h->h_addr, &(s.sin_addr.s_addr), h->h_length);
    7.83 +    s.sin_port = htons(port);
    7.84 +    if ( connect(sd, (struct sockaddr *) &s, sizeof(s)) ) goto serr;
    7.85 +    sockbufsize=128*1024;
    7.86 +    if ( setsockopt(sd, SOL_SOCKET, SO_SNDBUF, &sockbufsize, sizeof sockbufsize) < 0 ) goto serr;
    7.87  
    7.88 -        int writerfn(void *fd, const void *buf, size_t count)
    7.89 -        {
    7.90 -            int tot = 0, rc;
    7.91 -            do {
    7.92 -                rc = write( (int) fd, ((char*)buf)+tot, count-tot );
    7.93 -                if ( rc < 0 ) { perror("WRITE"); return rc; };
    7.94 -                tot += rc;
    7.95 -            }
    7.96 -            while ( tot < count );
    7.97 -            return 0;
    7.98 -        }
    7.99 -
   7.100 -        if (live == -1) flags |= XCFLAGS_LIVE; /* default to live for tcp */
   7.101 -
   7.102 -        strncpy( server, state_file+strlen("tcp://"), max_namelen);
   7.103 -        server[max_namelen-1]='\0';
   7.104 -        if ( (port_s = strchr(server,':')) != NULL )
   7.105 -        {
   7.106 -            *port_s = '\0';
   7.107 -            port = atoi(port_s+1);
   7.108 -        }
   7.109 -
   7.110 -        printf("X server=%s port=%d\n",server,port);
   7.111 - 
   7.112 -        h = gethostbyname(server);
   7.113 -        sd = socket (AF_INET,SOCK_STREAM,0);
   7.114 -        if ( sd < 0 )
   7.115 -            goto serr;
   7.116 -        s.sin_family = AF_INET;
   7.117 -        bcopy ( h->h_addr, &(s.sin_addr.s_addr), h->h_length);
   7.118 -        s.sin_port = htons(port);
   7.119 -        if ( connect(sd, (struct sockaddr *) &s, sizeof(s)) ) 
   7.120 -            goto serr;
   7.121 -
   7.122 -        sockbufsize=128*1024;
   7.123 -        if ( setsockopt(sd, SOL_SOCKET, SO_SNDBUF, 
   7.124 -                        &sockbufsize, sizeof sockbufsize) < 0 ) 
   7.125 -            goto serr;
   7.126 -
   7.127 -        if ( xc_linux_save(xc->xc_handle, dom, flags, 
   7.128 -                           writerfn, (void*)sd) == 0 )
   7.129 -        {
   7.130 -            if ( read( sd, &rc, sizeof(int) ) != sizeof(int) )
   7.131 -                goto serr;
   7.132 +    if ( xc_linux_save(xc->xc_handle, dom, flags, writerfn, (void*)sd) == 0 ) {
   7.133 +        if ( read( sd, &rc, sizeof(int) ) != sizeof(int) ) goto serr;
   7.134    
   7.135 -            if ( rc == 0 )
   7.136 -            {
   7.137 +        if ( rc == 0 ) {
   7.138                  printf("Migration succesful -- destroy local copy\n");
   7.139                  xc_domain_destroy(xc->xc_handle, dom);
   7.140                  close(sd);
   7.141                  Py_INCREF(zero);
   7.142                  return zero;
   7.143 -            }
   7.144 -            else
   7.145 -                errno = rc;
   7.146 +        } else {
   7.147 +            errno = rc;
   7.148          }
   7.149 +    }
   7.150  
   7.151 -    serr:
   7.152 -        printf("Migration failed -- restart local copy\n");
   7.153 -        xc_domain_unpause(xc->xc_handle, dom);
   7.154 -        PyErr_SetFromErrno(xc_error);
   7.155 -        if ( sd >= 0 ) close(sd);
   7.156 -        return NULL;
   7.157 -    }    
   7.158 -    else
   7.159 -    {
   7.160 +  serr:
   7.161 +    printf("Migration failed -- restart local copy\n");
   7.162 +    xc_domain_unpause(xc->xc_handle, dom);
   7.163 +    PyErr_SetFromErrno(xc_error);
   7.164 +    if ( sd >= 0 ) close(sd);
   7.165 +    return NULL;
   7.166 +
   7.167 +}
   7.168 +
   7.169 +static PyObject *file_save(XcObject *xc, u32 dom, char *state_file, unsigned flags){
   7.170          int fd = -1;
   7.171          gzFile gfd = NULL;
   7.172  
   7.173 -        int writerfn(void *fd, const void *buf, size_t count)
   7.174 -        {
   7.175 +        int writerfn(void *fd, const void *buf, size_t count) {
   7.176              int rc;
   7.177              while ( ((rc = gzwrite( (gzFile*)fd, (void*)buf, count)) == -1) && 
   7.178                      (errno = EINTR) )
   7.179 @@ -300,30 +263,24 @@ static PyObject *pyxc_linux_save(PyObjec
   7.180              return ! (rc == count);
   7.181          }
   7.182  
   7.183 -        if (strncmp(state_file,"file:",strlen("file:")) == 0)
   7.184 +        if (strncmp(state_file,"file:",strlen("file:")) == 0){
   7.185              state_file += strlen("file:");
   7.186 +        }
   7.187  
   7.188 -        if ( (fd = open(state_file, O_CREAT|O_EXCL|O_WRONLY, 0644)) == -1 )
   7.189 -        {
   7.190 +        if ( (fd = open(state_file, O_CREAT|O_EXCL|O_WRONLY, 0644)) == -1 ) {
   7.191              perror("Could not open file for writing");
   7.192              goto err;
   7.193          }
   7.194 -
   7.195          /*
   7.196           * Compression rate 1: we want speed over compression. 
   7.197           * We're mainly going for those zero pages, after all.
   7.198           */
   7.199 -
   7.200 -        if ( (gfd = gzdopen(fd, "wb1")) == NULL )
   7.201 -        {
   7.202 +        if ( (gfd = gzdopen(fd, "wb1")) == NULL ) {
   7.203              perror("Could not allocate compression state for state file");
   7.204              close(fd);
   7.205              goto err;
   7.206          }
   7.207 -
   7.208 -
   7.209 -        if ( xc_linux_save(xc->xc_handle, dom, flags, writerfn, gfd) == 0 )
   7.210 -        {
   7.211 +        if ( xc_linux_save(xc->xc_handle, dom, flags, writerfn, gfd) == 0 ) {
   7.212              /* kill domain. We don't want to do this for checkpointing, but
   7.213                 if we don't do it here I think people will hurt themselves
   7.214                 by accident... */
   7.215 @@ -337,14 +294,45 @@ static PyObject *pyxc_linux_save(PyObjec
   7.216  
   7.217      err:
   7.218          PyErr_SetFromErrno(xc_error);
   7.219 -        if ( gfd != NULL )
   7.220 -            gzclose(gfd);
   7.221 -        if ( fd >= 0 )
   7.222 -            close(fd);
   7.223 +        if ( gfd != NULL ) gzclose(gfd);
   7.224 +        if ( fd >= 0 ) close(fd);
   7.225          unlink(state_file);
   7.226          return NULL;
   7.227 +}
   7.228 +
   7.229 +static PyObject *pyxc_linux_save(PyObject *self,
   7.230 +                                 PyObject *args,
   7.231 +                                 PyObject *kwds)
   7.232 +{
   7.233 +    XcObject *xc = (XcObject *)self;
   7.234 +
   7.235 +    u32   dom;
   7.236 +    char *state_file;
   7.237 +    int   progress = 1, live = -1, debug = 0;
   7.238 +    unsigned int flags = 0;
   7.239 +    PyObject *val = NULL;
   7.240 +
   7.241 +    static char *kwd_list[] = { "dom", "state_file", "progress", 
   7.242 +                                "live", "debug", NULL };
   7.243 +
   7.244 +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|iii", kwd_list, 
   7.245 +                                      &dom, &state_file, &progress, 
   7.246 +                                      &live, &debug) )
   7.247 +        goto exit;
   7.248 +
   7.249 +    if (progress)  flags |= XCFLAGS_VERBOSE;
   7.250 +    if (live == 1) flags |= XCFLAGS_LIVE;
   7.251 +    if (debug)     flags |= XCFLAGS_DEBUG;
   7.252 +
   7.253 +    if ( strncmp(state_file,"tcp:", strlen("tcp:")) == 0 ) {
   7.254 +        /* default to live for tcp */
   7.255 +        if (live == -1) flags |= XCFLAGS_LIVE;
   7.256 +        val = tcp_save(xc, dom, state_file, flags);
   7.257 +    } else {
   7.258 +        val = file_save(xc, dom, state_file, flags);
   7.259      }
   7.260 -
   7.261 +  exit:
   7.262 +    return val;
   7.263  }
   7.264  
   7.265  static PyObject *pyxc_linux_restore(PyObject *self,
   7.266 @@ -1335,18 +1323,18 @@ static PyTypeObject PyXcType = {
   7.267  };
   7.268  
   7.269  static PyMethodDef PyXc_methods[] = {
   7.270 -    { "new", PyXc_new, METH_VARARGS, "Create a new Xc object." },
   7.271 +    { "new", PyXc_new, METH_VARARGS, "Create a new " XENPKG " object." },
   7.272      { NULL, NULL, 0, NULL }
   7.273  };
   7.274  
   7.275 -PyMODINIT_FUNC initXc(void)
   7.276 +PyMODINIT_FUNC initxc(void)
   7.277  {
   7.278      PyObject *m, *d;
   7.279  
   7.280 -    m = Py_InitModule("Xc", PyXc_methods);
   7.281 +    m = Py_InitModule(XENPKG, PyXc_methods);
   7.282  
   7.283      d = PyModule_GetDict(m);
   7.284 -    xc_error = PyErr_NewException("Xc.error", NULL, NULL);
   7.285 +    xc_error = PyErr_NewException(XENPKG ".error", NULL, NULL);
   7.286      PyDict_SetItemString(d, "error", xc_error);
   7.287  
   7.288      zero = PyInt_FromLong(0);
     8.1 --- a/tools/xc/py/setup.py	Fri Jun 25 13:44:22 2004 +0000
     8.2 +++ b/tools/xc/py/setup.py	Fri Jun 25 15:10:48 2004 +0000
     8.3 @@ -1,11 +1,14 @@
     8.4  
     8.5  from distutils.core import setup, Extension
     8.6  
     8.7 -module = Extension("Xc",
     8.8 +module = Extension("xc",
     8.9                     extra_compile_args   = ["-fno-strict-aliasing"],
    8.10                     include_dirs         = ["../lib"],
    8.11                     library_dirs         = ["../lib"],
    8.12                     libraries            = ["xc"],
    8.13                     sources              = ["Xc.c"])
    8.14  
    8.15 -setup(name = "Xc", version = "1.0", ext_modules = [module])
    8.16 +setup(name = "xc",
    8.17 +      version = "1.0",
    8.18 +      ext_package = "xen.ext",
    8.19 +      ext_modules = [module])
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/tools/xen/Makefile	Fri Jun 25 15:10:48 2004 +0000
     9.3 @@ -0,0 +1,19 @@
     9.4 +
     9.5 +all:
     9.6 +	python setup.py build
     9.7 +
     9.8 +install: all
     9.9 +	if [ "$(prefix)" = "" ]; then                   \
    9.10 +	    python setup.py install;                    \
    9.11 +	elif [ "$(dist)" = "yes" ]; then                \
    9.12 +	    python setup.py install --home="$(prefix)"; \
    9.13 +	else                                            \
    9.14 +	    python setup.py install --root="$(prefix)"; \
    9.15 +	fi
    9.16 +	mkdir -p $(prefix)/usr/sbin
    9.17 +	install -m0755 xend $(prefix)/usr/sbin
    9.18 +	install -m0755 netfix $(prefix)/usr/sbin
    9.19 +	install -m0755 xm $(prefix)/usr/sbin
    9.20 +
    9.21 +clean:
    9.22 +	rm -rf build *.pyc *.pyo *.o *.a *~
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/tools/xen/lib/__init__.py	Fri Jun 25 15:10:48 2004 +0000
    10.3 @@ -0,0 +1,1 @@
    10.4 + 
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/tools/xen/lib/xend/Args.py	Fri Jun 25 15:10:48 2004 +0000
    11.3 @@ -0,0 +1,126 @@
    11.4 +import sxp
    11.5 +
    11.6 +class ArgError(StandardError):
    11.7 +    pass
    11.8 +
    11.9 +class Args:
   11.10 +    """Argument encoding support for HTTP.
   11.11 +    """
   11.12 +    
   11.13 +    def __init__(self, paramspec, keyspec):
   11.14 +        self.arg_ord = []
   11.15 +        self.arg_dict = {}
   11.16 +        self.key_ord = []
   11.17 +        self.key_dict = {}
   11.18 +        for (name, type) in paramspec:
   11.19 +                self.arg_ord.append(name)
   11.20 +                self.arg_dict[name] = type
   11.21 +        for (name, type) in keyspec:
   11.22 +                self.key_ord.append(name)
   11.23 +                self.key_dict[name] = type
   11.24 +
   11.25 +    def get_args(self, d, xargs=None):
   11.26 +        args = {}
   11.27 +        keys = {}
   11.28 +        params = []
   11.29 +        if xargs:
   11.30 +            self.split_args(xargs, args, keys)
   11.31 +        self.split_args(d, args, keys)
   11.32 +        for a in self.arg_ord:
   11.33 +            if a in args:
   11.34 +                params.append(args[a])
   11.35 +            else:
   11.36 +                raise ArgError('Missing parameter: %s' % a)
   11.37 +        return (params, keys)
   11.38 +
   11.39 +    def split_args(self, d, args, keys):
   11.40 +        for (k, v) in d.items():
   11.41 +            if k in self.arg_dict:
   11.42 +                type = self.arg_dict[k]
   11.43 +                val = self.coerce(type, v)
   11.44 +                args[k] = val
   11.45 +            elif k in self.key_dict:
   11.46 +                type = self.key_dict[k]
   11.47 +                val = self.coerce(type, v)
   11.48 +                keys[k] = val
   11.49 +            else:
   11.50 +                raise ArgError('Invalid parameter: %s' % k)
   11.51 +
   11.52 +    def get_form_args(self, f, xargs=None):
   11.53 +        d = {}
   11.54 +        for (k, v) in f.items():
   11.55 +            n = len(v)
   11.56 +            if ((k not in self.arg_dict) and
   11.57 +                (k not in self.key_dict)):
   11.58 +                continue
   11.59 +            if n == 0:
   11.60 +                continue
   11.61 +            elif n == 1:
   11.62 +                d[k] = v[0]
   11.63 +            else:
   11.64 +                raise ArgError('Too many values for %s' % k)
   11.65 +        return self.get_args(d, xargs=xargs)
   11.66 +
   11.67 +    def coerce(self, type, v):
   11.68 +        try:
   11.69 +            if type == 'int':
   11.70 +                return int(v)
   11.71 +            if type == 'str':
   11.72 +                return str(v)
   11.73 +            if type == 'sxpr':
   11.74 +                return self.sxpr(v)
   11.75 +        except ArgError:
   11.76 +            raise
   11.77 +        except StandardError, ex:
   11.78 +            raise ArgError(str(ex))
   11.79 +
   11.80 +    def sxpr(self, v):
   11.81 +        if instanceof(v, types.ListType):
   11.82 +            return v
   11.83 +        if instanceof(v, types.File) or hasattr(v, 'readline'):
   11.84 +            return sxpr_file(v)
   11.85 +        if instanceof(v, types.StringType):
   11.86 +            return sxpr_file(StringIO(v))
   11.87 +        return str(v)
   11.88 +
   11.89 +    def sxpr_file(self, fin):
   11.90 +        try:
   11.91 +            vals = sxp.parse(fin)
   11.92 +        except:
   11.93 +            raise ArgError('Coercion to sxpr failed')
   11.94 +        if len(vals) == 1:
   11.95 +            return vals[0]
   11.96 +        else:
   11.97 +            raise ArgError('Too many sxprs')
   11.98 +
   11.99 +    def call_with_args(self, fn, args, xargs=None):
  11.100 +        (params, keys) = self.get_args(args, xargs=xargs)
  11.101 +        fn(*params, **keys)
  11.102 +
  11.103 +    def call_with_form_args(self, fn, fargs, xargs=None):
  11.104 +        (params, keys) = self.get_form_args(fargs, xargs=xargs)
  11.105 +        fn(*params, **keys)
  11.106 +
  11.107 +class ArgFn(Args):
  11.108 +    """Represent a remote HTTP operation as a function.
  11.109 +    Used on the client.
  11.110 +    """
  11.111 +
  11.112 +    def __init__(self, fn, paramspec, keyspec={}):
  11.113 +        Args.__init__(self, paramspec, keyspec)
  11.114 +        self.fn = fn
  11.115 +
  11.116 +    def __call__(self, fargs, xargs=None):
  11.117 +        return self.call_with_args(self.fn, fargs, xargs=xargs)
  11.118 +    
  11.119 +class FormFn(Args):
  11.120 +    """Represent an operation as a function over a form.
  11.121 +    Used in the HTTP server.
  11.122 +    """
  11.123 +
  11.124 +    def __init__(self, fn, paramspec, keyspec={}):
  11.125 +        Args.__init__(self, paramspec, keyspec)
  11.126 +        self.fn = fn
  11.127 +
  11.128 +    def __call__(self, fargs, xargs=None):
  11.129 +        return self.call_with_form_args(self.fn, fargs, xargs=xargs)
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/tools/xen/lib/xend/EventServer.py	Fri Jun 25 15:10:48 2004 +0000
    12.3 @@ -0,0 +1,215 @@
    12.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    12.5 +"""Simple publish/subscribe event server.
    12.6 +
    12.7 +"""
    12.8 +import string
    12.9 +
   12.10 +from twisted.internet import reactor
   12.11 +
   12.12 +# subscribe a.b.c h: map a.b.c -> h
   12.13 +# subscribe a.b.* h: map a.b.* -> h
   12.14 +# subscribe a.b.? h: map a.b.? -> h
   12.15 +#
   12.16 +# for event a.b.c.d:
   12.17 +#
   12.18 +# lookup a.b.c.d, call handlers
   12.19 +#
   12.20 +# lookup a.b.c.?, call handlers
   12.21 +#
   12.22 +# lookup a.b.c.d.*, call handlers
   12.23 +# lookup a.b.c.*, call handlers
   12.24 +# lookup a.b.*, call handlers
   12.25 +# lookup a.*, call handlers
   12.26 +# lookup *, call handlers
   12.27 +
   12.28 +# a.b.c.d = (a b c d)
   12.29 +# a.b.c.? = (a b c _)
   12.30 +# a.b.c.* = (a b c . _)
   12.31 +
   12.32 +class EventServer:
   12.33 +
   12.34 +    DOT = '.'
   12.35 +    QUERY = '?'
   12.36 +    DOT_QUERY = DOT + QUERY
   12.37 +    STAR = '*'
   12.38 +    DOT_STAR = DOT + STAR
   12.39 +
   12.40 +    def __init__(self, run=0):
   12.41 +        self.handlers = {}
   12.42 +        self.run = run
   12.43 +        self.queue = []
   12.44 +
   12.45 +    def start(self):
   12.46 +        """Enable event handling. Sends any queued events.
   12.47 +        """
   12.48 +        self.run = 1
   12.49 +        for (e,v) in self.queue:
   12.50 +            self.inject(e, v)
   12.51 +        self.queue = []
   12.52 +
   12.53 +    def stop(self):
   12.54 +        """Suspend event handling. Events injected while suspended
   12.55 +        are queued until we are started again.
   12.56 +        """
   12.57 +        self.run = 0
   12.58 +
   12.59 +    def subscribe(self, event, handler):
   12.60 +        """Subscribe to an event. For example 'a.b.c.d'.
   12.61 +        A subcription like 'a.b.c.?' ending in '?' matches any value
   12.62 +        for the '?'. A subscription like 'a.b.c.*' ending in '*' matches
   12.63 +        any event type with the same prefix, 'a.b.c' in this case.
   12.64 +
   12.65 +        event	event name
   12.66 +        handler event handler fn(event, val)
   12.67 +        """
   12.68 +        hl = self.handlers.get(event)
   12.69 +        if hl is None:
   12.70 +            self.handlers[event] = [handler]
   12.71 +        else:
   12.72 +            hl.append(handler)
   12.73 +
   12.74 +    def unsubscribe_all(self, event=None):
   12.75 +        """Unsubscribe all handlers for a given event, or all handlers.
   12.76 +
   12.77 +        event	event (optional)
   12.78 +        """
   12.79 +        if event == None:
   12.80 +            self.handlers.clear()
   12.81 +        elif event in self.handlers:
   12.82 +            del self.handlers[event]
   12.83 +        
   12.84 +    def unsubscribe(self, event, handler):
   12.85 +        """Unsubscribe a given event and handler.
   12.86 +
   12.87 +        event	event
   12.88 +        handler handler
   12.89 +        """
   12.90 +        hl = self.handlers.get(event)
   12.91 +        if hl is None:
   12.92 +            return
   12.93 +        if handler in hl:
   12.94 +            hl.remove(handler)
   12.95 +
   12.96 +    def inject(self, event, val, async=1):
   12.97 +        """Inject an event. Handlers for it are called if running, otherwise
   12.98 +        it is queued.
   12.99 +
  12.100 +        event	event type
  12.101 +        val	event value
  12.102 +        """
  12.103 +        if self.run:
  12.104 +            if async:
  12.105 +                reactor.callLater(0, self.call_handlers, event, val)
  12.106 +            else:
  12.107 +                self.notify_handlers(event, val)
  12.108 +        else:
  12.109 +            self.queue.append( (event, val) )
  12.110 +
  12.111 +    def call_handlers(self, event, val):
  12.112 +        """Internal method to call event handlers.
  12.113 +        """
  12.114 +        #print ">event", event, val
  12.115 +        self.call_event_handlers(event, event, val)
  12.116 +        self.call_query_handlers(event, val)
  12.117 +        self.call_star_handlers(event, val)
  12.118 +
  12.119 +    def call_event_handlers(self, key, event, val):
  12.120 +        """Call the handlers for an event.
  12.121 +        It is safe for handlers to subscribe or unsubscribe.
  12.122 +
  12.123 +        key	key for handler list
  12.124 +        event	event type
  12.125 +        val	event value
  12.126 +        """
  12.127 +        hl = self.handlers.get(key)
  12.128 +        if hl is None:
  12.129 +            return
  12.130 +        # Copy the handler list so that handlers can call
  12.131 +        # subscribe/unsubscribe safely - python list iteration
  12.132 +        # is not safe against list modification.
  12.133 +        for h in hl[:]:
  12.134 +            try:
  12.135 +                h(event, val)
  12.136 +            except:
  12.137 +                pass
  12.138 +        
  12.139 +    def call_query_handlers(self, event, val):
  12.140 +        """Call regex handlers for events matching 'event' that end in '?'.
  12.141 +
  12.142 +        event	event type
  12.143 +        val	event value
  12.144 +        """
  12.145 +        dot_idx = event.rfind(self.DOT)
  12.146 +        if dot_idx == -1:
  12.147 +            self.call_event_handlers(self.QUERY, event, val)
  12.148 +        else:
  12.149 +            event_query = event[0:dot_idx] + self.DOT_QUERY
  12.150 +            self.call_event_handlers(event_query, event, val)
  12.151 +
  12.152 +    def call_star_handlers(self, event, val):
  12.153 +        """Call regex handlers for events matching 'event' that end in '*'.
  12.154 +
  12.155 +        event	event type
  12.156 +        val	event value
  12.157 +        """
  12.158 +        etype = string.split(event, self.DOT)
  12.159 +        for i in range(len(etype), 0, -1):
  12.160 +            event_star = self.DOT.join(etype[0:i]) + self.DOT_STAR
  12.161 +            self.call_event_handlers(event_star, event, val)
  12.162 +        self.call_event_handlers(self.STAR, event, val)       
  12.163 +
  12.164 +def instance():
  12.165 +    global inst
  12.166 +    try:
  12.167 +        inst
  12.168 +    except:
  12.169 +        inst = EventServer()
  12.170 +        inst.start()
  12.171 +    return inst
  12.172 +
  12.173 +def main():
  12.174 +    def sys_star(event, val):
  12.175 +        print 'sys_star', event, val
  12.176 +
  12.177 +    def sys_foo(event, val):
  12.178 +        print 'sys_foo', event, val
  12.179 +        s.unsubscribe('sys.foo', sys_foo)
  12.180 +
  12.181 +    def sys_foo2(event, val):
  12.182 +        print 'sys_foo2', event, val
  12.183 +
  12.184 +    def sys_bar(event, val):
  12.185 +        print 'sys_bar', event, val
  12.186 +
  12.187 +    def sys_foo_bar(event, val):
  12.188 +        print 'sys_foo_bar', event, val
  12.189 +
  12.190 +    def foo_bar(event, val):
  12.191 +        print 'foo_bar', event, val
  12.192 +
  12.193 +    s = EventServer()
  12.194 +    s.start()
  12.195 +    s.subscribe('sys.*', sys_star)
  12.196 +    s.subscribe('sys.foo', sys_foo)
  12.197 +    s.subscribe('sys.foo', sys_foo2)
  12.198 +    s.subscribe('sys.bar', sys_bar)
  12.199 +    s.subscribe('sys.foo.bar', sys_foo_bar)
  12.200 +    s.subscribe('foo.bar', foo_bar)
  12.201 +    s.inject('sys.foo', 'hello')
  12.202 +    print
  12.203 +    s.inject('sys.bar', 'hello again')
  12.204 +    print
  12.205 +    s.inject('sys.foo.bar', 'hello again')
  12.206 +    print
  12.207 +    s.inject('foo.bar', 'hello again')
  12.208 +    print
  12.209 +    s.inject('foo', 'hello again')
  12.210 +    print
  12.211 +    s.start()
  12.212 +    s.unsubscribe('sys.*', sys_star)
  12.213 +    s.unsubscribe_all('sys.*')
  12.214 +    s.inject('sys.foo', 'hello')
  12.215 +
  12.216 +if __name__ == "__main__":
  12.217 +    main()
  12.218 +
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/tools/xen/lib/xend/EventTypes.py	Fri Jun 25 15:10:48 2004 +0000
    13.3 @@ -0,0 +1,34 @@
    13.4 +#   Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    13.5 +
    13.6 +## XEND_DOMAIN_CREATE = "xend.domain.create": dom
    13.7 +## create: 
    13.8 +## xend.domain.destroy: dom, reason:died/crashed
    13.9 +## xend.domain.up ?
   13.10 +
   13.11 +## xend.domain.unpause: dom
   13.12 +## xend.domain.pause: dom
   13.13 +## xend.domain.shutdown: dom
   13.14 +## xend.domain.destroy: dom
   13.15 +
   13.16 +## xend.domain.migrate.begin: dom, to
   13.17 +## Begin tells: src host, src domain uri, dst host. Dst id known?
   13.18 +## err: src host, src domain uri, dst host, dst id if known, status (of domain: ok, dead,...), reason
   13.19 +## end: src host, src domain uri, dst host, dst uri
   13.20 +
   13.21 +## Events for both ends of migrate: for exporter and importer?
   13.22 +## Include migrate id so can tie together.
   13.23 +## Have uri /xend/migrate/<id> for migrate info (migrations in progress).
   13.24 +
   13.25 +## (xend.domain.migrate.begin (src <host>) (src.domain <id>)
   13.26 +##                            (dst <host>) (id <migrate id>))
   13.27 + 
   13.28 +## xend.domain.migrate.end:
   13.29 +## (xend.domain.migrate.end (domain <id>) (to <host>)
   13.30 +
   13.31 +## xend.node.up:  xend uri
   13.32 +## xend.node.down: xend uri
   13.33 +
   13.34 +## xend.error ?
   13.35 +
   13.36 +## format:
   13.37 +
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/tools/xen/lib/xend/PrettyPrint.py	Fri Jun 25 15:10:48 2004 +0000
    14.3 @@ -0,0 +1,299 @@
    14.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    14.5 +
    14.6 +"""General pretty-printer, including support for SXP.
    14.7 +
    14.8 +"""
    14.9 +import sys
   14.10 +import types
   14.11 +import StringIO
   14.12 +import sxp
   14.13 +
   14.14 +class PrettyItem:
   14.15 +
   14.16 +    def __init__(self, width):
   14.17 +        self.width = width
   14.18 +
   14.19 +    def insert(self, block):
   14.20 +        block.addtoline(self)
   14.21 +
   14.22 +    def get_width(self):
   14.23 +        return self.width
   14.24 +
   14.25 +    def output(self, out):
   14.26 +        print '***PrettyItem>output>', self
   14.27 +        pass
   14.28 +
   14.29 +    def prettyprint(self, out, width):
   14.30 +        print '***PrettyItem>prettyprint>', self
   14.31 +        return width
   14.32 +
   14.33 +class PrettyString(PrettyItem):
   14.34 +
   14.35 +    def __init__(self, x):
   14.36 +        PrettyItem.__init__(self, len(x))
   14.37 +        self.value = x
   14.38 +
   14.39 +    def output(self, out):
   14.40 +        out.write(self.value)
   14.41 +
   14.42 +    def prettyprint(self, line):
   14.43 +        line.output(self)
   14.44 +
   14.45 +    def show(self, out):
   14.46 +        print >> out, ("(string (width %d) '%s')" % (self.width, self.value))
   14.47 +
   14.48 +class PrettySpace(PrettyItem):
   14.49 +
   14.50 +    def output(self, out):
   14.51 +        out.write(' ' * self.width)
   14.52 +
   14.53 +    def prettyprint(self, line):
   14.54 +        line.output(self)
   14.55 +
   14.56 +    def show(self, out):
   14.57 +        print >> out, ("(space (width %d))" % self.width)
   14.58 +        
   14.59 +class PrettyBreak(PrettyItem):
   14.60 +
   14.61 +    def __init__(self, width, indent):
   14.62 +        PrettyItem.__init__(self, width)
   14.63 +        self.indent = indent
   14.64 +        self.space = 0
   14.65 +        self.active = 0
   14.66 +
   14.67 +    def output(self, out):
   14.68 +        out.write(' ' * self.width)
   14.69 +
   14.70 +    def prettyprint(self, line):
   14.71 +        if line.breaks(self.space):
   14.72 +            self.active = 1
   14.73 +            line.newline(self.indent)
   14.74 +        else:
   14.75 +            line.output(self)
   14.76 +
   14.77 +    def show(self, out):
   14.78 +        print >> out, ("(break (width %d) (indent %d) (space %d) (active %d))"
   14.79 +                       % (self.width, self.indent, self.space, self.lspace, self.active))
   14.80 +
   14.81 +class PrettyNewline(PrettySpace):
   14.82 +
   14.83 +    def __init__(self, indent):
   14.84 +        PrettySpace.__init__(self, indent)
   14.85 +
   14.86 +    def insert(self, block):
   14.87 +        block.newline()
   14.88 +        block.addtoline(self)
   14.89 +
   14.90 +    def output(self, out):
   14.91 +        out.write(' ' * self.width)
   14.92 +
   14.93 +    def prettyprint(self, line):
   14.94 +        line.newline(0)
   14.95 +        line.output(self)
   14.96 +
   14.97 +    def show(self, out):
   14.98 +        print >> out, ("(nl (indent %d))" % self.indent)
   14.99 +
  14.100 +class PrettyLine(PrettyItem):
  14.101 +    def __init__(self):
  14.102 +        PrettyItem.__init__(self, 0)
  14.103 +        self.content = []
  14.104 +
  14.105 +    def write(self, x):
  14.106 +        self.content.append(x)
  14.107 +
  14.108 +    def end(self):
  14.109 +        width = 0
  14.110 +        lastwidth = 0
  14.111 +        lastbreak = None
  14.112 +        for x in self.content:
  14.113 +            if isinstance(x, PrettyBreak):
  14.114 +                if lastbreak:
  14.115 +                    lastbreak.space = (width - lastwidth)
  14.116 +                lastbreak = x
  14.117 +                lastwidth = width
  14.118 +            width += x.get_width()
  14.119 +        if lastbreak:
  14.120 +            lastbreak.space = (width - lastwidth)
  14.121 +        self.width = width
  14.122 + 
  14.123 +    def prettyprint(self, line):
  14.124 +        for x in self.content:
  14.125 +            x.prettyprint(line)
  14.126 +
  14.127 +    def show(self, out):
  14.128 +        print >> out, '(LINE (width %d)' % self.width
  14.129 +        for x in self.content:
  14.130 +            x.show(out)
  14.131 +        print >> out, ')'
  14.132 +
  14.133 +class PrettyBlock(PrettyItem):
  14.134 +
  14.135 +    def __init__(self, all=0, parent=None):
  14.136 +        self.width = 0
  14.137 +        self.lines = []
  14.138 +        self.parent = parent
  14.139 +        self.indent = 0
  14.140 +        self.all = all
  14.141 +        self.broken = 0
  14.142 +        self.newline()
  14.143 +
  14.144 +    def add(self, item):
  14.145 +        item.insert(self)
  14.146 +
  14.147 +    def end(self):
  14.148 +        self.width = 0
  14.149 +        for l in self.lines:
  14.150 +            l.end()
  14.151 +            if self.width < l.width:
  14.152 +                self.width = l.width
  14.153 +
  14.154 +    def breaks(self, n):
  14.155 +        return self.all and self.broken
  14.156 +
  14.157 +    def newline(self):
  14.158 +        self.lines.append(PrettyLine())
  14.159 +
  14.160 +    def addtoline(self, x):
  14.161 +        self.lines[-1].write(x)
  14.162 +
  14.163 +    def prettyprint(self, line):
  14.164 +        self.indent = line.used
  14.165 +        line.block = self
  14.166 +        if not line.fits(self.width):
  14.167 +            self.broken = 1
  14.168 +        for l in self.lines:
  14.169 +            l.prettyprint(line)
  14.170 +        line.block = self.parent
  14.171 +
  14.172 +    def show(self, out):
  14.173 +        print >> out, ('(BLOCK (width %d) (indent %d) (all %d) (broken %d)' %
  14.174 +                       (self.width, self.indent, self.all, self.broken))
  14.175 +        for l in self.lines:
  14.176 +            l.show(out)
  14.177 +        print >> out, ')'
  14.178 +
  14.179 +class Line:
  14.180 +
  14.181 +    def __init__(self, out, width):
  14.182 +        self.out = out
  14.183 +        self.width = width
  14.184 +        self.used = 0
  14.185 +        self.space = self.width
  14.186 +
  14.187 +    def newline(self, indent):
  14.188 +        indent += self.block.indent
  14.189 +        self.out.write('\n')
  14.190 +        self.out.write(' ' * indent)
  14.191 +        self.used = indent
  14.192 +        self.space = self.width - self.used
  14.193 +
  14.194 +    def fits(self, n):
  14.195 +        return self.space - n >= 0
  14.196 +
  14.197 +    def breaks(self, n):
  14.198 +        return self.block.breaks(n) or not self.fits(n)
  14.199 +
  14.200 +    def output(self, x):
  14.201 +        n = x.get_width()
  14.202 +        self.space -= n
  14.203 +        self.used += n
  14.204 +        if self.space < 0:
  14.205 +            self.space = 0
  14.206 +        x.output(self.out)
  14.207 +
  14.208 +class PrettyPrinter:
  14.209 +    """A prettyprinter based on what I remember of Derek Oppen's
  14.210 +    prettyprint algorithm from TOPLAS way back.
  14.211 +    """
  14.212 +
  14.213 +    def __init__(self, width=40):
  14.214 +        self.width = width
  14.215 +        self.block = None
  14.216 +        self.top = None
  14.217 +
  14.218 +    def write(self, x):
  14.219 +        self.block.add(PrettyString(x))
  14.220 +
  14.221 +    def add(self, item):
  14.222 +        self.block.add(item)
  14.223 +
  14.224 +    def addbreak(self, width=1, indent=4):
  14.225 +        self.add(PrettyBreak(width, indent))
  14.226 +
  14.227 +    def addspace(self, width=1):
  14.228 +        self.add(PrettySpace(width))
  14.229 +
  14.230 +    def addnl(self, indent=0):
  14.231 +        self.add(PrettyNewline(indent))
  14.232 +
  14.233 +    def begin(self, all=0):
  14.234 +        block = PrettyBlock(all=all, parent=self.block)
  14.235 +        self.block = block
  14.236 +
  14.237 +    def end(self):
  14.238 +        self.block.end()
  14.239 +        if self.block.parent:
  14.240 +            self.block.parent.add(self.block)
  14.241 +        else:
  14.242 +            self.top = self.block
  14.243 +        self.block = self.block.parent
  14.244 +
  14.245 +    def prettyprint(self, out=sys.stdout):
  14.246 +        line = Line(out, self.width)
  14.247 +        self.top.prettyprint(line)
  14.248 +
  14.249 +class SXPPrettyPrinter(PrettyPrinter):
  14.250 +    """An SXP prettyprinter.
  14.251 +    """
  14.252 +    
  14.253 +    def pstring(self, x):
  14.254 +        io = StringIO.StringIO()
  14.255 +        sxp.show(x, out=io)
  14.256 +        io.seek(0)
  14.257 +        val = io.getvalue()
  14.258 +        io.close()
  14.259 +        return val
  14.260 +
  14.261 +    def pprint(self, l):
  14.262 +        if isinstance(l, types.ListType):
  14.263 +            self.begin(all=1)
  14.264 +            self.write('(')
  14.265 +            i = 0
  14.266 +            for x in l:
  14.267 +                if(i): self.addbreak()
  14.268 +                self.pprint(x)
  14.269 +                i += 1
  14.270 +            self.addbreak(width=0, indent=0)
  14.271 +            self.write(')')
  14.272 +            self.end()
  14.273 +        else:
  14.274 +            self.write(self.pstring(l))
  14.275 +
  14.276 +def prettyprint(sxpr, out=sys.stdout, width=80):
  14.277 +    """Prettyprint an SXP form.
  14.278 +
  14.279 +    sxpr	s-expression
  14.280 +    out		destination
  14.281 +    width	maximum output width
  14.282 +    """
  14.283 +    if isinstance(sxpr, types.ListType):
  14.284 +        pp = SXPPrettyPrinter(width=width)
  14.285 +        pp.pprint(sxpr)
  14.286 +        pp.prettyprint(out=out)
  14.287 +    else:
  14.288 +        sxp.show(sxpr, out=out)
  14.289 +    print >> out
  14.290 +
  14.291 +def main():
  14.292 +    pin = sxp.Parser()
  14.293 +    while 1:
  14.294 +        buf = sys.stdin.read(100)
  14.295 +        pin.input(buf)
  14.296 +        if buf == '': break
  14.297 +    l = pin.get_val()
  14.298 +    prettyprint(l, width=80)
  14.299 +
  14.300 +if __name__ == "__main__":
  14.301 +    main()
  14.302 +    
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/tools/xen/lib/xend/XendBridge.py	Fri Jun 25 15:10:48 2004 +0000
    15.3 @@ -0,0 +1,193 @@
    15.4 +"""Bridge control utilities.
    15.5 +"""
    15.6 +import os
    15.7 +import os.path
    15.8 +import re
    15.9 +import sys
   15.10 +
   15.11 +from xen.xend import XendRoot
   15.12 +xroot = XendRoot.instance()
   15.13 +
   15.14 +os.defpath = os.defpath + ':/sbin:/usr/sbin:/usr/local/sbin'
   15.15 +CMD_IFCONFIG = 'ifconfig'
   15.16 +CMD_ROUTE    = 'route'
   15.17 +CMD_BRCTL    = 'brctl'
   15.18 +CMD_IPTABLES = "iptables"
   15.19 +
   15.20 +DEFAULT_BRIDGE = 'nbe-br'
   15.21 +DEFAULT_INTERFACE = 'eth0'
   15.22 +
   15.23 +opts = None
   15.24 +
   15.25 +class Opts:
   15.26 +
   15.27 +    def __init__(self, defaults):
   15.28 +        for (k, v) in defaults.items():
   15.29 +            setattr(self, k, v)
   15.30 +        pass
   15.31 +
   15.32 +def cmd(p, s):
   15.33 +    """Print and execute command 'p' with args 's'.
   15.34 +    """
   15.35 +    global opts
   15.36 +    c = p + ' ' + s
   15.37 +    if opts.verbose: print c
   15.38 +    if not opts.dryrun:
   15.39 +        os.system(c)
   15.40 +
   15.41 +def default_bridge():
   15.42 +    return xroot.get_config_value('bridge', DEFAULT_BRIDGE)
   15.43 +
   15.44 +def default_interface():
   15.45 +    return xroot.get_config_value('interface', DEFAULT_INTERFACE)
   15.46 +
   15.47 +def vif_dev(dom, vif):
   15.48 +    """Return the name of the network interface for vif on domain dom.
   15.49 +    """
   15.50 +    return "vif%d.%d" % (dom, vif)
   15.51 +
   15.52 +def vif_bridge_add(dom, vif, bridge=None):
   15.53 +    """Add the network interface for vif on dom to a bridge.
   15.54 +    """
   15.55 +    if not bridge: bridge = default_bridge()
   15.56 +    d = { 'bridge': bridge, 'vif': vif_dev(dom, vif) }
   15.57 +    cmd(CMD_BRCTL, 'addif %(bridge)s %(vif)s' % d)
   15.58 +    return bridge
   15.59 +
   15.60 +def vif_bridge_rem(dom, vif, bridge=None):
   15.61 +    """Remove the network interface for vif on dom from a bridge.
   15.62 +    """
   15.63 +    if not bridge: bridge = default_bridge()
   15.64 +    print 'vif_bridge_rem>', dom, vif, bridge
   15.65 +    d = { 'bridge': bridge, 'vif': vif_dev(dom, vif) }
   15.66 +    cmd(CMD_BRCTL, 'delif %(bridge)s %(vif)s' % d)
   15.67 +
   15.68 +def vif_restrict_addr(dom, vif, addr, delete=0):
   15.69 +    d = { 'vif': vif_dev(dom, vif), 'addr': addr}
   15.70 +    if delete:
   15.71 +        d['flag'] = '-D'
   15.72 +    else:
   15.73 +        d['flag'] = '-A'
   15.74 +    cmd(CMD_IPTABLES, '-P FORWARD DROP')
   15.75 +    cmd(CMD_IPTABLES, '%(flag)s FORWARD -m physdev --physdev-in %(vif)s -s %(addr)s -j ACCEPT' % d)
   15.76 +    cmd(CMD_IPTABLES, '%(flag)s FORWARD -m physdev --physdev-out %(vif)s -d %(addr)s -j ACCEPT' % d)
   15.77 +
   15.78 +def bridge_create(bridge=None, **kwd):
   15.79 +    """Create a bridge.
   15.80 +    Defaults hello time to 0, forward delay to 0 and stp off.
   15.81 +    """
   15.82 +    if not bridge: bridge = default_bridge()
   15.83 +    cmd(CMD_BRCTL, 'addbr %s' % bridge)
   15.84 +    if kwd.get('hello', None) is None:
   15.85 +        kwd['hello'] = 0
   15.86 +    if kwd.get('fd', None) is None:
   15.87 +        kwd['fd'] = 0
   15.88 +    if kwd.get('stp', None) is None:
   15.89 +        kwd['stp'] = 'off'
   15.90 +    bridge_set(bridge, **kwd)
   15.91 +
   15.92 +def bridge_set(bridge, hello=None, fd=None, stp=None):
   15.93 +    """Set bridge parameters.
   15.94 +    """
   15.95 +    if hello is not None:
   15.96 +        cmd(CMD_BRCTL, 'sethello %s %d' % (bridge, hello))
   15.97 +    if fd is not None:
   15.98 +        cmd(CMD_BRCTL, 'setfd %s %d' % (bridge, fd))
   15.99 +    if stp is not None:
  15.100 +        cmd(CMD_BRCTL, 'stp %s %s' % (bridge, stp))
  15.101 +
  15.102 +def bridge_del(bridge=None):
  15.103 +    """Delete a bridge.
  15.104 +    """
  15.105 +    if not bridge: bridge = default_bridge()
  15.106 +    cmd(CMD_BRCTL, 'delbr %s' % bridge)
  15.107 +
  15.108 +def routes():
  15.109 +    """Return a list of the routes.
  15.110 +    """
  15.111 +    fin = os.popen(CMD_ROUTE + ' -n', 'r')
  15.112 +    routes = []
  15.113 +    for x in fin:
  15.114 +        if x.startswith('Kernel'): continue
  15.115 +        if x.startswith('Destination'): continue
  15.116 +        x = x.strip()
  15.117 +        y = x.split()
  15.118 +        z = { 'destination': y[0],
  15.119 +              'gateway'    : y[1],
  15.120 +              'mask'       : y[2],
  15.121 +              'flags'      : y[3],
  15.122 +              'metric'     : y[4],
  15.123 +              'ref'        : y[5],
  15.124 +              'use'        : y[6],
  15.125 +              'interface'  : y[7] }
  15.126 +        routes.append(z)
  15.127 +    return routes
  15.128 +
  15.129 +def ifconfig(interface):
  15.130 +    """Return the ip config for an interface,
  15.131 +    """
  15.132 +    fin = os.popen(CMD_IFCONFIG + ' %s' % interface, 'r')
  15.133 +    inetre = re.compile('\s*inet\s*addr:(?P<address>\S*)\s*Bcast:(?P<broadcast>\S*)\s*Mask:(?P<mask>\S*)')
  15.134 +    info = None
  15.135 +    for x in fin:
  15.136 +        m = inetre.match(x)
  15.137 +        if not m: continue
  15.138 +        info = m.groupdict()
  15.139 +        info['interface'] = interface
  15.140 +        break
  15.141 +    return info
  15.142 +
  15.143 +def reconfigure(interface=None, bridge=None):
  15.144 +    """Reconfigure an interface to be attached to a bridge, and give the bridge
  15.145 +    the IP address etc. from interface. Move the default route to the interface
  15.146 +    to the bridge.
  15.147 +
  15.148 +    If opts.create is true, creates the bridge.
  15.149 +    """
  15.150 +    global opts
  15.151 +    if not interface: interface = default_interface()
  15.152 +    if not bridge: bridge = default_bridge()
  15.153 +    intf_info = ifconfig(interface)
  15.154 +    if not intf_info:
  15.155 +        print 'Interface not found:', interface
  15.156 +        return
  15.157 +    if opts.create:
  15.158 +        bridge_create(bridge)
  15.159 +    #bridge_info = ifconfig(bridge)
  15.160 +    #if not bridge_info:
  15.161 +    #    print 'Bridge not found:', bridge
  15.162 +    #    return
  15.163 +    route_info = routes()
  15.164 +    intf_info['bridge'] = bridge
  15.165 +    intf_info['gateway'] = None
  15.166 +    for r in route_info:
  15.167 +        if (r['destination'] == '0.0.0.0' and
  15.168 +            'G' in r['flags'] and
  15.169 +            r['interface'] == interface):
  15.170 +            intf_info['gateway'] = r['gateway']
  15.171 +    if not intf_info['gateway']:
  15.172 +        print 'Gateway not found: ', interface
  15.173 +        return
  15.174 +    cmd(CMD_IFCONFIG,
  15.175 +        '%(bridge)s %(address)s netmask %(mask)s broadcast %(broadcast)s up'
  15.176 +        % intf_info)
  15.177 +    cmd(CMD_ROUTE,
  15.178 +        'add default gateway %(gateway)s dev %(bridge)s'
  15.179 +        % intf_info)
  15.180 +    cmd(CMD_BRCTL, 'addif %(bridge)s %(interface)s' % intf_info)
  15.181 +    cmd(CMD_IFCONFIG, '%(interface)s 0.0.0.0' % intf_info)
  15.182 +
  15.183 +defaults = {
  15.184 +    'interface': default_interface(),
  15.185 +    'bridge'   : default_bridge(),
  15.186 +    'verbose'  : 1,
  15.187 +    'dryrun'   : 0,
  15.188 +    'create'   : 0,
  15.189 +    }
  15.190 +
  15.191 +opts = Opts(defaults)
  15.192 +
  15.193 +def set_opts(val):
  15.194 +    global opts
  15.195 +    opts = val
  15.196 +    return opts
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/tools/xen/lib/xend/XendClient.py	Fri Jun 25 15:10:48 2004 +0000
    16.3 @@ -0,0 +1,311 @@
    16.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    16.5 +"""Client API for the HTTP interface on xend.
    16.6 +Callable as a script - see main().
    16.7 +"""
    16.8 +import sys
    16.9 +import httplib
   16.10 +import types
   16.11 +from StringIO import StringIO
   16.12 +import urlparse
   16.13 +
   16.14 +from encode import *
   16.15 +import sxp
   16.16 +import PrettyPrint
   16.17 +
   16.18 +DEBUG = 0
   16.19 +
   16.20 +class Foo(httplib.HTTPResponse):
   16.21 +
   16.22 +    def begin(self):
   16.23 +        fin = self.fp
   16.24 +        while(1):
   16.25 +            buf = fin.readline()
   16.26 +            print "***", buf
   16.27 +            if buf == '':
   16.28 +                print
   16.29 +                sys.exit()
   16.30 +
   16.31 +
   16.32 +def sxprio(sxpr):
   16.33 +    io = StringIO()
   16.34 +    sxp.show(sxpr, out=io)
   16.35 +    print >> io
   16.36 +    io.seek(0)
   16.37 +    return io
   16.38 +
   16.39 +def fileof(val):
   16.40 +    """Converter for passing configs.
   16.41 +    Handles lists, files directly.
   16.42 +    Assumes a string is a file name and passes its contents.
   16.43 +    """
   16.44 +    if isinstance(val, types.ListType):
   16.45 +        return sxprio(val)
   16.46 +    if isinstance(val, types.StringType):
   16.47 +        return file(val)
   16.48 +    if hasattr(val, 'readlines'):
   16.49 +        return val
   16.50 +
   16.51 +# todo: need to sort of what urls/paths are using for objects.
   16.52 +# e.g. for domains at the moment return '0'.
   16.53 +# should probably return abs path w.r.t. server, e.g. /xend/domain/0.
   16.54 +# As an arg, assume abs path is obj uri, otherwise just id.
   16.55 +
   16.56 +# Function to convert to full url: Xend.uri(path), e.g.
   16.57 +# maps /xend/domain/0 to http://wray-m-3.hpl.hp.com:8000/xend/domain/0
   16.58 +# And should accept urls for ids?
   16.59 +
   16.60 +def urljoin(location, root, prefix='', rest=''):
   16.61 +    prefix = str(prefix)
   16.62 +    rest = str(rest)
   16.63 +    base = 'http://' + location + root + prefix
   16.64 +    url = urlparse.urljoin(base, rest)
   16.65 +    return url
   16.66 +
   16.67 +def nodeurl(location, root, id=''):
   16.68 +    return urljoin(location, root, 'node/', id)
   16.69 +
   16.70 +def domainurl(location, root, id=''):
   16.71 +    return urljoin(location, root, 'domain/', id)
   16.72 +
   16.73 +def consoleurl(location, root, id=''):
   16.74 +    return urljoin(location, root, 'console/', id)
   16.75 +
   16.76 +def deviceurl(location, root, id=''):
   16.77 +    return urljoin(location, root, 'device/', id)
   16.78 +
   16.79 +def vneturl(location, root, id=''):
   16.80 +    return urljoin(location, root, 'vnet/', id)
   16.81 +
   16.82 +def eventurl(location, root, id=''):
   16.83 +    return urljoin(location, root, 'event/', id)
   16.84 +
   16.85 +def xend_request(url, method, data=None):
   16.86 +    urlinfo = urlparse.urlparse(url)
   16.87 +    (uproto, ulocation, upath, uparam, uquery, ufrag) = urlinfo
   16.88 +    if DEBUG: print url, urlinfo
   16.89 +    if uproto != 'http':
   16.90 +        raise StandardError('Invalid protocol: ' + uproto)
   16.91 +    if DEBUG: print '>xend_request', ulocation, upath, method, data
   16.92 +    (hdr, args) = encode_data(data)
   16.93 +    if data and method == 'GET':
   16.94 +        upath += '?' + args
   16.95 +        args = None
   16.96 +    if method == "POST" and upath.endswith('/'):
   16.97 +        upath = upath[:-1]
   16.98 +    if DEBUG: print "ulocation=", ulocation, "upath=", upath, "args=", args
   16.99 +    #hdr['User-Agent'] = 'Mozilla'
  16.100 +    #hdr['Accept'] = 'text/html,text/plain'
  16.101 +    conn = httplib.HTTPConnection(ulocation)
  16.102 +    #conn.response_class = Foo
  16.103 +    if DEBUG: conn.set_debuglevel(1)
  16.104 +    conn.request(method, upath, args, hdr)
  16.105 +    resp = conn.getresponse()
  16.106 +    if DEBUG: print resp.status, resp.reason
  16.107 +    if DEBUG: print resp.msg.headers
  16.108 +    if resp.status in [204, 404]:
  16.109 +        return None
  16.110 +    if resp.status not in [200, 201, 202, 203]:
  16.111 +        raise RuntimeError(resp.reason)
  16.112 +    pin = sxp.Parser()
  16.113 +    data = resp.read()
  16.114 +    if DEBUG: print "***data" , data
  16.115 +    if DEBUG: print "***"
  16.116 +    pin.input(data);
  16.117 +    pin.input_eof()
  16.118 +    conn.close()
  16.119 +    val = pin.get_val()
  16.120 +    #if isinstance(val, types.ListType) and sxp.name(val) == 'val':
  16.121 +    #    val = val[1]
  16.122 +    if isinstance(val, types.ListType) and sxp.name(val) == 'err':
  16.123 +        raise RuntimeError(val[1])
  16.124 +    if DEBUG: print '**val='; sxp.show(val); print
  16.125 +    return val
  16.126 +
  16.127 +def xend_get(url, args=None):
  16.128 +    return xend_request(url, "GET", args)
  16.129 +
  16.130 +def xend_call(url, data):
  16.131 +    return xend_request(url, "POST", data)
  16.132 +
  16.133 +class Xend:
  16.134 +
  16.135 +    SRV_DEFAULT = "localhost:8000"
  16.136 +    ROOT_DEFAULT = "/xend/"
  16.137 +
  16.138 +    def __init__(self, srv=None, root=None):
  16.139 +        self.bind(srv, root)
  16.140 +
  16.141 +    def bind(self, srv=None, root=None):
  16.142 +        if srv is None: srv = self.SRV_DEFAULT
  16.143 +        if root is None: root = self.ROOT_DEFAULT
  16.144 +        if not root.endswith('/'): root += '/'
  16.145 +        self.location = srv
  16.146 +        self.root = root
  16.147 +
  16.148 +    def nodeurl(self, id=''):
  16.149 +        return nodeurl(self.location, self.root, id)
  16.150 +
  16.151 +    def domainurl(self, id=''):
  16.152 +        return domainurl(self.location, self.root, id)
  16.153 +
  16.154 +    def consoleurl(self, id=''):
  16.155 +        return consoleurl(self.location, self.root, id)
  16.156 +
  16.157 +    def deviceurl(self, id=''):
  16.158 +        return deviceurl(self.location, self.root, id)
  16.159 +
  16.160 +    def vneturl(self, id=''):
  16.161 +        return vneturl(self.location, self.root, id)
  16.162 +
  16.163 +    def eventurl(self, id=''):
  16.164 +        return eventurl(self.location, self.root, id)
  16.165 +
  16.166 +    def xend(self):
  16.167 +        return xend_get(urljoin(self.location, self.root))
  16.168 +
  16.169 +    def xend_node(self):
  16.170 +        return xend_get(self.nodeurl())
  16.171 +
  16.172 +    def xend_node_cpu_rrobin_slice_set(self, slice):
  16.173 +        return xend_call(self.nodeurl(),
  16.174 +                         {'op'      : 'cpu_rrobin_slice_set',
  16.175 +                          'slice'   : slice })
  16.176 +    
  16.177 +    def xend_node_cpu_bvt_slice_set(self, slice):
  16.178 +        return xend_call(self.nodeurl(),
  16.179 +                         {'op'      : 'cpu_bvt_slice_set',
  16.180 +                          'slice'   : slice })
  16.181 +
  16.182 +    def xend_domains(self):
  16.183 +        return xend_get(self.domainurl())
  16.184 +
  16.185 +    def xend_domain_create(self, conf):
  16.186 +        return xend_call(self.domainurl(),
  16.187 +                         {'op'      : 'create',
  16.188 +                          'config'  : fileof(conf) })
  16.189 +
  16.190 +    def xend_domain(self, id):
  16.191 +        return xend_get(self.domainurl(id))
  16.192 +
  16.193 +    def xend_domain_unpause(self, id):
  16.194 +        return xend_call(self.domainurl(id),
  16.195 +                         {'op'      : 'unpause'})
  16.196 +
  16.197 +    def xend_domain_pause(self, id):
  16.198 +        return xend_call(self.domainurl(id),
  16.199 +                         {'op'      : 'pause'})
  16.200 +
  16.201 +    def xend_domain_shutdown(self, id):
  16.202 +        return xend_call(self.domainurl(id),
  16.203 +                         {'op'      : 'shutdown'})
  16.204 +
  16.205 +    def xend_domain_destroy(self, id):
  16.206 +        return xend_call(self.domainurl(id),
  16.207 +                         {'op'      : 'destroy'})
  16.208 +
  16.209 +    def xend_domain_save(self, id, filename):
  16.210 +        return xend_call(self.domainurl(id),
  16.211 +                         {'op'      : 'save',
  16.212 +                          'file'    : filename})
  16.213 +
  16.214 +    def xend_domain_restore(self, id, filename):
  16.215 +        return xend_call(self.domainurl(id),
  16.216 +                         {'op'      : 'restore',
  16.217 +                          'file'    : filename })
  16.218 +
  16.219 +    def xend_domain_migrate(self, id, dst):
  16.220 +        return xend_call(self.domainurl(id),
  16.221 +                         {'op'      : 'migrate',
  16.222 +                          'destination': dst})
  16.223 +
  16.224 +    def xend_domain_pincpu(self, id, cpu):
  16.225 +        return xend_call(self.domainurl(id),
  16.226 +                         {'op'      : 'pincpu',
  16.227 +                          'cpu'     : cpu})
  16.228 +
  16.229 +    def xend_domain_cpu_bvt_set(self, id, mcuadv, warp, warpl, warpu):
  16.230 +        return xend_call(self.domainurl(id),
  16.231 +                         {'op'      : 'cpu_bvt_set',
  16.232 +                          'mcuadv'  : mvuadv,
  16.233 +                          'warp'    : warp,
  16.234 +                          'warpl'   : warpl,
  16.235 +                          'warpu'   : warpu })
  16.236 +
  16.237 +    def xend_domain_cpu_atropos_set(self, id, period, slice, latency, xtratime):
  16.238 +        return xend_call(self.domainurl(id),
  16.239 +                         {'op'      : 'cpu_atropos_set',
  16.240 +                          'period'  : period,
  16.241 +                          'slice'   : slice,
  16.242 +                          'latency' : latency,
  16.243 +                          'xtratime': xtratime })
  16.244 +
  16.245 +    def xend_domain_vifs(self, id):
  16.246 +        return xend_get(self.domainurl(id),
  16.247 +                        { 'op'      : 'vifs' })
  16.248 +    
  16.249 +    def xend_domain_vif_ip_add(self, id, vif, ipaddr):
  16.250 +        return xend_call(self.domainurl(id),
  16.251 +                         {'op'      : 'vif_ip_add',
  16.252 +                          'vif'     : vif,
  16.253 +                          'ip'      : ipaddr })
  16.254 +        
  16.255 +    def xend_domain_vbds(self, id):
  16.256 +        return xend_get(self.domainurl(id),
  16.257 +                        {'op'       : 'vbds'})
  16.258 +
  16.259 +    def xend_domain_vbd(self, id, vbd):
  16.260 +        return xend_get(self.domainurl(id),
  16.261 +                        {'op'       : 'vbd',
  16.262 +                         'vbd'      : vbd})
  16.263 +
  16.264 +    def xend_consoles(self):
  16.265 +        return xend_get(self.consoleurl())
  16.266 +
  16.267 +    def xend_console(self, id):
  16.268 +        return xend_get(self.consoleurl(id))
  16.269 +
  16.270 +    def xend_vnets(self):
  16.271 +        return xend_get(self.vneturl())
  16.272 +
  16.273 +    def xend_vnet_create(self, conf):
  16.274 +        return xend_call(self.vneturl(),
  16.275 +                         {'op': 'create', 'config': fileof(conf) })
  16.276 +
  16.277 +    def xend_vnet(self, id):
  16.278 +        return xend_get(self.vneturl(id))
  16.279 +
  16.280 +    def xend_vnet_delete(self, id):
  16.281 +        return xend_call(self.vneturl(id),
  16.282 +                         {'op': 'delete'})
  16.283 +
  16.284 +    def xend_event_inject(self, sxpr):
  16.285 +        val = xend_call(self.eventurl(),
  16.286 +                        {'op': 'inject', 'event': fileof(sxpr) })
  16.287 +    
  16.288 +
  16.289 +def main(argv):
  16.290 +    """Call an API function:
  16.291 +    
  16.292 +    python XendClient.py fn args...
  16.293 +
  16.294 +    The leading 'xend_' on the function can be omitted.
  16.295 +    Example:
  16.296 +
  16.297 +    > python XendClient.py domains
  16.298 +    (domain 0 8)
  16.299 +    > python XendClient.py domain 0
  16.300 +    (domain (id 0) (name Domain-0) (memory 128))
  16.301 +    """
  16.302 +    server = Xend()
  16.303 +    fn = argv[1]
  16.304 +    if not fn.startswith('xend'):
  16.305 +        fn = 'xend_' + fn
  16.306 +    args = argv[2:]
  16.307 +    val = getattr(server, fn)(*args)
  16.308 +    PrettyPrint.prettyprint(val)
  16.309 +    print
  16.310 +
  16.311 +if __name__ == "__main__":
  16.312 +    main(sys.argv)
  16.313 +else:    
  16.314 +    server = Xend()
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/tools/xen/lib/xend/XendConsole.py	Fri Jun 25 15:10:48 2004 +0000
    17.3 @@ -0,0 +1,179 @@
    17.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    17.5 +
    17.6 +import socket
    17.7 +import xen.ext.xc
    17.8 +xc = xen.ext.xc.new()
    17.9 +
   17.10 +import sxp
   17.11 +import XendRoot
   17.12 +xroot = XendRoot.instance()
   17.13 +import XendDB
   17.14 +
   17.15 +import EventServer
   17.16 +eserver = EventServer.instance()
   17.17 +
   17.18 +from xen.xend.server import SrvDaemon
   17.19 +daemon = SrvDaemon.instance()
   17.20 +
   17.21 +class XendConsoleInfo:
   17.22 +    """Console information record.
   17.23 +    """
   17.24 +
   17.25 +    def __init__(self, console, dom1, port1, dom2, port2, conn=None):
   17.26 +        self.console = console
   17.27 +        self.dom1  = int(dom1)
   17.28 +        self.port1 = int(port1)
   17.29 +        self.dom2  = int(dom2)
   17.30 +        self.port2 = int(port2)
   17.31 +        self.conn  = conn
   17.32 +        #self.id = "%d.%d-%d.%d" % (self.dom1, self.port1, self.dom2, self.port2)
   17.33 +        self.id = str(port1)
   17.34 +
   17.35 +    def __str__(self):
   17.36 +        s = "console"
   17.37 +        s += " id=%s" % self.id
   17.38 +        s += " src=%d.%d" % (self.dom1, self.port1)
   17.39 +        s += " dst=%d.%d" % (self.dom2, self.port2)
   17.40 +        s += " port=%s" % self.console
   17.41 +        if self.conn:
   17.42 +            s += " conn=%s:%s" % (self.conn[0], self.conn[1])
   17.43 +        return s
   17.44 +
   17.45 +    def sxpr(self):
   17.46 +        sxpr = ['console',
   17.47 +                ['id', self.id],
   17.48 +                ['src', self.dom1, self.port1],
   17.49 +                ['dst', self.dom2, self.port2],
   17.50 +                ['port', self.console],
   17.51 +                ]
   17.52 +        if self.conn:
   17.53 +            sxpr.append(['connected', self.conn[0], self.conn[1]])
   17.54 +        return sxpr
   17.55 +
   17.56 +    def connection(self):
   17.57 +        return self.conn
   17.58 +
   17.59 +    def update(self, consinfo):
   17.60 +        conn = sxp.child(consinfo, 'connected')
   17.61 +        if conn:
   17.62 +            self.conn = conn[1:]
   17.63 +        else:
   17.64 +            self.conn = None
   17.65 +
   17.66 +    def uri(self):
   17.67 +        """Get the uri to use to connect to the console.
   17.68 +        This will be a telnet: uri.
   17.69 +
   17.70 +        return uri
   17.71 +        """
   17.72 +        host = socket.gethostname()
   17.73 +        return "telnet://%s:%s" % (host, self.console)
   17.74 +
   17.75 +class XendConsole:
   17.76 +
   17.77 +    dbpath = "console"
   17.78 +
   17.79 +    def  __init__(self):
   17.80 +        self.db = XendDB.XendDB(self.dbpath)
   17.81 +        self.console = {}
   17.82 +        self.console_db = self.db.fetchall("")
   17.83 +        if xroot.get_rebooted():
   17.84 +            print 'XendConsole> rebooted: removing all console info'
   17.85 +            self.rm_all()
   17.86 +        eserver.subscribe('xend.domain.died', self.onDomainDied)
   17.87 +        eserver.subscribe('xend.domain.destroy', self.onDomainDied)
   17.88 +
   17.89 +    def rm_all(self):
   17.90 +        """Remove all console info. Used after reboot.
   17.91 +        """
   17.92 +        for (k, v) in self.console_db.items():
   17.93 +            self._delete_console(k)
   17.94 +
   17.95 +    def refresh(self):
   17.96 +        consoles = daemon.consoles()
   17.97 +        cons = {}
   17.98 +        for consinfo in consoles:
   17.99 +            id = str(sxp.child_value(consinfo, 'id'))
  17.100 +            cons[id] = consinfo
  17.101 +            if id not in self.console:
  17.102 +                self._new_console(consinfo)
  17.103 +        for c in self.console.values():
  17.104 +            consinfo = cons.get(c.id)
  17.105 +            if consinfo:
  17.106 +                c.update(consinfo)
  17.107 +            else:
  17.108 +                self._delete_console(c.id)
  17.109 +
  17.110 +    def onDomainDied(self, event, val):
  17.111 +        dom = int(val)
  17.112 +        #print 'XendConsole>onDomainDied', 'event', event, "dom=", dom
  17.113 +        for c in self.consoles():
  17.114 +            #print 'onDomainDied', "dom=", dom, "dom1=", c.dom1, "dom2=", c.dom2
  17.115 +            if (c.dom1 == dom) or (c.dom2 == dom):
  17.116 +                'XendConsole>onDomainDied', 'delete console dom=', dom
  17.117 +                ctrl = daemon.get_domain_console(dom)
  17.118 +                if ctrl:
  17.119 +                    ctrl.close()
  17.120 +                self._delete_console(c.id)
  17.121 +
  17.122 +    def sync(self):
  17.123 +        self.db.saveall("", self.console_db)
  17.124 +
  17.125 +    def sync_console(self, id):
  17.126 +        self.db.save(id, self.console_db[id])
  17.127 +
  17.128 +    def _new_console(self, consinfo):
  17.129 +        # todo: xen needs a call to get current domain id.
  17.130 +        dom1 = 0
  17.131 +        port1 = sxp.child_value(consinfo, 'local_port')
  17.132 +        dom2 = sxp.child_value(consinfo, 'domain')
  17.133 +        port2 = sxp.child_value(consinfo, 'remote_port')
  17.134 +        console = sxp.child_value(consinfo, 'console_port')
  17.135 +        info = XendConsoleInfo(console, dom1, int(port1), int(dom2), int(port2))
  17.136 +        info.update(consinfo)
  17.137 +        self._add_console(info.id, info)
  17.138 +        return info
  17.139 +
  17.140 +    def _add_console(self, id, info):
  17.141 +        self.console[id] = info
  17.142 +        self.console_db[id] = info.sxpr()
  17.143 +        self.sync_console(id)
  17.144 +
  17.145 +    def _delete_console(self, id):
  17.146 +        if id in self.console:
  17.147 +            del self.console[id]
  17.148 +        if id in self.console_db:
  17.149 +            del self.console_db[id]
  17.150 +            self.db.delete(id)
  17.151 +
  17.152 +    def console_ls(self):
  17.153 +        self.refresh()
  17.154 +        return self.console.keys()
  17.155 +
  17.156 +    def consoles(self):
  17.157 +        self.refresh()
  17.158 +        return self.console.values()
  17.159 +    
  17.160 +    def console_create(self, dom):
  17.161 +        consinfo = daemon.console_create(dom)
  17.162 +        info = self._new_console(consinfo)
  17.163 +        return info
  17.164 +    
  17.165 +    def console_get(self, id):
  17.166 +        self.refresh()
  17.167 +        return self.console.get(id)
  17.168 +
  17.169 +    def console_delete(self, id):
  17.170 +        self._delete_console(id)
  17.171 +
  17.172 +    def console_disconnect(self, id):
  17.173 +        id = int(id)
  17.174 +        daemon.console_disconnect(id)
  17.175 +
  17.176 +def instance():
  17.177 +    global inst
  17.178 +    try:
  17.179 +        inst
  17.180 +    except:
  17.181 +        inst = XendConsole()
  17.182 +    return inst
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/tools/xen/lib/xend/XendDB.py	Fri Jun 25 15:10:48 2004 +0000
    18.3 @@ -0,0 +1,91 @@
    18.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    18.5 +
    18.6 +import os
    18.7 +import os.path
    18.8 +import errno
    18.9 +import dircache
   18.10 +import time
   18.11 +
   18.12 +import sxp
   18.13 +import XendRoot
   18.14 +xroot = XendRoot.instance()
   18.15 +
   18.16 +class XendDB:
   18.17 +    """Persistence for Xend. Stores data in files and directories.
   18.18 +    """
   18.19 +
   18.20 +    def __init__(self, path=None):
   18.21 +        self.dbpath = xroot.get_dbroot()
   18.22 +        if path:
   18.23 +            self.dbpath = os.path.join(self.dbpath, path)
   18.24 +        pass
   18.25 +
   18.26 +    def filepath(self, path):
   18.27 +        return os.path.join(self.dbpath, path)
   18.28 +        
   18.29 +    def fetch(self, path):
   18.30 +        fpath = self.filepath(path)
   18.31 +        return self.fetchfile(fpath)
   18.32 +
   18.33 +    def fetchfile(self, fpath):
   18.34 +        pin = sxp.Parser()
   18.35 +        fin = file(fpath, "rb")
   18.36 +        try:
   18.37 +            while 1:
   18.38 +                try:
   18.39 +                    buf = fin.read(1024)
   18.40 +                except IOError, ex:
   18.41 +                    if ex.errno == errno.EINTR:
   18.42 +                        continue
   18.43 +                    else:
   18.44 +                        raise
   18.45 +                pin.input(buf)
   18.46 +                if buf == '':
   18.47 +                    pin.input_eof()
   18.48 +                    break
   18.49 +        finally:
   18.50 +            fin.close()
   18.51 +        return pin.get_val()
   18.52 +
   18.53 +    def save(self, path, sxpr):
   18.54 +        fpath = self.filepath(path)
   18.55 +        return self.savefile(fpath, sxpr)
   18.56 +    
   18.57 +    def savefile(self, fpath, sxpr):
   18.58 +        fdir = os.path.dirname(fpath)
   18.59 +        if not os.path.isdir(fdir):
   18.60 +            os.makedirs(fdir)
   18.61 +        fout = file(fpath, "wb+")
   18.62 +        try:
   18.63 +            t = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
   18.64 +            fout.write("# %s %s\n" % (fpath, t))
   18.65 +            sxp.show(sxpr, out=fout)
   18.66 +        finally:
   18.67 +            fout.close()
   18.68 +
   18.69 +    def fetchall(self, path):
   18.70 +        dpath = self.filepath(path)
   18.71 +        d = {}
   18.72 +        for k in dircache.listdir(dpath):
   18.73 +            try:
   18.74 +                v = self.fetchfile(os.path.join(dpath, k))
   18.75 +                d[k] = v
   18.76 +            except:
   18.77 +                pass
   18.78 +        return d
   18.79 +
   18.80 +    def saveall(self, path, d):
   18.81 +        for (k, v) in d.items():
   18.82 +            self.save(os.path.join(path, k), v)
   18.83 +
   18.84 +    def delete(self, path):
   18.85 +        dpath = self.filepath(path)
   18.86 +        os.unlink(dpath)
   18.87 +
   18.88 +    def ls(self, path):
   18.89 +        dpath = self.filepath(path)
   18.90 +        return dircache.listdir(dpath)
   18.91 +            
   18.92 +        
   18.93 +
   18.94 +        
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/tools/xen/lib/xend/XendDomain.py	Fri Jun 25 15:10:48 2004 +0000
    19.3 @@ -0,0 +1,366 @@
    19.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    19.5 +
    19.6 +"""Handler for domain operations.
    19.7 + Nothing here is persistent (across reboots).
    19.8 + Needs to be persistent for one uptime.
    19.9 +"""
   19.10 +import sys
   19.11 +
   19.12 +from twisted.internet import defer
   19.13 +
   19.14 +import xen.ext.xc; xc = xen.ext.xc.new()
   19.15 +import xenctl.ip
   19.16 +
   19.17 +import sxp
   19.18 +import XendRoot
   19.19 +xroot = XendRoot.instance()
   19.20 +import XendDB
   19.21 +import XendDomainInfo
   19.22 +import XendConsole
   19.23 +import EventServer
   19.24 +
   19.25 +from xen.xend.server import SrvDaemon
   19.26 +xend = SrvDaemon.instance()
   19.27 +
   19.28 +eserver = EventServer.instance()
   19.29 +
   19.30 +__all__ = [ "XendDomain" ]
   19.31 +        
   19.32 +class XendDomain:
   19.33 +    """Index of all domains. Singleton.
   19.34 +    """
   19.35 +    
   19.36 +    dbpath = "domain"
   19.37 +    domain = {}
   19.38 +    
   19.39 +    def __init__(self):
   19.40 +        self.xconsole = XendConsole.instance()
   19.41 +        # Table of domain info indexed by domain id.
   19.42 +        self.db = XendDB.XendDB(self.dbpath)
   19.43 +        #self.domain = {}
   19.44 +        self.domain_db = self.db.fetchall("")
   19.45 +        if xroot.get_rebooted():
   19.46 +            print 'XendDomain> rebooted: removing all domain info'
   19.47 +            self.rm_all()
   19.48 +        eserver.subscribe('xend.virq', self.onVirq)
   19.49 +        self.initial_refresh()
   19.50 +
   19.51 +    def onVirq(self, event, val):
   19.52 +        print 'XendDomain> virq', val
   19.53 +        self.reap()
   19.54 +
   19.55 +    def rm_all(self):
   19.56 +        """Remove all domain info. Used after reboot.
   19.57 +        """
   19.58 +        for (k, v) in self.domain_db.items():
   19.59 +            self._delete_domain(k, notify=0)
   19.60 +            
   19.61 +    def initial_refresh(self):
   19.62 +        """Refresh initial domain info from domain_db.
   19.63 +        """
   19.64 +        print "initial_refresh>"
   19.65 +        for d in self.domain_db.values(): print 'db dom=', d
   19.66 +        domlist = xc.domain_getinfo()
   19.67 +        for d in domlist: print 'xc dom=', d
   19.68 +        doms = {}
   19.69 +        for d in domlist:
   19.70 +            domid = str(d['dom'])
   19.71 +            doms[domid] = d
   19.72 +        dlist = []
   19.73 +        for config in self.domain_db.values():
   19.74 +            domid = str(sxp.child_value(config, 'id'))
   19.75 +            print "dom=", domid, "config=", config
   19.76 +            if domid in doms:
   19.77 +                print "dom=", domid, "new"
   19.78 +                deferred = self._new_domain(config, doms[domid])
   19.79 +                dlist.append(deferred)
   19.80 +            else:
   19.81 +                print "dom=", domid, "del"
   19.82 +                self._delete_domain(domid)
   19.83 +        deferred = defer.DeferredList(dlist, fireOnOneErrback=1)
   19.84 +        def cbok(val):
   19.85 +            #print "doms:"
   19.86 +            #for d in self.domain.values(): print 'dom', d
   19.87 +            self.refresh()
   19.88 +            print "XendDomain>initial_refresh> doms:"
   19.89 +            for d in self.domain.values(): print 'dom', d
   19.90 +        deferred.addCallback(cbok)
   19.91 +
   19.92 +    def sync(self):
   19.93 +        """Sync domain db to disk.
   19.94 +        """
   19.95 +        self.db.saveall("", self.domain_db)
   19.96 +
   19.97 +    def sync_domain(self, dom):
   19.98 +        """Sync info for a domain to disk.
   19.99 +
  19.100 +        dom	domain id (string)
  19.101 +        """
  19.102 +        self.db.save(dom, self.domain_db[dom])
  19.103 +
  19.104 +    def close(self):
  19.105 +        pass
  19.106 +
  19.107 +    def _new_domain(self, savedinfo, info):
  19.108 +        """Create a domain entry from saved info.
  19.109 +        """
  19.110 +##         console = None
  19.111 +##         kernel = None
  19.112 +##         id = sxp.child_value(info, 'id')
  19.113 +##         dom = int(id)
  19.114 +##         name = sxp.child_value(info, 'name')
  19.115 +##         memory = int(sxp.child_value(info, 'memory'))
  19.116 +##         consoleinfo = sxp.child(info, 'console')
  19.117 +##         if consoleinfo:
  19.118 +##             consoleid = sxp.child_value(consoleinfo, 'id')
  19.119 +##             console = self.xconsole.console_get(consoleid)
  19.120 +##         if dom and console is None:
  19.121 +##             # Try to connect a console.
  19.122 +##             console = self.xconsole.console_create(dom)
  19.123 +##         config = sxp.child(info, 'config')
  19.124 +##         if config:
  19.125 +##             image = sxp.child(info, 'image')
  19.126 +##             if image:
  19.127 +##                 image = sxp.child0(image)
  19.128 +##                 kernel = sxp.child_value(image, 'kernel')
  19.129 +##         dominfo = XendDomainInfo.XendDomainInfo(
  19.130 +##             config, dom, name, memory, kernel, console)
  19.131 +        config = sxp.child_value(savedinfo, 'config')
  19.132 +        deferred = XendDomainInfo.vm_recreate(config, info)
  19.133 +        def fn(dominfo):
  19.134 +            self.domain[dominfo.id] = dominfo
  19.135 +        deferred.addCallback(fn)
  19.136 +        return deferred
  19.137 +
  19.138 +    def _add_domain(self, id, info, notify=1):
  19.139 +        self.domain[id] = info
  19.140 +        self.domain_db[id] = info.sxpr()
  19.141 +        self.sync_domain(id)
  19.142 +        if notify: eserver.inject('xend.domain.created', id)
  19.143 +
  19.144 +    def _delete_domain(self, id, notify=1):
  19.145 +        if id in self.domain:
  19.146 +            if notify: eserver.inject('xend.domain.died', id)
  19.147 +            del self.domain[id]
  19.148 +        if id in self.domain_db:
  19.149 +            del self.domain_db[id]
  19.150 +            self.db.delete(id)
  19.151 +
  19.152 +    def reap(self):
  19.153 +        """Go through the domains looking for ones that have crashed or stopped.
  19.154 +        Tidy them up.
  19.155 +        """
  19.156 +        print 'XendDomain>reap>'
  19.157 +        domlist = xc.domain_getinfo()
  19.158 +        casualties = []
  19.159 +        for d in domlist:
  19.160 +            #print 'dom', d
  19.161 +            dead = 0
  19.162 +            dead = dead or (d['crashed'] or d['shutdown'])
  19.163 +            dead = dead or (d['dying'] and
  19.164 +                            not(d['running'] or d['paused'] or d['blocked']))
  19.165 +            if dead:
  19.166 +                casualties.append(d)
  19.167 +        for d in casualties:
  19.168 +            id = str(d['dom'])
  19.169 +            print 'XendDomain>reap> died id=', id, d
  19.170 +            dominfo = self.domain.get(id)
  19.171 +            if not dominfo: continue
  19.172 +            dominfo.died()
  19.173 +            self.domain_destroy(id, refresh=0)
  19.174 +        print 'XendDomain>reap<'
  19.175 +
  19.176 +    def refresh(self):
  19.177 +        """Refresh domain list from Xen.
  19.178 +        """
  19.179 +        domlist = xc.domain_getinfo()
  19.180 +        # Index the domlist by id.
  19.181 +        # Add entries for any domains we don't know about.
  19.182 +        doms = {}
  19.183 +        for d in domlist:
  19.184 +            id = str(d['dom'])
  19.185 +            doms[id] = d
  19.186 +            if id not in self.domain:
  19.187 +                config = None
  19.188 +                #image = None
  19.189 +                #newinfo = XendDomainInfo.XendDomainInfo(
  19.190 +                #    config, d['dom'], d['name'], d['mem_kb']/1024, image=image, info=d)
  19.191 +                deferred = XendDomainInfo.vm_recreate(config, d)
  19.192 +                def fn(dominfo):
  19.193 +                    self._add_domain(dominfo.id, dominfo)
  19.194 +                deferred.addCallback(fn)
  19.195 +        # Remove entries for domains that no longer exist.
  19.196 +        for d in self.domain.values():
  19.197 +            dominfo = doms.get(d.id)
  19.198 +            if dominfo:
  19.199 +                d.update(dominfo)
  19.200 +            else:
  19.201 +                self._delete_domain(d.id)
  19.202 +        self.reap()
  19.203 +
  19.204 +    def refresh_domain(self, id):
  19.205 +        dom = int(id)
  19.206 +        dominfo = xc.domain_getinfo(dom, 1)
  19.207 +        if dominfo == [] or dominfo[0]['dom'] != dom:
  19.208 +            try:
  19.209 +                self._delete_domain(id)
  19.210 +            except:
  19.211 +                print 'refresh_domain: error'
  19.212 +                raise
  19.213 +                pass
  19.214 +        else:
  19.215 +            d = self.domain.get(id)
  19.216 +            if d:
  19.217 +                d.update(dominfo[0])
  19.218 +
  19.219 +    def domain_ls(self):
  19.220 +        # List domains.
  19.221 +        # Update info from kernel first.
  19.222 +        self.refresh()
  19.223 +        return self.domain.keys()
  19.224 +
  19.225 +    def domains(self):
  19.226 +        self.refresh()
  19.227 +        return self.domain.values()
  19.228 +    
  19.229 +    def domain_create(self, config):
  19.230 +        # Create domain, log it.
  19.231 +        deferred = XendDomainInfo.vm_create(config)
  19.232 +        def fn(dominfo):
  19.233 +            self._add_domain(dominfo.id, dominfo)
  19.234 +            return dominfo
  19.235 +        deferred.addCallback(fn)
  19.236 +        return deferred
  19.237 +    
  19.238 +    def domain_get(self, id):
  19.239 +        id = str(id)
  19.240 +        self.refresh_domain(id)
  19.241 +        return self.domain[id]
  19.242 +    
  19.243 +    def domain_unpause(self, id):
  19.244 +        """(Re)start domain running.
  19.245 +        """
  19.246 +        dom = int(id)
  19.247 +        eserver.inject('xend.domain.unpause', id)
  19.248 +        return xc.domain_unpause(dom=dom)
  19.249 +    
  19.250 +    def domain_pause(self, id):
  19.251 +        """Pause domain execution.
  19.252 +        """
  19.253 +        dom = int(id)
  19.254 +        eserver.inject('xend.domain.pause', id)
  19.255 +        return xc.domain_pause(dom=dom)
  19.256 +    
  19.257 +    def domain_shutdown(self, id, reason='poweroff'):
  19.258 +        """Shutdown domain (nicely).
  19.259 +        """
  19.260 +        dom = int(id)
  19.261 +        if dom <= 0:
  19.262 +            return 0
  19.263 +        eserver.inject('xend.domain.shutdown', [id, reason])
  19.264 +        val = xend.domain_shutdown(dom, reason)
  19.265 +        self.refresh()
  19.266 +        return val
  19.267 +    
  19.268 +    def domain_destroy(self, id, refresh=1):
  19.269 +        """Terminate domain immediately.
  19.270 +        """
  19.271 +        dom = int(id)
  19.272 +        if dom <= 0:
  19.273 +            return 0
  19.274 +        eserver.inject('xend.domain.destroy', id)
  19.275 +        val = xc.domain_destroy(dom=dom)
  19.276 +        if refresh: self.refresh()
  19.277 +        return val       
  19.278 +
  19.279 +    def domain_migrate(self, id, dst):
  19.280 +        """Start domain migration.
  19.281 +        """
  19.282 +        # Need a cancel too?
  19.283 +        pass
  19.284 +    
  19.285 +    def domain_save(self, id, dst, progress=0):
  19.286 +        """Save domain state to file, destroy domain.
  19.287 +        """
  19.288 +        dom = int(id)
  19.289 +        self.domain_pause(id)
  19.290 +        eserver.inject('xend.domain.save', id)
  19.291 +        rc = xc.linux_save(dom=dom, state_file=dst, progress=progress)
  19.292 +        if rc == 0:
  19.293 +            self.domain_destroy(id)
  19.294 +        return rc
  19.295 +    
  19.296 +    def domain_restore(self, src, config, progress=0):
  19.297 +        """Restore domain from file.
  19.298 +        """
  19.299 +        dominfo = XendDomainInfo.dom_restore(dom, config)
  19.300 +        self._add_domain(dominfo.id, dominfo)
  19.301 +        return dominfo
  19.302 +    
  19.303 +    #============================================================================
  19.304 +    # Backward compatibility stuff from here on.
  19.305 +
  19.306 +    def domain_pincpu(self, dom, cpu):
  19.307 +        dom = int(dom)
  19.308 +        return xc.domain_pincpu(dom, cpu)
  19.309 +
  19.310 +    def domain_cpu_bvt_set(self, dom, mcuadv, warp, warpl, warpu):
  19.311 +        dom = int(dom)
  19.312 +        return xc.bvtsched_domain_set(dom=dom, mcuadv=mcuadv,
  19.313 +                                      warp=warp, warpl=warpl, warpu=warpu)
  19.314 +
  19.315 +    def domain_cpu_bvt_get(self, dom):
  19.316 +        dom = int(dom)
  19.317 +        return xc.bvtsched_domain_get(dom)
  19.318 +    
  19.319 +    def domain_cpu_atropos_set(self, dom, period, slice, latency, xtratime):
  19.320 +        dom = int(dom)
  19.321 +        return xc.atropos_domain_set(dom, period, slice, latency, xtratime)
  19.322 +
  19.323 +    def domain_cpu_atropos_get(self, dom):
  19.324 +        dom = int(dom)
  19.325 +        return xc.atropos_domain_get(dom)
  19.326 +
  19.327 +    def domain_vif_ls(self, dom):
  19.328 +        dominfo = self.domain_get(dom)
  19.329 +        if not dominfo: return None
  19.330 +        devs = dominfo.get_devices('vif')
  19.331 +        return range(0, len(devs))
  19.332 +
  19.333 +    def domain_vif_get(self, dom, vif):
  19.334 +        dominfo = self.domain_get(dom)
  19.335 +        if not dominfo: return None
  19.336 +        return dominfo.get_device_by_index(vif)
  19.337 +
  19.338 +    def domain_vif_ip_add(self, dom, vif, ip):
  19.339 +        dom = int(dom)
  19.340 +        return xenctl.ip.setup_vfr_rules_for_vif(dom, vif, ip)
  19.341 +
  19.342 +    def domain_vbd_ls(self, dom):
  19.343 +        dominfo = self.domain_get(dom)
  19.344 +        if not dominfo: return []
  19.345 +        devs = dominfo.get_devices('vbd')
  19.346 +        return [ sxp.child_value(v, 'dev') for v in devs ]
  19.347 +
  19.348 +    def domain_vbd_get(self, dom, vbd):
  19.349 +        dominfo = self.domain_get(dom)
  19.350 +        if not dominfo: return None
  19.351 +        devs = dominfo.get_devices('vbd')
  19.352 +        for v in devs:
  19.353 +            if sxp.child_value(v, 'dev') == vbd:
  19.354 +                return v
  19.355 +        return None
  19.356 +
  19.357 +    def domain_shadow_control(self, dom, op):
  19.358 +        dom = int(dom)
  19.359 +        return xc.shadow_control(dom, op)
  19.360 +
  19.361 +    #============================================================================
  19.362 +
  19.363 +def instance():
  19.364 +    global inst
  19.365 +    try:
  19.366 +        inst
  19.367 +    except:
  19.368 +        inst = XendDomain()
  19.369 +    return inst
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/tools/xen/lib/xend/XendDomainConfig.py	Fri Jun 25 15:10:48 2004 +0000
    20.3 @@ -0,0 +1,44 @@
    20.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    20.5 +
    20.6 +"""Handler for persistent domain configs.
    20.7 +
    20.8 +"""
    20.9 +
   20.10 +import sxp
   20.11 +import XendDB
   20.12 +import XendDomain
   20.13 +
   20.14 +__all__ = [ "XendDomainConfig" ]
   20.15 +
   20.16 +class XendDomainConfig:
   20.17 +
   20.18 +    dbpath = 'config'
   20.19 +
   20.20 +    def __init__(self):
   20.21 +        self.db = XendDB.XendDB(self.dbpath)
   20.22 +
   20.23 +    def domain_config_ls(self, path):
   20.24 +        return self.db.ls(path)
   20.25 +
   20.26 +    def domain_config_create(self, path, sxpr):
   20.27 +        self.db.save(path, sxpr)
   20.28 +        pass
   20.29 +
   20.30 +    def domain_config_delete(self, path):
   20.31 +        self.db.delete(path)
   20.32 +
   20.33 +    def domain_config_instance(self, path):
   20.34 +        """Create a domain from a config.
   20.35 +        """
   20.36 +        config = self.db.fetch(path)
   20.37 +        xd = XendDomain.instance()
   20.38 +        newdom = xd.domain_create(config)
   20.39 +        return newdom
   20.40 +
   20.41 +def instance():
   20.42 +    global inst
   20.43 +    try:
   20.44 +        inst
   20.45 +    except:
   20.46 +        inst = XendDomainConfig()
   20.47 +    return inst
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/tools/xen/lib/xend/XendDomainInfo.py	Fri Jun 25 15:10:48 2004 +0000
    21.3 @@ -0,0 +1,911 @@
    21.4 +#!/usr/bin/python
    21.5 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    21.6 +
    21.7 +"""Representation of a single domain.
    21.8 +Includes support for domain construction, using
    21.9 +open-ended configurations.
   21.10 +
   21.11 +Author: Mike Wray <mike.wray@hpl.hp.com>
   21.12 +
   21.13 +"""
   21.14 +
   21.15 +import string
   21.16 +import re
   21.17 +import sys
   21.18 +import os
   21.19 +
   21.20 +from twisted.internet import defer
   21.21 +
   21.22 +import xen.ext.xc; xc = xen.ext.xc.new()
   21.23 +import xenctl.ip
   21.24 +
   21.25 +import sxp
   21.26 +
   21.27 +import XendConsole
   21.28 +xendConsole = XendConsole.instance()
   21.29 +
   21.30 +import XendBridge
   21.31 +
   21.32 +import server.SrvDaemon
   21.33 +xend = server.SrvDaemon.instance()
   21.34 +
   21.35 +SIF_BLK_BE_DOMAIN = (1<<4)
   21.36 +SIF_NET_BE_DOMAIN = (1<<5)
   21.37 +
   21.38 +def readlines(fd):
   21.39 +    """Version of readlines safe against EINTR.
   21.40 +    """
   21.41 +    import errno
   21.42 +    
   21.43 +    lines = []
   21.44 +    while 1:
   21.45 +        try:
   21.46 +            line = fd.readline()
   21.47 +        except IOError, ex:
   21.48 +            if ex.errno == errno.EINTR:
   21.49 +                continue
   21.50 +            else:
   21.51 +                raise
   21.52 +        if line == '': break
   21.53 +        lines.append(line)
   21.54 +    return lines
   21.55 +
   21.56 +class VmError(ValueError):
   21.57 +    """Vm construction error."""
   21.58 +
   21.59 +    def __init__(self, value):
   21.60 +        self.value = value
   21.61 +
   21.62 +    def __str__(self):
   21.63 +        return self.value
   21.64 +
   21.65 +
   21.66 +def blkdev_name_to_number(name):
   21.67 +    """Take the given textual block-device name (e.g., '/dev/sda1',
   21.68 +    'hda') and return the device number used by the OS. """
   21.69 +
   21.70 +    if not re.match( '/dev/', name ):
   21.71 +        name = '/dev/' + name
   21.72 +        
   21.73 +    return os.stat(name).st_rdev
   21.74 +
   21.75 +def lookup_raw_partn(partition):
   21.76 +    """Take the given block-device name (e.g., '/dev/sda1', 'hda')
   21.77 +    and return a dictionary { device, start_sector,
   21.78 +    nr_sectors, type }
   21.79 +        device:       Device number of the given partition
   21.80 +        start_sector: Index of first sector of the partition
   21.81 +        nr_sectors:   Number of sectors comprising this partition
   21.82 +        type:         'Disk' or identifying name for partition type
   21.83 +    """
   21.84 +
   21.85 +    if not re.match( '/dev/', partition ):
   21.86 +        partition = '/dev/' + partition
   21.87 +
   21.88 +    drive = re.split( '[0-9]', partition )[0]
   21.89 +
   21.90 +    if drive == partition:
   21.91 +        fd = os.popen( '/sbin/sfdisk -s ' + drive + ' 2>/dev/null' )
   21.92 +        line = readline(fd)
   21.93 +        if line:
   21.94 +            return [ { 'device' : blkdev_name_to_number(drive),
   21.95 +                       'start_sector' : long(0),
   21.96 +                       'nr_sectors' : long(line) * 2,
   21.97 +                       'type' : 'Disk' } ]
   21.98 +        return None
   21.99 +
  21.100 +    # determine position on disk
  21.101 +    fd = os.popen( '/sbin/sfdisk -d ' + drive + ' 2>/dev/null' )
  21.102 +
  21.103 +    #['/dev/sda3 : start= 16948575, size=16836120, Id=83, bootable\012']
  21.104 +    lines = readlines(fd)
  21.105 +    for line in lines:
  21.106 +        m = re.search( '^' + partition + '\s*: start=\s*([0-9]+), ' +
  21.107 +                       'size=\s*([0-9]+), Id=\s*(\S+).*$', line)
  21.108 +        if m:
  21.109 +            return [ { 'device' : blkdev_name_to_number(drive),
  21.110 +                       'start_sector' : long(m.group(1)),
  21.111 +                       'nr_sectors' : long(m.group(2)),
  21.112 +                       'type' : m.group(3) } ]
  21.113 +    
  21.114 +    return None
  21.115 +
  21.116 +def lookup_disk_uname(uname):
  21.117 +    """Lookup a list of segments for a physical device.
  21.118 +    uname [string]:  name of the device in the format \'phy:dev\' for a physical device
  21.119 +    returns [list of dicts]: list of extents that make up the named device
  21.120 +    """
  21.121 +    ( type, d_name ) = string.split( uname, ':' )
  21.122 +
  21.123 +    if type == "phy":
  21.124 +        segments = lookup_raw_partn( d_name )
  21.125 +    else:
  21.126 +        segments = None
  21.127 +    return segments
  21.128 +
  21.129 +def make_disk(dom, uname, dev, mode, recreate=0):
  21.130 +    """Create a virtual disk device for a domain.
  21.131 +
  21.132 +    @returns Deferred
  21.133 +    """
  21.134 +    segments = lookup_disk_uname(uname)
  21.135 +    if not segments:
  21.136 +        raise VmError("vbd: Segments not found: uname=%s" % uname)
  21.137 +    if len(segments) > 1:
  21.138 +        raise VmError("vbd: Multi-segment vdisk: uname=%s" % uname)
  21.139 +    segment = segments[0]
  21.140 +    vdev = blkdev_name_to_number(dev)
  21.141 +    ctrl = xend.blkif_create(dom, recreate=recreate)
  21.142 +    
  21.143 +    def fn(ctrl):
  21.144 +        return xend.blkif_dev_create(dom, vdev, mode, segment, recreate=recreate)
  21.145 +    ctrl.addCallback(fn)
  21.146 +    return ctrl
  21.147 +        
  21.148 +def make_vif(dom, vif, vmac, recreate=0):
  21.149 +    """Create a virtual network device for a domain.
  21.150 +
  21.151 +    
  21.152 +    @returns Deferred
  21.153 +    """
  21.154 +    xend.netif_create(dom, recreate=recreate)
  21.155 +    d = xend.netif_dev_create(dom, vif, vmac, recreate=recreate)
  21.156 +    return d
  21.157 +
  21.158 +def vif_up(iplist):
  21.159 +    """send an unsolicited ARP reply for all non link-local IP addresses.
  21.160 +
  21.161 +    iplist IP addresses
  21.162 +    """
  21.163 +
  21.164 +    IP_NONLOCAL_BIND = '/proc/sys/net/ipv4/ip_nonlocal_bind'
  21.165 +    
  21.166 +    def get_ip_nonlocal_bind():
  21.167 +        return int(open(IP_NONLOCAL_BIND, 'r').read()[0])
  21.168 +
  21.169 +    def set_ip_nonlocal_bind(v):
  21.170 +        print >> open(IP_NONLOCAL_BIND, 'w'), str(v)
  21.171 +
  21.172 +    def link_local(ip):
  21.173 +        return xenctl.ip.check_subnet(ip, '169.254.0.0', '255.255.0.0')
  21.174 +
  21.175 +    def arping(ip, gw):
  21.176 +        cmd = '/usr/sbin/arping -A -b -I eth0 -c 1 -s %s %s' % (ip, gw)
  21.177 +        print cmd
  21.178 +        os.system(cmd)
  21.179 +        
  21.180 +    gateway = xenctl.ip.get_current_ipgw() or '255.255.255.255'
  21.181 +    nlb = get_ip_nonlocal_bind()
  21.182 +    if not nlb: set_ip_nonlocal_bind(1)
  21.183 +    try:
  21.184 +        for ip in iplist:
  21.185 +            if not link_local(ip):
  21.186 +                arping(ip, gateway)
  21.187 +    finally:
  21.188 +        if not nlb: set_ip_nonlocal_bind(0)
  21.189 +
  21.190 +config_handlers = {}
  21.191 +
  21.192 +def add_config_handler(name, h):
  21.193 +    """Add a handler for a config field.
  21.194 +
  21.195 +    name     field name
  21.196 +    h        handler: fn(vm, config, field, index)
  21.197 +    """
  21.198 +    config_handlers[name] = h
  21.199 +
  21.200 +def get_config_handler(name):
  21.201 +    """Get a handler for a config field.
  21.202 +
  21.203 +    returns handler or None
  21.204 +    """
  21.205 +    return config_handlers.get(name)
  21.206 +
  21.207 +"""Table of handlers for virtual machine images.
  21.208 +Indexed by image type.
  21.209 +"""
  21.210 +image_handlers = {}
  21.211 +
  21.212 +def add_image_handler(name, h):
  21.213 +    """Add a handler for an image type
  21.214 +    name     image type
  21.215 +    h        handler: fn(config, name, memory, image)
  21.216 +    """
  21.217 +    image_handlers[name] = h
  21.218 +
  21.219 +def get_image_handler(name):
  21.220 +    """Get the handler for an image type.
  21.221 +    name     image type
  21.222 +
  21.223 +    returns handler or None
  21.224 +    """
  21.225 +    return image_handlers.get(name)
  21.226 +
  21.227 +"""Table of handlers for devices.
  21.228 +Indexed by device type.
  21.229 +"""
  21.230 +device_handlers = {}
  21.231 +
  21.232 +def add_device_handler(name, h):
  21.233 +    """Add a handler for a device type.
  21.234 +
  21.235 +    name      device type
  21.236 +    h         handler: fn(vm, dev)
  21.237 +    """
  21.238 +    device_handlers[name] = h
  21.239 +
  21.240 +def get_device_handler(name):
  21.241 +    """Get the handler for a device type.
  21.242 +
  21.243 +    name      device type
  21.244 +
  21.245 +    returns handler or None
  21.246 +    """
  21.247 +    return device_handlers.get(name)
  21.248 +
  21.249 +def vm_create(config):
  21.250 +    """Create a VM from a configuration.
  21.251 +    If a vm has been partially created and there is an error it
  21.252 +    is destroyed.
  21.253 +
  21.254 +    config    configuration
  21.255 +
  21.256 +    returns Deferred
  21.257 +    raises VmError for invalid configuration
  21.258 +    """
  21.259 +    print 'vm_create>'
  21.260 +    vm = XendDomainInfo()
  21.261 +    return vm.construct(config)
  21.262 +
  21.263 +def vm_recreate(config, info):
  21.264 +    """Create the VM object for an existing domain.
  21.265 +    """
  21.266 +    vm = XendDomainInfo()
  21.267 +    vm.recreate = 1
  21.268 +    vm.setdom(info['dom'])
  21.269 +    vm.name = info['name']
  21.270 +    vm.memory = info['mem_kb']/1024
  21.271 +    if config:
  21.272 +        d = vm.construct(config)
  21.273 +    else:
  21.274 +        d = defer.Deferred()
  21.275 +        d.callback(vm)
  21.276 +    return d
  21.277 +
  21.278 +def vm_restore(src, config, progress=0):
  21.279 +    """Restore a VM from a disk image.
  21.280 +
  21.281 +    src      saved state to restore
  21.282 +    config   configuration
  21.283 +    progress progress reporting flag
  21.284 +    returns  deferred
  21.285 +    raises   VmError for invalid configuration
  21.286 +    """
  21.287 +    vm = XendDomainInfo()
  21.288 +    vm.config = config
  21.289 +    ostype = "linux" #todo set from config
  21.290 +    restorefn = getattr(xc, "%s_restore" % ostype)
  21.291 +    dom = restorefn(state_file=src, progress=progress)
  21.292 +    if dom < 0:
  21.293 +        raise VMError('restore failed')
  21.294 +    deferred = vm.dom_configure(dom)
  21.295 +    def vifs_cb(val, vm):
  21.296 +        vif_up(vm.ipaddrs)
  21.297 +    deferred.addCallback(vifs_cb, vm)
  21.298 +    return deferred
  21.299 +    
  21.300 +def dom_get(dom):
  21.301 +    domlist = xc.domain_getinfo(dom=dom)
  21.302 +    if domlist and dom == domlist[0]['dom']:
  21.303 +        return domlist[0]
  21.304 +    return None
  21.305 +    
  21.306 +
  21.307 +def append_deferred(dlist, v):
  21.308 +    if isinstance(v, defer.Deferred):
  21.309 +        dlist.append(v)
  21.310 +
  21.311 +def _vm_configure1(val, vm):
  21.312 +    d = vm.create_devices()
  21.313 +    print '_vm_configure1> made devices...'
  21.314 +    def cbok(x):
  21.315 +        print '_vm_configure1> cbok', x
  21.316 +        return x
  21.317 +    d.addCallback(cbok)
  21.318 +    d.addCallback(_vm_configure2, vm)
  21.319 +    print '_vm_configure1<'
  21.320 +    return d
  21.321 +
  21.322 +def _vm_configure2(val, vm):
  21.323 +    print '>callback _vm_configure2...'
  21.324 +    d = vm.configure_fields()
  21.325 +    def cbok(results):
  21.326 +        print '_vm_configure2> cbok', results
  21.327 +        return vm
  21.328 +    def cberr(err):
  21.329 +        print '_vm_configure2> cberr', err
  21.330 +        vm.destroy()
  21.331 +        return err
  21.332 +    d.addCallback(cbok)
  21.333 +    d.addErrback(cberr)
  21.334 +    print '<_vm_configure2'
  21.335 +    return d
  21.336 +
  21.337 +class XendDomainInfo:
  21.338 +    """Virtual machine object."""
  21.339 +
  21.340 +    def __init__(self):
  21.341 +        self.recreate = 0
  21.342 +        self.config = None
  21.343 +        self.id = None
  21.344 +        self.dom = None
  21.345 +        self.name = None
  21.346 +        self.memory = None
  21.347 +        self.image = None
  21.348 +        self.ramdisk = None
  21.349 +        self.cmdline = None
  21.350 +        self.console = None
  21.351 +        self.devices = {}
  21.352 +        self.configs = []
  21.353 +        self.info = None
  21.354 +        self.ipaddrs = []
  21.355 +        self.blkif_backend = 0
  21.356 +        self.netif_backend = 0
  21.357 +        #todo: state: running, suspended
  21.358 +        self.state = 'running'
  21.359 +        #todo: set to migrate info if migrating
  21.360 +        self.migrate = None
  21.361 +
  21.362 +    def setdom(self, dom):
  21.363 +        self.dom = int(dom)
  21.364 +        self.id = str(dom)
  21.365 +        
  21.366 +    def update(self, info):
  21.367 +        """Update with  info from xc.domain_getinfo().
  21.368 +        """
  21.369 +        self.info = info
  21.370 +        self.memory = self.info['mem_kb'] / 1024
  21.371 +
  21.372 +    def __str__(self):
  21.373 +        s = "domain"
  21.374 +        s += " id=" + self.id
  21.375 +        s += " name=" + self.name
  21.376 +        s += " memory=" + str(self.memory)
  21.377 +        if self.console:
  21.378 +            s += " console=" + self.console.id
  21.379 +        if self.image:
  21.380 +            s += " image=" + self.image
  21.381 +        s += ""
  21.382 +        return s
  21.383 +
  21.384 +    __repr__ = __str__
  21.385 +
  21.386 +    def sxpr(self):
  21.387 +        sxpr = ['domain',
  21.388 +                ['id', self.id],
  21.389 +                ['name', self.name],
  21.390 +                ['memory', self.memory] ]
  21.391 +        if self.info:
  21.392 +            run   = (self.info['running'] and 'r') or '-'
  21.393 +            block = (self.info['blocked'] and 'b') or '-'
  21.394 +            stop  = (self.info['paused']  and 'p') or '-'
  21.395 +            susp  = (self.info['shutdown'] and 's') or '-'
  21.396 +            crash = (self.info['crashed'] and 'c') or '-'
  21.397 +            state = run + block + stop + susp + crash
  21.398 +            sxpr.append(['state', state])
  21.399 +            if self.info['shutdown']:
  21.400 +                reasons = ["poweroff", "reboot", "suspend"]
  21.401 +                reason = reasons[self.info['shutdown_reason']]
  21.402 +                sxpr.append(['shutdown_reason', reason])
  21.403 +            sxpr.append(['cpu', self.info['cpu']])
  21.404 +            sxpr.append(['cpu_time', self.info['cpu_time']/1e9])
  21.405 +        if self.console:
  21.406 +            sxpr.append(self.console.sxpr())
  21.407 +        if self.config:
  21.408 +            sxpr.append(['config', self.config])
  21.409 +        return sxpr
  21.410 +
  21.411 +    def construct(self, config):
  21.412 +        # todo - add support for scheduling params?
  21.413 +        self.config = config
  21.414 +        try:
  21.415 +            self.name = sxp.child_value(config, 'name')
  21.416 +            self.memory = int(sxp.child_value(config, 'memory', '128'))
  21.417 +            self.configure_backends()
  21.418 +            image = sxp.child_value(config, 'image')
  21.419 +            image_name = sxp.name(image)
  21.420 +            image_handler = get_image_handler(image_name)
  21.421 +            if image_handler is None:
  21.422 +                raise VmError('unknown image type: ' + image_name)
  21.423 +            image_handler(self, image)
  21.424 +            deferred = self.configure()
  21.425 +        except StandardError, ex:
  21.426 +            # Catch errors, cleanup and re-raise.
  21.427 +            self.destroy()
  21.428 +            raise
  21.429 +        def cbok(x):
  21.430 +            print 'vm_create> cbok', x
  21.431 +            return x
  21.432 +        deferred.addCallback(cbok)
  21.433 +        print 'vm_create<'
  21.434 +        return deferred
  21.435 +
  21.436 +    def config_devices(self, name):
  21.437 +        """Get a list of the 'device' nodes of a given type from the config.
  21.438 +
  21.439 +        name	device type
  21.440 +        return list of device configs
  21.441 +        """
  21.442 +        devices = []
  21.443 +        for d in sxp.children(self.config, 'device'):
  21.444 +            dev = sxp.child0(d)
  21.445 +            if dev is None: continue
  21.446 +            if name == sxp.name(dev):
  21.447 +                devices.append(dev)
  21.448 +        return devices
  21.449 +
  21.450 +    def add_device(self, type, dev):
  21.451 +        """Add a device to a virtual machine.
  21.452 +
  21.453 +        dev      device to add
  21.454 +        """
  21.455 +        dl = self.devices.get(type, [])
  21.456 +        dl.append(dev)
  21.457 +        self.devices[type] = dl
  21.458 +
  21.459 +    def get_devices(self, type):
  21.460 +        val = self.devices.get(type, [])
  21.461 +        return val
  21.462 +
  21.463 +    def get_device_by_id(self, type, id):
  21.464 +        """Get the device with the given id.
  21.465 +
  21.466 +        id       device id
  21.467 +
  21.468 +        returns  device or None
  21.469 +        """
  21.470 +        dl = self.get_devices(type)
  21.471 +        for d in dl:
  21.472 +            if d.getprop('id') == id:
  21.473 +                return d
  21.474 +        return None
  21.475 +
  21.476 +    def get_device_by_index(self, type, idx):
  21.477 +        """Get the device with the given index.
  21.478 +
  21.479 +        idx       device index
  21.480 +
  21.481 +        returns  device or None
  21.482 +        """
  21.483 +        dl = self.get_devices(type)
  21.484 +        if 0 <= idx < len(dl):
  21.485 +            return dl[idx]
  21.486 +        else:
  21.487 +            return None
  21.488 +
  21.489 +    def add_config(self, val):
  21.490 +        """Add configuration data to a virtual machine.
  21.491 +
  21.492 +        val      data to add
  21.493 +        """
  21.494 +        self.configs.append(val)
  21.495 +
  21.496 +    def destroy(self):
  21.497 +        if self.dom <= 0:
  21.498 +            return 0
  21.499 +        return xc.domain_destroy(dom=self.dom)
  21.500 +
  21.501 +    def died(self):
  21.502 +        print 'died>', self.dom
  21.503 +        self.release_devices()
  21.504 +
  21.505 +    def release_devices(self):
  21.506 +        print 'release_devices>', self.dom
  21.507 +        self.release_vifs()
  21.508 +        self.release_vbds()
  21.509 +        self.devices = {}
  21.510 +
  21.511 +    def release_vifs(self):
  21.512 +        print 'release_vifs>', self.dom
  21.513 +        if self.dom is None: return
  21.514 +        ctrl = xend.netif_get(self.dom)
  21.515 +        if ctrl:
  21.516 +            ctrl.destroy()
  21.517 +
  21.518 +    def release_vbds(self):
  21.519 +        print 'release_vbds>', self.dom
  21.520 +        if self.dom is None: return
  21.521 +        ctrl = xend.blkif_get(self.dom)
  21.522 +        if ctrl:
  21.523 +            ctrl.destroy()
  21.524 +
  21.525 +    def show(self):
  21.526 +        """Print virtual machine info.
  21.527 +        """
  21.528 +        print "[VM dom=%d name=%s memory=%d" % (self.dom, self.name, self.memory)
  21.529 +        print "image:"
  21.530 +        sxp.show(self.image)
  21.531 +        print
  21.532 +        for dl in self.devices:
  21.533 +            for dev in dl:
  21.534 +                print "device:"
  21.535 +                sxp.show(dev)
  21.536 +                print
  21.537 +        for val in self.configs:
  21.538 +            print "config:"
  21.539 +            sxp.show(val)
  21.540 +            print
  21.541 +        print "]"
  21.542 +
  21.543 +    def init_domain(self):
  21.544 +        """Initialize the domain memory.
  21.545 +        """
  21.546 +        if self.recreate: return
  21.547 +        memory = self.memory
  21.548 +        name = self.name
  21.549 +        cpu = int(sxp.child_value(self.config, 'cpu', '-1'))
  21.550 +        print 'init_domain>', memory, name, cpu
  21.551 +        dom = xc.domain_create(mem_kb= memory * 1024, name= name, cpu= cpu)
  21.552 +        if dom <= 0:
  21.553 +            raise VmError('Creating domain failed: name=%s memory=%d'
  21.554 +                          % (name, memory))
  21.555 +        self.setdom(dom)
  21.556 +
  21.557 +    def build_domain(self, ostype, kernel, ramdisk, cmdline, vifs_n):
  21.558 +        """Build the domain boot image.
  21.559 +        """
  21.560 +        if self.recreate: return
  21.561 +        if len(cmdline) >= 256:
  21.562 +            print 'Warning: kernel cmdline too long'
  21.563 +        dom = self.dom
  21.564 +        buildfn = getattr(xc, '%s_build' % ostype)
  21.565 +        print 'build_domain>', ostype, dom, kernel, cmdline, ramdisk
  21.566 +        flags = 0
  21.567 +        if self.netif_backend: flags |= SIF_NET_BE_DOMAIN
  21.568 +        if self.blkif_backend: flags |= SIF_BLK_BE_DOMAIN
  21.569 +        err = buildfn(dom            = dom,
  21.570 +                      image          = kernel,
  21.571 +                      control_evtchn = self.console.port2,
  21.572 +                      cmdline        = cmdline,
  21.573 +                      ramdisk        = ramdisk,
  21.574 +                      flags          = flags)
  21.575 +        if err != 0:
  21.576 +            raise VmError('Building domain failed: type=%s dom=%d err=%d'
  21.577 +                          % (ostype, dom, err))
  21.578 +
  21.579 +    def create_domain(self, ostype, kernel, ramdisk, cmdline, vifs_n):
  21.580 +        """Create a domain. Builds the image but does not configure it.
  21.581 +
  21.582 +        ostype  OS type
  21.583 +        kernel  kernel image
  21.584 +        ramdisk kernel ramdisk
  21.585 +        cmdline kernel commandline
  21.586 +        vifs_n  number of network interfaces
  21.587 +        """
  21.588 +        print 'create_domain>', ostype, kernel
  21.589 +        if not self.recreate:
  21.590 +            if not os.path.isfile(kernel):
  21.591 +                raise VmError('Kernel image does not exist: %s' % kernel)
  21.592 +            if ramdisk and not os.path.isfile(ramdisk):
  21.593 +                raise VMError('Kernel ramdisk does not exist: %s' % ramdisk)
  21.594 +        print 'create-domain> init_domain...'
  21.595 +        self.init_domain()
  21.596 +        print 'create_domain>', 'dom=', self.dom
  21.597 +        self.console = xendConsole.console_create(self.dom)
  21.598 +        self.build_domain(ostype, kernel, ramdisk, cmdline, vifs_n)
  21.599 +        self.image = kernel
  21.600 +        self.ramdisk = ramdisk
  21.601 +        self.cmdline = cmdline
  21.602 +
  21.603 +    def create_devices(self):
  21.604 +        """Create the devices for a vm.
  21.605 +
  21.606 +        returns Deferred
  21.607 +        raises VmError for invalid devices
  21.608 +        """
  21.609 +        print '>create_devices'
  21.610 +        dlist = []
  21.611 +        devices = sxp.children(self.config, 'device')
  21.612 +        index = {}
  21.613 +        for d in devices:
  21.614 +            dev = sxp.child0(d)
  21.615 +            if dev is None:
  21.616 +                raise VmError('invalid device')
  21.617 +            dev_name = sxp.name(dev)
  21.618 +            dev_index = index.get(dev_name, 0)
  21.619 +            dev_handler = get_device_handler(dev_name)
  21.620 +            if dev_handler is None:
  21.621 +                raise VmError('unknown device type: ' + dev_name)
  21.622 +            v = dev_handler(self, dev, dev_index)
  21.623 +            append_deferred(dlist, v)
  21.624 +            index[dev_name] = dev_index + 1
  21.625 +        deferred = defer.DeferredList(dlist, fireOnOneErrback=1)
  21.626 +        print '<create_devices'
  21.627 +        return deferred
  21.628 +
  21.629 +    def configure_backends(self):
  21.630 +        """Set configuration flags if the vm is a backend for netif of blkif.
  21.631 +        """
  21.632 +        for c in sxp.children(self.config, 'backend'):
  21.633 +            name = sxp.name(c)
  21.634 +            if name == 'blkif':
  21.635 +                self.blkif_backend = 1
  21.636 +            elif name == 'netif':
  21.637 +                self.netif_backend = 1
  21.638 +            else:
  21.639 +                raise VmError('invalid backend type:' + str(name))
  21.640 +
  21.641 +    def create_backends(self):
  21.642 +        """Setup the netif and blkif backends.
  21.643 +        """
  21.644 +        if self.blkif_backend:
  21.645 +            xend.blkif_set_control_domain(self.dom, recreate=self.recreate)
  21.646 +        if self.netif_backend:
  21.647 +            xend.netif_set_control_domain(self.dom, recreate=self.recreate)
  21.648 +            
  21.649 +    def configure(self):
  21.650 +        """Configure a vm.
  21.651 +
  21.652 +        vm         virtual machine
  21.653 +        config     configuration
  21.654 +
  21.655 +        returns Deferred - calls callback with vm
  21.656 +        """
  21.657 +        if self.blkif_backend:
  21.658 +            d = defer.Deferred()
  21.659 +            d.callback(1)
  21.660 +        else:
  21.661 +            d = xend.blkif_create(self.dom, recreate=self.recreate)
  21.662 +        d.addCallback(_vm_configure1, self)
  21.663 +        return d
  21.664 +
  21.665 +    def dom_configure(self, dom):
  21.666 +        """Configure a domain.
  21.667 +
  21.668 +        dom    domain id
  21.669 +        returns deferred
  21.670 +        """
  21.671 +        d = dom_get(dom)
  21.672 +        if not d:
  21.673 +            raise VMError("Domain not found: %d" % dom)
  21.674 +        try:
  21.675 +            self.setdom(dom)
  21.676 +            self.name = d['name']
  21.677 +            self.memory = d['memory']/1024
  21.678 +            deferred = self.configure()
  21.679 +        except StandardError, ex:
  21.680 +            self.destroy()
  21.681 +            raise
  21.682 +        return deferred
  21.683 +
  21.684 +    def configure_fields(self):
  21.685 +        dlist = []
  21.686 +        index = {}
  21.687 +        for field in sxp.children(self.config):
  21.688 +            field_name = sxp.name(field)
  21.689 +            field_index = index.get(field_name, 0)
  21.690 +            field_handler = get_config_handler(field_name)
  21.691 +            # Ignore unknown fields. Warn?
  21.692 +            if field_handler:
  21.693 +                v = field_handler(self, self.config, field, field_index)
  21.694 +                append_deferred(dlist, v)
  21.695 +            index[field_name] = field_index + 1
  21.696 +        d = defer.DeferredList(dlist, fireOnOneErrback=1)
  21.697 +        return d
  21.698 +
  21.699 +
  21.700 +def vm_image_linux(vm, image):
  21.701 +    """Create a VM for a linux image.
  21.702 +
  21.703 +    name      vm name
  21.704 +    memory    vm memory
  21.705 +    image     image config
  21.706 +
  21.707 +    returns vm
  21.708 +    """
  21.709 +    kernel = sxp.child_value(image, "kernel")
  21.710 +    cmdline = ""
  21.711 +    ip = sxp.child_value(image, "ip", "dhcp")
  21.712 +    if ip:
  21.713 +        cmdline += " ip=" + ip
  21.714 +    root = sxp.child_value(image, "root")
  21.715 +    if root:
  21.716 +        cmdline += " root=" + root
  21.717 +    args = sxp.child_value(image, "args")
  21.718 +    if args:
  21.719 +        cmdline += " " + args
  21.720 +    ramdisk = sxp.child_value(image, "ramdisk", '')
  21.721 +    vifs = vm.config_devices("vif")
  21.722 +    vm.create_domain("linux", kernel, ramdisk, cmdline, len(vifs))
  21.723 +    return vm
  21.724 +
  21.725 +def vm_image_netbsd(vm, image):
  21.726 +    """Create a VM for a bsd image.
  21.727 +
  21.728 +    name      vm name
  21.729 +    memory    vm memory
  21.730 +    image     image config
  21.731 +
  21.732 +    returns vm
  21.733 +    """
  21.734 +    #todo: Same as for linux. Is that right? If so can unify them.
  21.735 +    kernel = sxp.child_value(image, "kernel")
  21.736 +    cmdline = ""
  21.737 +    ip = sxp.child_value(image, "ip", "dhcp")
  21.738 +    if ip:
  21.739 +        cmdline += "ip=" + ip
  21.740 +    root = sxp.child_value(image, "root")
  21.741 +    if root:
  21.742 +        cmdline += "root=" + root
  21.743 +    args = sxp.child_value(image, "args")
  21.744 +    if args:
  21.745 +        cmdline += " " + args
  21.746 +    ramdisk = sxp.child_value(image, "ramdisk")
  21.747 +    vifs = vm.config_devices("vif")
  21.748 +    vm.create_domain("netbsd", kernel, ramdisk, cmdline, len(vifs))
  21.749 +    return vm
  21.750 +
  21.751 +
  21.752 +def vm_dev_vif(vm, val, index):
  21.753 +    """Create a virtual network interface (vif).
  21.754 +
  21.755 +    vm        virtual machine
  21.756 +    val       vif config
  21.757 +    index     vif index
  21.758 +    """
  21.759 +    if vm.netif_backend:
  21.760 +        raise VmError('vif: vif in netif backend domain')
  21.761 +    vif = index #todo
  21.762 +    vmac = sxp.child_value(val, "mac")
  21.763 +    defer = make_vif(vm.dom, vif, vmac, vm.recreate)
  21.764 +    def fn(id):
  21.765 +        dev = xend.netif_dev(vm.dom, vif)
  21.766 +        devid = sxp.attribute(val, 'id')
  21.767 +        if devid:
  21.768 +            dev.setprop('id', devid)
  21.769 +        bridge = sxp.child_value(val, "bridge")
  21.770 +        dev.bridge_add(bridge)
  21.771 +        vm.add_device('vif', dev)
  21.772 +        print 'vm_dev_vif> created', dev
  21.773 +        return id
  21.774 +    defer.addCallback(fn)
  21.775 +    return defer
  21.776 +
  21.777 +def vm_dev_vbd(vm, val, index):
  21.778 +    """Create a virtual block device (vbd).
  21.779 +
  21.780 +    vm        virtual machine
  21.781 +    val       vbd config
  21.782 +    index     vbd index
  21.783 +    """
  21.784 +    if vm.blkif_backend:
  21.785 +        raise VmError('vbd: vbd in blkif backend domain')
  21.786 +    vdev = index
  21.787 +    uname = sxp.child_value(val, 'uname')
  21.788 +    if not uname:
  21.789 +        raise VMError('vbd: Missing uname')
  21.790 +    dev = sxp.child_value(val, 'dev')
  21.791 +    if not dev:
  21.792 +        raise VMError('vbd: Missing dev')
  21.793 +    mode = sxp.child_value(val, 'mode', 'r')
  21.794 +    defer = make_disk(vm.dom, uname, dev, mode, vm.recreate)
  21.795 +    def fn(vbd):
  21.796 +        dev = xend.blkif_dev(vm.dom, vdev)
  21.797 +        vm.add_device('vbd', dev)
  21.798 +        return vbd
  21.799 +    defer.addCallback(fn)
  21.800 +    return defer
  21.801 +
  21.802 +def parse_pci(val):
  21.803 +    if isinstance(val, StringType):
  21.804 +        radix = 10
  21.805 +        if val.startswith('0x') or val.startswith('0X'):
  21.806 +            radix = 16
  21.807 +        v = int(val, radix)
  21.808 +    else:
  21.809 +        v = val
  21.810 +    return v
  21.811 +
  21.812 +def vm_dev_pci(vm, val, index):
  21.813 +    bus = sxp.child_value(val, 'bus')
  21.814 +    if not bus:
  21.815 +        raise VMError('pci: Missing bus')
  21.816 +    dev = sxp.child_value(val, 'dev')
  21.817 +    if not dev:
  21.818 +        raise VMError('pci: Missing dev')
  21.819 +    func = sxp.child_value(val, 'func')
  21.820 +    if not func:
  21.821 +        raise VMError('pci: Missing func')
  21.822 +    try:
  21.823 +        bus = parse_pci(bus)
  21.824 +        dev = parse_pci(dev)
  21.825 +        func = parse_pci(func)
  21.826 +    except:
  21.827 +        raise VMError('pci: invalid parameter')
  21.828 +    rc = xc.physdev_pci_access_modify(dom=vm.dom, bus=bus, dev=dev,
  21.829 +                                      func=func, enable=1)
  21.830 +    if rc < 0:
  21.831 +        #todo non-fatal
  21.832 +        raise VMError('pci: Failed to configure device: bus=%s dev=%s func=%s' %
  21.833 +                      (bus, dev, func))
  21.834 +    return rc
  21.835 +    
  21.836 +
  21.837 +def vm_field_vfr(vm, config, val, index):
  21.838 +    """Handle a vfr field in a config.
  21.839 +
  21.840 +    vm        virtual machine
  21.841 +    config    vm config
  21.842 +    val       vfr field
  21.843 +    """
  21.844 +    # Get the rules and add them.
  21.845 +    # (vfr (vif (id foo) (ip x.x.x.x)) ... ) 
  21.846 +    list = sxp.children(val, 'vif')
  21.847 +    ipaddrs = []
  21.848 +    for v in list:
  21.849 +        id = sxp.child_value(v, 'id')
  21.850 +        if id is None:
  21.851 +            raise VmError('vfr: missing vif id')
  21.852 +        id = int(id)
  21.853 +        dev = vm.get_device_by_index('vif', id)
  21.854 +        if not dev:
  21.855 +            raise VmError('vfr: invalid vif id %d' % id)
  21.856 +        vif = sxp.child_value(dev, 'vif')
  21.857 +        ip = sxp.child_value(v, 'ip')
  21.858 +        if not ip:
  21.859 +            raise VmError('vfr: missing ip address')
  21.860 +        ipaddrs.append(ip);
  21.861 +        #Don't do this in new i/o model.
  21.862 +        #print 'vm_field_vfr> add rule', 'dom=', vm.dom, 'vif=', vif, 'ip=', ip
  21.863 +        #xenctl.ip.setup_vfr_rules_for_vif(vm.dom, vif, ip)
  21.864 +    vm.ipaddrs = ipaddrs
  21.865 +
  21.866 +def vnet_bridge(vnet, vmac, dom, idx):
  21.867 +    """Add the device for the vif to the bridge for its vnet.
  21.868 +    """
  21.869 +    vif = "vif%d.%d" % (dom, idx)
  21.870 +    try:
  21.871 +        cmd = "(vif.conn (vif %s) (vnet %s) (vmac %s))" % (vif, vnet, vmac)
  21.872 +        print "*** vnet_bridge>", cmd
  21.873 +        out = file("/proc/vnet/policy", "wb")
  21.874 +        out.write(cmd)
  21.875 +        err = out.close()
  21.876 +        print "vnet_bridge>", "err=", err
  21.877 +    except IOError, ex:
  21.878 +        print "vnet_bridge>", ex
  21.879 +    
  21.880 +def vm_field_vnet(vm, config, val, index):
  21.881 +    """Handle a vnet field in a config.
  21.882 +
  21.883 +    vm        virtual machine
  21.884 +    config    vm config
  21.885 +    val       vnet field
  21.886 +    index     index
  21.887 +    """
  21.888 +    # Get the vif children. For each vif look up the vif device
  21.889 +    # with the given id and configure its vnet.
  21.890 +    # (vnet (vif (id foo) (vnet 2) (mac x:x:x:x:x:x)) ... )
  21.891 +    vif_vnets = sxp.children(val, 'vif')
  21.892 +    for v in vif_vnets:
  21.893 +        id = sxp.child_value(v, 'id')
  21.894 +        if id is None:
  21.895 +            raise VmError('vnet: missing vif id')
  21.896 +        dev = vm.get_device_by_id('vif', id)
  21.897 +        #vnet = sxp.child_value(v, 'vnet', 1)
  21.898 +        #mac = sxp.child_value(dev, 'mac')
  21.899 +        #vif = sxp.child_value(dev, 'vif')
  21.900 +        #vnet_bridge(vnet, mac, vm.dom, 0)
  21.901 +        #vm.add_config([ 'vif.vnet', ['id', id], ['vnet', vnet], ['mac', mac]])
  21.902 +
  21.903 +# Register image handlers for linux and bsd.
  21.904 +add_image_handler('linux',  vm_image_linux)
  21.905 +add_image_handler('netbsd', vm_image_netbsd)
  21.906 +
  21.907 +# Register device handlers for vifs and vbds.
  21.908 +add_device_handler('vif',  vm_dev_vif)
  21.909 +add_device_handler('vbd',  vm_dev_vbd)
  21.910 +add_device_handler('pci',  vm_dev_pci)
  21.911 +
  21.912 +# Register config handlers for vfr and vnet.
  21.913 +add_config_handler('vfr',  vm_field_vfr)
  21.914 +add_config_handler('vnet', vm_field_vnet)
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/tools/xen/lib/xend/XendMigrate.py	Fri Jun 25 15:10:48 2004 +0000
    22.3 @@ -0,0 +1,103 @@
    22.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    22.5 +
    22.6 +import sys
    22.7 +import socket
    22.8 +
    22.9 +import sxp
   22.10 +import XendDB
   22.11 +import EventServer; eserver = EventServer.instance()
   22.12 +
   22.13 +class XendMigrateInfo:
   22.14 +
   22.15 +    # states: begin, active, failed, succeeded?
   22.16 +
   22.17 +    def __init__(self, id, dom, dst):
   22.18 +        self.id = id
   22.19 +        self.state = 'begin'
   22.20 +        self.src_host = socket.gethostname()
   22.21 +        self.src_dom = dom
   22.22 +        self.dst_host = dst
   22.23 +        self.dst_dom = None
   22.24 +        
   22.25 +    def set_state(self, state):
   22.26 +        self.state = state
   22.27 +
   22.28 +    def get_state(self):
   22.29 +        return self.state
   22.30 +
   22.31 +    def sxpr(self):
   22.32 +        sxpr = ['migrate', ['id', self.id], ['state', self.state] ]
   22.33 +        sxpr_src = ['src', ['host', self.src_host], ['domain', self.src_dom] ]
   22.34 +        sxpr.append(sxpr_src)
   22.35 +        sxpr_dst = ['dst', ['host', self.dst] ]
   22.36 +        if self.dst_dom:
   22.37 +            sxpr_dst.append(['domain', self.dst_dom])
   22.38 +        sxpr.append(sxpr_dst)
   22.39 +        return sxpr
   22.40 +    
   22.41 +
   22.42 +class XendMigrate:
   22.43 +    # Represents migration in progress.
   22.44 +    # Use log for indications of begin/end/errors?
   22.45 +    # Need logging of: domain create/halt, migrate begin/end/fail
   22.46 +    # Log via event server?
   22.47 +
   22.48 +    dbpath = "migrate"
   22.49 +    
   22.50 +    def __init__(self):
   22.51 +        self.db = XendDB.XendDB(self.dbpath)
   22.52 +        self.migrate = {}
   22.53 +        self.migrate_db = self.db.fetchall("")
   22.54 +        self.id = 0
   22.55 +
   22.56 +    def nextid(self):
   22.57 +        self.id += 1
   22.58 +        return "%d" % self.id
   22.59 +
   22.60 +    def sync(self):
   22.61 +        self.db.saveall("", self.migrate_db)
   22.62 +
   22.63 +    def sync_migrate(self, id):
   22.64 +        self.db.save(id, self.migrate_db[id])
   22.65 +
   22.66 +    def close(self):
   22.67 +        pass
   22.68 +
   22.69 +    def _add_migrate(self, id, info):
   22.70 +        self.migrate[id] = info
   22.71 +        self.migrate_db[id] = info.sxpr()
   22.72 +        self.sync_migrate(id)
   22.73 +        #eserver.inject('xend.migrate.begin', info.sxpr())
   22.74 +
   22.75 +    def _delete_migrate(self, id):
   22.76 +        #eserver.inject('xend.migrate.end', id)
   22.77 +        del self.migrate[id]
   22.78 +        del self.migrate_db[id]
   22.79 +        self.db.delete(id)
   22.80 +
   22.81 +    def migrate_ls(self):
   22.82 +        return self.migrate.keys()
   22.83 +
   22.84 +    def migrates(self):
   22.85 +        return self.migrate.values()
   22.86 +
   22.87 +    def migrate_get(self, id):
   22.88 +        return self.migrate.get(id)
   22.89 +    
   22.90 +    def migrate_begin(self, dom, dst):
   22.91 +        # Check dom for existence, not migrating already.
   22.92 +        # Create migrate info, tell xend to migrate it?
   22.93 +        # - or fork migrate command ourselves?
   22.94 +        # Subscribe to migrate notifications (for updating).
   22.95 +        id = self.nextid()
   22.96 +        info = XenMigrateInfo(id, dom, dst)
   22.97 +        self._add_migrate(id, info)
   22.98 +        return id
   22.99 +
  22.100 +def instance():
  22.101 +    global inst
  22.102 +    try:
  22.103 +        inst
  22.104 +    except:
  22.105 +        inst = XendMigrate()
  22.106 +    return inst
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/tools/xen/lib/xend/XendNode.py	Fri Jun 25 15:10:48 2004 +0000
    23.3 @@ -0,0 +1,71 @@
    23.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    23.5 +
    23.6 +"""Handler for node operations.
    23.7 + Has some persistent state:
    23.8 + - logs
    23.9 + - notification urls
   23.10 +
   23.11 +"""
   23.12 +
   23.13 +import os
   23.14 +import xen.ext.xc
   23.15 +
   23.16 +class XendNode:
   23.17 +
   23.18 +    def __init__(self):
   23.19 +        self.xc = xen.ext.xc.new()
   23.20 +
   23.21 +    def shutdown(self):
   23.22 +        return 0
   23.23 +
   23.24 +    def reboot(self):
   23.25 +        return 0
   23.26 +
   23.27 +    def notify(self, uri):
   23.28 +        return 0
   23.29 +    
   23.30 +    def cpu_bvt_slice_set(self, slice):
   23.31 +        ret = 0
   23.32 +        #ret = self.xc.bvtsched_global_set(ctx_allow=slice)
   23.33 +        return ret
   23.34 +
   23.35 +    def cpu_bvt_slice_get(self, slice):
   23.36 +        ret = 0
   23.37 +        #ret = self.xc.bvtsched_global_get()
   23.38 +        return ret
   23.39 +    
   23.40 +    def cpu_rrobin_slice_set(self, slice):
   23.41 +        ret = 0
   23.42 +        #ret = self.xc.rrobin_global_set(slice)
   23.43 +        return ret
   23.44 +
   23.45 +    def info(self):
   23.46 +        return self.nodeinfo() + self.physinfo()
   23.47 +
   23.48 +    def nodeinfo(self):
   23.49 +        (sys, host, rel, ver, mch) = os.uname()
   23.50 +        return [['system',  sys],
   23.51 +                ['host',    host],
   23.52 +                ['release', rel],
   23.53 +                ['version', ver],
   23.54 +                ['machine', mch]]
   23.55 +
   23.56 +    def physinfo(self):
   23.57 +        pinfo = self.xc.physinfo()
   23.58 +        info = [['cores', pinfo['cores']],
   23.59 +                ['hyperthreads_per_core', pinfo['ht_per_core']],
   23.60 +                ['cpu_mhz', pinfo['cpu_khz']/1000],
   23.61 +                ['memory', pinfo['total_pages']/256],
   23.62 +                ['free_memory', pinfo['free_pages']/256]]
   23.63 +        return info
   23.64 +        
   23.65 +        
   23.66 +
   23.67 +def instance():
   23.68 +    global inst
   23.69 +    try:
   23.70 +        inst
   23.71 +    except:
   23.72 +        inst = XendNode()
   23.73 +    return inst
   23.74 +
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/tools/xen/lib/xend/XendRoot.py	Fri Jun 25 15:10:48 2004 +0000
    24.3 @@ -0,0 +1,156 @@
    24.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    24.5 +
    24.6 +"""Xend root class.
    24.7 +Creates the event server and handles configuration.
    24.8 +"""
    24.9 +
   24.10 +import os
   24.11 +import os.path
   24.12 +import sys
   24.13 +import EventServer
   24.14 +
   24.15 +# Initial create of the event server.
   24.16 +eserver = EventServer.instance()
   24.17 +
   24.18 +import sxp
   24.19 +
   24.20 +def reboots():
   24.21 +    """Get a list of system reboots from wtmp.
   24.22 +    """
   24.23 +    out = os.popen('/usr/bin/last reboot', 'r')
   24.24 +    list = [ x.strip() for x in out if x.startswith('reboot') ]
   24.25 +    return list
   24.26 +
   24.27 +def last_reboot():
   24.28 +    """Get the last known system reboot.
   24.29 +    """
   24.30 +    l = reboots()
   24.31 +    return (l and l[-1]) or None
   24.32 +
   24.33 +class XendRoot:
   24.34 +    """Root of the management classes."""
   24.35 +
   24.36 +    lastboot_default = "/var/xen/lastboot"
   24.37 +
   24.38 +    """Default path to the root of the database."""
   24.39 +    dbroot_default = "/var/xen/xend-db"
   24.40 +
   24.41 +    """Default path to the config file."""
   24.42 +    config_default = "/etc/xen/xend-config.sxp"
   24.43 +
   24.44 +    """Environment variable used to override config_default."""
   24.45 +    config_var     = "XEND_CONFIG"
   24.46 +
   24.47 +    def __init__(self):
   24.48 +        self.rebooted = 0
   24.49 +        self.last_reboot = None
   24.50 +        self.dbroot = None
   24.51 +        self.config_path = None
   24.52 +        self.config = None
   24.53 +        self.configure()
   24.54 +        self.check_lastboot()
   24.55 +        eserver.subscribe('xend.*', self.event_handler)
   24.56 +        #eserver.subscribe('xend.domain.created', self.event_handler)
   24.57 +        #eserver.subscribe('xend.domain.died', self.event_handler)
   24.58 +
   24.59 +    def start(self):
   24.60 +        eserver.inject('xend.start', self.rebooted)
   24.61 +
   24.62 +    def event_handler(self, event, val):
   24.63 +        print >> sys.stderr, "EVENT>", event, val
   24.64 +
   24.65 +    def read_lastboot(self):
   24.66 +        try:
   24.67 +            val = file(self.lastboot, 'rb').readlines()[0]
   24.68 +        except StandardError, ex:
   24.69 +            print 'warning: Error reading', self.lastboot, ex
   24.70 +            val = None
   24.71 +        return val
   24.72 +
   24.73 +    def write_lastboot(self, val):
   24.74 +        if not val: return
   24.75 +        try:
   24.76 +            fdir = os.path.dirname(self.lastboot)
   24.77 +            if not os.path.isdir(fdir):
   24.78 +                os.makedirs(fdir)
   24.79 +            out = file(self.lastboot, 'wb+')
   24.80 +            out.write(val)
   24.81 +            out.close()
   24.82 +        except IOError, ex:
   24.83 +            print 'warning: Error writing', self.lastboot, ex
   24.84 +            pass
   24.85 +
   24.86 +    def check_lastboot(self):
   24.87 +        """Check if there has been a system reboot since we saved lastboot.
   24.88 +        """
   24.89 +        last_val = self.read_lastboot()
   24.90 +        this_val = last_reboot()
   24.91 +        if this_val == last_val:
   24.92 +            self.rebooted = 0
   24.93 +        else:
   24.94 +            self.rebooted = 1
   24.95 +            self.write_lastboot(this_val)
   24.96 +        self.last_reboot = this_val
   24.97 +
   24.98 +    def get_last_reboot(self):
   24.99 +        return self.last_reboot
  24.100 +
  24.101 +    def get_rebooted(self):
  24.102 +        return self.rebooted
  24.103 +
  24.104 +    def configure(self):
  24.105 +        self.set_config()
  24.106 +        self.dbroot = self.get_config_value("dbroot", self.dbroot_default)
  24.107 +        self.lastboot = self.get_config_value("lastboot", self.lastboot_default)
  24.108 +
  24.109 +    def get_dbroot(self):
  24.110 +        """Get the path to the database root.
  24.111 +        """
  24.112 +        return self.dbroot
  24.113 +
  24.114 +    def set_config(self):
  24.115 +        """If the config file exists, read it. If not, ignore it.
  24.116 +
  24.117 +        The config file is a sequence of sxp forms.
  24.118 +        """
  24.119 +        self.config_path = os.getenv(self.config_var, self.config_default)
  24.120 +        if os.path.exists(self.config_path):
  24.121 +            fin = file(self.config_path, 'rb')
  24.122 +            try:
  24.123 +                config = sxp.parse(fin)
  24.124 +                config.insert(0, 'config')
  24.125 +                self.config = config
  24.126 +            finally:
  24.127 +                fin.close()
  24.128 +        else:
  24.129 +            self.config = ['config']
  24.130 +
  24.131 +    def get_config(self, name=None):
  24.132 +        """Get the configuration element with the given name, or
  24.133 +        the whole configuration if no name is given.
  24.134 +
  24.135 +        name	element name (optional)
  24.136 +        returns config or none
  24.137 +        """
  24.138 +        if name is None:
  24.139 +            val = self.config
  24.140 +        else:
  24.141 +            val = sxp.child(self.config, name)
  24.142 +        return val
  24.143 +
  24.144 +    def get_config_value(self, name, val=None):
  24.145 +        """Get the value of an atomic configuration element.
  24.146 +
  24.147 +        name	element name
  24.148 +        val	default value (optional, defaults to None)
  24.149 +        returns value
  24.150 +        """
  24.151 +        return sxp.child_value(self.config, name, val=val)
  24.152 +
  24.153 +def instance():
  24.154 +    global inst
  24.155 +    try:
  24.156 +        inst
  24.157 +    except:
  24.158 +        inst = XendRoot()
  24.159 +    return inst
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/tools/xen/lib/xend/XendVnet.py	Fri Jun 25 15:10:48 2004 +0000
    25.3 @@ -0,0 +1,69 @@
    25.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    25.5 +
    25.6 +"""Handler for vnet operations.
    25.7 +"""
    25.8 +
    25.9 +import sxp
   25.10 +import XendDB
   25.11 +
   25.12 +class XendVnet:
   25.13 +    """Index of all vnets. Singleton.
   25.14 +    """
   25.15 +
   25.16 +    dbpath = "vnet"
   25.17 +
   25.18 +    def __init__(self):
   25.19 +        # Table of vnet info indexed by vnet id.
   25.20 +        self.vnet = {}
   25.21 +        self.db = XendDB.XendDB(self.dbpath)
   25.22 +        self.vnet = self.db.fetchall("")
   25.23 +
   25.24 +    def vnet_ls(self):
   25.25 +        """List all vnets.
   25.26 +        """
   25.27 +        return self.vnet.keys()
   25.28 +
   25.29 +    def vnets(self):
   25.30 +        return self.vnet.values()
   25.31 +
   25.32 +    def vnet_get(self, id):
   25.33 +        """Get a vnet.
   25.34 +
   25.35 +        id	vnet id
   25.36 +        """
   25.37 +        return self.vnet.get(id)
   25.38 +
   25.39 +    def vnet_create(self, info):
   25.40 +        """Create a vnet.
   25.41 +
   25.42 +        info	config
   25.43 +        """
   25.44 +        self.vnet_configure(info)
   25.45 +
   25.46 +    def vnet_configure(self, info):
   25.47 +        """Configure a vnet.
   25.48 +        id	vnet id
   25.49 +        info	config
   25.50 +        """
   25.51 +        # Need to configure for real.
   25.52 +        # Only sync if succeeded - otherwise need to back out.
   25.53 +        self.vnet[info.id] = info
   25.54 +        self.db.save(info.id, info)
   25.55 +
   25.56 +    def vnet_delete(self, id):
   25.57 +        """Delete a vnet.
   25.58 +
   25.59 +        id	vnet id
   25.60 +        """
   25.61 +        # Need to delete for real. What if fails?
   25.62 +        if id in self.vnet:
   25.63 +            del self.vnet[id]
   25.64 +            self.db.delete(id)
   25.65 +
   25.66 +def instance():
   25.67 +    global inst
   25.68 +    try:
   25.69 +        inst
   25.70 +    except:
   25.71 +        inst = XendVnet()
   25.72 +    return inst
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/tools/xen/lib/xend/__init__.py	Fri Jun 25 15:10:48 2004 +0000
    26.3 @@ -0,0 +1,1 @@
    26.4 + 
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/tools/xen/lib/xend/encode.py	Fri Jun 25 15:10:48 2004 +0000
    27.3 @@ -0,0 +1,165 @@
    27.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    27.5 +"""Encoding for arguments to HTTP calls.
    27.6 +   Uses the url-encoding with MIME type 'application/x-www-form-urlencoded'
    27.7 +   if the data does not include files. Otherwise it uses the encoding with
    27.8 +   MIME type 'multipart/form-data'. See the HTML4 spec for details.
    27.9 +
   27.10 +   """
   27.11 +import sys
   27.12 +import types
   27.13 +from StringIO import StringIO
   27.14 +
   27.15 +import urllib
   27.16 +import httplib
   27.17 +import random
   27.18 +import md5
   27.19 +
   27.20 +# Extract from HTML4 spec.
   27.21 +## The following example illustrates "multipart/form-data"
   27.22 +## encoding. Suppose we have the following form:
   27.23 +
   27.24 +##  <FORM action="http://server.com/cgi/handle"
   27.25 +##        enctype="multipart/form-data"
   27.26 +##        method="post">
   27.27 +##    <P>
   27.28 +##    What is your name? <INPUT type="text" name="submit-name"><BR>
   27.29 +##    What files are you sending? <INPUT type="file" name="files"><BR>
   27.30 +##    <INPUT type="submit" value="Send"> <INPUT type="reset">
   27.31 +##  </FORM>
   27.32 +
   27.33 +## If the user enters "Larry" in the text input, and selects the text
   27.34 +## file "file1.txt", the user agent might send back the following data:
   27.35 +
   27.36 +##    Content-Type: multipart/form-data; boundary=AaB03x
   27.37 +
   27.38 +##    --AaB03x
   27.39 +##    Content-Disposition: form-data; name="submit-name"
   27.40 +
   27.41 +##    Larry
   27.42 +##    --AaB03x
   27.43 +##    Content-Disposition: form-data; name="files"; filename="file1.txt"
   27.44 +##    Content-Type: text/plain
   27.45 +
   27.46 +##    ... contents of file1.txt ...
   27.47 +##    --AaB03x--
   27.48 +
   27.49 +## If the user selected a second (image) file "file2.gif", the user agent
   27.50 +## might construct the parts as follows:
   27.51 +
   27.52 +##    Content-Type: multipart/form-data; boundary=AaB03x
   27.53 +
   27.54 +##    --AaB03x
   27.55 +##    Content-Disposition: form-data; name="submit-name"
   27.56 +
   27.57 +##    Larry
   27.58 +##    --AaB03x
   27.59 +##    Content-Disposition: form-data; name="files"
   27.60 +##    Content-Type: multipart/mixed; boundary=BbC04y
   27.61 +
   27.62 +##    --BbC04y
   27.63 +##    Content-Disposition: file; filename="file1.txt"
   27.64 +##    Content-Type: text/plain
   27.65 +
   27.66 +##    ... contents of file1.txt ...
   27.67 +##    --BbC04y
   27.68 +##    Content-Disposition: file; filename="file2.gif"
   27.69 +##    Content-Type: image/gif
   27.70 +##    Content-Transfer-Encoding: binary
   27.71 +
   27.72 +##    ...contents of file2.gif...
   27.73 +##    --BbC04y--
   27.74 +##    --AaB03x--
   27.75 +
   27.76 +__all__ = ['encode_data', 'encode_multipart', 'encode_form', 'mime_boundary' ]
   27.77 +
   27.78 +def data_values(d):
   27.79 +    if isinstance(d, types.DictType):
   27.80 +        return d.items()
   27.81 +    else:
   27.82 +        return d
   27.83 +
   27.84 +def encode_data(d):
   27.85 +    """Encode some data for HTTP transport.
   27.86 +    The encoding used is stored in 'Content-Type' in the headers.
   27.87 +
   27.88 +    d	data - sequence of tuples or dictionary
   27.89 +    returns a 2-tuple of the headers and the encoded data
   27.90 +    """
   27.91 +    val = ({}, None)
   27.92 +    if d is None: return val
   27.93 +    multipart = 0
   27.94 +    for (k, v) in data_values(d):
   27.95 +        if encode_isfile(v):
   27.96 +            multipart = 1
   27.97 +            break
   27.98 +    if multipart:
   27.99 +        val = encode_multipart(d)
  27.100 +    else:
  27.101 +        val = encode_form(d)
  27.102 +    return val
  27.103 +
  27.104 +def encode_isfile(v):
  27.105 +    if isinstance(v, types.FileType):
  27.106 +        return 1
  27.107 +    if hasattr(v, 'readlines'):
  27.108 +        return 1
  27.109 +    return 0
  27.110 +
  27.111 +def encode_multipart(d):
  27.112 +    boundary = mime_boundary()
  27.113 +    hdr = { 'Content-Type': 'multipart/form-data; boundary=' + boundary }
  27.114 +    out = StringIO()
  27.115 +    for (k,v) in data_values(d):
  27.116 +        out.write('--')
  27.117 +        out.write(boundary)
  27.118 +        out.write('\r\n')
  27.119 +        if encode_isfile(v):
  27.120 +            out.write('Content-Disposition: form-data; name="')
  27.121 +            out.write(k)
  27.122 +            if hasattr(v, 'name'):
  27.123 +                out.write('"; filename="')
  27.124 +                out.write(v.name)
  27.125 +            out.write('"\r\n')
  27.126 +            out.write('Content-Type: application/octet-stream\r\n')
  27.127 +            out.write('\r\n')
  27.128 +            for l in v.readlines():
  27.129 +               out.write(l)  
  27.130 +        else:
  27.131 +            out.write('Content-Disposition: form-data; name="')
  27.132 +            out.write(k)
  27.133 +            out.write('"\r\n')
  27.134 +            out.write('\r\n')
  27.135 +            out.write(str(v))
  27.136 +            out.write('\r\n')
  27.137 +    out.write('--')
  27.138 +    out.write(boundary)
  27.139 +    out.write('--')
  27.140 +    out.write('\r\n')
  27.141 +    return (hdr, out.getvalue())
  27.142 +
  27.143 +def mime_boundary():
  27.144 +    random.seed()
  27.145 +    m = md5.new()
  27.146 +    for i in range(0, 10):
  27.147 +        c = chr(random.randint(1, 255))
  27.148 +        m.update(c)
  27.149 +    b = m.hexdigest()
  27.150 +    return b[0:16]
  27.151 +
  27.152 +def encode_form(d):
  27.153 +    hdr = { 'Content-Type': 'application/x-www-form-urlencoded' }
  27.154 +    val = urllib.urlencode(d)
  27.155 +    return (hdr, val)
  27.156 +
  27.157 +def main():
  27.158 +    #d = {'a': 1, 'b': 'x y', 'c': file('conf.sxp') }
  27.159 +    #d = {'a': 1, 'b': 'x y' }
  27.160 +    d = [ ('a', 1), ('b', 'x y'), ('c', file('conf.sxp')) ]
  27.161 +    #d = [ ('a', 1), ('b', 'x y')]
  27.162 +    v = encode_data(d)
  27.163 +    print v[0]
  27.164 +    sys.stdout.write(v[1])
  27.165 +    print
  27.166 +
  27.167 +if __name__ == "__main__":
  27.168 +    main()
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/tools/xen/lib/xend/server/SrvBase.py	Fri Jun 25 15:10:48 2004 +0000
    28.3 @@ -0,0 +1,137 @@
    28.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    28.5 +
    28.6 +import cgi
    28.7 +
    28.8 +import os
    28.9 +import sys
   28.10 +import types
   28.11 +import StringIO
   28.12 +
   28.13 +from twisted.internet import defer
   28.14 +from twisted.internet import reactor
   28.15 +from twisted.web import error
   28.16 +from twisted.web import resource
   28.17 +from twisted.web import server
   28.18 +
   28.19 +from xen.xend import sxp
   28.20 +from xen.xend import PrettyPrint
   28.21 +
   28.22 +def uri_pathlist(p):
   28.23 +    """Split a path into a list.
   28.24 +    p		path
   28.25 +    return list of path elements
   28.26 +    """
   28.27 +    l = []
   28.28 +    for x in p.split('/'):
   28.29 +        if x == '': continue
   28.30 +        l.append(x)
   28.31 +    return l
   28.32 +
   28.33 +class SrvBase(resource.Resource):
   28.34 +    """Base class for services.
   28.35 +    """
   28.36 +
   28.37 +    def parse_form(self, req, method):
   28.38 +        """Parse the data for a request, GET using the URL, POST using encoded data.
   28.39 +        Posts should use enctype='multipart/form-data' in the <form> tag,
   28.40 +        rather than 'application/x-www-form-urlencoded'. Only 'multipart/form-data'
   28.41 +        handles file upload.
   28.42 +
   28.43 +        req		request
   28.44 +        returns a cgi.FieldStorage instance
   28.45 +        """
   28.46 +        env = {}
   28.47 +        env['REQUEST_METHOD'] = method
   28.48 +        if self.query:
   28.49 +            env['QUERY_STRING'] = self.query
   28.50 +        val = cgi.FieldStorage(fp=req.rfile, headers=req.headers, environ=env)
   28.51 +        return val
   28.52 +    
   28.53 +    def use_sxp(self, req):
   28.54 +        """Determine whether to send an SXP response to a request.
   28.55 +        Uses SXP if there is no User-Agent, no Accept, or application/sxp is in Accept.
   28.56 +
   28.57 +        req		request
   28.58 +        returns 1 for SXP, 0 otherwise
   28.59 +        """
   28.60 +        ok = 0
   28.61 +        user_agent = req.getHeader('User-Agent')
   28.62 +        accept = req.getHeader('Accept')
   28.63 +        if (not user_agent) or (not accept) or (accept.find(sxp.mime_type) >= 0):
   28.64 +            ok = 1
   28.65 +        return ok
   28.66 +
   28.67 +    def get_op_method(self, op):
   28.68 +        """Get the method for an operation.
   28.69 +        For operation 'foo' looks for 'op_foo'.
   28.70 +
   28.71 +        op	operation name
   28.72 +        returns method or None
   28.73 +        """
   28.74 +        op_method_name = 'op_' + op
   28.75 +        return getattr(self, op_method_name, None)
   28.76 +        
   28.77 +    def perform(self, req):
   28.78 +        """General operation handler for posted operations.
   28.79 +        For operation 'foo' looks for a method op_foo and calls
   28.80 +        it with op_foo(op, req). Replies with code 500 if op_foo
   28.81 +        is not found.
   28.82 +
   28.83 +        The method must return a list when req.use_sxp is true
   28.84 +        and an HTML string otherwise (or list).
   28.85 +        Methods may also return a Deferred (for incomplete processing).
   28.86 +
   28.87 +        req	request
   28.88 +        """
   28.89 +        op = req.args.get('op')
   28.90 +        if op is None or len(op) != 1:
   28.91 +            req.setResponseCode(404, "Invalid")
   28.92 +            return ''
   28.93 +        op = op[0]
   28.94 +        op_method = self.get_op_method(op)
   28.95 +        if op_method is None:
   28.96 +            req.setResponseCode(501, "Not implemented")
   28.97 +            req.setHeader("Content-Type", "text/plain")
   28.98 +            req.write("Not implemented: " + op)
   28.99 +            return ''
  28.100 +        else:
  28.101 +            val = op_method(op, req)
  28.102 +            if isinstance(val, defer.Deferred):
  28.103 +                val.addCallback(self._cb_perform, req, 1)
  28.104 +                return server.NOT_DONE_YET
  28.105 +            else:
  28.106 +                self._cb_perform(val, req, 0)
  28.107 +                return ''
  28.108 +
  28.109 +    def _cb_perform(self, val, req, dfr):
  28.110 +        """Callback to complete the request.
  28.111 +        May be called from a Deferred.
  28.112 +        """
  28.113 +        if isinstance(val, error.ErrorPage):
  28.114 +            req.write(val.render(req))
  28.115 +        elif self.use_sxp(req):
  28.116 +            req.setHeader("Content-Type", sxp.mime_type)
  28.117 +            sxp.show(val, req)
  28.118 +        else:
  28.119 +            req.write('<html><head></head><body>')
  28.120 +            self.print_path(req)
  28.121 +            if isinstance(val, types.ListType):
  28.122 +                req.write('<code><pre>')
  28.123 +                PrettyPrint.prettyprint(val, out=req)
  28.124 +                req.write('</pre></code>')
  28.125 +            else:
  28.126 +                req.write(str(val))
  28.127 +            req.write('</body></html>')
  28.128 +        if dfr:
  28.129 +            req.finish()
  28.130 +
  28.131 +    def print_path(self, req):
  28.132 +        """Print the path with hyperlinks.
  28.133 +        """
  28.134 +        pathlist = [x for x in req.prepath if x != '' ]
  28.135 +        s = "/"
  28.136 +        req.write('<h1><a href="/">/</a>')
  28.137 +        for x in pathlist:
  28.138 +            s += x + "/"
  28.139 +            req.write(' <a href="%s">%s</a>/' % (s, x))
  28.140 +        req.write("</h1>")
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/tools/xen/lib/xend/server/SrvConsole.py	Fri Jun 25 15:10:48 2004 +0000
    29.3 @@ -0,0 +1,42 @@
    29.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    29.5 +
    29.6 +from xen.xend import sxp
    29.7 +from xen.xend import XendConsole
    29.8 +from SrvDir import SrvDir
    29.9 +
   29.10 +class SrvConsole(SrvDir):
   29.11 +    """An individual console.
   29.12 +    """
   29.13 +
   29.14 +    def __init__(self, info):
   29.15 +        SrvDir.__init__(self)
   29.16 +        self.info = info
   29.17 +        self.xc = XendConsole.instance()
   29.18 +
   29.19 +    def op_disconnect(self, op, req):
   29.20 +        val = self.xc.console_disconnect(self.info.id)
   29.21 +        return val
   29.22 +
   29.23 +    def render_POST(self, req):
   29.24 +        return self.perform(req)
   29.25 +        
   29.26 +    def render_GET(self, req):
   29.27 +        if self.use_sxp(req):
   29.28 +            req.setHeader("Content-Type", sxp.mime_type)
   29.29 +            sxp.show(self.info.sxpr(), out=req)
   29.30 +        else:
   29.31 +            req.write('<html><head></head><body>')
   29.32 +            self.print_path(req)
   29.33 +            #self.ls()
   29.34 +            req.write('<p>%s</p>' % self.info)
   29.35 +            req.write('<p><a href="%s">Connect to domain %d</a></p>'
   29.36 +                      % (self.info.uri(), self.info.dom2))
   29.37 +            self.form(req)
   29.38 +            req.write('</body></html>')
   29.39 +        return ''
   29.40 +
   29.41 +    def form(self, req):
   29.42 +        req.write('<form method="post" action="%s">' % req.prePathURL())
   29.43 +        if self.info.connection():
   29.44 +            req.write('<input type="submit" name="op" value="disconnect">')
   29.45 +        req.write('</form>')
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/tools/xen/lib/xend/server/SrvConsoleDir.py	Fri Jun 25 15:10:48 2004 +0000
    30.3 @@ -0,0 +1,59 @@
    30.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    30.5 +
    30.6 +from SrvDir import SrvDir
    30.7 +from SrvConsole import SrvConsole
    30.8 +from xen.xend import XendConsole
    30.9 +from xen.xend import sxp
   30.10 +
   30.11 +class SrvConsoleDir(SrvDir):
   30.12 +    """Console directory.
   30.13 +    """
   30.14 +
   30.15 +    def __init__(self):
   30.16 +        SrvDir.__init__(self)
   30.17 +        self.xconsole = XendConsole.instance()
   30.18 +
   30.19 +    def console(self, x):
   30.20 +        val = None
   30.21 +        try:
   30.22 +            info = self.xconsole.console_get(x)
   30.23 +            val = SrvConsole(info)
   30.24 +        except KeyError, ex:
   30.25 +            print 'SrvConsoleDir>', ex
   30.26 +            pass
   30.27 +        return val
   30.28 +
   30.29 +    def get(self, x):
   30.30 +        v = SrvDir.get(self, x)
   30.31 +        if v is not None:
   30.32 +            return v
   30.33 +        v = self.console(x)
   30.34 +        return v
   30.35 +
   30.36 +    def render_GET(self, req):
   30.37 +        if self.use_sxp(req):
   30.38 +            req.setHeader("Content-Type", sxp.mime_type)
   30.39 +            self.ls_console(req, 1)
   30.40 +        else:
   30.41 +            req.write("<html><head></head><body>")
   30.42 +            self.print_path(req)
   30.43 +            self.ls(req)
   30.44 +            self.ls_console(req)
   30.45 +            #self.form(req.wfile)
   30.46 +            req.write("</body></html>")
   30.47 +        return ''
   30.48 +
   30.49 +    def ls_console(self, req, use_sxp=0):
   30.50 +        url = req.prePathURL()
   30.51 +        if not url.endswith('/'):
   30.52 +            url += '/'
   30.53 +        if use_sxp:
   30.54 +            consoles = self.xconsole.console_ls()
   30.55 +            sxp.show(consoles, out=req)
   30.56 +        else:
   30.57 +            consoles = self.xconsole.consoles()
   30.58 +            consoles.sort(lambda x, y: cmp(x.id, y.id))
   30.59 +            req.write('<ul>')
   30.60 +            for c in consoles:
   30.61 +                req.write('<li><a href="%s%s"> %s</a></li>' % (url, c.id, c))
   30.62 +            req.write('</ul>')
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/tools/xen/lib/xend/server/SrvDaemon.py	Fri Jun 25 15:10:48 2004 +0000
    31.3 @@ -0,0 +1,704 @@
    31.4 +###########################################################
    31.5 +## Xen controller daemon
    31.6 +## Copyright (c) 2004, K A Fraser (University of Cambridge)
    31.7 +## Copyright (C) 2004, Mike Wray <mike.wray@hp.com>
    31.8 +###########################################################
    31.9 +
   31.10 +import os
   31.11 +import os.path
   31.12 +import signal
   31.13 +import sys
   31.14 +import socket
   31.15 +import pwd
   31.16 +import re
   31.17 +import StringIO
   31.18 +
   31.19 +from twisted.internet import pollreactor
   31.20 +pollreactor.install()
   31.21 +
   31.22 +from twisted.internet import reactor
   31.23 +from twisted.internet import protocol
   31.24 +from twisted.internet import abstract
   31.25 +from twisted.internet import defer
   31.26 +
   31.27 +from xen.ext import xu
   31.28 +
   31.29 +from xen.xend import sxp
   31.30 +from xen.xend import PrettyPrint
   31.31 +from xen.xend import EventServer
   31.32 +eserver = EventServer.instance()
   31.33 +
   31.34 +from xen.xend.server import SrvServer
   31.35 +
   31.36 +import channel
   31.37 +import blkif
   31.38 +import netif
   31.39 +import console
   31.40 +import domain
   31.41 +from params import *
   31.42 +
   31.43 +DEBUG = 1
   31.44 +
   31.45 +class MgmtProtocol(protocol.DatagramProtocol):
   31.46 +    """Handler for the management socket (unix-domain).
   31.47 +    """
   31.48 +
   31.49 +    def __init__(self, daemon):
   31.50 +        #protocol.DatagramProtocol.__init__(self)
   31.51 +        self.daemon = daemon
   31.52 +    
   31.53 +    def write(self, data, addr):
   31.54 +        return self.transport.write(data, addr)
   31.55 +
   31.56 +    def datagramReceived(self, data, addr):
   31.57 +        if DEBUG: print 'datagramReceived> addr=', addr, 'data=', data
   31.58 +        io = StringIO.StringIO(data)
   31.59 +        try:
   31.60 +            vals = sxp.parse(io)
   31.61 +            res = self.dispatch(vals[0])
   31.62 +            self.send_result(addr, res)
   31.63 +        except SystemExit:
   31.64 +            raise
   31.65 +        except:
   31.66 +            if DEBUG:
   31.67 +                raise
   31.68 +            else:
   31.69 +                self.send_error(addr)
   31.70 +
   31.71 +    def send_reply(self, addr, sxpr):
   31.72 +        io = StringIO.StringIO()
   31.73 +        sxp.show(sxpr, out=io)
   31.74 +        io.seek(0)
   31.75 +        self.write(io.getvalue(), addr)
   31.76 +
   31.77 +    def send_result(self, addr, res):
   31.78 +        
   31.79 +        def fn(res, self=self, addr=addr):
   31.80 +            self.send_reply(addr, ['ok', res])
   31.81 +            
   31.82 +        if isinstance(res, defer.Deferred):
   31.83 +            res.addCallback(fn)
   31.84 +        else:
   31.85 +            fn(res)
   31.86 +
   31.87 +    def send_error(self, addr):
   31.88 +        (extype, exval) = sys.exc_info()[:2]
   31.89 +        self.send_reply(addr, ['err',
   31.90 +                               ['type',  str(extype) ],
   31.91 +                               ['value', str(exval)  ] ] )
   31.92 +
   31.93 +    def opname(self, name):
   31.94 +        """Get the name of the method for an operation.
   31.95 +        """
   31.96 +        return 'op_' + name.replace('.', '_')
   31.97 +
   31.98 +    def operror(self, name, v):
   31.99 +        """Default operation handler - signals an error.
  31.100 +        """
  31.101 +        raise NotImplementedError('Invalid operation: ' +name)
  31.102 +
  31.103 +    def dispatch(self, req):
  31.104 +        """Dispatch a request to its handler.
  31.105 +        """
  31.106 +        op_name = sxp.name(req)
  31.107 +        op_method_name = self.opname(op_name)
  31.108 +        op_method = getattr(self, op_method_name, self.operror)
  31.109 +        return op_method(op_name, req)
  31.110 +
  31.111 +    def op_console_create(self, name, req):
  31.112 +        """Create a new control interface - console for a domain.
  31.113 +        """
  31.114 +        print name, req
  31.115 +        dom = sxp.child_value(req, 'domain')
  31.116 +        if not dom: raise ValueError('Missing domain')
  31.117 +        dom = int(dom)
  31.118 +        console_port = sxp.child_value(req, 'console_port')
  31.119 +        if console_port:
  31.120 +            console_port = int(console_port)
  31.121 +        resp = self.daemon.console_create(dom, console_port)
  31.122 +        print name, resp
  31.123 +        return resp
  31.124 +
  31.125 +    def op_consoles(self, name, req):
  31.126 +        """Get a list of the consoles.
  31.127 +        """
  31.128 +        return self.daemon.consoles()
  31.129 +
  31.130 +    def op_console_disconnect(self, name, req):
  31.131 +        id = sxp.child_value(req, 'id')
  31.132 +        if not id:
  31.133 +            raise ValueError('Missing console id')
  31.134 +        id = int(id)
  31.135 +        console = self.daemon.get_console(id)
  31.136 +        if not console:
  31.137 +            raise ValueError('Invalid console id')
  31.138 +        if console.conn:
  31.139 +            console.conn.loseConnection()
  31.140 +        return ['ok']
  31.141 +
  31.142 +    def op_blkifs(self, name, req):
  31.143 +        pass
  31.144 +    
  31.145 +    def op_blkif_devs(self, name, req):
  31.146 +        pass
  31.147 +
  31.148 +    def op_blkif_create(self, name, req):
  31.149 +        pass
  31.150 +    
  31.151 +    def op_blkif_dev_create(self, name, req):
  31.152 +        pass
  31.153 +
  31.154 +    def op_netifs(self, name, req):
  31.155 +        pass
  31.156 +
  31.157 +    def op_netif_devs(self, name, req):
  31.158 +        pass
  31.159 +
  31.160 +    def op_netif_create(self, name, req):
  31.161 +        pass
  31.162 +
  31.163 +    def op_netif_dev_create(self, name, req):
  31.164 +        pass
  31.165 +
  31.166 +class NotifierProtocol(protocol.Protocol):
  31.167 +    """Asynchronous handler for i/o on the notifier (event channel).
  31.168 +    """
  31.169 +
  31.170 +    def __init__(self, channelFactory):
  31.171 +        self.channelFactory = channelFactory
  31.172 +
  31.173 +    def notificationReceived(self, idx, type):
  31.174 +        #print 'NotifierProtocol>notificationReceived>', idx, type
  31.175 +        channel = self.channelFactory.getChannel(idx)
  31.176 +        if not channel:
  31.177 +            return
  31.178 +        #print 'NotifierProtocol>notificationReceived> channel', channel
  31.179 +        channel.notificationReceived(type)
  31.180 +
  31.181 +    def connectionLost(self, reason=None):
  31.182 +        pass
  31.183 +
  31.184 +    def doStart(self):
  31.185 +        pass
  31.186 +
  31.187 +    def doStop(self):
  31.188 +        pass
  31.189 +
  31.190 +    def startProtocol(self):
  31.191 +        pass
  31.192 +
  31.193 +    def stopProtocol(self):
  31.194 +        pass
  31.195 +
  31.196 +class NotifierPort(abstract.FileDescriptor):
  31.197 +    """Transport class for the event channel.
  31.198 +    """
  31.199 +
  31.200 +    def __init__(self, daemon, notifier, proto, reactor=None):
  31.201 +        assert isinstance(proto, NotifierProtocol)
  31.202 +        abstract.FileDescriptor.__init__(self, reactor)
  31.203 +        self.daemon = daemon
  31.204 +        self.notifier = notifier
  31.205 +        self.protocol = proto
  31.206 +
  31.207 +    def startListening(self):
  31.208 +        self._bindNotifier()
  31.209 +        self._connectToProtocol()
  31.210 +
  31.211 +    def stopListening(self):
  31.212 +        if self.connected:
  31.213 +            result = self.d = defer.Deferred()
  31.214 +        else:
  31.215 +            result = None
  31.216 +        self.loseConnection()
  31.217 +        return result
  31.218 +
  31.219 +    def fileno(self):
  31.220 +        return self.notifier.fileno()
  31.221 +
  31.222 +    def _bindNotifier(self):
  31.223 +        self.connected = 1
  31.224 +
  31.225 +    def _connectToProtocol(self):
  31.226 +        self.protocol.makeConnection(self)
  31.227 +        self.startReading()
  31.228 +
  31.229 +    def loseConnection(self):
  31.230 +        if self.connected:
  31.231 +            self.stopReading()
  31.232 +            self.disconnecting = 1
  31.233 +            reactor.callLater(0, self.connectionLost)
  31.234 +
  31.235 +    def connectionLost(self, reason=None):
  31.236 +        abstract.FileDescriptor.connectionLost(self, reason)
  31.237 +        if hasattr(self, 'protocol'):
  31.238 +            self.protocol.doStop()
  31.239 +        self.connected = 0
  31.240 +        #self.notifier.close() # Not implemented.
  31.241 +        os.close(self.fileno())
  31.242 +        del self.notifier
  31.243 +        if hasattr(self, 'd'):
  31.244 +            self.d.callback(None)
  31.245 +            del self.d
  31.246 +        
  31.247 +    def doRead(self):
  31.248 +        #print 'NotifierPort>doRead>', self
  31.249 +        count = 0
  31.250 +        while 1:            
  31.251 +            #print 'NotifierPort>doRead>', count
  31.252 +            notification = self.notifier.read()
  31.253 +            if not notification:
  31.254 +                break
  31.255 +            (idx, type) = notification
  31.256 +            self.protocol.notificationReceived(idx, type)
  31.257 +            self.notifier.unmask(idx)
  31.258 +            count += 1
  31.259 +        #print 'NotifierPort>doRead<'
  31.260 +
  31.261 +class EventProtocol(protocol.Protocol):
  31.262 +    """Asynchronous handler for a connected event socket.
  31.263 +    """
  31.264 +
  31.265 +    def __init__(self, daemon):
  31.266 +        #protocol.Protocol.__init__(self)
  31.267 +        self.daemon = daemon
  31.268 +        # Event queue.
  31.269 +        self.queue = []
  31.270 +        # Subscribed events.
  31.271 +        self.events = []
  31.272 +        self.parser = sxp.Parser()
  31.273 +        self.pretty = 0
  31.274 +
  31.275 +        # For debugging subscribe to everything and make output pretty.
  31.276 +        self.subscribe(['*'])
  31.277 +        self.pretty = 1
  31.278 +
  31.279 +    def dataReceived(self, data):
  31.280 +        try:
  31.281 +            self.parser.input(data)
  31.282 +            if self.parser.ready():
  31.283 +                val = self.parser.get_val()
  31.284 +                res = self.dispatch(val)
  31.285 +                self.send_result(res)
  31.286 +            if self.parser.at_eof():
  31.287 +                self.loseConnection()
  31.288 +        except SystemExit:
  31.289 +            raise
  31.290 +        except:
  31.291 +            if DEBUG:
  31.292 +                raise
  31.293 +            else:
  31.294 +                self.send_error()
  31.295 +
  31.296 +    def loseConnection(self):
  31.297 +        if self.transport:
  31.298 +            self.transport.loseConnection()
  31.299 +        if self.connected:
  31.300 +            reactor.callLater(0, self.connectionLost)
  31.301 +
  31.302 +    def connectionLost(self, reason=None):
  31.303 +        self.unsubscribe()
  31.304 +
  31.305 +    def send_reply(self, sxpr):
  31.306 +        io = StringIO.StringIO()
  31.307 +        if self.pretty:
  31.308 +            PrettyPrint.prettyprint(sxpr, out=io)
  31.309 +        else:
  31.310 +            sxp.show(sxpr, out=io)
  31.311 +        print >> io
  31.312 +        io.seek(0)
  31.313 +        return self.transport.write(io.getvalue())
  31.314 +
  31.315 +    def send_result(self, res):
  31.316 +        return self.send_reply(['ok', res])
  31.317 +
  31.318 +    def send_error(self):
  31.319 +        (extype, exval) = sys.exc_info()[:2]
  31.320 +        return self.send_reply(['err',
  31.321 +                                ['type', str(extype)],
  31.322 +                                ['value', str(exval)]])
  31.323 +
  31.324 +    def send_event(self, val):
  31.325 +        return self.send_reply(['event', val[0], val[1]])
  31.326 +
  31.327 +    def unsubscribe(self):
  31.328 +        for event in self.events:
  31.329 +            eserver.unsubscribe(event, self.queue_event)
  31.330 +
  31.331 +    def subscribe(self, events):
  31.332 +        self.unsubscribe()
  31.333 +        for event in events:
  31.334 +            eserver.subscribe(event, self.queue_event)
  31.335 +        self.events = events
  31.336 +
  31.337 +    def queue_event(self, name, v):
  31.338 +        # Despite the name we dont' queue the event here.
  31.339 +        # We send it because the transport will queue it.
  31.340 +        self.send_event([name, v])
  31.341 +        
  31.342 +    def opname(self, name):
  31.343 +         return 'op_' + name.replace('.', '_')
  31.344 +
  31.345 +    def operror(self, name, req):
  31.346 +        raise NotImplementedError('Invalid operation: ' +name)
  31.347 +
  31.348 +    def dispatch(self, req):
  31.349 +        op_name = sxp.name(req)
  31.350 +        op_method_name = self.opname(op_name)
  31.351 +        op_method = getattr(self, op_method_name, self.operror)
  31.352 +        return op_method(op_name, req)
  31.353 +
  31.354 +    def op_help(self, name, req):
  31.355 +        def nameop(x):
  31.356 +            if x.startswith('op_'):
  31.357 +                return x[3:].replace('_', '.')
  31.358 +            else:
  31.359 +                return x
  31.360 +        
  31.361 +        l = [ nameop(k) for k in dir(self) if k.startswith('op_') ]
  31.362 +        return l
  31.363 +
  31.364 +    def op_quit(self, name, req):
  31.365 +        self.loseConnection()
  31.366 +
  31.367 +    def op_exit(self, name, req):
  31.368 +        sys.exit(0)
  31.369 +
  31.370 +    def op_pretty(self, name, req):
  31.371 +        self.pretty = 1
  31.372 +        return ['ok']
  31.373 +
  31.374 +    def op_console_disconnect(self, name, req):
  31.375 +        id = sxp.child_value(req, 'id')
  31.376 +        if not id:
  31.377 +            raise ValueError('Missing console id')
  31.378 +        self.daemon.console_disconnect(id)
  31.379 +        return ['ok']
  31.380 +
  31.381 +    def op_info(self, name, req):
  31.382 +        val = ['info']
  31.383 +        val += self.daemon.consoles()
  31.384 +        val += self.daemon.blkifs()
  31.385 +        val += self.daemon.netifs()
  31.386 +        return val
  31.387 +
  31.388 +    def op_sys_subscribe(self, name, v):
  31.389 +        # (sys.subscribe event*)
  31.390 +        # Subscribe to the events:
  31.391 +        self.subscribe(v[1:])
  31.392 +        return ['ok']
  31.393 +
  31.394 +    def op_sys_inject(self, name, v):
  31.395 +        # (sys.inject event)
  31.396 +        event = v[1]
  31.397 +        eserver.inject(sxp.name(event), event)
  31.398 +        return ['ok']
  31.399 +
  31.400 +
  31.401 +class EventFactory(protocol.Factory):
  31.402 +    """Asynchronous handler for the event server socket.
  31.403 +    """
  31.404 +    protocol = EventProtocol
  31.405 +    service = None
  31.406 +
  31.407 +    def __init__(self, daemon):
  31.408 +        #protocol.Factory.__init__(self)
  31.409 +        self.daemon = daemon
  31.410 +
  31.411 +    def buildProtocol(self, addr):
  31.412 +        proto = self.protocol(self.daemon)
  31.413 +        proto.factory = self
  31.414 +        return proto
  31.415 +
  31.416 +class VirqClient:
  31.417 +    def __init__(self, daemon):
  31.418 +        self.daemon = daemon
  31.419 +
  31.420 +    def virqReceived(self, virq):
  31.421 +        print 'VirqClient.virqReceived>', virq
  31.422 +        eserver.inject('xend.virq', virq)
  31.423 +
  31.424 +    def lostChannel(self, channel):
  31.425 +        print 'VirqClient.lostChannel>', channel
  31.426 +        
  31.427 +class Daemon:
  31.428 +    """The xend daemon.
  31.429 +    """
  31.430 +    def __init__(self):
  31.431 +        self.shutdown = 0
  31.432 +
  31.433 +    def daemon_pids(self):
  31.434 +        pids = []
  31.435 +        pidex = '(?P<pid>\d+)'
  31.436 +        pythonex = '(?P<python>\S*python\S*)'
  31.437 +        cmdex = '(?P<cmd>.*)'
  31.438 +        procre = re.compile('^\s*' + pidex + '\s*' + pythonex + '\s*' + cmdex + '$')
  31.439 +        xendre = re.compile('^/usr/sbin/xend\s*(start|restart)\s*.*$')
  31.440 +        procs = os.popen('ps -e -o pid,args 2>/dev/null')
  31.441 +        for proc in procs:
  31.442 +            pm = procre.match(proc)
  31.443 +            if not pm: continue
  31.444 +            xm = xendre.match(pm.group('cmd'))
  31.445 +            if not xm: continue
  31.446 +            #print 'pid=', pm.group('pid'), 'cmd=', pm.group('cmd')
  31.447 +            pids.append(int(pm.group('pid')))
  31.448 +        return pids
  31.449 +
  31.450 +    def new_cleanup(self, kill=0):
  31.451 +        err = 0
  31.452 +        pids = self.daemon_pids()
  31.453 +        if kill:
  31.454 +            for pid in pids:
  31.455 +                print "Killing daemon pid=%d" % pid
  31.456 +                os.kill(pid, signal.SIGHUP)
  31.457 +        elif pids:
  31.458 +            err = 1
  31.459 +            print "Daemon already running: ", pids
  31.460 +        return err
  31.461 +            
  31.462 +    def cleanup(self, kill=False):
  31.463 +        # No cleanup to do if PID_FILE is empty.
  31.464 +        if not os.path.isfile(PID_FILE) or not os.path.getsize(PID_FILE):
  31.465 +            return 0
  31.466 +        # Read the pid of the previous invocation and search active process list.
  31.467 +        pid = open(PID_FILE, 'r').read()
  31.468 +        lines = os.popen('ps ' + pid + ' 2>/dev/null').readlines()
  31.469 +        for line in lines:
  31.470 +            if re.search('^ *' + pid + '.+xend', line):
  31.471 +                if not kill:
  31.472 +                    print "Daemon is already running (pid %d)" % int(pid)
  31.473 +                    return 1
  31.474 +                # Old daemon is still active: terminate it.
  31.475 +                os.kill(int(pid), 1)
  31.476 +        # Delete the stale PID_FILE.
  31.477 +        os.remove(PID_FILE)
  31.478 +        return 0
  31.479 +
  31.480 +    def install_child_reaper(self):
  31.481 +        #signal.signal(signal.SIGCHLD, self.onSIGCHLD)
  31.482 +        # Ensure that zombie children are automatically reaped.
  31.483 +        xu.autoreap()
  31.484 +
  31.485 +    def onSIGCHLD(self, signum, frame):
  31.486 +        code = 1
  31.487 +        while code > 0:
  31.488 +            code = os.waitpid(-1, os.WNOHANG)
  31.489 +
  31.490 +    def start(self):
  31.491 +        if self.cleanup(kill=False):
  31.492 +            return 1
  31.493 +
  31.494 +        # Detach from TTY.
  31.495 +        if not DEBUG:
  31.496 +            os.setsid()
  31.497 +
  31.498 +        if self.set_user():
  31.499 +            return 1
  31.500 +
  31.501 +        self.install_child_reaper()
  31.502 +
  31.503 +        # Fork -- parent writes PID_FILE and exits.
  31.504 +        pid = os.fork()
  31.505 +        if pid:
  31.506 +            # Parent
  31.507 +            pidfile = open(PID_FILE, 'w')
  31.508 +            pidfile.write(str(pid))
  31.509 +            pidfile.close()
  31.510 +            return 0
  31.511 +        # Child
  31.512 +        logfile = self.open_logfile()
  31.513 +        self.redirect_output(logfile)
  31.514 +        self.run()
  31.515 +        return 0
  31.516 +
  31.517 +    def open_logfile(self):
  31.518 +        if not os.path.exists(CONTROL_DIR):
  31.519 +            os.makedirs(CONTROL_DIR)
  31.520 +
  31.521 +        # Open log file. Truncate it if non-empty, and request line buffering.
  31.522 +        if os.path.isfile(LOG_FILE):
  31.523 +            os.rename(LOG_FILE, LOG_FILE+'.old')
  31.524 +        logfile = open(LOG_FILE, 'w+', 1)
  31.525 +        return logfile
  31.526 +
  31.527 +    def set_user(self):
  31.528 +        # Set the UID.
  31.529 +        try:
  31.530 +            os.setuid(pwd.getpwnam(USER)[2])
  31.531 +            return 0
  31.532 +        except KeyError, error:
  31.533 +            print "Error: no such user '%s'" % USER
  31.534 +            return 1
  31.535 +
  31.536 +    def redirect_output(self, logfile):
  31.537 +        if DEBUG: return
  31.538 +        # Close down standard file handles
  31.539 +        try:
  31.540 +            os.close(0) # stdin
  31.541 +            os.close(1) # stdout
  31.542 +            os.close(2) # stderr
  31.543 +        except:
  31.544 +            pass
  31.545 +        # Redirect output to log file.
  31.546 +        sys.stdout = sys.stderr = logfile
  31.547 +
  31.548 +    def stop(self):
  31.549 +        return self.cleanup(kill=True)
  31.550 +
  31.551 +    def run(self):
  31.552 +        self.createFactories()
  31.553 +        self.listenMgmt()
  31.554 +        self.listenEvent()
  31.555 +        self.listenNotifier()
  31.556 +        self.listenVirq()
  31.557 +        SrvServer.create(bridge=1)
  31.558 +        reactor.run()
  31.559 +
  31.560 +    def createFactories(self):
  31.561 +        self.channelF = channel.channelFactory()
  31.562 +        self.domainCF = domain.DomainControllerFactory()
  31.563 +        self.blkifCF = blkif.BlkifControllerFactory()
  31.564 +        self.netifCF = netif.NetifControllerFactory()
  31.565 +        self.consoleCF = console.ConsoleControllerFactory()
  31.566 +
  31.567 +    def listenMgmt(self):
  31.568 +        protocol = MgmtProtocol(self)
  31.569 +        s = os.path.join(CONTROL_DIR, MGMT_SOCK)
  31.570 +        if os.path.exists(s):
  31.571 +            os.unlink(s)
  31.572 +        return reactor.listenUNIXDatagram(s, protocol)
  31.573 +
  31.574 +    def listenEvent(self):
  31.575 +        protocol = EventFactory(self)
  31.576 +        return reactor.listenTCP(EVENT_PORT, protocol)
  31.577 +
  31.578 +    def listenNotifier(self):
  31.579 +        protocol = NotifierProtocol(self.channelF)
  31.580 +        p = NotifierPort(self, self.channelF.notifier, protocol, reactor)
  31.581 +        p.startListening()
  31.582 +        return p
  31.583 +
  31.584 +    def listenVirq(self):
  31.585 +        virqChan = self.channelF.virqChannel(channel.VIRQ_DOM_EXC)
  31.586 +        virqChan.registerClient(VirqClient(self))
  31.587 +
  31.588 +    def exit(self):
  31.589 +        reactor.diconnectAll()
  31.590 +        sys.exit(0)
  31.591 +
  31.592 +    def blkif_set_control_domain(self, dom, recreate=0):
  31.593 +        """Set the block device backend control domain.
  31.594 +        """
  31.595 +        return self.blkifCF.setControlDomain(dom, recreate=recreate)
  31.596 +    
  31.597 +    def blkif_get_control_domain(self, dom):
  31.598 +        """Get the block device backend control domain.
  31.599 +        """
  31.600 +        return self.blkifCF.getControlDomain()
  31.601 +    
  31.602 +    def blkif_create(self, dom, recreate=0):
  31.603 +        """Create a block device interface controller.
  31.604 +        
  31.605 +        Returns Deferred
  31.606 +        """
  31.607 +        d = self.blkifCF.createInstance(dom, recreate=recreate)
  31.608 +        return d
  31.609 +
  31.610 +    def blkifs(self):
  31.611 +        return [ x.sxpr() for x in self.blkifCF.getInstances() ]
  31.612 +
  31.613 +    def blkif_get(self, dom):
  31.614 +        return self.blkifCF.getInstanceByDom(dom)
  31.615 +
  31.616 +    def blkif_dev(self, dom, vdev):
  31.617 +        return self.blkifCF.getDomainDevice(dom, vdev)
  31.618 +
  31.619 +    def blkif_dev_create(self, dom, vdev, mode, segment, recreate=0):
  31.620 +        """Create a block device.
  31.621 +        
  31.622 +        Returns Deferred
  31.623 +        """
  31.624 +        ctrl = self.blkifCF.getInstanceByDom(dom)
  31.625 +        if not ctrl:
  31.626 +            raise ValueError('No blkif controller: %d' % dom)
  31.627 +        print 'blkif_dev_create>', dom, vdev, mode, segment
  31.628 +        d = ctrl.attachDevice(vdev, mode, segment, recreate=recreate)
  31.629 +        return d
  31.630 +
  31.631 +    def netif_set_control_domain(self, dom, recreate=0):
  31.632 +        """Set the network interface backend control domain.
  31.633 +        """
  31.634 +        return self.netifCF.setControlDomain(dom, recreate=recreate)
  31.635 +
  31.636 +    def netif_get_control_domain(self, dom):
  31.637 +        """Get the network interface backend control domain.
  31.638 +        """
  31.639 +        return self.netifCF.getControlDomain()
  31.640 +    
  31.641 +    def netif_create(self, dom, recreate=0):
  31.642 +        """Create a network interface controller.
  31.643 +        
  31.644 +        """
  31.645 +        return self.netifCF.createInstance(dom, recreate=recreate)
  31.646 +
  31.647 +    def netifs(self):
  31.648 +        return [ x.sxpr() for x in self.netifCF.getInstances() ]
  31.649 +
  31.650 +    def netif_get(self, dom):
  31.651 +        return self.netifCF.getInstanceByDom(dom)
  31.652 +
  31.653 +    def netif_dev_create(self, dom, vif, vmac, recreate=0):
  31.654 +        """Create a network device.
  31.655 +
  31.656 +        todo
  31.657 +        """
  31.658 +        ctrl = self.netifCF.getInstanceByDom(dom)
  31.659 +        if not ctrl:
  31.660 +            raise ValueError('No netif controller: %d' % dom)
  31.661 +        d = ctrl.attachDevice(vif, vmac, recreate=recreate)
  31.662 +        return d
  31.663 +
  31.664 +    def netif_dev(self, dom, vif):
  31.665 +        return self.netifCF.getDomainDevice(dom, vif)
  31.666 +
  31.667 +    def console_create(self, dom, console_port=None):
  31.668 +        """Create a console for a domain.
  31.669 +        """
  31.670 +        console = self.consoleCF.getInstanceByDom(dom)
  31.671 +        if console is None:
  31.672 +            console = self.consoleCF.createInstance(dom, console_port)
  31.673 +        return console.sxpr()
  31.674 +
  31.675 +    def consoles(self):
  31.676 +        return [ c.sxpr() for c in self.consoleCF.getInstances() ]
  31.677 +
  31.678 +    def get_console(self, id):
  31.679 +        return self.consoleCF.getInstance(id)
  31.680 +
  31.681 +    def get_domain_console(self, dom):
  31.682 +        return self.consoleCF.getInstanceByDom(dom)
  31.683 +
  31.684 +    def console_disconnect(self, id):
  31.685 +        """Disconnect any connected console client.
  31.686 +        """
  31.687 +        console = self.get_console(id)
  31.688 +        if not console:
  31.689 +            raise ValueError('Invalid console id')
  31.690 +        console.disconnect()
  31.691 +
  31.692 +    def domain_shutdown(self, dom, reason):
  31.693 +        """Shutdown a domain.
  31.694 +        """
  31.695 +        ctrl = self.domainCF.getInstanceByDom(dom)
  31.696 +        if not ctrl:
  31.697 +            raise ValueError('No domain controller: %d' % dom)
  31.698 +        ctrl.shutdown(reason)
  31.699 +        return 0
  31.700 +        
  31.701 +def instance():
  31.702 +    global inst
  31.703 +    try:
  31.704 +        inst
  31.705 +    except:
  31.706 +        inst = Daemon()
  31.707 +    return inst
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/tools/xen/lib/xend/server/SrvDeviceDir.py	Fri Jun 25 15:10:48 2004 +0000
    32.3 @@ -0,0 +1,9 @@
    32.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    32.5 +
    32.6 +from SrvDir import SrvDir
    32.7 +
    32.8 +class SrvDeviceDir(SrvDir):
    32.9 +    """Device directory.
   32.10 +    """
   32.11 +
   32.12 +    pass
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/tools/xen/lib/xend/server/SrvDir.py	Fri Jun 25 15:10:48 2004 +0000
    33.3 @@ -0,0 +1,91 @@
    33.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    33.5 +
    33.6 +from twisted.web import error
    33.7 +from xen.xend import sxp
    33.8 +from SrvBase import SrvBase
    33.9 +
   33.10 +class SrvConstructor:
   33.11 +    """Delayed constructor for sub-servers.
   33.12 +    Does not import the sub-server class or create the object until needed.
   33.13 +    """
   33.14 +    
   33.15 +    def __init__(self, klass):
   33.16 +        """Create a constructor. It is assumed that the class
   33.17 +        should be imported as 'import klass from klass'.
   33.18 +
   33.19 +        klass	name of its class
   33.20 +        """
   33.21 +        self.klass = klass
   33.22 +        self.obj = None
   33.23 +
   33.24 +    def getobj(self):
   33.25 +        """Get the sub-server object, importing its class and instantiating it if
   33.26 +        necessary.
   33.27 +        """
   33.28 +        if not self.obj:
   33.29 +            exec 'from %s import %s' % (self.klass, self.klass)
   33.30 +            klassobj = eval(self.klass)
   33.31 +            self.obj = klassobj()
   33.32 +        return self.obj
   33.33 +
   33.34 +class SrvDir(SrvBase):
   33.35 +    """Base class for directory servlets.
   33.36 +    """
   33.37 +    isLeaf = False
   33.38 +    
   33.39 +    def __init__(self):
   33.40 +        SrvBase.__init__(self)
   33.41 +        self.table = {}
   33.42 +        self.order = []
   33.43 +
   33.44 +    def getChild(self, x, req):
   33.45 +        if x == '': return self
   33.46 +        val = self.get(x)
   33.47 +        if val is None:
   33.48 +            return error.NoResource('Not found')
   33.49 +        else:
   33.50 +            return val
   33.51 +
   33.52 +    def get(self, x):
   33.53 +        val = self.table.get(x)
   33.54 +        if val is not None:
   33.55 +            val = val.getobj()
   33.56 +        return val
   33.57 +
   33.58 +    def add(self, x, xclass = None):
   33.59 +        if xclass is None:
   33.60 +            xclass = 'SrvDir'
   33.61 +        self.table[x] = SrvConstructor(xclass)
   33.62 +        self.order.append(x)
   33.63 +
   33.64 +    def render_GET(self, req):
   33.65 +        if self.use_sxp(req):
   33.66 +            req.setHeader("Content-type", sxp.mime_type)
   33.67 +            self.ls(req, 1)
   33.68 +        else:
   33.69 +            req.write('<html><head></head><body>')
   33.70 +            self.print_path(req)
   33.71 +            self.ls(req)
   33.72 +            self.form(req)
   33.73 +            req.write('</body></html>')
   33.74 +        return ''
   33.75 +            
   33.76 +    def ls(self, req, use_sxp=0):
   33.77 +        url = req.prePathURL()
   33.78 +        if not url.endswith('/'):
   33.79 +            url += '/'
   33.80 +        if use_sxp:
   33.81 +           req.write('(ls ')
   33.82 +           for k in self.order:
   33.83 +               req.write(' ' + k)
   33.84 +           req.write(')')
   33.85 +        else:
   33.86 +            req.write('<ul>')
   33.87 +            for k in self.order:
   33.88 +                v = self.get(k)
   33.89 +                req.write('<li><a href="%s%s">%s</a></li>'
   33.90 +                          % (url, k, k))
   33.91 +            req.write('</ul>')
   33.92 +
   33.93 +    def form(self, req):
   33.94 +        pass
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/tools/xen/lib/xend/server/SrvDomain.py	Fri Jun 25 15:10:48 2004 +0000
    34.3 @@ -0,0 +1,202 @@
    34.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    34.5 +
    34.6 +from xen.xend import sxp
    34.7 +from xen.xend import XendDomain
    34.8 +from xen.xend import XendConsole
    34.9 +from xen.xend import PrettyPrint
   34.10 +from xen.xend.Args import FormFn
   34.11 +
   34.12 +from SrvDir import SrvDir
   34.13 +
   34.14 +class SrvDomain(SrvDir):
   34.15 +    """Service managing a single domain.
   34.16 +    """
   34.17 +
   34.18 +    def __init__(self, dom):
   34.19 +        SrvDir.__init__(self)
   34.20 +        self.dom = dom
   34.21 +        self.xd = XendDomain.instance()
   34.22 +        self.xconsole = XendConsole.instance()
   34.23 +
   34.24 +    def op_unpause(self, op, req):
   34.25 +        val = self.xd.domain_unpause(self.dom.id)
   34.26 +        return val
   34.27 +        
   34.28 +    def op_pause(self, op, req):
   34.29 +        val = self.xd.domain_pause(self.dom.id)
   34.30 +        return val
   34.31 +
   34.32 +    def op_shutdown(self, op, req):
   34.33 +        val = self.xd.domain_shutdown(self.dom.id)
   34.34 +        req.setResponseCode(202)
   34.35 +        req.setHeader("Location", "%s/.." % req.prePathURL())
   34.36 +        return val
   34.37 +
   34.38 +    def op_destroy(self, op, req):
   34.39 +        val = self.xd.domain_destroy(self.dom.id)
   34.40 +        req.setHeader("Location", "%s/.." % req.prePathURL())
   34.41 +        return val
   34.42 +
   34.43 +    def op_save(self, op, req):
   34.44 +        fn = FormFn(self.xd.domain_save,
   34.45 +                    [['dom', 'int'],
   34.46 +                     ['file', 'str']])
   34.47 +        val = fn(req.args, {'dom': self.dom.id})
   34.48 +        return val
   34.49 +
   34.50 +    def op_restore(self, op, req):
   34.51 +        fn = FormFn(self.xd.domain_restore,
   34.52 +                    [['dom', 'int'],
   34.53 +                     ['file', 'str']])
   34.54 +        val = fn(req.args, {'dom': self.dom.id})
   34.55 +        return val
   34.56 +        
   34.57 +    def op_migrate(self, op, req):
   34.58 +        fn = FormFn(self.xd.domain_migrate,
   34.59 +                    [['dom', 'int'],
   34.60 +                     ['destination', 'str']])
   34.61 +        val = fn(req.args, {'dom': self.dom.id})
   34.62 +        val = 0 # Some migrate id.
   34.63 +        req.setResponseCode(202)
   34.64 +        #req.send_header("Location", "%s/.." % self.path) # Some migrate url.
   34.65 +        return val
   34.66 +
   34.67 +    def op_pincpu(self, op, req):
   34.68 +        fn = FormFn(self.xd.domain_migrate,
   34.69 +                    [['dom', 'int'],
   34.70 +                     ['cpu', 'int']])
   34.71 +        val = fn(req.args, {'dom': self.dom.id})
   34.72 +        return val
   34.73 +
   34.74 +    def op_cpu_bvt_set(self, op, req):
   34.75 +        fn = FormFn(self.xd.domain_cpu_bvt_set,
   34.76 +                    [['dom', 'int'],
   34.77 +                     ['mcuadv', 'int'],
   34.78 +                     ['warp', 'int'],
   34.79 +                     ['warpl', 'int'],
   34.80 +                     ['warpu', 'int']])
   34.81 +        val = fn(req.args, {'dom': self.dom.id})
   34.82 +        return val
   34.83 +
   34.84 +    def op_cpu_atropos_set(self, op, req):
   34.85 +        fn = FormFn(self.xd.domain_cpu_atropos_set,
   34.86 +                    [['dom', 'int'],
   34.87 +                     ['period', 'int'],
   34.88 +                     ['slice', 'int'],
   34.89 +                     ['latency', 'int'],
   34.90 +                     ['xtratime', 'int']])
   34.91 +        val = fn(req.args, {'dom': self.dom.id})
   34.92 +        return val
   34.93 +
   34.94 +    def op_vifs(self, op, req):
   34.95 +        return self.xd.domain_vif_ls(self.dom.id)
   34.96 +
   34.97 +    def op_vif(self, op, req):
   34.98 +        fn = FormFn(self.xd.domain_vif_get,
   34.99 +                    [['dom', 'int'],
  34.100 +                     ['vif', 'int']])
  34.101 +        val = fn(req.args, {'dom': self.dom.id})
  34.102 +        return val
  34.103 +
  34.104 +    def op_vif_stats(self, op, req):
  34.105 +        #todo
  34.106 +        fn = FormFn(self.xd.domain_vif_stats,
  34.107 +                    [['dom', 'int'],
  34.108 +                     ['vif', 'int']])
  34.109 +        #val = fn(req.args, {'dom': self.dom.id})
  34.110 +        val = 999
  34.111 +        #return val
  34.112 +        return val
  34.113 +
  34.114 +    def op_vif_ip_add(self, op, req):
  34.115 +        fn = FormFn(self.xd.domain_vif_ip_add,
  34.116 +                    [['dom', 'int'],
  34.117 +                     ['vif', 'int'],
  34.118 +                     ['ip', 'str']])
  34.119 +        val = fn(req.args, {'dom': self.dom.id})
  34.120 +        return val
  34.121 +
  34.122 +    def op_vif_scheduler_set(self, op, req):
  34.123 +        fn = FormFn(self.xd.domain_vif_scheduler_set,
  34.124 +                    [['dom', 'int'],
  34.125 +                     ['vif', 'int'],
  34.126 +                     ['bytes', 'int'],
  34.127 +                     ['usecs', 'int']])
  34.128 +        val = fn(req.args, {'dom': self.dom.id})
  34.129 +        return val
  34.130 +
  34.131 +    def op_vif_scheduler_get(self, op, req):
  34.132 +        fn = FormFn(self.xd.domain_vif_scheduler_set,
  34.133 +                    [['dom', 'int'],
  34.134 +                     ['vif', 'int']])
  34.135 +        val = fn(req.args, {'dom': self.dom.id})
  34.136 +        return val
  34.137 +
  34.138 +    def op_vbds(self, op, req):
  34.139 +        return self.xd.domain_vbd_ls(self.dom.id)
  34.140 +
  34.141 +    def op_vbd(self, op, req):
  34.142 +        fn = FormFn(self.xd.domain_vbd_get,
  34.143 +                    [['dom', 'int'],
  34.144 +                     ['vbd', 'int']])
  34.145 +        val = fn(req.args, {'dom': self.dom.id})
  34.146 +        return val
  34.147 +
  34.148 +    def op_vbd_add(self, op, req):
  34.149 +        fn = FormFn(self.xd.domain_vbd_add,
  34.150 +                    [['dom', 'int'],
  34.151 +                     ['uname', 'str'],
  34.152 +                     ['dev', 'str'],
  34.153 +                     ['mode', 'str']])
  34.154 +        val = fn(req.args, {'dom': self.dom.id})
  34.155 +        return val
  34.156 +
  34.157 +    def op_vbd_remove(self, op, req):
  34.158 +        fn = FormFn(self.xd.domain_vbd_remove,
  34.159 +                    [['dom', 'int'],
  34.160 +                     ['dev', 'str']])
  34.161 +        val = fn(req.args, {'dom': self.dom.id})
  34.162 +        return val
  34.163 +
  34.164 +    def render_POST(self, req):
  34.165 +        return self.perform(req)
  34.166 +        
  34.167 +    def render_GET(self, req):
  34.168 +        op = req.args.get('op')
  34.169 +        if op and op[0] in ['vifs', 'vif', 'vif_stats', 'vbds', 'vbd']:
  34.170 +            return self.perform(req)
  34.171 +        if self.use_sxp(req):
  34.172 +            req.setHeader("Content-Type", sxp.mime_type)
  34.173 +            sxp.show(self.dom.sxpr(), out=req)
  34.174 +        else:
  34.175 +            req.write('<html><head></head><body>')
  34.176 +            self.print_path(req)
  34.177 +            #self.ls()
  34.178 +            req.write('<p>%s</p>' % self.dom)
  34.179 +            if self.dom.console:
  34.180 +                cinfo = self.dom.console
  34.181 +                cid = cinfo.id
  34.182 +                #todo: Local xref: need to know server prefix.
  34.183 +                req.write('<p><a href="/xend/console/%s">Console %s</a></p>'
  34.184 +                          % (cid, cid))
  34.185 +                req.write('<p><a href="%s">Connect to console</a></p>'
  34.186 +                          % cinfo.uri())
  34.187 +            if self.dom.config:
  34.188 +                req.write("<code><pre>")
  34.189 +                PrettyPrint.prettyprint(self.dom.config, out=req)
  34.190 +                req.write("</pre></code>")
  34.191 +            req.write('<a href="%s?op=vif_stats&vif=0">vif 0 stats</a>'
  34.192 +                      % req.prePathURL())
  34.193 +            self.form(req)
  34.194 +            req.write('</body></html>')
  34.195 +        return ''
  34.196 +
  34.197 +    def form(self, req):
  34.198 +        req.write('<form method="post" action="%s">' % req.prePathURL())
  34.199 +        req.write('<input type="submit" name="op" value="unpause">')
  34.200 +        req.write('<input type="submit" name="op" value="pause">')
  34.201 +        req.write('<input type="submit" name="op" value="shutdown">')
  34.202 +        req.write('<input type="submit" name="op" value="destroy">')
  34.203 +        req.write('<br><input type="submit" name="op" value="migrate">')
  34.204 +        req.write('To: <input type="text" name="destination">')
  34.205 +        req.write('</form>')
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/tools/xen/lib/xend/server/SrvDomainDir.py	Fri Jun 25 15:10:48 2004 +0000
    35.3 @@ -0,0 +1,131 @@
    35.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    35.5 +
    35.6 +from StringIO import StringIO
    35.7 +
    35.8 +from twisted.protocols import http
    35.9 +from twisted.web import error
   35.10 +
   35.11 +from xen.xend import sxp
   35.12 +from xen.xend import XendDomain
   35.13 +
   35.14 +from SrvDir import SrvDir
   35.15 +from SrvDomain import SrvDomain
   35.16 +
   35.17 +class SrvDomainDir(SrvDir):
   35.18 +    """Service that manages the domain directory.
   35.19 +    """
   35.20 +
   35.21 +    def __init__(self):
   35.22 +        SrvDir.__init__(self)
   35.23 +        self.xd = XendDomain.instance()
   35.24 +
   35.25 +    def domain(self, x):
   35.26 +        val = None
   35.27 +        try:
   35.28 +            dom = self.xd.domain_get(x)
   35.29 +            val = SrvDomain(dom)
   35.30 +        except KeyError, ex:
   35.31 +            print 'SrvDomainDir>', ex
   35.32 +            pass
   35.33 +        return val
   35.34 +
   35.35 +    def get(self, x):
   35.36 +        v = SrvDir.get(self, x)
   35.37 +        if v is not None:
   35.38 +            return v
   35.39 +        v = self.domain(x)
   35.40 +        return v
   35.41 +
   35.42 +    def op_create(self, op, req):
   35.43 +        ok = 0
   35.44 +        try:
   35.45 +            configstring = req.args.get('config')[0]
   35.46 +            print 'config:', configstring
   35.47 +            pin = sxp.Parser()
   35.48 +            pin.input(configstring)
   35.49 +            pin.input_eof()
   35.50 +            config = pin.get_val()
   35.51 +            ok = 1
   35.52 +        except Exception, ex:
   35.53 +            print 'op_create>', ex
   35.54 +        if not ok:
   35.55 +            req.setResponseCode(http.BAD_REQUEST, "Invalid configuration")
   35.56 +            return "Invalid configuration"
   35.57 +            return error.ErrorPage(http.BAD_REQUEST,
   35.58 +                                   "Invalid",
   35.59 +                                   "Invalid configuration")
   35.60 +        try:
   35.61 +            deferred = self.xd.domain_create(config)
   35.62 +            deferred.addCallback(self._cb_op_create, configstring, req)
   35.63 +            return deferred
   35.64 +        except Exception, ex:
   35.65 +            raise
   35.66 +            #return ['err', str(ex) ]
   35.67 +            #req.setResponseCode(http.BAD_REQUEST, "Error creating domain")
   35.68 +            #return str(ex)
   35.69 +            #return error.ErrorPage(http.BAD_REQUEST,
   35.70 +            #                       "Error creating domain",
   35.71 +            #                       str(ex))
   35.72 +                                   
   35.73 +
   35.74 +    def _cb_op_create(self, dominfo, configstring, req):
   35.75 +        """Callback to handle deferred domain creation.
   35.76 +        """
   35.77 +        dom = dominfo.id
   35.78 +        domurl = "%s/%s" % (req.prePathURL(), dom)
   35.79 +        req.setResponseCode(201, "created")
   35.80 +        req.setHeader("Location", domurl)
   35.81 +        if self.use_sxp(req):
   35.82 +            return dominfo.sxpr()
   35.83 +        else:
   35.84 +            out = StringIO()
   35.85 +            print >> out, ('<p> Created <a href="%s">Domain %s</a></p>'
   35.86 +                           % (domurl, dom))
   35.87 +            print >> out, '<p><pre>'
   35.88 +            print >> out, configstring
   35.89 +            print >> out, '</pre></p>'
   35.90 +            val = out.getvalue()
   35.91 +            out.close()
   35.92 +            return val
   35.93 +
   35.94 +    def render_POST(self, req):
   35.95 +        return self.perform(req)
   35.96 +
   35.97 +    def render_GET(self, req):
   35.98 +        if self.use_sxp(req):
   35.99 +            req.setHeader("Content-Type", sxp.mime_type)
  35.100 +            self.ls_domain(req, 1)
  35.101 +        else:
  35.102 +            req.write("<html><head></head><body>")
  35.103 +            self.print_path(req)
  35.104 +            self.ls(req)
  35.105 +            self.ls_domain(req)
  35.106 +            self.form(req)
  35.107 +            req.write("</body></html>")
  35.108 +        return ''
  35.109 +
  35.110 +    def ls_domain(self, req, use_sxp=0):
  35.111 +        url = req.prePathURL()
  35.112 +        if not url.endswith('/'):
  35.113 +            url += '/'
  35.114 +        if use_sxp:
  35.115 +            domains = self.xd.domain_ls()
  35.116 +            sxp.show(domains, out=req)
  35.117 +        else:
  35.118 +            domains = self.xd.domains()
  35.119 +            domains.sort(lambda x, y: cmp(x.id, y.id))
  35.120 +            req.write('<ul>')
  35.121 +            for d in domains:
  35.122 +               req.write('<li><a href="%s%s"> Domain %s</a>'
  35.123 +                         % (url, d.id, d.id))
  35.124 +               req.write('name=%s' % d.name)
  35.125 +               req.write('memory=%d'% d.memory)
  35.126 +               req.write('</li>')
  35.127 +            req.write('</ul>')
  35.128 +
  35.129 +    def form(self, req):
  35.130 +        req.write('<form method="post" action="%s" enctype="multipart/form-data">'
  35.131 +                  % req.prePathURL())
  35.132 +        req.write('<button type="submit" name="op" value="create">Create Domain</button>')
  35.133 +        req.write('Config <input type="file" name="config"><br>')
  35.134 +        req.write('</form>')
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/tools/xen/lib/xend/server/SrvEventDir.py	Fri Jun 25 15:10:48 2004 +0000
    36.3 @@ -0,0 +1,41 @@
    36.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    36.5 +
    36.6 +from xen.xend import sxp
    36.7 +from xen.xend import EventServer
    36.8 +from SrvDir import SrvDir
    36.9 +
   36.10 +class SrvEventDir(SrvDir):
   36.11 +    """Event directory.
   36.12 +    """
   36.13 +
   36.14 +    def __init__(self):
   36.15 +        SrvDir.__init__(self)
   36.16 +        self.eserver = EventServer.instance()
   36.17 +
   36.18 +    def op_inject(self, op, req):
   36.19 +        eventstring = req.args.get('event')
   36.20 +        pin = sxp.Parser()
   36.21 +        pin.input(eventstring)
   36.22 +        pin.input_eof()
   36.23 +        sxpr = pin.get_val()
   36.24 +        self.eserver.inject(sxp.name(sxpr), sxpr)
   36.25 +        if req.use_sxp:
   36.26 +            sxp.name(sxpr)
   36.27 +        else:
   36.28 +            return '<code>' + eventstring + '</code>'
   36.29 +        
   36.30 +    def render_POST(self, req):
   36.31 +        return self.perform(req)
   36.32 +
   36.33 +    def form(self, req):
   36.34 +        action = req.prePathURL()
   36.35 +        req.write('<form method="post" action="%s" enctype="multipart/form-data">'
   36.36 +                  % action)
   36.37 +        req.write('<button type="submit" name="op" value="inject">Inject</button>')
   36.38 +        req.write('Event <input type="text" name="event" size="40"><br>')
   36.39 +        req.write('</form>')
   36.40 +        req.write('<form method="post" action="%s" enctype="multipart/form-data">'
   36.41 +                  % action)
   36.42 +        req.write('<button type="submit" name="op" value="inject">Inject</button>')
   36.43 +        req.write('Event file<input type="file" name="event"><br>')
   36.44 +        req.write('</form>')
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/tools/xen/lib/xend/server/SrvNode.py	Fri Jun 25 15:10:48 2004 +0000
    37.3 @@ -0,0 +1,54 @@
    37.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    37.5 +
    37.6 +import os
    37.7 +from SrvDir import SrvDir
    37.8 +from xen.xend import sxp
    37.9 +from xen.xend import XendNode
   37.10 +
   37.11 +class SrvNode(SrvDir):
   37.12 +    """Information about the node.
   37.13 +    """
   37.14 +
   37.15 +    def __init__(self):
   37.16 +        SrvDir.__init__(self)
   37.17 +        self.xn = XendNode.instance()
   37.18 +
   37.19 +    def op_shutdown(self, op, req):
   37.20 +        val = self.xn.shutdown()
   37.21 +        return val
   37.22 +
   37.23 +    def op_reboot(self, op, req):
   37.24 +        val = self.xn.reboot()
   37.25 +        return val
   37.26 +
   37.27 +    def op_cpu_rrobin_slice_set(self, op, req):
   37.28 +        fn = FormFn(self.xn.cpu_rrobin_slice_set,
   37.29 +                    [['slice', 'int']])
   37.30 +        val = fn(req.args, {})
   37.31 +        return val
   37.32 +
   37.33 +    def op_cpu_bvt_slice_set(self, op, req):
   37.34 +        fn = FormFn(self.xn.cpu_bvt_slice_set,
   37.35 +                    [['slice', 'int']])
   37.36 +        val = fn(req.args, {})
   37.37 +        return val
   37.38 +
   37.39 +    def render_POST(self, req):
   37.40 +        return self.perform(req)
   37.41 +
   37.42 +    def render_GET(self, req):
   37.43 +        if self.use_sxp(req):
   37.44 +            req.setHeader("Content-Type", sxp.mime_type)
   37.45 +            sxp.show(['node'] + self.info(), out=req)
   37.46 +        else:
   37.47 +            req.write('<html><head></head><body>')
   37.48 +            self.print_path(req)
   37.49 +            req.write('<ul>')
   37.50 +            for d in self.info():
   37.51 +                req.write('<li> %10s: %s' % (d[0], str(d[1])))
   37.52 +            req.write('</ul>')
   37.53 +            req.write('</body></html>')
   37.54 +        return ''
   37.55 +            
   37.56 +    def info(self):
   37.57 +        return self.xn.info()
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/tools/xen/lib/xend/server/SrvRoot.py	Fri Jun 25 15:10:48 2004 +0000
    38.3 @@ -0,0 +1,30 @@
    38.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    38.5 +
    38.6 +from xen.xend import XendRoot
    38.7 +xroot = XendRoot.instance()
    38.8 +from SrvDir import SrvDir
    38.9 +
   38.10 +class SrvRoot(SrvDir):
   38.11 +    """The root of the xend server.
   38.12 +    """
   38.13 +
   38.14 +    """Server sub-components. Each entry is (name, class), where
   38.15 +    'name' is the entry name and  'class' is the name of its class.
   38.16 +    """
   38.17 +    #todo Get this list from the XendRoot config.
   38.18 +    subdirs = [
   38.19 +        ('node',    'SrvNode'       ),
   38.20 +        ('domain',  'SrvDomainDir'  ),
   38.21 +        ('console', 'SrvConsoleDir' ),
   38.22 +        ('event',   'SrvEventDir'   ),
   38.23 +        ('device',  'SrvDeviceDir'  ),
   38.24 +        ('vnet',    'SrvVnetDir'    ),
   38.25 +        ]
   38.26 +
   38.27 +    def __init__(self):
   38.28 +        SrvDir.__init__(self)
   38.29 +        for (name, klass) in self.subdirs:
   38.30 +            self.add(name, klass)
   38.31 +        for (name, klass) in self.subdirs:
   38.32 +            self.get(name)
   38.33 +        xroot.start()
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/tools/xen/lib/xend/server/SrvServer.py	Fri Jun 25 15:10:48 2004 +0000
    39.3 @@ -0,0 +1,60 @@
    39.4 +#!/usr/bin/python2
    39.5 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    39.6 +
    39.7 +"""Example xend HTTP and console server.
    39.8 +
    39.9 +   Can be accessed from a browser or from a program.
   39.10 +   Do 'python SrvServer.py' to run the server.
   39.11 +   Then point a web browser at http://localhost:8000/xend and follow the links.
   39.12 +   Most are stubs, except /domain which has a list of domains and a 'create domain'
   39.13 +   button.
   39.14 +
   39.15 +   You can also access the server from a program.
   39.16 +   Do 'python XendClient.py' to run a few test operations.
   39.17 +
   39.18 +   The data served differs depending on the client (as defined by User-Agent
   39.19 +   and Accept in the HTTP headers). If the client is a browser, data
   39.20 +   is returned in HTML, with interactive forms. If the client is a program,
   39.21 +   data is returned in SXP format, with no forms.
   39.22 +
   39.23 +   The server serves to the world by default. To restrict it to the local host
   39.24 +   change 'interface' in main().
   39.25 +
   39.26 +   Mike Wray <mike.wray@hp.com>
   39.27 +"""
   39.28 +# todo Support security settings etc. in the config file.
   39.29 +# todo Support command-line args.
   39.30 +
   39.31 +from twisted.web import server
   39.32 +from twisted.web import resource
   39.33 +from twisted.internet import reactor
   39.34 +
   39.35 +from xen.xend import XendRoot
   39.36 +xroot = XendRoot.instance()
   39.37 +
   39.38 +from xen.xend import XendBridge
   39.39 +
   39.40 +from SrvRoot import SrvRoot
   39.41 +
   39.42 +def create(port=None, interface=None, bridge=0):
   39.43 +    if port is None: port = 8000
   39.44 +    if interface is None: interface = ''
   39.45 +    if bridge or xroot.rebooted:
   39.46 +        init_bridge()
   39.47 +    root = resource.Resource()
   39.48 +    xend = SrvRoot()
   39.49 +    root.putChild('xend', xend)
   39.50 +    site = server.Site(root)
   39.51 +    reactor.listenTCP(port, site, interface=interface)
   39.52 +
   39.53 +def init_bridge():
   39.54 +    XendBridge.bridge_create()
   39.55 +    XendBridge.reconfigure()
   39.56 +
   39.57 +def main(port=None, interface=None):
   39.58 +    create(port, interface)
   39.59 +    reactor.run()
   39.60 +
   39.61 +
   39.62 +if __name__ == '__main__':
   39.63 +    main()
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/tools/xen/lib/xend/server/SrvVnetDir.py	Fri Jun 25 15:10:48 2004 +0000
    40.3 @@ -0,0 +1,9 @@
    40.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    40.5 +
    40.6 +from SrvDir import SrvDir
    40.7 +
    40.8 +class SrvVnetDir(SrvDir):
    40.9 +    """Vnet directory.
   40.10 +    """
   40.11 +
   40.12 +    pass
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/tools/xen/lib/xend/server/__init__.py	Fri Jun 25 15:10:48 2004 +0000
    41.3 @@ -0,0 +1,1 @@
    41.4 +
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/tools/xen/lib/xend/server/blkif.py	Fri Jun 25 15:10:48 2004 +0000
    42.3 @@ -0,0 +1,341 @@
    42.4 +from twisted.internet import defer
    42.5 +
    42.6 +from xen.xend import sxp
    42.7 +from xen.xend import PrettyPrint
    42.8 +
    42.9 +import channel
   42.10 +import controller
   42.11 +from messages import *
   42.12 +
   42.13 +class BlkifControllerFactory(controller.ControllerFactory):
   42.14 +    """Factory for creating block device interface controllers.
   42.15 +    Also handles the 'back-end' channel to the device driver domain.
   42.16 +    """
   42.17 +
   42.18 +    def __init__(self):
   42.19 +        controller.ControllerFactory.__init__(self)
   42.20 +
   42.21 +        self.majorTypes = [ CMSG_BLKIF_BE ]
   42.22 +
   42.23 +        self.subTypes = {
   42.24 +            CMSG_BLKIF_BE_CREATE     : self.recv_be_create,
   42.25 +            CMSG_BLKIF_BE_CONNECT    : self.recv_be_connect,
   42.26 +            CMSG_BLKIF_BE_VBD_CREATE : self.recv_be_vbd_create,
   42.27 +            CMSG_BLKIF_BE_VBD_GROW   : self.recv_be_vbd_grow,
   42.28 +            CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED: self.recv_be_driver_status_changed,
   42.29 +            }
   42.30 +        self.attached = 1
   42.31 +        self.registerChannel()
   42.32 +
   42.33 +    def createInstance(self, dom, recreate=0):
   42.34 +        d = self.addDeferred()
   42.35 +        blkif = self.getInstanceByDom(dom)
   42.36 +        if blkif:
   42.37 +            self.callDeferred(blkif)
   42.38 +        else:
   42.39 +            blkif = BlkifController(self, dom)
   42.40 +            self.addInstance(blkif)
   42.41 +            if recreate:
   42.42 +                self.callDeferred(blkif)
   42.43 +            else:
   42.44 +                blkif.send_be_create()
   42.45 +        return d
   42.46 +
   42.47 +    def getDomainDevices(self, dom):
   42.48 +        blkif = self.getInstanceByDom(dom)
   42.49 +        return (blkif and blkif.getDevices()) or []
   42.50 +
   42.51 +    def getDomainDevice(self, dom, vdev):
   42.52 +        blkif = self.getInstanceByDom(dom)
   42.53 +        return (blkif and blkif.getDevice(vdev)) or None
   42.54 +
   42.55 +    def setControlDomain(self, dom, recreate=0):
   42.56 +        if self.dom == dom: return
   42.57 +        self.deregisterChannel()
   42.58 +        if not recreate:
   42.59 +            self.attached = 0
   42.60 +        self.dom = dom
   42.61 +        self.registerChannel()
   42.62 +        #
   42.63 +        #if xend.blkif.be_port:
   42.64 +        #    xend.blkif.recovery = True
   42.65 +        #xend.blkif.be_port = xend.main.port_from_dom(dom)
   42.66 +
   42.67 +    def getControlDomain(self):
   42.68 +        return self.dom
   42.69 +
   42.70 +    def reattachDevice(self, dom, vdev):
   42.71 +        blkif = self.getInstanceByDom(dom)
   42.72 +        if blkif:
   42.73 +            blkif.reattachDevice(vdev)
   42.74 +        self.attached = self.devicesAttached()
   42.75 +        if self.attached:
   42.76 +            self.reattached()
   42.77 +
   42.78 +    def devicesAttached(self):
   42.79 +        """Check if all devices are attached.
   42.80 +        """
   42.81 +        attached = 1
   42.82 +        for blkif in self.getInstances():
   42.83 +            if not blkif.attached:
   42.84 +                attached = 0
   42.85 +                break
   42.86 +        return attached
   42.87 +                         
   42.88 +    def reattached(self):
   42.89 +        for blkif in self.getInstances():
   42.90 +            blkif.reattached()
   42.91 +
   42.92 +    def recv_be_create(self, msg, req):
   42.93 +        #print 'recv_be_create>'
   42.94 +        val = unpackMsg('blkif_be_create_t', msg)
   42.95 +        blkif = self.getInstanceByDom(val['domid'])
   42.96 +        self.callDeferred(blkif)
   42.97 +    
   42.98 +    def recv_be_connect(self, msg, req):
   42.99 +        #print 'recv_be_create>'
  42.100 +        val = unpackMsg('blkif_be_connect_t', msg)
  42.101 +        blkif = self.getInstanceByDom(val['domid'])
  42.102 +        if blkif:
  42.103 +            blkif.send_fe_interface_status_changed()
  42.104 +        else:
  42.105 +            pass
  42.106 +    
  42.107 +    def recv_be_vbd_create(self, msg, req):
  42.108 +        #print 'recv_be_vbd_create>'
  42.109 +        val = unpackMsg('blkif_be_vbd_create_t', msg)
  42.110 +        blkif = self.getInstanceByDom(val['domid'])
  42.111 +        if blkif:
  42.112 +            blkif.send_be_vbd_grow(val['vdevice'])
  42.113 +        else:
  42.114 +            pass
  42.115 +    
  42.116 +    def recv_be_vbd_grow(self, msg, req):
  42.117 +        #print 'recv_be_vbd_grow>'
  42.118 +        val = unpackMsg('blkif_be_vbd_grow_t', msg)
  42.119 +        # Check status?
  42.120 +        if self.attached:
  42.121 +            self.callDeferred(0)
  42.122 +        else:
  42.123 +            self.reattachDevice(val['domid'], val['vdevice'])
  42.124 +
  42.125 +    def recv_be_driver_status_changed(self, msg, req):
  42.126 +        val = unpackMsg('blkif_be_driver_status_changed_t', msg)
  42.127 +        status = val['status']
  42.128 +        if status == BLKIF_DRIVER_STATUS_UP and not self.attached:
  42.129 +            for blkif in self.getInstances():
  42.130 +                blkif.detach()
  42.131 +
  42.132 +class BlkDev(controller.Dev):
  42.133 +    """Info record for a block device.
  42.134 +    """
  42.135 +
  42.136 +    def __init__(self, ctrl, vdev, mode, segment):
  42.137 +        controller.Dev.__init__(self, ctrl)
  42.138 +        self.vdev = vdev
  42.139 +        self.mode = mode
  42.140 +        self.device = segment['device']
  42.141 +        self.start_sector = segment['start_sector']
  42.142 +        self.nr_sectors = segment['nr_sectors']
  42.143 +        self.attached = 1
  42.144 +
  42.145 +    def readonly(self):
  42.146 +        return 'w' not in self.mode
  42.147 +
  42.148 +    def sxpr(self):
  42.149 +        val = ['blkdev', ['vdev', self.vdev], ['mode', self.mode] ]
  42.150 +        return val
  42.151 +
  42.152 +    def destroy(self):
  42.153 +        print 'BlkDev>destroy>', self.vdev
  42.154 +        PrettyPrint.prettyprint(self.sxpr())
  42.155 +        self.controller.send_be_vbd_destroy(self.vdev)
  42.156 +        
  42.157 +class BlkifController(controller.Controller):
  42.158 +    """Block device interface controller. Handles all block devices
  42.159 +    for a domain.
  42.160 +    """
  42.161 +    
  42.162 +    def __init__(self, factory, dom):
  42.163 +        #print 'BlkifController> dom=', dom
  42.164 +        controller.Controller.__init__(self, factory, dom)
  42.165 +        self.devices = {}
  42.166 +
  42.167 +        self.majorTypes = [ CMSG_BLKIF_FE ]
  42.168 +
  42.169 +        self.subTypes = {
  42.170 +            CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
  42.171 +                self.recv_fe_driver_status_changed,
  42.172 +            CMSG_BLKIF_FE_INTERFACE_CONNECT    :
  42.173 +                self.recv_fe_interface_connect,
  42.174 +            }
  42.175 +        self.attached = 1
  42.176 +        self.evtchn = None
  42.177 +        self.registerChannel()
  42.178 +        #print 'BlkifController<', 'dom=', self.dom, 'idx=', self.idx
  42.179 +
  42.180 +    def sxpr(self):
  42.181 +        val = ['blkif', ['dom', self.dom]]
  42.182 +        if self.evtchn:
  42.183 +            val.append(['evtchn',
  42.184 +                        self.evtchn['port1'],
  42.185 +                        self.evtchn['port2']])
  42.186 +        return val
  42.187 +
  42.188 +    def lostChannel(self):
  42.189 +        print 'BlkifController>lostChannel>', 'dom=', self.dom
  42.190 +        #self.destroyDevices()
  42.191 +        controller.Controller.lostChannel(self)
  42.192 +
  42.193 +    def getDevices(self):
  42.194 +        return self.devices.values()
  42.195 +
  42.196 +    def getDevice(self, vdev):
  42.197 +        return self.devices.get(vdev)
  42.198 +
  42.199 +    def addDevice(self, vdev, mode, segment):
  42.200 +        if vdev in self.devices: return None
  42.201 +        dev = BlkDev(self, vdev, mode, segment)
  42.202 +        self.devices[vdev] = dev
  42.203 +        return dev
  42.204 +
  42.205 +    def attachDevice(self, vdev, mode, segment, recreate=0):
  42.206 +        """Attach a device to the specified interface.
  42.207 +        """
  42.208 +        #print 'BlkifController>attach_device>', self.dom, vdev, mode, segment
  42.209 +        dev = self.addDevice(vdev, mode, segment)
  42.210 +        if not dev: return -1
  42.211 +        if recreate:
  42.212 +            d = defer.Deferred()
  42.213 +            d.callback(self)
  42.214 +        else:
  42.215 +            self.send_be_vbd_create(vdev)
  42.216 +            d = self.factory.addDeferred()
  42.217 +        return d
  42.218 +
  42.219 +    def destroy(self):
  42.220 +        print 'BlkifController>destroy> dom=', self.dom
  42.221 +        def cb_destroy(val):
  42.222 +            self.send_be_destroy()
  42.223 +        d = self.factory.addDeferred()
  42.224 +        d.addCallback(cb_destroy)
  42.225 +        self.send_be_disconnect()
  42.226 +        #self.destroyDevices()
  42.227 +
  42.228 +    def destroyDevices(self):
  42.229 +        for dev in self.getDevices():
  42.230 +            dev.destroy()
  42.231 +
  42.232 +    def detach(self):
  42.233 +        """Detach all devices, when the back-end control domain has changed.
  42.234 +        """
  42.235 +        self.attached = 0
  42.236 +        for dev in self.devices.values():
  42.237 +            dev.attached = 0
  42.238 +            self.send_be_vbd_create(vdev)
  42.239 +
  42.240 +    def reattachDevice(self, vdev):
  42.241 +        """Reattach a device, when the back-end control domain has changed.
  42.242 +        """
  42.243 +        dev = self.devices[vdev]
  42.244 +        dev.attached = 1
  42.245 +        attached = 1
  42.246 +        for dev in self.devices.values():
  42.247 +            if not dev.attached:
  42.248 +                attached = 0
  42.249 +                break
  42.250 +        self.attached = attached
  42.251 +        return self.attached
  42.252 +
  42.253 +    def reattached(self):
  42.254 +        """All devices have been reattached after the back-end control
  42.255 +        domain has changed.
  42.256 +        """
  42.257 +        msg = packMsg('blkif_fe_interface_status_changed_t',
  42.258 +                      { 'handle' : 0,
  42.259 +                        'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED})
  42.260 +        self.writeRequest(msg)
  42.261 +
  42.262 +    def recv_fe_driver_status_changed(self, msg, req):
  42.263 +        msg = packMsg('blkif_fe_interface_status_changed_t',
  42.264 +                      { 'handle' : 0,
  42.265 +                        'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED,
  42.266 +                        'evtchn' : 0 })
  42.267 +        self.writeRequest(msg)
  42.268 +    
  42.269 +    def recv_fe_interface_connect(self, msg, req):
  42.270 +        val = unpackMsg('blkif_fe_interface_connect_t', msg)
  42.271 +        self.evtchn = channel.eventChannel(0, self.dom)
  42.272 +        print 'recv_fe_interface_connect>'
  42.273 +        PrettyPrint.prettyprint(self.sxpr())
  42.274 +        msg = packMsg('blkif_be_connect_t',
  42.275 +                      { 'domid'        : self.dom,
  42.276 +                        'blkif_handle' : val['handle'],
  42.277 +                        'evtchn'       : self.evtchn['port1'],
  42.278 +                        'shmem_frame'  : val['shmem_frame'] })
  42.279 +        self.factory.writeRequest(msg)
  42.280 +        pass
  42.281 +
  42.282 +    #def recv_fe_interface_status_changed(self, msg, req):
  42.283 +    #    (hnd, status, chan) = unpackMsg('blkif_fe_interface_status_changed_t', msg)
  42.284 +    #    print 'recv_fe_interface_status_changed>', hnd, status, chan
  42.285 +    #   pass
  42.286 +
  42.287 +    def send_fe_interface_status_changed(self):
  42.288 +        msg = packMsg('blkif_fe_interface_status_changed_t',
  42.289 +                      { 'handle' : 0,
  42.290 +                        'status' : BLKIF_INTERFACE_STATUS_CONNECTED,
  42.291 +                        'evtchn' : self.evtchn['port2'] })
  42.292 +        self.writeRequest(msg)
  42.293 +
  42.294 +    def send_be_create(self):
  42.295 +        msg = packMsg('blkif_be_create_t',
  42.296 +                      { 'domid'        : self.dom,
  42.297 +                        'blkif_handle' : 0 })
  42.298 +        self.factory.writeRequest(msg)
  42.299 +
  42.300 +    def send_be_disconnect(self):
  42.301 +        print '>BlkifController>send_be_disconnect>', 'dom=', self.dom
  42.302 +        msg = packMsg('blkif_be_disconnect_t',
  42.303 +                      { 'domid'        : self.dom,
  42.304 +                        'blkif_handle' : 0 })
  42.305 +        self.factory.writeRequest(msg)
  42.306 +
  42.307 +    def send_be_destroy(self):
  42.308 +        print '>BlkifController>send_be_destroy>', 'dom=', self.dom
  42.309 +        msg = packMsg('blkif_be_destroy_t',
  42.310 +                      { 'domid'        : self.dom,
  42.311 +                        'blkif_handle' : 0 })
  42.312 +        self.factory.writeRequest(msg)
  42.313 +
  42.314 +    def send_be_vbd_create(self, vdev):
  42.315 +        dev = self.devices[vdev]
  42.316 +        msg = packMsg('blkif_be_vbd_create_t',
  42.317 +                      { 'domid'        : self.dom,
  42.318 +                        'blkif_handle' : 0,
  42.319 +                        'vdevice'      : dev.vdev,
  42.320 +                        'readonly'     : dev.readonly() })
  42.321 +        self.factory.writeRequest(msg)
  42.322 +        
  42.323 +    def send_be_vbd_grow(self, vdev):
  42.324 +        dev = self.devices[vdev]
  42.325 +        msg = packMsg('blkif_be_vbd_grow_t',
  42.326 +                      { 'domid'                : self.dom,
  42.327 +                        'blkif_handle'         : 0,
  42.328 +                        'vdevice'              : dev.vdev,
  42.329 +                        'extent.device'        : dev.device,
  42.330 +                        'extent.sector_start'  : dev.start_sector,
  42.331 +                        'extent.sector_length' : dev.nr_sectors })
  42.332 +        self.factory.writeRequest(msg)
  42.333 +
  42.334 +    def send_be_vbd_destroy(self, vdev):
  42.335 +        print '>BlkifController>send_be_vbd_destroy>', 'dom=', self.dom, 'vdev=', vdev
  42.336 +        PrettyPrint.prettyprint(self.sxpr())
  42.337 +        dev = self.devices[vdev]
  42.338 +        msg = packMsg('blkif_be_vbd_destroy_t',
  42.339 +                      { 'domid'                : self.dom,
  42.340 +                        'blkif_handle'         : 0,
  42.341 +                        'vdevice'              : dev.vdev })
  42.342 +        del self.devices[vdev]
  42.343 +        self.factory.writeRequest(msg)
  42.344 +    
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/tools/xen/lib/xend/server/channel.py	Fri Jun 25 15:10:48 2004 +0000
    43.3 @@ -0,0 +1,378 @@
    43.4 +import xen.ext.xc; xc = xen.ext.xc.new()
    43.5 +from xen.ext import xu
    43.6 +from messages import msgTypeName
    43.7 +
    43.8 +VIRQ_MISDIRECT  = 0  # Catch-all interrupt for unbound VIRQs.
    43.9 +VIRQ_TIMER      = 1  # Timebase update, and/or requested timeout.
   43.10 +VIRQ_DEBUG      = 2  # Request guest to dump debug info.
   43.11 +VIRQ_CONSOLE    = 3  # (DOM0) bytes received on emergency console.
   43.12 +VIRQ_DOM_EXC    = 4  # (DOM0) Exceptional event for some domain.
   43.13 +
   43.14 +def eventChannel(dom1, dom2):
   43.15 +    return xc.evtchn_bind_interdomain(dom1=dom1, dom2=dom2)
   43.16 +
   43.17 +class ChannelFactory:
   43.18 +    """Factory for creating channels.
   43.19 +    Maintains a table of channels.
   43.20 +    """
   43.21 +
   43.22 +    """ Channels indexed by index. """
   43.23 +    channels = {}
   43.24 +
   43.25 +    def __init__(self):
   43.26 +        """Constructor - do not use. Use the channelFactory function."""
   43.27 +        self.notifier = xu.notifier()
   43.28 +    
   43.29 +    def addChannel(self, channel):
   43.30 +        """Add a channel.
   43.31 +        """
   43.32 +        idx = channel.idx
   43.33 +        self.channels[idx] = channel
   43.34 +        self.notifier.bind(idx)
   43.35 +        # Try to wake it up
   43.36 +        #self.notifier.unmask(idx)
   43.37 +        #channel.notify()
   43.38 +
   43.39 +    def getChannel(self, idx):
   43.40 +        """Get the channel with the given index (if any).
   43.41 +        """
   43.42 +        return self.channels.get(idx)
   43.43 +
   43.44 +    def delChannel(self, idx):
   43.45 +        """Remove the channel with the given index (if any).
   43.46 +        """
   43.47 +        if idx in self.channels:
   43.48 +            del self.channels[idx]
   43.49 +            self.notifier.unbind(idx)
   43.50 +
   43.51 +    def domChannel(self, dom):
   43.52 +        """Get the channel for the given domain.
   43.53 +        Construct if necessary.
   43.54 +        """
   43.55 +        dom = int(dom)
   43.56 +        for chan in self.channels.values():
   43.57 +            if not isinstance(chan, Channel): continue
   43.58 +            if chan.dom == dom:
   43.59 +                return chan
   43.60 +        chan = Channel(self, dom)
   43.61 +        self.addChannel(chan)
   43.62 +        return chan
   43.63 +
   43.64 +    def virqChannel(self, virq):
   43.65 +        """Get the channel for the given virq.
   43.66 +        Construct if necessary.
   43.67 +        """
   43.68 +        for chan in self.channels.values():
   43.69 +            if not isinstance(chan, VirqChannel): continue
   43.70 +            if chan.virq == virq:
   43.71 +                return chan
   43.72 +        chan = VirqChannel(self, virq)
   43.73 +        self.addChannel(chan)
   43.74 +        return chan
   43.75 +
   43.76 +    def channelClosed(self, channel):
   43.77 +        """The given channel has been closed - remove it.
   43.78 +        """
   43.79 +        self.delChannel(channel.idx)
   43.80 +
   43.81 +    def createPort(self, dom):
   43.82 +        """Create a port for a channel to the given domain.
   43.83 +        """
   43.84 +        return xu.port(dom)
   43.85 +
   43.86 +def channelFactory():
   43.87 +    """Singleton constructor for the channel factory.
   43.88 +    Use this instead of the class constructor.
   43.89 +    """
   43.90 +    global inst
   43.91 +    try:
   43.92 +        inst
   43.93 +    except:
   43.94 +        inst = ChannelFactory()
   43.95 +    return inst
   43.96 +
   43.97 +class BaseChannel:
   43.98 +    """Abstract superclass for channels.
   43.99 +
  43.100 +    The subclass constructor must set idx to the port to use.
  43.101 +    """
  43.102 +
  43.103 +    def __init__(self, factory):
  43.104 +        self.factory = factory
  43.105 +        self.idx = -1
  43.106 +        self.closed = 0
  43.107 +
  43.108 +    def getIndex(self):
  43.109 +        """Get the channel index.
  43.110 +        """
  43.111 +        return self.idx
  43.112 +
  43.113 +    def notificationReceived(self, type):
  43.114 +        """Called when a notification is received.
  43.115 +        Closes the channel on error, otherwise calls
  43.116 +        handleNotification(type), which should be defined
  43.117 +        in a subclass.
  43.118 +        """
  43.119 +        #print 'notificationReceived> type=', type, self
  43.120 +        if self.closed: return
  43.121 +        if type == self.factory.notifier.EXCEPTION:
  43.122 +            print 'notificationReceived> EXCEPTION'
  43.123 +            info = xc.evtchn_status(self.idx)
  43.124 +            if info['status'] == 'unbound':
  43.125 +                print 'notificationReceived> EXCEPTION closing...'
  43.126 +                self.close()
  43.127 +                return
  43.128 +        self.handleNotification(type)
  43.129 +
  43.130 +    def close(self):
  43.131 +        """Close the channel. Calls channelClosed() on the factory.
  43.132 +        Override in subclass.
  43.133 +        """
  43.134 +        self.factory.channelClosed(self)
  43.135 +
  43.136 +    def handleNotification(self, type):
  43.137 +        """Handle notification.
  43.138 +        Define in subclass.
  43.139 +        """
  43.140 +        pass
  43.141 +        
  43.142 +
  43.143 +class VirqChannel(BaseChannel):
  43.144 +    """A channel for handling a virq.
  43.145 +    """
  43.146 +    
  43.147 +    def __init__(self, factory, virq):
  43.148 +        """Create a channel for the given virq using the given factory.
  43.149 +
  43.150 +        Do not call directly, use virqChannel on the factory.
  43.151 +        """
  43.152 +        BaseChannel.__init__(self, factory)
  43.153 +        self.virq = virq
  43.154 +        # Notification port (int).
  43.155 +        self.port = xc.evtchn_bind_virq(virq)
  43.156 +        self.idx = self.port
  43.157 +        # Clients to call when a virq arrives.
  43.158 +        self.clients = []
  43.159 +
  43.160 +    def __repr__(self):
  43.161 +        return ('<VirqChannel virq=%d port=%d>'
  43.162 +                % (self.virq, self.port))
  43.163 +
  43.164 +    def getVirq(self):
  43.165 +        """Get the channel's virq.
  43.166 +        """
  43.167 +        return self.virq
  43.168 +
  43.169 +    def close(self):
  43.170 +        """Close the channel. Calls lostChannel(self) on all its clients and
  43.171 +        channelClosed() on the factory.
  43.172 +        """
  43.173 +        for c in self.clients:
  43.174 +            c.lostChannel(self)
  43.175 +        del self.clients
  43.176 +        BaseChannel.close(self)
  43.177 +
  43.178 +    def registerClient(self, client):
  43.179 +        """Register a client. The client will be called with
  43.180 +        client.virqReceived(virq) when a virq is received.
  43.181 +        The client will be called with client.lostChannel(self) if the
  43.182 +        channel is closed.
  43.183 +        """
  43.184 +        self.clients.append(client)
  43.185 +
  43.186 +    def handleNotification(self, type):
  43.187 +        for c in self.clients:
  43.188 +            c.virqReceived(self.virq)
  43.189 +
  43.190 +    def notify(self):
  43.191 +        xc.evtchn_send(self.port)
  43.192 +
  43.193 +
  43.194 +class Channel(BaseChannel):
  43.195 +    """A control channel to a domain. Messages for the domain device controllers
  43.196 +    are multiplexed over the channel (console, block devs, net devs).
  43.197 +    """
  43.198 +
  43.199 +    def __init__(self, factory, dom):
  43.200 +        """Create a channel to the given domain using the given factory.
  43.201 +
  43.202 +        Do not call directly, use domChannel on the factory.
  43.203 +        """
  43.204 +        BaseChannel.__init__(self, factory)
  43.205 +        # Domain.
  43.206 +        self.dom = int(dom)
  43.207 +        # Domain port (object).
  43.208 +        self.port = self.factory.createPort(dom)
  43.209 +        # Channel port (int).
  43.210 +        self.idx = self.port.local_port
  43.211 +        # Registered devices.
  43.212 +        self.devs = []
  43.213 +        # Devices indexed by the message types they handle.
  43.214 +        self.devs_by_type = {}
  43.215 +        # Output queue.
  43.216 +        self.queue = []
  43.217 +        self.closed = 0
  43.218 +
  43.219 +    def getLocalPort(self):
  43.220 +        """Get the local port.
  43.221 +        """
  43.222 +        return self.port.local_port
  43.223 +
  43.224 +    def getRemotePort(self):
  43.225 +        """Get the remote port.
  43.226 +        """
  43.227 +        return self.port.remote_port
  43.228 +
  43.229 +    def close(self):
  43.230 +        """Close the channel. Calls lostChannel() on all its devices and
  43.231 +        channelClosed() on the factory.
  43.232 +        """
  43.233 +        self.closed = 1
  43.234 +        for d in self.devs:
  43.235 +            d.lostChannel()
  43.236 +        self.factory.channelClosed(self)
  43.237 +        self.devs = []
  43.238 +        self.devs_by_type = {}
  43.239 +
  43.240 +    def registerDevice(self, types, dev):
  43.241 +        """Register a device controller.
  43.242 +
  43.243 +        @param types message types the controller handles
  43.244 +        @param dev   device controller
  43.245 +        """
  43.246 +        if self.closed: return
  43.247 +        self.devs.append(dev)
  43.248 +        for ty in types:
  43.249 +            self.devs_by_type[ty] = dev
  43.250 +
  43.251 +    def deregisterDevice(self, dev):
  43.252 +        """Remove the registration for a device controller.
  43.253 +
  43.254 +        @param dev device controller
  43.255 +        """
  43.256 +        if dev in self.devs:
  43.257 +            self.devs.remove(dev)
  43.258 +        types = [ ty for (ty, d) in self.devs_by_type.items() if d == dev ]
  43.259 +        for ty in types:
  43.260 +            del self.devs_by_type[ty]
  43.261 +
  43.262 +    def getDevice(self, type):
  43.263 +        """Get the device controller handling a message type.
  43.264 +
  43.265 +        @param type message type
  43.266 +        @returns controller or None
  43.267 +        """
  43.268 +        return self.devs_by_type.get(type)
  43.269 +
  43.270 +    def getMessageType(self, msg):
  43.271 +        """Get a 2-tuple of the message type and subtype.
  43.272 +        """
  43.273 +        hdr = msg.get_header()
  43.274 +        return (hdr['type'], hdr.get('subtype'))
  43.275 +
  43.276 +    def __repr__(self):
  43.277 +        return ('<Channel dom=%d ports=%d:%d>'
  43.278 +                % (self.dom,
  43.279 +                   self.port.local_port,
  43.280 +                   self.port.remote_port))
  43.281 +
  43.282 +    def handleNotification(self, type):
  43.283 +        work = 0
  43.284 +        work += self.handleRequests()
  43.285 +        work += self.handleResponses()
  43.286 +        work += self.handleWrites()
  43.287 +        if work:
  43.288 +            self.notify()
  43.289 +
  43.290 +    def notify(self):
  43.291 +        self.port.notify()
  43.292 +
  43.293 +    def handleRequests(self):
  43.294 +        work = 0
  43.295 +        while 1:
  43.296 +            msg = self.readRequest()
  43.297 +            if not msg: break
  43.298 +            self.requestReceived(msg)
  43.299 +            work += 1
  43.300 +        return work
  43.301 +
  43.302 +    def requestReceived(self, msg):
  43.303 +        (ty, subty) = self.getMessageType(msg)
  43.304 +        #todo:  Must respond before writing any more messages.
  43.305 +        #todo:  Should automate this (respond on write)
  43.306 +        self.port.write_response(msg)
  43.307 +        dev = self.getDevice(ty)
  43.308 +        if dev:
  43.309 +            dev.requestReceived(msg, ty, subty)
  43.310 +        else:
  43.311 +            print ("requestReceived> No device: Message type %s %d:%d"
  43.312 +                   % (msgTypeName(ty, subty), ty, subty)), self
  43.313 +
  43.314 +    def handleResponses(self):
  43.315 +        work = 0
  43.316 +        while 1:
  43.317 +            msg = self.readResponse()
  43.318 +            if not msg: break
  43.319 +            self.responseReceived(msg)
  43.320 +            work += 1
  43.321 +        return work
  43.322 +
  43.323 +    def responseReceived(self, msg):
  43.324 +        (ty, subty) = self.getMessageType(msg)
  43.325 +        dev = self.getDevice(ty)
  43.326 +        if dev:
  43.327 +            dev.responseReceived(msg, ty, subty)
  43.328 +        else:
  43.329 +            print ("responseReceived> No device: Message type %d:%d"
  43.330 +                   % (msgTypeName(ty, subty), ty, subty)), self
  43.331 +
  43.332 +    def handleWrites(self):
  43.333 +        work = 0
  43.334 +        # Pull data from producers.
  43.335 +        for dev in self.devs:
  43.336 +            work += dev.produceRequests()
  43.337 +        # Flush the queue.
  43.338 +        while self.queue and self.port.space_to_write_request():
  43.339 +            msg = self.queue.pop(0)
  43.340 +            self.port.write_request(msg)
  43.341 +            work += 1
  43.342 +        return work
  43.343 +
  43.344 +    def writeRequest(self, msg, notify=1):
  43.345 +        if self.closed:
  43.346 +            val = -1
  43.347 +        elif self.writeReady():
  43.348 +            self.port.write_request(msg)
  43.349 +            if notify: self.notify()
  43.350 +            val = 1
  43.351 +        else:
  43.352 +            self.queue.append(msg)
  43.353 +            val = 0
  43.354 +        return val
  43.355 +
  43.356 +    def writeResponse(self, msg):
  43.357 +        if self.closed: return -1
  43.358 +        self.port.write_response(msg)
  43.359 +        return 1
  43.360 +
  43.361 +    def writeReady(self):
  43.362 +        if self.closed or self.queue: return 0
  43.363 +        return self.port.space_to_write_request()
  43.364 +
  43.365 +    def readRequest(self):
  43.366 +        if self.closed:
  43.367 +            return None
  43.368 +        if self.port.request_to_read():
  43.369 +            val = self.port.read_request()
  43.370 +        else:
  43.371 +            val = None
  43.372 +        return val
  43.373 +        
  43.374 +    def readResponse(self):
  43.375 +        if self.closed:
  43.376 +            return None
  43.377 +        if self.port.response_to_read():
  43.378 +            val = self.port.read_response()
  43.379 +        else:
  43.380 +            val = None
  43.381 +        return val
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/tools/xen/lib/xend/server/console.py	Fri Jun 25 15:10:48 2004 +0000
    44.3 @@ -0,0 +1,230 @@
    44.4 +
    44.5 +from twisted.internet import reactor
    44.6 +from twisted.internet import protocol
    44.7 +from twisted.protocols import telnet
    44.8 +
    44.9 +from xen.ext import xu
   44.10 +
   44.11 +from xen.xend import EventServer
   44.12 +eserver = EventServer.instance()
   44.13 +
   44.14 +import controller
   44.15 +from messages import *
   44.16 +from params import *
   44.17 +
   44.18 +"""Telnet binary option."""
   44.19 +TRANSMIT_BINARY = '0'
   44.20 +WILL = chr(251)
   44.21 +IAC = chr(255)
   44.22 +
   44.23 +class ConsoleProtocol(protocol.Protocol):
   44.24 +    """Asynchronous handler for a console TCP socket.
   44.25 +    """
   44.26 +
   44.27 +    def __init__(self, controller, idx):
   44.28 +        self.controller = controller
   44.29 +        self.idx = idx
   44.30 +        self.addr = None
   44.31 +        self.binary = 0
   44.32 +
   44.33 +    def connectionMade(self):
   44.34 +        peer = self.transport.getPeer()
   44.35 +        self.addr = (peer.host, peer.port)
   44.36 +        if self.controller.connect(self.addr, self):
   44.37 +            self.transport.write("Cannot connect to console %d on domain %d\n"
   44.38 +                                 % (self.idx, self.controller.dom))
   44.39 +            self.loseConnection()
   44.40 +            return
   44.41 +        else:
   44.42 +            self.transport.write("Connected to console %d on domain %d\n"
   44.43 +                                 % (self.idx, self.controller.dom))
   44.44 +            self.setTelnetTransmitBinary()
   44.45 +            eserver.inject('xend.console.connect',
   44.46 +                           [self.idx, self.addr[0], self.addr[1]])
   44.47 +
   44.48 +    def setTelnetTransmitBinary(self):
   44.49 +        """Send the sequence to set the telnet TRANSMIT-BINARY option.
   44.50 +        """
   44.51 +        self.write(IAC + WILL + TRANSMIT_BINARY)
   44.52 +
   44.53 +    def dataReceived(self, data):
   44.54 +        if self.controller.handleInput(self, data):
   44.55 +            self.loseConnection()
   44.56 +
   44.57 +    def write(self, data):
   44.58 +        #if not self.connected: return -1
   44.59 +        self.transport.write(data)
   44.60 +        return len(data)
   44.61 +
   44.62 +    def connectionLost(self, reason=None):
   44.63 +        eserver.inject('xend.console.disconnect',
   44.64 +                       [self.idx, self.addr[0], self.addr[1]])
   44.65 +        self.controller.disconnect()
   44.66 +
   44.67 +    def loseConnection(self):
   44.68 +        self.transport.loseConnection()
   44.69 +
   44.70 +class ConsoleFactory(protocol.ServerFactory):
   44.71 +    """Asynchronous handler for a console server socket.
   44.72 +    """
   44.73 +    protocol = ConsoleProtocol
   44.74 +    
   44.75 +    def __init__(self, controller, idx):
   44.76 +        #protocol.ServerFactory.__init__(self)
   44.77 +        self.controller = controller
   44.78 +        self.idx = idx
   44.79 +
   44.80 +    def buildProtocol(self, addr):
   44.81 +        proto = self.protocol(self.controller, self.idx)
   44.82 +        proto.factory = self
   44.83 +        return proto
   44.84 +
   44.85 +class ConsoleControllerFactory(controller.ControllerFactory):
   44.86 +    """Factory for creating console controllers.
   44.87 +    """
   44.88 +
   44.89 +    def createInstance(self, dom, console_port=None):
   44.90 +        if console_port is None:
   44.91 +            console_port = CONSOLE_PORT_BASE + dom
   44.92 +        console = ConsoleController(self, dom, console_port)
   44.93 +        self.addInstance(console)
   44.94 +        eserver.inject('xend.console.create',
   44.95 +                       [console.idx, console.dom, console.console_port])
   44.96 +        return console
   44.97 +        
   44.98 +    def consoleClosed(self, console):
   44.99 +        eserver.inject('xend.console.close', console.idx)
  44.100 +        self.delInstance(console)
  44.101 +
  44.102 +class ConsoleController(controller.Controller):
  44.103 +    """Console controller for a domain.
  44.104 +    Does not poll for i/o itself, but relies on the notifier to post console
  44.105 +    output and the connected TCP sockets to post console input.
  44.106 +    """
  44.107 +
  44.108 +    def __init__(self, factory, dom, console_port):
  44.109 +        #print 'ConsoleController> dom=', dom, type(dom)
  44.110 +        controller.Controller.__init__(self, factory, dom)
  44.111 +        self.majorTypes = [ CMSG_CONSOLE ]
  44.112 +        self.status = "new"
  44.113 +        self.addr = None
  44.114 +        self.conn = None
  44.115 +        self.rbuf = xu.buffer()
  44.116 +        self.wbuf = xu.buffer()
  44.117 +        self.console_port = console_port
  44.118 +
  44.119 +        self.registerChannel()
  44.120 +        self.listener = None
  44.121 +        self.listen()
  44.122 +        #print 'ConsoleController<', 'dom=', self.dom, 'idx=', self.idx
  44.123 +
  44.124 +    def sxpr(self):
  44.125 +        val =['console',
  44.126 +              ['status',       self.status ],
  44.127 +              ['id',           self.idx ],
  44.128 +              ['domain',       self.dom ],
  44.129 +              ['local_port',   self.channel.getLocalPort() ],
  44.130 +              ['remote_port',  self.channel.getRemotePort() ],
  44.131 +              ['console_port', self.console_port ] ]
  44.132 +        if self.addr:
  44.133 +            val.append(['connected', self.addr[0], self.addr[1]])
  44.134 +        return val
  44.135 +
  44.136 +    def ready(self):
  44.137 +        return not (self.closed() or self.rbuf.empty())
  44.138 +
  44.139 +    def closed(self):
  44.140 +        return self.status == 'closed'
  44.141 +
  44.142 +    def connected(self):
  44.143 +        return self.status == 'connected'
  44.144 +
  44.145 +    def close(self):
  44.146 +        try:
  44.147 +            #print 'ConsoleController> close dom=', self.dom
  44.148 +            self.status = "closed"
  44.149 +            if self.conn:
  44.150 +                self.conn.loseConnection()
  44.151 +            self.listener.stopListening()
  44.152 +            self.deregisterChannel()
  44.153 +            self.lostChannel()
  44.154 +        except Exception, ex:
  44.155 +            print 'ConsoleController>close>', ex
  44.156 +            raise
  44.157 +
  44.158 +    def listen(self):
  44.159 +        """Listen for TCP connections to the console port..
  44.160 +        """
  44.161 +        if self.closed(): return
  44.162 +        self.status = "listening"
  44.163 +        if self.listener:
  44.164 +            #self.listener.startListening()
  44.165 +            pass
  44.166 +        else:
  44.167 +            f = ConsoleFactory(self, self.idx)
  44.168 +            self.listener = reactor.listenTCP(self.console_port, f)
  44.169 +
  44.170 +    def connect(self, addr, conn):
  44.171 +        if self.closed(): return -1
  44.172 +        if self.connected(): return -1
  44.173 +        self.addr = addr
  44.174 +        self.conn = conn
  44.175 +        self.status = "connected"
  44.176 +        self.handleOutput()
  44.177 +        return 0
  44.178 +
  44.179 +    def disconnect(self):
  44.180 +        if self.conn:
  44.181 +            self.conn.loseConnection()
  44.182 +        self.addr = None
  44.183 +        self.conn = None
  44.184 +        self.listen()
  44.185 +
  44.186 +    def requestReceived(self, msg, type, subtype):
  44.187 +        #print '***Console', self.dom, msg.get_payload()
  44.188 +        self.rbuf.write(msg.get_payload())
  44.189 +        self.handleOutput()
  44.190 +        
  44.191 +    def responseReceived(self, msg, type, subtype):
  44.192 +        pass
  44.193 +
  44.194 +    def produceRequests(self):
  44.195 +        # Send as much pending console data as there is room for.
  44.196 +        work = 0
  44.197 +        while not self.wbuf.empty() and self.channel.writeReady():
  44.198 +            msg = xu.message(CMSG_CONSOLE, 0, 0)
  44.199 +            msg.append_payload(self.wbuf.read(msg.MAX_PAYLOAD))
  44.200 +            work += self.channel.writeRequest(msg, notify=0)
  44.201 +        return work
  44.202 +
  44.203 +    def handleInput(self, conn, data):
  44.204 +        """Handle some external input aimed at the console.
  44.205 +        Called from a TCP connection (conn).
  44.206 +        """
  44.207 +        if self.closed(): return -1
  44.208 +        if conn != self.conn: return 0
  44.209 +        self.wbuf.write(data)
  44.210 +        if self.produceRequests():
  44.211 +            self.channel.notify()
  44.212 +        return 0
  44.213 +
  44.214 +    def handleOutput(self):
  44.215 +        """Handle buffered output from the console.
  44.216 +        Sends it to the connected console (if any).
  44.217 +        """
  44.218 +        if self.closed():
  44.219 +            #print 'Console>handleOutput> closed'
  44.220 +            return -1
  44.221 +        if not self.conn:
  44.222 +            #print 'Console>handleOutput> not connected'
  44.223 +            return 0
  44.224 +        while not self.rbuf.empty():
  44.225 +            try:
  44.226 +                #print 'Console>handleOutput> writing...'
  44.227 +                bytes = self.conn.write(self.rbuf.peek())
  44.228 +                if bytes > 0:
  44.229 +                    self.rbuf.discard(bytes)
  44.230 +            except socket.error, error:
  44.231 +                pass
  44.232 +        #print 'Console>handleOutput<'
  44.233 +        return 0
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/tools/xen/lib/xend/server/controller.py	Fri Jun 25 15:10:48 2004 +0000
    45.3 @@ -0,0 +1,169 @@
    45.4 +from twisted.internet import defer
    45.5 +
    45.6 +import channel
    45.7 +from messages import msgTypeName
    45.8 +
    45.9 +class CtrlMsgRcvr:
   45.10 +    """Abstract class for things that deal with a control interface to a domain.
   45.11 +    """
   45.12 +
   45.13 +
   45.14 +    def __init__(self):
   45.15 +        self.channelFactory = channel.channelFactory()
   45.16 +        self.majorTypes = [ ]
   45.17 +        self.subTypes = {}
   45.18 +        self.dom = None
   45.19 +        self.channel = None
   45.20 +        self.idx = None
   45.21 +
   45.22 +    def requestReceived(self, msg, type, subtype):
   45.23 +        method = self.subTypes.get(subtype)
   45.24 +        if method:
   45.25 +            method(msg, 1)
   45.26 +        else:
   45.27 +            print ('requestReceived> No handler: Message type %s %d:%d'
   45.28 +                   % (msgTypeName(type, subtype), type, subtype)), self
   45.29 +        
   45.30 +    def responseReceived(self, msg, type, subtype):
   45.31 +        method = self.subTypes.get(subtype)
   45.32 +        if method:
   45.33 +            method(msg, 0)
   45.34 +        else:
   45.35 +            print ('responseReceived> No handler: Message type %s %d:%d'
   45.36 +                   % (msgTypeName(type, subtype), type, subtype)), self
   45.37 +
   45.38 +    def lostChannel(self):
   45.39 +        pass
   45.40 +    
   45.41 +    def registerChannel(self):
   45.42 +        #print 'CtrlMsgRcvr>registerChannel>', self
   45.43 +        self.channel = self.channelFactory.domChannel(self.dom)
   45.44 +        self.idx = self.channel.getIndex()
   45.45 +        if self.majorTypes:
   45.46 +            self.channel.registerDevice(self.majorTypes, self)
   45.47 +        
   45.48 +    def deregisterChannel(self):
   45.49 +        #print 'CtrlMsgRcvr>deregisterChannel>', self
   45.50 +        if self.channel:
   45.51 +            self.channel.deregisterDevice(self)
   45.52 +            del self.channel
   45.53 +
   45.54 +    def produceRequests(self):
   45.55 +        return 0
   45.56 +
   45.57 +    def writeRequest(self, msg):
   45.58 +        if self.channel:
   45.59 +            self.channel.writeRequest(msg)
   45.60 +        else:
   45.61 +            print 'CtrlMsgRcvr>writeRequest>', 'no channel!', self
   45.62 +
   45.63 +    def writeResponse(self, msg):
   45.64 +        if self.channel:
   45.65 +            self.channel.writeResponse(msg)
   45.66 +        else:
   45.67 +            print 'CtrlMsgRcvr>writeResponse>', 'no channel!', self
   45.68 +            
   45.69 +class ControllerFactory(CtrlMsgRcvr):
   45.70 +    """Abstract class for factories creating controllers.
   45.71 +    Maintains a table of instances.
   45.72 +    """
   45.73 +
   45.74 +    def __init__(self):
   45.75 +        CtrlMsgRcvr.__init__(self)
   45.76 +        self.instances = {}
   45.77 +        self.dlist = []
   45.78 +        self.dom = 0
   45.79 +        # Timeout (in seconds) for deferreds.
   45.80 +        self.timeout = 10
   45.81 +        
   45.82 +    def addInstance(self, instance):
   45.83 +        self.instances[instance.idx] = instance
   45.84 +
   45.85 +    def getInstance(self, idx):
   45.86 +        return self.instances.get(idx)
   45.87 +
   45.88 +    def getInstances(self):
   45.89 +        return self.instances.values()
   45.90 +
   45.91 +    def getInstanceByDom(self, dom):
   45.92 +        for inst in self.instances.values():
   45.93 +            if inst.dom == dom:
   45.94 +                return inst
   45.95 +        return None
   45.96 +
   45.97 +    def delInstance(self, instance):
   45.98 +        #print 'ControllerFactory>delInstance>', instance.idx
   45.99 +        if instance.idx in self.instances:
  45.100 +            #print 'ControllerFactory>delInstance> remove', instance.idx
  45.101 +            del self.instances[instance.idx]
  45.102 +
  45.103 +    def createInstance(self, dom, recreate=0):
  45.104 +        raise NotImplementedError()
  45.105 +
  45.106 +    def instanceClosed(self, instance):
  45.107 +        #print 'ControllerFactory>instanceClosed>', instance.idx, instance
  45.108 +        self.delInstance(instance)
  45.109 +
  45.110 +    def addDeferred(self):
  45.111 +        d = defer.Deferred()
  45.112 +        if self.timeout > 0:
  45.113 +            # The deferred will error if not called before timeout.
  45.114 +            d.setTimeout(self.timeout)
  45.115 +        self.dlist.append(d)
  45.116 +        return d
  45.117 +
  45.118 +    def callDeferred(self, *args):
  45.119 +        if self.dlist:
  45.120 +            d = self.dlist.pop(0)
  45.121 +            d.callback(*args)
  45.122 +
  45.123 +    def errDeferred(self, *args):
  45.124 +        if self.dlist:
  45.125 +            d = self.dlist.pop(0)
  45.126 +            d.errback(*args)
  45.127 +
  45.128 +class Controller(CtrlMsgRcvr):
  45.129 +    """Abstract class for a device controller attached to a domain.
  45.130 +    """
  45.131 +
  45.132 +    def __init__(self, factory, dom):
  45.133 +        CtrlMsgRcvr.__init__(self)
  45.134 +        self.factory = factory
  45.135 +        self.dom = int(dom)
  45.136 +        self.channel = None
  45.137 +        self.idx = None
  45.138 +
  45.139 +    def close(self):
  45.140 +        self.deregisterChannel()
  45.141 +        self.lostChannel()
  45.142 +
  45.143 +    def lostChannel(self):
  45.144 +        #print 'Controller>lostChannel>', self, self.factory
  45.145 +        self.factory.instanceClosed(self)
  45.146 +
  45.147 +class Dev:
  45.148 +
  45.149 +    def __init__(self, controller):
  45.150 +        self.controller = controller
  45.151 +        self.props = {}
  45.152 +
  45.153 +    def setprop(self, k, v):
  45.154 +        self.props[k] = v
  45.155 +
  45.156 +    def getprop(self, k, v=None):
  45.157 +        return self.props.get(k, v)
  45.158 +
  45.159 +    def hasprop(self, k):
  45.160 +        return k in self.props
  45.161 +
  45.162 +    def delprop(self, k):
  45.163 +        if k in self.props:
  45.164 +            del self.props[k]
  45.165 +
  45.166 +    #def __repr__(self):
  45.167 +    #    return str(self.sxpr())
  45.168 +
  45.169 +    def sxpr(self):
  45.170 +        raise NotImplementedError()
  45.171 +
  45.172 +    
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/tools/xen/lib/xend/server/cstruct.py	Fri Jun 25 15:10:48 2004 +0000
    46.3 @@ -0,0 +1,269 @@
    46.4 +import struct
    46.5 +
    46.6 +class Struct:
    46.7 +
    46.8 +    maxDepth = 10
    46.9 +
   46.10 +    base = ['x', 'B', 'H', 'I', 'L', 'Q', 'c', 'h', 'i', 'l', 'q', ]
   46.11 +
   46.12 +    sizes = {'B': 1,
   46.13 +            'H': 2,
   46.14 +            'I': 4,
   46.15 +            'L': 4,
   46.16 +            'Q': 8,
   46.17 +            'c': 1,
   46.18 +            'h': 2,
   46.19 +            'i': 4,
   46.20 +            'l': 4,
   46.21 +            'q': 8,
   46.22 +            'x': 1,
   46.23 +            }
   46.24 +
   46.25 +    formats = {
   46.26 +        'int8'          : 'B',
   46.27 +        'int16'         : 'H',
   46.28 +        'int32'         : 'I',
   46.29 +        'int64'         : 'Q',
   46.30 +        'u8'            : 'B',
   46.31 +        'u16'           : 'H',
   46.32 +        'u32'           : 'I',
   46.33 +        'u64'           : 'Q'
   46.34 +        }
   46.35 +
   46.36 +    def typedef(self, name, val):
   46.37 +        self.formats[name] = val
   46.38 +
   46.39 +    def struct(self, name, *f):
   46.40 +        self.typedef(name, StructInfo(self, f))
   46.41 +        
   46.42 +    def getType(self, name):
   46.43 +        return self.formats[name]
   46.44 +
   46.45 +    def format(self, ty):
   46.46 +        d = 0
   46.47 +        f = ty
   46.48 +        while d < self.maxDepth:
   46.49 +            d += 1
   46.50 +            f = self.formats[f]
   46.51 +            if isinstance(f, StructInfo):
   46.52 +                return f.format()
   46.53 +            if f in self.base:
   46.54 +                return f
   46.55 +        return -1
   46.56 +
   46.57 +    def alignedformat(self, ty):
   46.58 +        fmt = self.format(ty)
   46.59 +        #print 'alignedformat> %s |%s|' %(ty, fmt)
   46.60 +        afmt = self.align(fmt)
   46.61 +        #print 'alignedformat< %s |%s| |%s|' % (ty, fmt, afmt)
   46.62 +        return afmt
   46.63 +
   46.64 +    def align(self, fmt):
   46.65 +        n1 = 0
   46.66 +        afmt = ''
   46.67 +        for a in fmt:
   46.68 +            n2 = self.getSize(a)
   46.69 +            m = n1 % n2
   46.70 +            if m:
   46.71 +                d = (n2 - m)
   46.72 +                afmt += 'x' * d
   46.73 +                n1 += d
   46.74 +            afmt += a
   46.75 +            n1 += n2
   46.76 +        return afmt
   46.77 +
   46.78 +    def fmtsize(self, fmt):
   46.79 +        s = 0
   46.80 +        for f in fmt:
   46.81 +            s += self.getSize(f)
   46.82 +        return s
   46.83 +
   46.84 +    def getSize(self, f):
   46.85 +        return self.sizes[f]
   46.86 +
   46.87 +    def pack(self, ty, data):
   46.88 +        return self.getType(ty).pack(data)
   46.89 +
   46.90 +    def unpack(self, ty, data):
   46.91 +        return self.getType(ty).unpack(data)
   46.92 +
   46.93 +    def show(self):
   46.94 +        l = self.formats.keys()
   46.95 +        l.sort()
   46.96 +        for v in l:
   46.97 +            print "%-35s %-10s %s" % (v, self.format(v), self.alignedformat(v))
   46.98 +
   46.99 +
  46.100 +class StructInfo:
  46.101 +
  46.102 +    def __init__(self, s, f):
  46.103 +        self.fmt = None
  46.104 +        self.structs = s
  46.105 +        self.fields = f
  46.106 +
  46.107 +    def alignedformat(self):
  46.108 +        if self.afmt: return self.afmt
  46.109 +        self.afmt = self.structs.align(self.format())
  46.110 +        return self.afmt
  46.111 +    
  46.112 +    def format(self):
  46.113 +        if self.fmt: return self.fmt
  46.114 +        fmt = ""
  46.115 +        for (ty, name) in self.fields:
  46.116 +            fmt += self.formatString(ty)
  46.117 +        self.fmt = fmt
  46.118 +        return fmt
  46.119 +
  46.120 +    def formatString(self, ty):
  46.121 +        if ty in self.fields:
  46.122 +            ty = self.fields[ty]
  46.123 +        return self.structs.format(ty)
  46.124 +
  46.125 +    def pack(self, *args):
  46.126 +        return struct.pack(self.alignedformat(), *args)
  46.127 +
  46.128 +    def unpack(self, data):
  46.129 +        return struct.unpack(self.alignedformat(), data)
  46.130 +
  46.131 +types = Struct()
  46.132 +
  46.133 +types.typedef('short'         , 'h')
  46.134 +types.typedef('int'           , 'i')
  46.135 +types.typedef('long'          , 'l')
  46.136 +types.typedef('unsigned short', 'H')
  46.137 +types.typedef('unsigned int'  , 'I')
  46.138 +types.typedef('unsigned long' , 'L')
  46.139 +types.typedef('domid_t'       , 'u64')
  46.140 +types.typedef('blkif_vdev_t'  , 'u16')
  46.141 +types.typedef('blkif_pdev_t'  , 'u16')
  46.142 +types.typedef('blkif_sector_t', 'u64')
  46.143 +
  46.144 +types.struct('u8[6]',
  46.145 +             ('u8', 'a1'),
  46.146 +             ('u8', 'a2'),
  46.147 +             ('u8', 'a3'),
  46.148 +             ('u8', 'a4'),
  46.149 +             ('u8', 'a5'),
  46.150 +             ('u8', 'a6'))
  46.151 +             
  46.152 +types.struct('blkif_fe_interface_status_changed_t',
  46.153 +    ('unsigned int',    'handle'),
  46.154 +    ('unsigned int',    'status'),
  46.155 +    ('unsigned int',    'evtchn'))
  46.156 +
  46.157 +types.struct('blkif_fe_driver_status_changed_t',
  46.158 +    ('unsigned int',    'status'),
  46.159 +    ('unsigned int',    'nr_interfaces'))
  46.160 +
  46.161 +types.struct('blkif_fe_interface_connect_t',
  46.162 +    ('unsigned int' ,   'handle'),
  46.163 +    ('unsigned long',   'shmem_frame'))
  46.164 +
  46.165 +types.struct('blkif_fe_interface_disconnect_t',
  46.166 +    ('unsigned int',   'handle'))
  46.167 +
  46.168 +types.struct('blkif_extent_t',
  46.169 +    ('blkif_pdev_t'  , 'device'),
  46.170 +    ('blkif_sector_t', 'sector_start'),
  46.171 +    ('blkif_sector_t', 'sector_length'))
  46.172 +
  46.173 +types.struct('blkif_be_create_t', 
  46.174 +    ('domid_t'     ,   'domid'),
  46.175 +    ('unsigned int',   'blkif_handle'),
  46.176 +    ('unsigned int',   'status'))
  46.177 +             
  46.178 +types.struct('blkif_be_destroy_t',
  46.179 +    ('domid_t'     ,   'domid'),
  46.180 +    ('unsigned int',   'blkif_handle'),
  46.181 +    ('unsigned int',   'status'))
  46.182 +
  46.183 +types.struct('blkif_be_connect_t',
  46.184 +    ('domid_t'      ,  'domid'),
  46.185 +    ('unsigned int' ,  'blkif_handle'),
  46.186 +    ('unsigned int' ,  'evtchn'),
  46.187 +    ('unsigned long',  'shmem_frame'),
  46.188 +    ('unsigned int' ,  'status'))
  46.189 +
  46.190 +types.struct('blkif_be_disconnect_t',
  46.191 +    ('domid_t'     ,   'domid'),
  46.192 +    ('unsigned int',   'blkif_handle'),
  46.193 +    ('unsigned int',   'status'))
  46.194 +
  46.195 +types.struct('blkif_be_vbd_create_t', 
  46.196 +    ('domid_t'     ,   'domid'),         #Q
  46.197 +    ('unsigned int',   'blkif_handle'),  #I
  46.198 +    ('blkif_vdev_t',   'vdevice'),       #H
  46.199 +    ('int'         ,   'readonly'),      #i
  46.200 +    ('unsigned int',   'status'))        #I
  46.201 +
  46.202 +types.struct('blkif_be_vbd_destroy_t', 
  46.203 +    ('domid_t'     ,   'domid'),
  46.204 +    ('unsigned int',   'blkif_handle'),
  46.205 +    ('blkif_vdev_t',   'vdevice'),
  46.206 +    ('unsigned int',   'status'))
  46.207 +
  46.208 +types.struct('blkif_be_vbd_grow_t', 
  46.209 +    ('domid_t'       , 'domid'),         #Q
  46.210 +    ('unsigned int'  , 'blkif_handle'),  #I
  46.211 +    ('blkif_vdev_t'  , 'vdevice'),       #H   
  46.212 +    ('blkif_extent_t', 'extent'),        #HQQ
  46.213 +    ('unsigned int'  , 'status'))        #I
  46.214 +
  46.215 +types.struct('blkif_be_vbd_shrink_t', 
  46.216 +    ('domid_t'     ,   'domid'),
  46.217 +    ('unsigned int',   'blkif_handle'),
  46.218 +    ('blkif_vdev_t',   'vdevice'),
  46.219 +    ('unsigned int',   'status'))
  46.220 +
  46.221 +types.struct('blkif_be_driver_status_changed_t',
  46.222 +    ('unsigned int',   'status'),
  46.223 +    ('unsigned int',   'nr_interfaces'))
  46.224 +
  46.225 +types.struct('netif_fe_interface_status_changed_t',
  46.226 +    ('unsigned int',   'handle'),
  46.227 +    ('unsigned int',   'status'),
  46.228 +    ('unsigned int',   'evtchn'),
  46.229 +    ('u8[6]',          'mac'))
  46.230 +
  46.231 +types.struct('netif_fe_driver_status_changed_t',
  46.232 +    ('unsigned int',   'status'),
  46.233 +    ('unsigned int',   'nr_interfaces'))
  46.234 +
  46.235 +types.struct('netif_fe_interface_connect_t',
  46.236 +    ('unsigned int',   'handle'),
  46.237 +    ('unsigned long',  'tx_shmem_frame'),
  46.238 +    ('unsigned long',  'rx_shmem_frame'))
  46.239 +
  46.240 +types.struct('netif_fe_interface_disconnect_t',
  46.241 +    ('unsigned int',   'handle'))
  46.242 +
  46.243 +types.struct('netif_be_create_t', 
  46.244 +    ('domid_t'     ,   'domid'),
  46.245 +    ('unsigned int',   'netif_handle'),
  46.246 +    ('u8[6]'       ,   'mac'),
  46.247 +    ('unsigned int',   'status'))
  46.248 +
  46.249 +types.struct('netif_be_destroy_t',
  46.250 +    ('domid_t'     ,   'domid'),
  46.251 +    ('unsigned int',   'netif_handle'),
  46.252 +    ('unsigned int',   'status'))
  46.253 +
  46.254 +types.struct('netif_be_connect_t', 
  46.255 +    ('domid_t'      ,  'domid'),
  46.256 +    ('unsigned int' ,  'netif_handle'),
  46.257 +    ('unsigned int' ,  'evtchn'),
  46.258 +    ('unsigned long',  'tx_shmem_frame'),
  46.259 +    ('unsigned long',  'rx_shmem_frame'),
  46.260 +    ('unsigned int' ,  'status'))
  46.261 +
  46.262 +types.struct('netif_be_disconnect_t',
  46.263 +    ('domid_t'     ,   'domid'),
  46.264 +    ('unsigned int',   'netif_handle'),
  46.265 +    ('unsigned int',   'status'))
  46.266 +
  46.267 +types.struct('netif_be_driver_status_changed_t',
  46.268 +    ('unsigned int',   'status'),
  46.269 +    ('unsigned int',   'nr_interfaces'))
  46.270 +
  46.271 +if 1 or __name__ == "__main__":
  46.272 +    types.show()
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/tools/xen/lib/xend/server/domain.py	Fri Jun 25 15:10:48 2004 +0000
    47.3 @@ -0,0 +1,41 @@
    47.4 +import channel
    47.5 +import controller
    47.6 +from messages import *
    47.7 +
    47.8 +class DomainControllerFactory(controller.ControllerFactory):
    47.9 +    """Factory for creating domain controllers.
   47.10 +    """
   47.11 +
   47.12 +    def createInstance(self, dom):
   47.13 +        d = DomainController(self, dom)
   47.14 +        self.addInstance(d)
   47.15 +        return d
   47.16 +    
   47.17 +    def getInstanceByDom(self, dom):
   47.18 +        for inst in self.instances.values():
   47.19 +            if inst.dom == dom:
   47.20 +                return inst
   47.21 +        inst = self.createInstance(dom)
   47.22 +        return inst
   47.23 +
   47.24 +
   47.25 +class DomainController(controller.Controller):
   47.26 +    """Generic controller for a domain.
   47.27 +    """
   47.28 +
   47.29 +    reasons = {'poweroff' : 'shutdown_poweroff_t',
   47.30 +               'reboot'   : 'shutdown_reboot_t',
   47.31 +               'suspend'  : 'shutdown_suspend_t' }
   47.32 +
   47.33 +    def __init__(self, factory, dom):
   47.34 +        controller.Controller.__init__(self, factory, dom)
   47.35 +        self.majorTypes = [ CMSG_SHUTDOWN ]
   47.36 +        self.registerChannel()
   47.37 +        print 'DomainController>', self, self.channel, self.idx
   47.38 +
   47.39 +    def shutdown(self, reason):
   47.40 +        msgtype = self.reasons.get(reason)
   47.41 +        if not msgtype:
   47.42 +            raise ValueError('invalid reason:' + reason)
   47.43 +        msg = packMsg(msgtype, {})
   47.44 +        self.writeRequest(msg)
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/tools/xen/lib/xend/server/messages.py	Fri Jun 25 15:10:48 2004 +0000
    48.3 @@ -0,0 +1,219 @@
    48.4 +import struct
    48.5 +
    48.6 +from xen.ext import xu
    48.7 +
    48.8 +DEBUG = 0
    48.9 +
   48.10 +""" All message formats.
   48.11 +Added to incrementally for the various message types.
   48.12 +See below.
   48.13 +"""
   48.14 +msg_formats = {}
   48.15 +
   48.16 +#============================================================================
   48.17 +# Console message types.
   48.18 +#============================================================================
   48.19 +
   48.20 +CMSG_CONSOLE  = 0
   48.21 +
   48.22 +console_formats = { 'console_data': (CMSG_CONSOLE, 0) }
   48.23 +
   48.24 +msg_formats.update(console_formats)
   48.25 +
   48.26 +#============================================================================
   48.27 +# Block interface message types.
   48.28 +#============================================================================
   48.29 +
   48.30 +CMSG_BLKIF_BE = 1
   48.31 +CMSG_BLKIF_FE = 2
   48.32 +
   48.33 +CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED =  0
   48.34 +CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED    = 32
   48.35 +CMSG_BLKIF_FE_INTERFACE_CONNECT        = 33
   48.36 +CMSG_BLKIF_FE_INTERFACE_DISCONNECT     = 34
   48.37 +
   48.38 +CMSG_BLKIF_BE_CREATE      = 0
   48.39 +CMSG_BLKIF_BE_DESTROY     = 1
   48.40 +CMSG_BLKIF_BE_CONNECT     = 2
   48.41 +CMSG_BLKIF_BE_DISCONNECT  = 3
   48.42 +CMSG_BLKIF_BE_VBD_CREATE  = 4
   48.43 +CMSG_BLKIF_BE_VBD_DESTROY = 5
   48.44 +CMSG_BLKIF_BE_VBD_GROW    = 6
   48.45 +CMSG_BLKIF_BE_VBD_SHRINK  = 7
   48.46 +CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED    = 32
   48.47 +
   48.48 +BLKIF_DRIVER_STATUS_DOWN  = 0
   48.49 +BLKIF_DRIVER_STATUS_UP    = 1
   48.50 +
   48.51 +BLKIF_INTERFACE_STATUS_DESTROYED    = 0 #/* Interface doesn't exist.    */
   48.52 +BLKIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */
   48.53 +BLKIF_INTERFACE_STATUS_CONNECTED    = 2 #/* Exists and is connected.    */
   48.54 +
   48.55 +BLKIF_BE_STATUS_OKAY                = 0
   48.56 +BLKIF_BE_STATUS_ERROR               = 1
   48.57 +BLKIF_BE_STATUS_INTERFACE_EXISTS    = 2
   48.58 +BLKIF_BE_STATUS_INTERFACE_NOT_FOUND = 3
   48.59 +BLKIF_BE_STATUS_INTERFACE_CONNECTED = 4
   48.60 +BLKIF_BE_STATUS_VBD_EXISTS          = 5
   48.61 +BLKIF_BE_STATUS_VBD_NOT_FOUND       = 6
   48.62 +BLKIF_BE_STATUS_OUT_OF_MEMORY       = 7
   48.63 +BLKIF_BE_STATUS_EXTENT_NOT_FOUND    = 8
   48.64 +BLKIF_BE_STATUS_MAPPING_ERROR       = 9
   48.65 +
   48.66 +blkif_formats = {
   48.67 +    'blkif_be_connect_t':
   48.68 +    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT),
   48.69 +
   48.70 +    'blkif_be_create_t':
   48.71 +    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE),
   48.72 +
   48.73 +    'blkif_be_disconnect_t':
   48.74 +    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT),
   48.75 +
   48.76 +    'blkif_be_destroy_t':
   48.77 +    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY),
   48.78 +
   48.79 +    'blkif_be_vbd_create_t':
   48.80 +    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE),
   48.81 +
   48.82 +    'blkif_be_vbd_grow_t':
   48.83 +    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW),
   48.84 +
   48.85 +    'blkif_be_vbd_destroy_t':
   48.86 +    (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY),
   48.87 +
   48.88 +    'blkif_fe_interface_status_changed_t':
   48.89 +    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED),
   48.90 +
   48.91 +    'blkif_fe_driver_status_changed_t':
   48.92 +    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED),
   48.93 +
   48.94 +    'blkif_fe_interface_connect_t':
   48.95 +    (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT),
   48.96 +}
   48.97 +
   48.98 +msg_formats.update(blkif_formats)
   48.99 +
  48.100 +#============================================================================
  48.101 +# Network interface message types.
  48.102 +#============================================================================
  48.103 +
  48.104 +CMSG_NETIF_BE = 3
  48.105 +CMSG_NETIF_FE = 4
  48.106 +
  48.107 +CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED =  0
  48.108 +CMSG_NETIF_FE_DRIVER_STATUS_CHANGED    = 32
  48.109 +CMSG_NETIF_FE_INTERFACE_CONNECT        = 33
  48.110 +CMSG_NETIF_FE_INTERFACE_DISCONNECT     = 34
  48.111 +
  48.112 +CMSG_NETIF_BE_CREATE      = 0
  48.113 +CMSG_NETIF_BE_DESTROY     = 1
  48.114 +CMSG_NETIF_BE_CONNECT     = 2
  48.115 +CMSG_NETIF_BE_DISCONNECT  = 3
  48.116 +CMSG_NETIF_BE_DRIVER_STATUS_CHANGED    = 32
  48.117 +
  48.118 +NETIF_INTERFACE_STATUS_DESTROYED    = 0 #/* Interface doesn't exist.    */
  48.119 +NETIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */
  48.120 +NETIF_INTERFACE_STATUS_CONNECTED    = 2 #/* Exists and is connected.    */
  48.121 +
  48.122 +NETIF_DRIVER_STATUS_DOWN   = 0
  48.123 +NETIF_DRIVER_STATUS_UP     = 1
  48.124 +
  48.125 +netif_formats = {
  48.126 +    'netif_be_connect_t':
  48.127 +    (CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT),
  48.128 +
  48.129 +    'netif_be_create_t':
  48.130 +    (CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE),
  48.131 +
  48.132 +    'netif_be_disconnect_t':
  48.133 +    (CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT),
  48.134 +
  48.135 +    'netif_be_destroy_t':
  48.136 +    (CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY),
  48.137 +
  48.138 +    'netif_be_driver_status_changed_t':
  48.139 +    (CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS_CHANGED),
  48.140 +
  48.141 +    'netif_fe_driver_status_changed_t':
  48.142 +    (CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED),
  48.143 +
  48.144 +    'netif_fe_interface_connect_t':
  48.145 +    (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT),
  48.146 +
  48.147 +    'netif_fe_interface_status_changed_t':
  48.148 +    (CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED),
  48.149 +    }
  48.150 +
  48.151 +msg_formats.update(netif_formats)
  48.152 +
  48.153 +#============================================================================
  48.154 +CMSG_SHUTDOWN = 6
  48.155 +
  48.156 +CMSG_SHUTDOWN_POWEROFF  = 0
  48.157 +CMSG_SHUTDOWN_REBOOT    = 1
  48.158 +CMSG_SHUTDOWN_SUSPEND   = 2
  48.159 +
  48.160 +STOPCODE_shutdown       = 0
  48.161 +STOPCODE_reboot         = 1
  48.162 +STOPCODE_suspend        = 2
  48.163 +
  48.164 +shutdown_formats = {
  48.165 +    'shutdown_poweroff_t':
  48.166 +    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_POWEROFF),
  48.167 +    
  48.168 +    'shutdown_reboot_t':
  48.169 +    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_REBOOT),
  48.170 +
  48.171 +    'shutdown_suspend_t':
  48.172 +    (CMSG_SHUTDOWN, CMSG_SHUTDOWN_SUSPEND),
  48.173 +    }
  48.174 +
  48.175 +msg_formats.update(shutdown_formats)
  48.176 +
  48.177 +#============================================================================
  48.178 +
  48.179 +class Msg:
  48.180 +    pass
  48.181 +
  48.182 +def packMsg(ty, params):
  48.183 +    if DEBUG: print '>packMsg', ty, params
  48.184 +    (major, minor) = msg_formats[ty]
  48.185 +    args = {}
  48.186 +    for (k, v) in params.items():
  48.187 +        if k == 'mac':
  48.188 +            for i in range(0, 6):
  48.189 +                args['mac[%d]' % i] = v[i]
  48.190 +        else:
  48.191 +            args[k] = v
  48.192 +    if DEBUG:
  48.193 +        for (k, v) in args.items():
  48.194 +            print 'packMsg>', k, v, type(v)
  48.195 +    msgid = 0
  48.196 +    msg = xu.message(major, minor, msgid, args)
  48.197 +    return msg
  48.198 +
  48.199 +def unpackMsg(ty, msg):
  48.200 +    args = msg.get_payload()
  48.201 +    mac = [0, 0, 0, 0, 0, 0]
  48.202 +    macs = []
  48.203 +    for (k, v) in args.items():
  48.204 +        if k.startswith('mac['):
  48.205 +            macs += k
  48.206 +            i = int(k[4:5])
  48.207 +            mac[i] = v
  48.208 +        else:
  48.209 +            pass
  48.210 +    if macs:
  48.211 +        args['mac'] = mac
  48.212 +        for k in macs:
  48.213 +            del args[k]
  48.214 +    if DEBUG: print '<unpackMsg', ty, args
  48.215 +    return args
  48.216 +
  48.217 +def msgTypeName(ty, subty):
  48.218 +    for (name, info) in msg_formats.items():
  48.219 +        if info[0] == ty and info[1] == subty:
  48.220 +            return name
  48.221 +    return None
  48.222 +
    49.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2 +++ b/tools/xen/lib/xend/server/netif.py	Fri Jun 25 15:10:48 2004 +0000
    49.3 @@ -0,0 +1,304 @@
    49.4 +import random
    49.5 +
    49.6 +from twisted.internet import defer
    49.7 +
    49.8 +from xen.xend import sxp
    49.9 +from xen.xend import PrettyPrint
   49.10 +from xen.xend import XendBridge
   49.11 +
   49.12 +import channel
   49.13 +import controller
   49.14 +from messages import *
   49.15 +
   49.16 +class NetifControllerFactory(controller.ControllerFactory):
   49.17 +    """Factory for creating network interface controllers.
   49.18 +    Also handles the 'back-end' channel to the device driver domain.
   49.19 +    """
   49.20 +
   49.21 +    def __init__(self):
   49.22 +        controller.ControllerFactory.__init__(self)
   49.23 +
   49.24 +        self.majorTypes = [ CMSG_NETIF_BE ]
   49.25 +
   49.26 +        self.subTypes = {
   49.27 +            CMSG_NETIF_BE_CREATE : self.recv_be_create,
   49.28 +            CMSG_NETIF_BE_CONNECT: self.recv_be_connect,
   49.29 +            CMSG_NETIF_BE_DRIVER_STATUS_CHANGED: self.recv_be_driver_status_changed,
   49.30 +            }
   49.31 +        self.attached = 1
   49.32 +        self.registerChannel()
   49.33 +
   49.34 +    def createInstance(self, dom, recreate=0):
   49.35 +        """Create or find the network interface controller for a domain.
   49.36 +        """
   49.37 +        #print 'netif>createInstance> dom=', dom
   49.38 +        netif = self.getInstanceByDom(dom)
   49.39 +        if netif is None:
   49.40 +            netif = NetifController(self, dom)
   49.41 +            self.addInstance(netif)
   49.42 +        return netif
   49.43 +
   49.44 +    def getDomainDevices(self, dom):
   49.45 +        netif = self.getInstanceByDom(dom)
   49.46 +        return (netif and netif.getDevices()) or []
   49.47 +
   49.48 +    def getDomainDevice(self, dom, vif):
   49.49 +        netif = self.getInstanceByDom(dom)
   49.50 +        return (netif and netif.getDevice(vif)) or None
   49.51 +        
   49.52 +    def setControlDomain(self, dom, recreate=0):
   49.53 +        """Set the 'back-end' device driver domain.
   49.54 +        """
   49.55 +        if self.dom == dom: return
   49.56 +        self.deregisterChannel()
   49.57 +        if not recreate:
   49.58 +            self.attached = 0
   49.59 +        self.dom = dom
   49.60 +        self.registerChannel()
   49.61 +        #
   49.62 +        #if xend.netif.be_port.remote_dom != 0:
   49.63 +        #    xend.netif.recovery = True
   49.64 +        #    xend.netif.be_port = xend.main.port_from_dom(dom)
   49.65 +        #
   49.66 +
   49.67 +    def getControlDomain(self):
   49.68 +        return self.dom
   49.69 +
   49.70 +    def recv_be_create(self, msg, req):
   49.71 +        self.callDeferred(0)
   49.72 +    
   49.73 +    def recv_be_connect(self, msg, req):
   49.74 +        val = unpackMsg('netif_be_connect_t', msg)
   49.75 +        dom = val['domid']
   49.76 +        vif = val['netif_handle']
   49.77 +        netif = self.getInstanceByDom(dom)
   49.78 +        if netif:
   49.79 +            netif.send_interface_connected(vif)
   49.80 +        else:
   49.81 +            print "recv_be_connect> unknown vif=", vif
   49.82 +            pass
   49.83 +
   49.84 +    def recv_be_driver_status_changed(self, msg, req):
   49.85 +        val = unpackMsg('netif_be_driver_status_changed_t', msg)
   49.86 +        status = val['status']
   49.87 +        if status == NETIF_DRIVER_STATUS_UP and not self.attached:
   49.88 +            # If we are not attached the driver domain was changed, and
   49.89 +            # this signals the new driver domain is ready.
   49.90 +            for netif in self.getInstances():
   49.91 +                netif.reattach_devices()
   49.92 +            self.attached = 1
   49.93 +
   49.94 +##         pl = msg.get_payload()
   49.95 +##         status = pl['status']
   49.96 +##         if status == NETIF_DRIVER_STATUS_UP:
   49.97 +##             if xend.netif.recovery:
   49.98 +##                 print "New netif backend now UP, notifying guests:"
   49.99 +##                 for netif_key in interface.list.keys():
  49.100 +##                     netif = interface.list[netif_key]
  49.101 +##                     netif.create()
  49.102 +##                     print "  Notifying %d" % netif.dom
  49.103 +##                     msg = xu.message(
  49.104 +##                         CMSG_NETIF_FE,
  49.105 +##                         CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED, 0,
  49.106 +##                         { 'handle' : 0, 'status' : 1 })
  49.107 +##                     netif.ctrlif_tx_req(xend.main.port_from_dom(netif.dom),msg)
  49.108 +##                 print "Done notifying guests"
  49.109 +##                 recovery = False
  49.110 +                
  49.111 +class NetDev(controller.Dev):
  49.112 +    """Info record for a network device.
  49.113 +    """
  49.114 +
  49.115 +    def __init__(self, ctrl, vif, mac):
  49.116 +        controller.Dev.__init__(self, ctrl)
  49.117 +        self.vif = vif
  49.118 +        self.mac = mac
  49.119 +        self.evtchn = None
  49.120 +        self.bridge = None
  49.121 +
  49.122 +    def sxpr(self):
  49.123 +        vif = str(self.vif)
  49.124 +        mac = ':'.join(map(lambda x: "%x" % x, self.mac))
  49.125 +        val = ['netdev', ['vif', vif], ['mac', mac]]
  49.126 +        if self.bridge:
  49.127 +            val.append(['bridge', self.bridge])
  49.128 +        if self.evtchn:
  49.129 +            val.append(['evtchn',
  49.130 +                        self.evtchn['port1'],
  49.131 +                        self.evtchn['port2']])
  49.132 +        return val
  49.133 +
  49.134 +    def bridge_add(self, bridge):
  49.135 +        self.bridge = XendBridge.vif_bridge_add(self.controller.dom, self.vif, bridge)
  49.136 +
  49.137 +    def bridge_rem(self):
  49.138 +        if not self.bridge: return
  49.139 +        XendBridge.vif_bridge_rem(self.controller.dom, self.vif, self.bridge)
  49.140 +        self.bridge = None
  49.141 +
  49.142 +    def destroy(self):
  49.143 +        def cb_destroy(val):
  49.144 +            self.controller.send_be_destroy(self.vif)
  49.145 +        print 'NetDev>destroy>', 'vif=', self.vif
  49.146 +        PrettyPrint.prettyprint(self.sxpr())
  49.147 +        self.bridge_rem()
  49.148 +        d = self.controller.factory.addDeferred()
  49.149 +        d.addCallback(cb_destroy)
  49.150 +        self.controller.send_be_disconnect(self.vif)
  49.151 +        #self.controller.send_be_destroy(self.vif)
  49.152 +        
  49.153 +
  49.154 +class NetifController(controller.Controller):
  49.155 +    """Network interface controller. Handles all network devices for a domain.
  49.156 +    """
  49.157 +    
  49.158 +    def __init__(self, factory, dom):
  49.159 +        #print 'NetifController> dom=', dom
  49.160 +        controller.Controller.__init__(self, factory, dom)
  49.161 +        self.devices = {}
  49.162 +        
  49.163 +        self.majorTypes = [ CMSG_NETIF_FE ]
  49.164 +
  49.165 +        self.subTypes = {
  49.166 +            CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
  49.167 +                self.recv_fe_driver_status_changed,
  49.168 +            CMSG_NETIF_FE_INTERFACE_CONNECT    :
  49.169 +                self.recv_fe_interface_connect,
  49.170 +            }
  49.171 +        self.registerChannel()
  49.172 +        #print 'NetifController<', 'dom=', self.dom, 'idx=', self.idx
  49.173 +
  49.174 +    def sxpr(self):
  49.175 +        val = ['netif', ['dom', self.dom]]
  49.176 +        return val
  49.177 +    
  49.178 +    def randomMAC(self):
  49.179 +        # VIFs get a random MAC address with a "special" vendor id.
  49.180 +        # 
  49.181 +        # NB. The vendor is currently an "obsolete" one that used to belong
  49.182 +        # to DEC (AA-00-00). Using it is probably a bit rude :-)
  49.183 +        # 
  49.184 +        # NB2. The first bit of the first random octet is set to zero for
  49.185 +        # all dynamic MAC addresses. This may allow us to manually specify
  49.186 +        # MAC addresses for some VIFs with no fear of clashes.
  49.187 +        mac = [ 0xaa, 0x00, 0x00,
  49.188 +                random.randint(0x00, 0x7f),
  49.189 +                random.randint(0x00, 0xff),
  49.190 +                random.randint(0x00, 0xff) ]
  49.191 +        return mac
  49.192 +
  49.193 +    def lostChannel(self):
  49.194 +        print 'NetifController>lostChannel>', 'dom=', self.dom
  49.195 +        #self.destroyDevices()
  49.196 +        controller.Controller.lostChannel(self)
  49.197 +
  49.198 +    def getDevices(self):
  49.199 +        return self.devices.values()
  49.200 +
  49.201 +    def getDevice(self, vif):
  49.202 +        return self.devices.get(vif)
  49.203 +
  49.204 +    def addDevice(self, vif, vmac):
  49.205 +        if vmac is None:
  49.206 +            mac = self.randomMAC()
  49.207 +        else:
  49.208 +            mac = [ int(x, 16) for x in vmac.split(':') ]
  49.209 +        if len(mac) != 6: raise ValueError("invalid mac")
  49.210 +        #print "attach_device>", "vif=", vif, "mac=", mac
  49.211 +        dev = NetDev(self, vif, mac)
  49.212 +        self.devices[vif] = dev
  49.213 +        return dev
  49.214 +
  49.215 +    def destroy(self):
  49.216 +        print 'NetifController>destroy>', 'dom=', self.dom
  49.217 +        self.destroyDevices()
  49.218 +        
  49.219 +    def destroyDevices(self):
  49.220 +        for dev in self.getDevices():
  49.221 +            dev.destroy()
  49.222 +
  49.223 +    def attachDevice(self, vif, vmac, recreate=0):
  49.224 +        """Attach a network device.
  49.225 +        If vmac is None a random mac address is assigned.
  49.226 +
  49.227 +        @param vif interface index
  49.228 +        @param vmac mac address (string)
  49.229 +        """
  49.230 +        self.addDevice(vif, vmac)
  49.231 +        if recreate:
  49.232 +            d = defer.Deferred()
  49.233 +            d.callback(self)
  49.234 +        else:
  49.235 +            d = self.factory.addDeferred()
  49.236 +            self.send_be_create(vif)
  49.237 +        return d
  49.238 +
  49.239 +    def reattach_devices(self):
  49.240 +        """Reattach all devices when the back-end control domain has changed.
  49.241 +        """
  49.242 +        d = self.factory.addDeferred()
  49.243 +        self.send_be_create(vif)
  49.244 +        self.attach_fe_devices(0)
  49.245 +
  49.246 +    def attach_fe_devices(self):
  49.247 +        for dev in self.devices.values():
  49.248 +            msg = packMsg('netif_fe_interface_status_changed_t',
  49.249 +                          { 'handle' : dev.vif,
  49.250 +                            'status' : NETIF_INTERFACE_STATUS_DISCONNECTED,
  49.251 +                            'evtchn' : 0,
  49.252 +                            'mac'    : dev.mac })
  49.253 +            self.writeRequest(msg)
  49.254 +    
  49.255 +    def recv_fe_driver_status_changed(self, msg, req):
  49.256 +        if not req: return
  49.257 +        msg = packMsg('netif_fe_driver_status_changed_t',
  49.258 +                      { 'status'        : NETIF_DRIVER_STATUS_UP,
  49.259 +                        'nr_interfaces' : len(self.devices) })
  49.260 +        self.writeRequest(msg)
  49.261 +        self.attach_fe_devices()
  49.262 +
  49.263 +    def recv_fe_interface_connect(self, msg, req):
  49.264 +        val = unpackMsg('netif_fe_interface_connect_t', msg)
  49.265 +        dev = self.devices[val['handle']]
  49.266 +        dev.evtchn = channel.eventChannel(0, self.dom)
  49.267 +        msg = packMsg('netif_be_connect_t',
  49.268 +                      { 'domid'          : self.dom,
  49.269 +                        'netif_handle'   : dev.vif,
  49.270 +                        'evtchn'         : dev.evtchn['port1'],
  49.271 +                        'tx_shmem_frame' : val['tx_shmem_frame'],
  49.272 +                        'rx_shmem_frame' : val['rx_shmem_frame'] })
  49.273 +        self.factory.writeRequest(msg)
  49.274 +
  49.275 +    def send_interface_connected(self, vif):
  49.276 +        dev = self.devices[vif]
  49.277 +        msg = packMsg('netif_fe_interface_status_changed_t',
  49.278 +                      { 'handle' : dev.vif,
  49.279 +                        'status' : NETIF_INTERFACE_STATUS_CONNECTED,
  49.280 +                        'evtchn' : dev.evtchn['port2'],
  49.281 +                        'mac'    : dev.mac })
  49.282 +        self.writeRequest(msg)
  49.283 +
  49.284 +    def send_be_create(self, vif):
  49.285 +        dev = self.devices[vif]
  49.286 +        msg = packMsg('netif_be_create_t',
  49.287 +                      { 'domid'        : self.dom,
  49.288 +                        'netif_handle' : dev.vif,
  49.289 +                        'mac'          : dev.mac })
  49.290 +        self.factory.writeRequest(msg)
  49.291 +
  49.292 +    def send_be_disconnect(self, vif):
  49.293 +        dev = self.devices[vif]
  49.294 +        msg = packMsg('netif_be_disconnect_t',
  49.295 +                      { 'domid'        : self.dom,
  49.296 +                        'netif_handle' : dev.vif })
  49.297 +        self.factory.writeRequest(msg)
  49.298 +
  49.299 +    def send_be_destroy(self, vif):
  49.300 +        print 'NetifController>send_be_destroy>', 'dom=', self.dom, 'vif=', vif
  49.301 +        PrettyPrint.prettyprint(self.sxpr())
  49.302 +        dev = self.devices[vif]
  49.303 +        del self.devices[vif]
  49.304 +        msg = packMsg('netif_be_destroy_t',
  49.305 +                      { 'domid'        : self.dom,
  49.306 +                        'netif_handle' : vif })
  49.307 +        self.factory.writeRequest(msg)
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/tools/xen/lib/xend/server/params.py	Fri Jun 25 15:10:48 2004 +0000
    50.3 @@ -0,0 +1,10 @@
    50.4 +# The following parameters could be placed in a configuration file.
    50.5 +PID_FILE  = '/var/run/xend.pid'
    50.6 +LOG_FILE  = '/var/log/xend.log'
    50.7 +USER = 'root'
    50.8 +CONTROL_DIR  = '/var/run/xend'
    50.9 +MGMT_SOCK    = 'xendsock' # relative to CONTROL_DIR
   50.10 +EVENT_PORT = 8001
   50.11 +
   50.12 +CONSOLE_PORT_BASE = 9600
   50.13 +
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/tools/xen/lib/xend/sxp.py	Fri Jun 25 15:10:48 2004 +0000
    51.3 @@ -0,0 +1,557 @@
    51.4 +#!/usr/bin/python2
    51.5 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    51.6 +"""
    51.7 +Input-driven parsing for s-expression (sxp) format.
    51.8 +Create a parser: pin = Parser();
    51.9 +Then call pin.input(buf) with your input.
   51.10 +Call pin.input_eof() when done.
   51.11 +Use pin.read() to see if a value has been parsed, pin.get_val()
   51.12 +to get a parsed value. You can call ready and get_val at any time -
   51.13 +you don't have to wait until after calling input_eof.
   51.14 +
   51.15 +"""
   51.16 +from __future__ import generators
   51.17 +
   51.18 +import sys
   51.19 +import types
   51.20 +import errno
   51.21 +import string
   51.22 +
   51.23 +__all__ = [
   51.24 +    "mime_type", 
   51.25 +    "ParseError", 
   51.26 +    "Parser", 
   51.27 +    "atomp", 
   51.28 +    "show", 
   51.29 +    "show_xml", 
   51.30 +    "elementp", 
   51.31 +    "name", 
   51.32 +    "attributes", 
   51.33 +    "attribute", 
   51.34 +    "children", 
   51.35 +    "child", 
   51.36 +    "child_at", 
   51.37 +    "child0", 
   51.38 +    "child1", 
   51.39 +    "child2", 
   51.40 +    "child3", 
   51.41 +    "child4", 
   51.42 +    "child_value", 
   51.43 +    "has_id", 
   51.44 +    "with_id", 
   51.45 +    "child_with_id", 
   51.46 +    "elements", 
   51.47 +    "parse", 
   51.48 +    ]
   51.49 +
   51.50 +mime_type = "application/sxp"
   51.51 +
   51.52 +escapes = {
   51.53 +    'a': '\a',
   51.54 +    'b': '\b',
   51.55 +    't': '\t',
   51.56 +    'n': '\n',
   51.57 +    'v': '\v',
   51.58 +    'f': '\f',
   51.59 +    'r': '\r',
   51.60 +    '\\': '\\',
   51.61 +    '\'': '\'',
   51.62 +    '\"': '\"'}
   51.63 +
   51.64 +k_list_open  = "("
   51.65 +k_list_close = ")"
   51.66 +k_attr_open  = "@"
   51.67 +k_eval       = "!"
   51.68 +
   51.69 +escapes_rev = {}
   51.70 +for k in escapes:
   51.71 +    escapes_rev[escapes[k]] = k
   51.72 +
   51.73 +class ParseError(StandardError):
   51.74 +
   51.75 +    def __init__(self, parser, value):
   51.76 +        self.parser = parser
   51.77 +        self.value = value
   51.78 +
   51.79 +    def __str__(self):
   51.80 +        return self.value
   51.81 +
   51.82 +class ParserState:
   51.83 +
   51.84 +    def __init__(self, fn, parent=None):
   51.85 +        self.parent = parent
   51.86 +        self.buf = ''
   51.87 +        self.val = []
   51.88 +        self.delim = None
   51.89 +        self.fn = fn
   51.90 +
   51.91 +    def push(self, fn):
   51.92 +        return ParserState(fn, parent=self)
   51.93 +    
   51.94 +class Parser:
   51.95 +
   51.96 +    def __init__(self):
   51.97 +        self.error = sys.stderr
   51.98 +        self.reset()
   51.99 +
  51.100 +    def reset(self):
  51.101 +        self.val = []
  51.102 +        self.eof = 0
  51.103 +        self.err = 0
  51.104 +        self.line_no = 0
  51.105 +        self.char_no = 0
  51.106 +        self.state = None
  51.107 +
  51.108 +    def push_state(self, fn):
  51.109 +        self.state = self.state.push(fn)
  51.110 +
  51.111 +    def pop_state(self):
  51.112 +        val = self.state
  51.113 +        self.state = self.state.parent
  51.114 +        if self.state and self.state.fn == self.state_start:
  51.115 +            # Return to start state - produce the value.
  51.116 +            self.val += self.state.val
  51.117 +            self.state.val = []
  51.118 +        return val
  51.119 +
  51.120 +    def in_class(self, c, s):
  51.121 +        return s.find(c) >= 0
  51.122 +        
  51.123 +    def in_space_class(self, c):
  51.124 +        return self.in_class(c, ' \t\n\v\f\r')
  51.125 +
  51.126 +    def is_separator(self, c):
  51.127 +        return self.in_class(c, '{}()<>[]!;')
  51.128 +
  51.129 +    def in_comment_class(self, c):
  51.130 +        return self.in_class(c, '#')
  51.131 +
  51.132 +    def in_string_quote_class(self, c):
  51.133 +        return self.in_class(c, '"\'')
  51.134 +
  51.135 +    def in_printable_class(self, c):
  51.136 +        return self.in_class(c, string.printable)
  51.137 +
  51.138 +    def set_error_stream(self, error):
  51.139 +        self.error = error
  51.140 +
  51.141 +    def has_error(self):
  51.142 +        return self.err > 0
  51.143 +
  51.144 +    def at_eof(self):
  51.145 +        return self.eof
  51.146 +
  51.147 +    def input_eof(self):
  51.148 +        self.eof = 1
  51.149 +        self.input_char(-1)
  51.150 +
  51.151 +    def input(self, buf):
  51.152 +        if not buf or len(buf) == 0:
  51.153 +            self.input_eof()
  51.154 +        else:
  51.155 +            for c in buf:
  51.156 +                self.input_char(c)
  51.157 +
  51.158 +    def input_char(self, c):
  51.159 +        if self.at_eof():
  51.160 +            pass
  51.161 +        elif c == '\n':
  51.162 +            self.line_no += 1
  51.163 +            self.char_no = 0
  51.164 +        else:
  51.165 +           self.char_no += 1 
  51.166 +
  51.167 +        if self.state is None:
  51.168 +            self.begin_start(None)
  51.169 +        self.state.fn(c)
  51.170 +
  51.171 +    def ready(self):
  51.172 +        return len(self.val) > 0
  51.173 +
  51.174 +    def get_val(self):
  51.175 +        v = self.val[0]
  51.176 +        self.val = self.val[1:]
  51.177 +        return v
  51.178 +
  51.179 +    def get_all(self):
  51.180 +        return self.val
  51.181 +
  51.182 +    def begin_start(self, c):
  51.183 +        self.state = ParserState(self.state_start)
  51.184 +
  51.185 +    def end_start(self):
  51.186 +        self.val += self.state.val
  51.187 +        self.pop_state()
  51.188 +    
  51.189 +    def state_start(self, c):
  51.190 +        if self.at_eof():
  51.191 +            self.end_start()
  51.192 +        elif self.in_space_class(c):
  51.193 +            pass
  51.194 +        elif self.in_comment_class(c):
  51.195 +            self.begin_comment(c)
  51.196 +        elif c == k_list_open:
  51.197 +            self.begin_list(c)
  51.198 +        elif c == k_list_close:
  51.199 +            raise ParseError(self, "syntax error: "+c)
  51.200 +        elif self.in_string_quote_class(c):
  51.201 +            self.begin_string(c)
  51.202 +        elif self.in_printable_class(c):
  51.203 +            self.begin_atom(c)
  51.204 +        elif c == chr(4):
  51.205 +            # ctrl-D, EOT: end-of-text.
  51.206 +            self.input_eof()
  51.207 +        else:
  51.208 +            raise ParseError(self, "invalid character: code %d" % ord(c))
  51.209 +
  51.210 +    def begin_comment(self, c):
  51.211 +        self.push_state(self.state_comment)
  51.212 +        self.state.buf += c
  51.213 +
  51.214 +    def end_comment(self):
  51.215 +        self.pop_state()
  51.216 +    
  51.217 +    def state_comment(self, c):
  51.218 +        if c == '\n' or self.at_eof():
  51.219 +            self.end_comment()
  51.220 +        else:
  51.221 +            self.state.buf += c
  51.222 +
  51.223 +    def begin_string(self, c):
  51.224 +        self.push_state(self.state_string)
  51.225 +        self.state.delim = c
  51.226 +
  51.227 +    def end_string(self):
  51.228 +        val = self.state.buf
  51.229 +        self.state.parent.val.append(val)
  51.230 +        self.pop_state()
  51.231 +        
  51.232 +    def state_string(self, c):
  51.233 +        if self.at_eof():
  51.234 +            raise ParseError(self, "unexpected EOF")
  51.235 +        elif c == self.state.delim:
  51.236 +            self.end_string()
  51.237 +        elif c == '\\':
  51.238 +            self.push_state(self.state_escape)
  51.239 +        else:
  51.240 +            self.state.buf += c
  51.241 +
  51.242 +    def state_escape(self, c):
  51.243 +        if self.at_eof():
  51.244 +            raise ParseError(self, "unexpected EOF")
  51.245 +        d = escapes.get(c)
  51.246 +        if d:
  51.247 +            self.state.parent.buf += d
  51.248 +            self.pop_state()
  51.249 +        elif c == 'x':
  51.250 +            self.state.fn = self.state_hex
  51.251 +            self.state.val = 0
  51.252 +        else:
  51.253 +            self.state.fn = self.state_octal
  51.254 +            self.state.val = 0
  51.255 +            self.input_char(c)
  51.256 +
  51.257 +    def state_octal(self, c):
  51.258 +        def octaldigit(c):
  51.259 +            self.state.val *= 8
  51.260 +            self.state.val += ord(c) - ord('0')
  51.261 +            self.state.buf += c
  51.262 +            if self.state.val < 0 or self.state.val > 0xff:
  51.263 +                raise ParseError(self, "invalid octal escape: out of range " + self.state.buf)
  51.264 +            if len(self.state.buf) == 3:
  51.265 +               octaldone()
  51.266 +               
  51.267 +        def octaldone():
  51.268 +            d = chr(self.state.val)
  51.269 +            self.state.parent.buf += d
  51.270 +            self.pop_state()
  51.271 +            
  51.272 +        if self.at_eof():
  51.273 +            raise ParseError(self, "unexpected EOF")
  51.274 +        elif '0' <= c <= '7':
  51.275 +            octaldigit(c)
  51.276 +        elif len(self.buf):
  51.277 +            octaldone()
  51.278 +            self.input_char(c)
  51.279 +
  51.280 +    def state_hex(self, c):
  51.281 +        def hexdone():
  51.282 +            d = chr(self.state.val)
  51.283 +            self.state.parent.buf += d
  51.284 +            self.pop_state()
  51.285 +            
  51.286 +        def hexdigit(c, d):
  51.287 +            self.state.val *= 16
  51.288 +            self.state.val += ord(c) - ord(d)
  51.289 +            self.state.buf += c
  51.290 +            if self.state.val < 0 or self.state.val > 0xff:
  51.291 +                raise ParseError(self, "invalid hex escape: out of range " + self.state.buf)
  51.292 +            if len(self.state.buf) == 2:
  51.293 +                hexdone()
  51.294 +            
  51.295 +        if self.at_eof():
  51.296 +            raise ParseError(self, "unexpected EOF")
  51.297 +        elif '0' <= c <= '9':
  51.298 +            hexdigit(c, '0')
  51.299 +        elif 'A' <= c <= 'F':
  51.300 +            hexdigit(c, 'A')
  51.301 +        elif 'a' <= c <= 'f':
  51.302 +            hexdigit(c, 'a')
  51.303 +        elif len(buf):
  51.304 +            hexdone()
  51.305 +            self.input_char(c)
  51.306 +
  51.307 +    def begin_atom(self, c):
  51.308 +        self.push_state(self.state_atom)
  51.309 +        self.state.buf = c
  51.310 +
  51.311 +    def end_atom(self):
  51.312 +        val = self.state.buf
  51.313 +        self.state.parent.val.append(val)
  51.314 +        self.pop_state()
  51.315 +    
  51.316 +    def state_atom(self, c):
  51.317 +        if self.at_eof():
  51.318 +            self.end_atom()
  51.319 +        elif (self.is_separator(c) or
  51.320 +              self.in_space_class(c) or
  51.321 +              self.in_comment_class(c)):
  51.322 +            self.end_atom()
  51.323 +            self.input_char(c)
  51.324 +        else:
  51.325 +            self.state.buf += c
  51.326 +
  51.327 +    def begin_list(self, c):
  51.328 +        self.push_state(self.state_list)
  51.329 +
  51.330 +    def end_list(self):
  51.331 +        val = self.state.val
  51.332 +        self.state.parent.val.append(val)
  51.333 +        self.pop_state()
  51.334 +
  51.335 +    def state_list(self, c):
  51.336 +        if self.at_eof():
  51.337 +            raise ParseError(self, "unexpected EOF")
  51.338 +        elif c == k_list_close:
  51.339 +            self.end_list()
  51.340 +        else:
  51.341 +            self.state_start(c)
  51.342 +
  51.343 +def atomp(sxpr):
  51.344 +    if sxpr.isalnum() or sxpr == '@':
  51.345 +        return 1
  51.346 +    for c in sxpr:
  51.347 +        if c in string.whitespace: return 0
  51.348 +        if c in '"\'\\(){}[]<>$#&%^': return 0
  51.349 +        if c in string.ascii_letters: continue
  51.350 +        if c in string.digits: continue
  51.351 +        if c in '.-_:/~': continue
  51.352 +        return 0
  51.353 +    return 1
  51.354 +    
  51.355 +def show(sxpr, out=sys.stdout):
  51.356 +    if isinstance(sxpr, types.ListType):
  51.357 +        out.write(k_list_open)
  51.358 +        i = 0
  51.359 +        for x in sxpr:
  51.360 +            if i: out.write(' ')
  51.361 +            show(x, out)
  51.362 +            i += 1
  51.363 +        out.write(k_list_close)
  51.364 +    elif isinstance(sxpr, types.StringType) and atomp(sxpr):
  51.365 +        out.write(sxpr)
  51.366 +    else:
  51.367 +        #out.write("'" + str(sxpr) + "'")
  51.368 +        out.write(repr(str(sxpr)))
  51.369 +
  51.370 +def show_xml(sxpr, out=sys.stdout):
  51.371 +    if isinstance(sxpr, types.ListType):
  51.372 +        element = name(sxpr)
  51.373 +        out.write('<%s' % element)
  51.374 +        for attr in attributes(sxpr):
  51.375 +            out.write(' %s=%s' % (attr[0], attr[1]))
  51.376 +        out.write('>')
  51.377 +        i = 0
  51.378 +        for x in children(sxpr):
  51.379 +            if i: out.write(' ')
  51.380 +            show_xml(x, out)
  51.381 +            i += 1
  51.382 +        out.write('</%s>' % element)
  51.383 +    elif isinstance(sxpr, types.StringType) and atomp(sxpr):
  51.384 +        out.write(sxpr)
  51.385 +    else:
  51.386 +        out.write(str(sxpr))
  51.387 +
  51.388 +def elementp(sxpr, elt=None):
  51.389 +    return (isinstance(sxpr, types.ListType)
  51.390 +            and len(sxpr)
  51.391 +            and (None == elt or sxpr[0] == elt))
  51.392 +
  51.393 +def name(sxpr):
  51.394 +    val = None
  51.395 +    if isinstance(sxpr, types.StringType):
  51.396 +        val = sxpr
  51.397 +    elif isinstance(sxpr, types.ListType) and len(sxpr):
  51.398 +        val = sxpr[0]
  51.399 +    return val
  51.400 +
  51.401 +def attributes(sxpr):
  51.402 +    val = []
  51.403 +    if isinstance(sxpr, types.ListType) and len(sxpr) > 1:
  51.404 +        attr = sxpr[1]
  51.405 +        if elementp(attr, k_attr_open):
  51.406 +            val = attr[1:]
  51.407 +    return val
  51.408 +
  51.409 +def attribute(sxpr, key, val=None):
  51.410 +    for x in attributes(sxpr):
  51.411 +        if x[0] == key:
  51.412 +            val = x[1]
  51.413 +            break
  51.414 +    return val
  51.415 +
  51.416 +def children(sxpr, elt=None):
  51.417 +    val = []
  51.418 +    if isinstance(sxpr, types.ListType) and len(sxpr) > 1:
  51.419 +        i = 1
  51.420 +        x = sxpr[i]
  51.421 +        if elementp(x, k_attr_open):
  51.422 +            i += 1
  51.423 +        val = sxpr[i : ]
  51.424 +    if elt:
  51.425 +        def iselt(x):
  51.426 +            return elementp(x, elt)
  51.427 +        val = filter(iselt, val)
  51.428 +    return val
  51.429 +
  51.430 +def child(sxpr, elt, val=None):
  51.431 +    for x in children(sxpr):
  51.432 +        if elementp(x, elt):
  51.433 +            val = x
  51.434 +            break
  51.435 +    return val
  51.436 +
  51.437 +def child_at(sxpr, index, val=None):
  51.438 +    kids = children(sxpr)
  51.439 +    if len(kids) > index:
  51.440 +        val = kids[index]
  51.441 +    return val
  51.442 +
  51.443 +def child0(sxpr, val=None):
  51.444 +    return child_at(sxpr, 0, val)
  51.445 +
  51.446 +def child1(sxpr, val=None):
  51.447 +    return child_at(sxpr, 1, val)
  51.448 +
  51.449 +def child2(sxpr, val=None):
  51.450 +    return child_at(sxpr, 2, val)
  51.451 +
  51.452 +def child3(sxpr, val=None):
  51.453 +    return child_at(sxpr, 3, val)
  51.454 +
  51.455 +def child4(sxpr, val=None):
  51.456 +    return child_at(sxpr, 4, val)
  51.457 +
  51.458 +def child_value(sxpr, elt, val=None):
  51.459 +    kid = child(sxpr, elt)
  51.460 +    if kid:
  51.461 +        val = child_at(kid, 0, val)
  51.462 +    return val
  51.463 +
  51.464 +def has_id(sxpr, id):
  51.465 +    """Test if an s-expression has a given id.
  51.466 +    """
  51.467 +    return attribute(sxpr, 'id') == id
  51.468 +
  51.469 +def with_id(sxpr, id, val=None):
  51.470 +    """Find the first s-expression with a given id, at any depth.
  51.471 +
  51.472 +    sxpr   s-exp or list
  51.473 +    id     id
  51.474 +    val    value if not found (default None)
  51.475 +
  51.476 +    return s-exp or val
  51.477 +    """
  51.478 +    if isinstance(sxpr, types.ListType):
  51.479 +        for n in sxpr:
  51.480 +            if has_id(n, id):
  51.481 +                val = n
  51.482 +                break
  51.483 +            v = with_id(n, id)
  51.484 +            if v is None: continue
  51.485 +            val = v
  51.486 +            break
  51.487 +    return val
  51.488 +
  51.489 +def child_with_id(sxpr, id, val=None):
  51.490 +    """Find the first child with a given id.
  51.491 +
  51.492 +    sxpr   s-exp or list
  51.493 +    id     id
  51.494 +    val    value if not found (default None)
  51.495 +
  51.496 +    return s-exp or val
  51.497 +    """
  51.498 +    if isinstance(sxpr, types.ListType):
  51.499 +        for n in sxpr:
  51.500 +            if has_id(n, id):
  51.501 +                val = n
  51.502 +                break
  51.503 +    return val
  51.504 +
  51.505 +def elements(sxpr, ctxt=None):
  51.506 +    """Generate elements (at any depth).
  51.507 +    Visit elements in pre-order.
  51.508 +    Values generated are (node, context)
  51.509 +    The context is None if there is no parent, otherwise
  51.510 +    (index, parent, context) where index is the node's index w.r.t its parent,
  51.511 +    and context is the parent's context.
  51.512 +
  51.513 +    sxpr   s-exp
  51.514 +
  51.515 +    returns generator
  51.516 +    """
  51.517 +    yield (sxpr, ctxt)
  51.518 +    i = 0
  51.519 +    for n in children(sxpr):
  51.520 +        if isinstance(n, types.ListType):
  51.521 +            # Calling elements() recursively does not generate recursively,
  51.522 +            # it just returns a generator object. So we must iterate over it.
  51.523 +            for v in elements(n, (i, sxpr, ctxt)):
  51.524 +                yield v
  51.525 +        i += 1
  51.526 +
  51.527 +def parse(io):
  51.528 +    """Completely parse all input from 'io'.
  51.529 +
  51.530 +    io	input file object
  51.531 +    returns list of values, None if incomplete
  51.532 +    raises ParseError on parse error
  51.533 +    """
  51.534 +    pin = Parser()
  51.535 +    while 1:
  51.536 +        buf = io.readline()
  51.537 +        pin.input(buf)
  51.538 +        if len(buf) == 0:
  51.539 +            break
  51.540 +    if pin.ready():
  51.541 +        val = pin.get_all()
  51.542 +    else:
  51.543 +        val = None
  51.544 +    return val
  51.545 +   
  51.546 +
  51.547 +if __name__ == '__main__':
  51.548 +    print ">main"
  51.549 +    pin = Parser()
  51.550 +    while 1:
  51.551 +        buf = sys.stdin.read(1024)
  51.552 +        #buf = sys.stdin.readline()
  51.553 +        pin.input(buf)
  51.554 +        while pin.ready():
  51.555 +            val = pin.get_val()
  51.556 +            print
  51.557 +            print '****** val=', val
  51.558 +        if len(buf) == 0:
  51.559 +            break
  51.560 +
    53.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2 +++ b/tools/xen/lib/xm/create.py	Fri Jun 25 15:10:48 2004 +0000
    53.3 @@ -0,0 +1,366 @@
    53.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    53.5 +"""Domain creation.
    53.6 +"""
    53.7 +import string
    53.8 +import sys
    53.9 +
   53.10 +from xen.xend import sxp
   53.11 +from xen.xend import PrettyPrint
   53.12 +from xen.xend.XendClient import server
   53.13 +
   53.14 +from xen.xend.xm.opts import *
   53.15 +
   53.16 +gopts = Opts(use="""[options]
   53.17 +
   53.18 +Create a domain.
   53.19 +""")
   53.20 +
   53.21 +gopts.opt('help', short='h',
   53.22 +         fn=set_true, default=0,
   53.23 +         use="Print this help.")
   53.24 +
   53.25 +gopts.opt('quiet', short='q',
   53.26 +         fn=set_true, default=0,
   53.27 +         use="Quiet.")
   53.28 +
   53.29 +gopts.opt('path', val='PATH',
   53.30 +         fn=set_value, default='.:/etc/xen',
   53.31 +         use="Search path for default scripts.")
   53.32 +
   53.33 +gopts.opt('defaults', short='f', val='FILE',
   53.34 +         fn=set_value, default='xmdefaults',
   53.35 +         use="Use the given default script.")
   53.36 +
   53.37 +gopts.opt('config', short='F', val='FILE',
   53.38 +         fn=set_value, default=None,
   53.39 +         use='Domain configuration to use (SXP).')
   53.40 +
   53.41 +gopts.opt('load', short='L', val='FILE',
   53.42 +          fn=set_value, default=None,
   53.43 +          use='Domain saved state to load.')
   53.44 +
   53.45 +gopts.opt('define', short='D', val='VAR=VAL',
   53.46 +         fn=set_var, default=None,
   53.47 +         use="""Set a variable before loading defaults, e.g. '-D vmid=3'
   53.48 +         to set vmid. May be repeated to set more thanone variable.""")
   53.49 +
   53.50 +gopts.opt('dryrun', short='n',
   53.51 +         fn=set_true, default=0,
   53.52 +         use="Dry run - print the config but don't create the domain.")
   53.53 +
   53.54 +gopts.opt('name', short='N', val='NAME',
   53.55 +          fn=set_value, default=None,
   53.56 +          use="Domain name.")
   53.57 +
   53.58 +gopts.opt('console', short='c',
   53.59 +         fn=set_true, default=0,
   53.60 +         use="Connect to console after domain is created.")
   53.61 +
   53.62 +gopts.opt('kernel', short='k', val='FILE',
   53.63 +         fn=set_value, default=None,
   53.64 +         use="Path to kernel image.")
   53.65 +
   53.66 +gopts.opt('ramdisk', short='r', val='FILE',
   53.67 +         fn=set_value, default='',
   53.68 +         use="Path to ramdisk.")
   53.69 +
   53.70 +gopts.opt('builder', short='b', val='FUNCTION',
   53.71 +         fn=set_value, default='linux',
   53.72 +         use="Function to use to build the domain.")
   53.73 +
   53.74 +gopts.opt('memory', short='m', val='MEMORY',
   53.75 +         fn=set_value, default=128,
   53.76 +         use="Domain memory in MB.")
   53.77 +
   53.78 +gopts.opt('blkif',
   53.79 +          fn=set_true, default=0,
   53.80 +          use="Make the domain a block device backend.")
   53.81 +
   53.82 +gopts.opt('netif',
   53.83 +          fn=set_true, default=0,
   53.84 +          use="Make the domain a network interface backend.")
   53.85 +
   53.86 +gopts.opt('disk', short='d', val='phy:DEV,VDEV,MODE',
   53.87 +         fn=append_value, default=[],
   53.88 +         use="""Add a disk device to a domain. The physical device is DEV, which
   53.89 +         is exported to the domain as VDEV. The disk is read-only if MODE
   53.90 +         is 'r', read-write if MODE is 'w'.
   53.91 +         The option may be repeated to add more than one disk.
   53.92 +         """)
   53.93 +
   53.94 +gopts.opt('pci', val='BUS,DEV,FUNC',
   53.95 +         fn=append_value, default=[],
   53.96 +         use="""Add a PCI device to a domain, using given params (in hex).
   53.97 +         For example '-pci c0,02,1a'.
   53.98 +         The option may be repeated to add more than one pci device.
   53.99 +         """)
  53.100 +
  53.101 +gopts.opt('ipaddr', short='i', val="IPADDR",
  53.102 +         fn=append_value, default=[],
  53.103 +         use="Add an IP address to the domain.")
  53.104 +
  53.105 +gopts.opt('vif', val="mac=MAC,bridge=BRIDGE",
  53.106 +         fn=append_value, default=[],
  53.107 +         use="""Add a network interface with the given MAC address and bridge.
  53.108 +         If mac is not specified a random MAC address is used.
  53.109 +         If bridge is not specified the default bridge is used.
  53.110 +         This option may be repeated to add more than one vif.
  53.111 +         Specifying vifs will increase the number of interfaces as needed.
  53.112 +         """)
  53.113 +
  53.114 +gopts.opt('nics', val="NUM",
  53.115 +         fn=set_int, default=1,
  53.116 +         use="""Set the number of network interfaces.
  53.117 +         Use the vif option to define interface parameters, otherwise
  53.118 +         defaults are used. Specifying vifs will increase the
  53.119 +         number of interfaces as needed.
  53.120 +         """)
  53.121 +
  53.122 +gopts.opt('root', short='R', val='DEVICE',
  53.123 +         fn=set_value, default='',
  53.124 +         use="""Set the root= parameter on the kernel command line.
  53.125 +         Use a device, e.g. /dev/sda1, or /dev/nfs for NFS root.""")
  53.126 +
  53.127 +gopts.opt('extra', short='E', val="ARGS",
  53.128 +         fn=set_value, default='',
  53.129 +         use="Set extra arguments to append to the kernel command line.")
  53.130 +
  53.131 +gopts.opt('ip', short='I', val='IPADDR',
  53.132 +         fn=set_value, default='',
  53.133 +         use="Set the kernel IP interface address.")
  53.134 +
  53.135 +gopts.opt('gateway', val="IPADDR",
  53.136 +         fn=set_value, default='',
  53.137 +         use="Set the kernel IP gateway.")
  53.138 +
  53.139 +gopts.opt('netmask', val="MASK",
  53.140 +         fn=set_value, default = '',
  53.141 +         use="Set the kernel IP netmask.")
  53.142 +
  53.143 +gopts.opt('hostname', val="NAME",
  53.144 +         fn=set_value, default='',
  53.145 +         use="Set the kernel IP hostname.")
  53.146 +
  53.147 +gopts.opt('interface', val="INTF",
  53.148 +         fn=set_value, default="eth0",
  53.149 +         use="Set the kernel IP interface name.")
  53.150 +
  53.151 +gopts.opt('dhcp', val="off|dhcp",
  53.152 +         fn=set_value, default='off',
  53.153 +         use="Set the kernel dhcp option.")
  53.154 +
  53.155 +gopts.opt('nfs_server', val="IPADDR",
  53.156 +         fn=set_value, default=None,
  53.157 +         use="Set the address of the NFS server for NFS root.")
  53.158 +
  53.159 +gopts.opt('nfs_root', val="PATH",
  53.160 +         fn=set_value, default=None,
  53.161 +         use="Set the path of the root NFS directory.")
  53.162 +
  53.163 +def strip(pre, s):
  53.164 +    """Strip prefix 'pre' if present.
  53.165 +    """
  53.166 +    if s.startswith(pre):
  53.167 +        return s[len(pre):]
  53.168 +    else:
  53.169 +        return s
  53.170 +
  53.171 +def configure_image(config, opts):
  53.172 +    """Create the image config.
  53.173 +    """
  53.174 +    config_image = [ opts.builder ]
  53.175 +    config_image.append([ 'kernel', os.path.abspath(opts.kernel) ])
  53.176 +    if opts.ramdisk:
  53.177 +        config_image.append([ 'ramdisk', os.path.abspath(opts.ramdisk) ])
  53.178 +    if opts.cmdline_ip:
  53.179 +        cmdline_ip = strip('ip=', opts.cmdline_ip)
  53.180 +        config_image.append(['ip', cmdline_ip])
  53.181 +    if opts.root:
  53.182 +        cmdline_root = strip('root=', opts.root)
  53.183 +        config_image.append(['root', cmdline_root])
  53.184 +    if opts.extra:
  53.185 +        config_image.append(['args', opts.extra])
  53.186 +    config.append(['image', config_image ])
  53.187 +    
  53.188 +def configure_disks(config_devs, opts):
  53.189 +    """Create the config for disks (virtual block devices).
  53.190 +    """
  53.191 +    for (uname, dev, mode) in opts.disk:
  53.192 +        config_vbd = ['vbd',
  53.193 +                      ['uname', uname],
  53.194 +                      ['dev', dev ],
  53.195 +                      ['mode', mode ] ]
  53.196 +        config_devs.append(['device', config_vbd])
  53.197 +
  53.198 +def configure_pci(config_devs, opts):
  53.199 +    """Create the config for pci devices.
  53.200 +    """
  53.201 +    for (bus, dev, func) in opts.pci:
  53.202 +        config_pci = ['pci', ['bus', bus], ['dev', dev], ['func', func]]
  53.203 +        config_devs.append(['device', config_pci])
  53.204 +
  53.205 +def configure_vifs(config_devs, opts):
  53.206 +    """Create the config for virtual network interfaces.
  53.207 +    """
  53.208 +    vifs = opts.vif
  53.209 +    vifs_n = max(opts.nics, len(vifs))
  53.210 +
  53.211 +    for idx in range(0, vifs_n):
  53.212 +        if idx < len(vifs):
  53.213 +            d = vifs[idx]
  53.214 +            mac = d.get('mac')
  53.215 +            bridge = d.get('bridge')
  53.216 +        else:
  53.217 +            mac = None
  53.218 +            bridge = None
  53.219 +        config_vif = ['vif']
  53.220 +        if mac:
  53.221 +            config_vif.append(['mac', mac])
  53.222 +        if bridge:
  53.223 +            config_vif.append(['bridge', bridge])
  53.224 +        config_devs.append(['device', config_vif])
  53.225 +
  53.226 +def configure_vfr(config, opts):
  53.227 +     if not opts.ipaddr: return
  53.228 +     config_vfr = ['vfr']
  53.229 +     idx = 0 # No way of saying which IP is for which vif?
  53.230 +     for ip in opts.ipaddr:
  53.231 +         config_vfr.append(['vif', ['id', idx], ['ip', ip]])
  53.232 +     config.append(config_vfr)
  53.233 +
  53.234 +
  53.235 +def make_config(opts):
  53.236 +    """Create the domain configuration.
  53.237 +    """
  53.238 +    
  53.239 +    config = ['vm',
  53.240 +              ['name', opts.name ],
  53.241 +              ['memory', opts.memory ] ]
  53.242 +    if opts.cpu:
  53.243 +        config.append(['cpu', opts.cpu])
  53.244 +    if opts.blkif:
  53.245 +        config.append(['backend', ['blkif']])
  53.246 +    if opts.netif:
  53.247 +        config.append(['backend', ['netif']])
  53.248 +    
  53.249 +    configure_image(config, opts)
  53.250 +    config_devs = []
  53.251 +    configure_disks(config_devs, opts)
  53.252 +    configure_pci(config_devs, opts)
  53.253 +    configure_vifs(config_devs, opts)
  53.254 +    config += config_devs
  53.255 +    return config
  53.256 +
  53.257 +def preprocess_disk(opts):
  53.258 +    if not opts.disk: return
  53.259 +    disk = []
  53.260 +    for v in opts.disk:
  53.261 +        d = v.split(',')
  53.262 +        if len(d) != 3:
  53.263 +            opts.err('Invalid disk specifier: ' + v)
  53.264 +        disk.append(d)
  53.265 +    opts.disk = disk
  53.266 +
  53.267 +def preprocess_pci(opts):
  53.268 +    if not opts.pci: return
  53.269 +    pci = []
  53.270 +    for v in opts.pci:
  53.271 +        d = v.split(',')
  53.272 +        if len(d) != 3:
  53.273 +            opts.err('Invalid pci specifier: ' + v)
  53.274 +        # Components are in hex: add hex specifier.
  53.275 +        hexd = map(lambda v: '0x'+v, d)
  53.276 +        pci.append(hexd)
  53.277 +    opts.pci = pci
  53.278 +
  53.279 +def preprocess_vifs(opts):
  53.280 +    if not opts.vif: return
  53.281 +    vifs = []
  53.282 +    for vif in opts.vif:
  53.283 +        d = {}
  53.284 +        a = vif.split(',')
  53.285 +        for b in a:
  53.286 +            (k, v) = b.strip().split('=')
  53.287 +            k = k.strip()
  53.288 +            v = v.strip()
  53.289 +            if k not in ['mac', 'bridge']:
  53.290 +                opts.err('Invalid vif specifier: ' + vif)
  53.291 +            d[k] = v
  53.292 +        vifs.append(d)
  53.293 +    opts.vif = vifs
  53.294 +
  53.295 +def preprocess_ip(opts):
  53.296 +    setip = (opts.hostname or opts.netmask
  53.297 +             or opts.gateway or opts.dhcp or opts.interface)
  53.298 +    if not setip: return
  53.299 +    #if not opts
  53.300 +    ip = (opts.ip
  53.301 +          + ':'
  53.302 +          + ':' + opts.gateway
  53.303 +          + ':' + opts.netmask
  53.304 +          + ':' + opts.hostname
  53.305 +          + ':' + opts.interface
  53.306 +          + ':' + opts.dhcp)
  53.307 +    opts.cmdline_ip = ip
  53.308 +
  53.309 +def preprocess_nfs(opts):
  53.310 +    if (opts.nfs_root or opts.nfs_server):
  53.311 +        if (not opts.nfs_root) or (not opts.nfs_server):
  53.312 +            opts.err('Must set nfs root and nfs server')
  53.313 +    else:
  53.314 +        return
  53.315 +    nfs = 'nfsroot=' + opts.nfs_server + ':' + opts.nfs_root
  53.316 +    opts.extra = nfs + ' ' + opts.extra
  53.317 +    
  53.318 +def preprocess(opts):
  53.319 +    if not opts.kernel:
  53.320 +        opts.err("No kernel specified")
  53.321 +    preprocess_disk(opts)
  53.322 +    preprocess_pci(opts)
  53.323 +    preprocess_vifs(opts)
  53.324 +    preprocess_ip(opts)
  53.325 +    preprocess_nfs(opts)
  53.326 +         
  53.327 +def make_domain(opts, config):
  53.328 +    """Create, build and start a domain.
  53.329 +    Returns: [int] the ID of the new domain.
  53.330 +    """
  53.331 +    if opts.vals.load:
  53.332 +        filename = os.path.abspath(opts.vals.load)
  53.333 +        dominfo = server.xend_domain_restore(filename, config)
  53.334 +    else:
  53.335 +        dominfo = server.xend_domain_create(config)
  53.336 +
  53.337 +    dom = int(sxp.child_value(dominfo, 'id'))
  53.338 +    console_info = sxp.child(dominfo, 'console')
  53.339 +    if console_info:
  53.340 +        console_port = int(sxp.child_value(console_info, 'port'))
  53.341 +    else:
  53.342 +        console_port = None
  53.343 +    
  53.344 +    if server.xend_domain_unpause(dom) < 0:
  53.345 +        server.xend_domain_destroy(dom)
  53.346 +        opts.err("Failed to start domain %d" % dom)
  53.347 +    opts.info("Started domain %d, console on port %d"
  53.348 +              % (dom, console_port))
  53.349 +    return (dom, console_port)
  53.350 +
  53.351 +def main(argv):
  53.352 +    opts = gopts
  53.353 +    args = opts.parse(argv)
  53.354 +    if opts.vals.help:
  53.355 +        opts.usage()
  53.356 +        return
  53.357 +    if opts.vals.config:
  53.358 +        pass
  53.359 +    else:
  53.360 +        opts.load_defaults()
  53.361 +    preprocess(opts.vals)
  53.362 +    config = make_config(opts.vals)
  53.363 +    if opts.vals.dryrun:
  53.364 +        PrettyPrint.prettyprint(config)
  53.365 +    else:
  53.366 +        make_domain(opts, config)
  53.367 +        
  53.368 +if __name__ == '__main__':
  53.369 +    main(sys.argv)
    54.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.2 +++ b/tools/xen/lib/xm/main.py	Fri Jun 25 15:10:48 2004 +0000
    54.3 @@ -0,0 +1,448 @@
    54.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    54.5 +"""Grand unified management application for Xen.
    54.6 +"""
    54.7 +import os
    54.8 +import os.path
    54.9 +import sys
   54.10 +from getopt import getopt
   54.11 +
   54.12 +from xen.xend import PrettyPrint
   54.13 +from xen.xend import sxp
   54.14 +from xen.xend.XendClient import server
   54.15 +from xen.xend.xm import create, shutdown
   54.16 +
   54.17 +class Prog:
   54.18 +    """Base class for sub-programs.
   54.19 +    """
   54.20 +
   54.21 +    """Program group it belongs to"""
   54.22 +    group = 'all'
   54.23 +    """Program name."""
   54.24 +    name = '??'
   54.25 +    """Short program info."""
   54.26 +    info = ''
   54.27 +
   54.28 +    def __init__(self, xm):
   54.29 +        self.xm = xm
   54.30 +
   54.31 +    def err(self, msg):
   54.32 +        self.xm.err(msg)
   54.33 +
   54.34 +    def help(self, args):
   54.35 +        self.shortHelp(args)
   54.36 +
   54.37 +    def shortHelp(self, args):
   54.38 +        print "%-14s %s" % (self.name, self.info)
   54.39 +
   54.40 +    def main(self, args):
   54.41 +        """Program main entry point.
   54.42 +        """
   54.43 +        pass
   54.44 +
   54.45 +
   54.46 +class ProgUnknown(Prog):
   54.47 +
   54.48 +    name = 'unknown'
   54.49 +    info = ''
   54.50 +    
   54.51 +    def help(self, args):
   54.52 +        self.xm.err("Unknown command: %s\nTry '%s help' for more information."
   54.53 +                    % (args[0], self.xm.name))
   54.54 +
   54.55 +    main = help
   54.56 +
   54.57 +class Xm:
   54.58 +    """Main application.
   54.59 +    """
   54.60 +
   54.61 +    def __init__(self):
   54.62 +        self.name = 'xm'
   54.63 +        self.unknown = ProgUnknown(self)
   54.64 +        self.progs = {}
   54.65 +
   54.66 +    def err(self, msg):
   54.67 +        print >>sys.stderr, "Error:", msg
   54.68 +        sys.exit(1)
   54.69 +
   54.70 +    def main(self, args):
   54.71 +        """Main entry point. Dispatches to the progs.
   54.72 +        """
   54.73 +        self.name = args[0]
   54.74 +        if len(args) < 2:
   54.75 +            self.err("Missing command\nTry '%s help' for more information."
   54.76 +                     % self.name)
   54.77 +        help = self.helparg(args)
   54.78 +        p = self.getprog(args[1], self.unknown)
   54.79 +        if help:
   54.80 +            p.help(args[1:])
   54.81 +        else:
   54.82 +            p.main(args[1:])
   54.83 +
   54.84 +    def helparg(self, args):
   54.85 +        for a in args:
   54.86 +            if a in ['-h', '--help']:
   54.87 +                return 1
   54.88 +        return 0
   54.89 +
   54.90 +    def prog(self, pklass):
   54.91 +        """Add a sub-program.
   54.92 +
   54.93 +        pklass  program class (Prog subclass)
   54.94 +        """
   54.95 +        p = pklass(self)
   54.96 +        self.progs[p.name] = p
   54.97 +        return p
   54.98 +
   54.99 +    def getprog(self, name, val=None):
  54.100 +        """Get a sub-program.
  54.101 +        """
  54.102 +        return self.progs.get(name, val)
  54.103 +
  54.104 +    def proglist(self):
  54.105 +        """Get a list of sub-programs, ordered by group.
  54.106 +        """
  54.107 +        groups = {}
  54.108 +        for p in self.progs.values():
  54.109 +            l = groups.get(p.group, [])
  54.110 +            l.append(p)
  54.111 +            groups[p.group] = l
  54.112 +        kl = groups.keys()
  54.113 +        kl.sort()
  54.114 +        pl = []
  54.115 +        for k in kl:
  54.116 +            l = groups[k]
  54.117 +            l.sort()
  54.118 +            pl += l
  54.119 +        return pl
  54.120 +        
  54.121 +# Create the application object, then add the sub-program classes.
  54.122 +xm = Xm()
  54.123 +
  54.124 +class ProgHelp(Prog):
  54.125 +
  54.126 +    name = "help"
  54.127 +    info = "Print help."
  54.128 +    
  54.129 +    def help(self, args):
  54.130 +        if len(args) == 2:
  54.131 +            name = args[1]
  54.132 +            p = self.xm.getprog(name)
  54.133 +            if p:
  54.134 +                p.help(args[1:])
  54.135 +            else:
  54.136 +                print '%s: Unknown command: %s' % (self.name, name)
  54.137 +        else:
  54.138 +            for p in self.xm.proglist():
  54.139 +                p.shortHelp(args)
  54.140 +            print "\nTry '%s help CMD' for help on CMD" % self.xm.name
  54.141 +
  54.142 +    main = help
  54.143 +
  54.144 +xm.prog(ProgHelp)
  54.145 +
  54.146 +class ProgCreate(Prog):
  54.147 +
  54.148 +    group = 'domain'
  54.149 +    name = "create"
  54.150 +    info = """Create a domain."""
  54.151 +
  54.152 +    def help(self, args):
  54.153 +        create.main([args[0], '-h'])
  54.154 +
  54.155 +    def main(self, args):
  54.156 +        create.main(args)
  54.157 +
  54.158 +xm.prog(ProgCreate)
  54.159 +
  54.160 +class ProgSave(Prog):
  54.161 +    group = 'domain'
  54.162 +    name = "save"
  54.163 +    info = """Save domain state (and config) to file."""
  54.164 +
  54.165 +    def help(self, args):
  54.166 +        print args[0], "DOM FILE"
  54.167 +        print """\nSave domain with id DOM to FILE."""
  54.168 +        
  54.169 +    def main(self, args):
  54.170 +        if len(args) < 3: self.err("%s: Missing arguments" % args[0])
  54.171 +        dom = args[1]
  54.172 +        savefile = os.path.abspath(args[2])
  54.173 +        server.xend_domain_save(dom, savefile)
  54.174 +
  54.175 +xm.prog(ProgSave)
  54.176 +
  54.177 +class ProgRestore(Prog):
  54.178 +    group = 'domain'
  54.179 +    name = "restore"
  54.180 +    info = """Create a domain from a saved state."""
  54.181 +
  54.182 +    def help(self, args):
  54.183 +        print args[0], "FILE [CONFIG]"
  54.184 +        print "\nRestore a domain from FILE using configuration CONFIG."
  54.185 +    
  54.186 +    def main(self, help, args):
  54.187 +        if len(args) < 2: self.err("%s: Missing arguments" % args[0])
  54.188 +        savefile =  os.path.abspath(args[1])
  54.189 +        if len(args) >= 3:
  54.190 +            configfile = os.path.abspath(args[2])
  54.191 +        else:
  54.192 +            configfile = None
  54.193 +        info = server.xend_domain_restore(savefile, configfile)
  54.194 +        PrettyPrint.prettyprint(info)
  54.195 +
  54.196 +xm.prog(ProgRestore)
  54.197 +
  54.198 +class ProgList(Prog):
  54.199 +    group = 'domain'
  54.200 +    name = "list"
  54.201 +    info = """List info about domains."""
  54.202 +
  54.203 +    short_options = 'l'
  54.204 +    long_options = ['long']
  54.205 +
  54.206 +    def help(self, args):
  54.207 +        if help:
  54.208 +            print args[0], '[options] [DOM...]'
  54.209 +            print """\nGet information about domains.
  54.210 +            Either all domains or the domains given.
  54.211 +
  54.212 +            -l, --long   Get more detailed information.
  54.213 +            """
  54.214 +            return
  54.215 +        
  54.216 +    def main(self, args):
  54.217 +        use_long = 0
  54.218 +        (options, params) = getopt(args[1:],
  54.219 +                                   self.short_options,
  54.220 +                                   self.long_options)
  54.221 +        n = len(params)
  54.222 +        for (k, v) in options:
  54.223 +            if k in ['-l', '--long']:
  54.224 +                use_long = 1
  54.225 +                
  54.226 +        if n == 0:
  54.227 +            doms = map(int, server.xend_domains())
  54.228 +            doms.sort()
  54.229 +        else:
  54.230 +            doms = map(int, params)
  54.231 +            
  54.232 +        if use_long:
  54.233 +            self.long_list(doms)
  54.234 +        else:
  54.235 +            self.brief_list(doms)
  54.236 +
  54.237 +    def brief_list(self, doms):
  54.238 +        print 'Dom  Name             Mem(MB)  CPU  State  Time(s)'
  54.239 +        for dom in doms:
  54.240 +            info = server.xend_domain(dom)
  54.241 +            d = {}
  54.242 +            d['dom'] = int(dom)
  54.243 +            d['name'] = sxp.child_value(info, 'name', '??')
  54.244 +            d['mem'] = int(sxp.child_value(info, 'memory', '0'))
  54.245 +            d['cpu'] = int(sxp.child_value(info, 'cpu', '0'))
  54.246 +            d['state'] = sxp.child_value(info, 'state', '??')
  54.247 +            d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
  54.248 +            print ("%(dom)-4d %(name)-16s %(mem)7d  %(cpu)3d  %(state)5s  %(cpu_time)7.1f" % d)
  54.249 +
  54.250 +    def long_list(self, doms):
  54.251 +        for dom in doms:
  54.252 +            info = server.xend_domain(dom)
  54.253 +            print '\nDomain %d' % dom
  54.254 +            PrettyPrint.prettyprint(info)
  54.255 +
  54.256 +xm.prog(ProgList)
  54.257 +
  54.258 +class ProgDestroy(Prog):
  54.259 +    group = 'domain'
  54.260 +    name = "destroy"
  54.261 +    info = """Terminate a domain immediately."""
  54.262 +
  54.263 +    def help(self, args):
  54.264 +        print args[0], 'DOM'
  54.265 +        print '\nTerminate domain DOM immediately.'
  54.266 +
  54.267 +    def main(self, args):
  54.268 +        if len(args) < 2: self.err("%s: Missing domain" % args[0])
  54.269 +        dom = args[1]
  54.270 +        server.xend_domain_destroy(dom)
  54.271 +
  54.272 +xm.prog(ProgDestroy)
  54.273 +
  54.274 +class ProgShutdown(Prog):
  54.275 +    group = 'domain'
  54.276 +    name = "shutdown"
  54.277 +    info = """Shutdown a domain."""
  54.278 +
  54.279 +    def help(self, args):
  54.280 +        shutdown.main([args[0], '-h'])
  54.281 +    
  54.282 +    def main(self, args):
  54.283 +        shutdown.main(args)
  54.284 +
  54.285 +xm.prog(ProgShutdown)
  54.286 +
  54.287 +class ProgPause(Prog):
  54.288 +    group = 'domain'
  54.289 +    name = "pause"
  54.290 +    info = """Pause execution of a domain."""
  54.291 +
  54.292 +    def help(self, args):
  54.293 +        print args[0], 'DOM'
  54.294 +        print '\nPause execution of domain DOM.'
  54.295 +
  54.296 +    def main(self, args):
  54.297 +        if len(args) < 2: self.err("%s: Missing domain" % args[0])
  54.298 +        dom = args[1]
  54.299 +        server.xend_domain_pause(dom)
  54.300 +
  54.301 +xm.prog(ProgPause)
  54.302 +
  54.303 +class ProgUnpause(Prog):
  54.304 +    group = 'domain'
  54.305 +    name = "unpause"
  54.306 +    info = """Unpause a paused domain."""
  54.307 +
  54.308 +    def help(self, args):
  54.309 +        print args[0], 'DOM'
  54.310 +        print '\nUnpause execution of domain DOM.'
  54.311 +
  54.312 +    def main(self, args):
  54.313 +        if len(args) < 2: self.err("%s: Missing domain" % args[0])
  54.314 +        dom = args[1]
  54.315 +        server.xend_domain_unpause(dom)
  54.316 +
  54.317 +xm.prog(ProgUnpause)
  54.318 +
  54.319 +class ProgPincpu(Prog):
  54.320 +    group = 'domain'
  54.321 +    name = "pincpu"
  54.322 +    info = """Pin a domain to a cpu. """
  54.323 +
  54.324 +    def help(self, args):
  54.325 +        print args[0],'DOM CPU'
  54.326 +        print '\nPin domain DOM to cpu CPU.'
  54.327 +
  54.328 +    def main(self, args):
  54.329 +        if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0])
  54.330 +        v = map(int, args[1:3])
  54.331 +        server.xend_domain_pincpu(*v)
  54.332 +
  54.333 +xm.prog(ProgPincpu)
  54.334 +
  54.335 +class ProgBvt(Prog):
  54.336 +    group = 'scheduler'
  54.337 +    name = "bvt"
  54.338 +    info = """Set BVT scheduler parameters."""
  54.339 +    
  54.340 +    def help(self, args):
  54.341 +        print args[0], "DOM MCUADV WARP WARPL WARPU"
  54.342 +        print '\nSet Borrowed Virtual Time scheduler parameters.'
  54.343 +
  54.344 +    def main(self, args):
  54.345 +        if len(args) != 6: self.err("%s: Invalid argument(s)" % args[0])
  54.346 +        v = map(int, args[1:6])
  54.347 +        server.xend_domain_cpu_bvt_set(*v)
  54.348 +
  54.349 +xm.prog(ProgBvt)
  54.350 +
  54.351 +class ProgBvtslice(Prog):
  54.352 +    group = 'scheduler'
  54.353 +    name = "bvtslice"
  54.354 +    info = """Set the BVT scheduler slice."""
  54.355 +
  54.356 +    def help(self, args):
  54.357 +        print args[0], 'SLICE'
  54.358 +        print '\nSet Borrowed Virtual Time scheduler slice.'
  54.359 +
  54.360 +    def main(self, args):
  54.361 +        if len(args) < 2: self.err('%s: Missing slice' % args[0])
  54.362 +        server.xend_node_cpu_bvt_slice_set(slice)
  54.363 +
  54.364 +xm.prog(ProgBvtslice)
  54.365 +
  54.366 +class ProgAtropos(Prog):
  54.367 +    group = 'scheduler'
  54.368 +    name= "atropos"
  54.369 +    info = """Set atropos parameters."""
  54.370 +
  54.371 +    def help(self, args):
  54.372 +        print args[0], "DOM PERIOD SLICE LATENCY XTRATIME"
  54.373 +        print "\nSet atropos parameters."
  54.374 +
  54.375 +    def main(self, args):
  54.376 +        if len(args) != 5: self.err("%s: Invalid argument(s)" % args[0])
  54.377 +        v = map(int, args[1:5])
  54.378 +        server.xend_domain_cpu_atropos_set(*v)
  54.379 +
  54.380 +xm.prog(ProgAtropos)
  54.381 +
  54.382 +class ProgRrobin(Prog):
  54.383 +    group = 'scheduler'
  54.384 +    name = "rrobin"
  54.385 +    info = """Set round robin slice."""
  54.386 +
  54.387 +    def help(self, args):
  54.388 +        print args[0], "SLICE"
  54.389 +        print "\nSet round robin scheduler slice."
  54.390 +
  54.391 +    def main(self, args):
  54.392 +        if len(args) != 2: self.err("%s: Invalid argument(s)" % args[0])
  54.393 +        rrslice = int(args[1])
  54.394 +        server.xend_node_rrobin_set(rrslice)
  54.395 +
  54.396 +xm.prog(ProgRrobin)
  54.397 +
  54.398 +class ProgInfo(Prog):
  54.399 +    group = 'host'
  54.400 +    name = "info"
  54.401 +    info = """Get information about the xen host."""
  54.402 +
  54.403 +    def main(self, args):
  54.404 +        info = server.xend_node()
  54.405 +        for x in info[1:]:
  54.406 +            print "%-23s:" % x[0], x[1]
  54.407 +
  54.408 +xm.prog(ProgInfo)
  54.409 +
  54.410 +class ProgConsoles(Prog):
  54.411 +    group = 'console'
  54.412 +    name = "consoles"
  54.413 +    info = """Get information about domain consoles."""
  54.414 +
  54.415 +    def main(self, args):
  54.416 +        l = server.xend_consoles()
  54.417 +        print "Dom Port  Id"
  54.418 +        for x in l:
  54.419 +            info = server.xend_console(x)
  54.420 +            d = {}
  54.421 +            d['dom'] = sxp.child(info, 'dst', ['dst', '?', '?'])[1]
  54.422 +            d['port'] = sxp.child_value(info, 'port', '?')
  54.423 +            d['id'] = sxp.child_value(info, 'id', '?')
  54.424 +            print "%(dom)3s %(port)4s %(id)3s" % d
  54.425 +
  54.426 +xm.prog(ProgConsoles)
  54.427 +
  54.428 +class ProgConsole(Prog):
  54.429 +    group = 'console'
  54.430 +    name = "console"
  54.431 +    info = """Open a console to a domain."""
  54.432 +    
  54.433 +    def help(self, args):
  54.434 +        print "console DOM"
  54.435 +        print "\nOpen a console to domain DOM."
  54.436 +
  54.437 +    def main(self, args):
  54.438 +        if len(args) < 2: self.err("%s: Missing domain" % args[0])
  54.439 +        dom = args[1]
  54.440 +        info = server.xend_domain(dom)
  54.441 +        console = sxp.child(info, "console")
  54.442 +        if not console:
  54.443 +            self.err("No console information")
  54.444 +        port = sxp.child_value(console, "port")
  54.445 +        from xenctl import console_client
  54.446 +        console_client.connect("localhost", int(port))
  54.447 +
  54.448 +xm.prog(ProgConsole)
  54.449 +
  54.450 +def main(args):
  54.451 +    xm.main(args)
    55.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.2 +++ b/tools/xen/lib/xm/opts.py	Fri Jun 25 15:10:48 2004 +0000
    55.3 @@ -0,0 +1,339 @@
    55.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    55.5 +"""Object-oriented command-line option support.
    55.6 +"""
    55.7 +from getopt import getopt
    55.8 +import os
    55.9 +import os.path
   55.10 +import sys
   55.11 +import types
   55.12 +
   55.13 +class Opt:
   55.14 +    """An individual option.
   55.15 +    """
   55.16 +    def __init__(self, opts, name, short=None, long=None,
   55.17 +                 val=None, fn=None, use=None, default=None):
   55.18 +        """Create an option.
   55.19 +
   55.20 +        opts    parent options object
   55.21 +        name    name of the field it controls
   55.22 +        short   short (1-char) command line switch (optional)
   55.23 +        long    long command-line switch. Defaults to option name.
   55.24 +        val     string used to print option args in help.
   55.25 +                If val is not specified the option has no arg.
   55.26 +        fn      function to call when the option is specified.
   55.27 +        use     usage (help) string
   55.28 +        default default value if not specified on command-line
   55.29 +        """
   55.30 +        self.opts = opts
   55.31 +        self.name = name
   55.32 +        self.short = short
   55.33 +        if long is None:
   55.34 +            long = name
   55.35 +        self.long = long
   55.36 +        self.val = val
   55.37 +        self.use = use
   55.38 +        self.default = default
   55.39 +        self.optkeys = []
   55.40 +        if self.short:
   55.41 +            self.optkeys.append('-' + self.short)
   55.42 +        if self.long:
   55.43 +            self.optkeys.append('--' + self.long)
   55.44 +        self.fn = fn
   55.45 +        self.specified_opt = None
   55.46 +        self.specified_val = None
   55.47 +        self.value = None
   55.48 +        self.set(default)
   55.49 +
   55.50 +    def __repr__(self):
   55.51 +        return self.name + '=' + str(self.specified_val)
   55.52 +
   55.53 +    __str__ = __repr__
   55.54 +
   55.55 +    def set(self, value):
   55.56 +        """Set the option value.
   55.57 +        """
   55.58 +        self.opts.setopt(self.name, value)
   55.59 +
   55.60 +    def get(self):
   55.61 +        """Get the option value.
   55.62 +        """
   55.63 +        return self.opts.getopt(self.name)
   55.64 +
   55.65 +    def append(self, value):
   55.66 +        """Append a value to the option value.
   55.67 +        """
   55.68 +        v = self.get() or []
   55.69 +        v.append(value)
   55.70 +        self.set(v)
   55.71 +
   55.72 +    def short_opt(self):
   55.73 +        """Short option spec.
   55.74 +        """
   55.75 +        if self.short:
   55.76 +            if self.val:
   55.77 +                return self.short + ':'
   55.78 +            else:
   55.79 +                return self.short
   55.80 +        else:
   55.81 +            return None
   55.82 +
   55.83 +    def long_opt(self):
   55.84 +        """Long option spec.
   55.85 +        """
   55.86 +        if self.long:
   55.87 +            if self.val:
   55.88 +                return self.long + '='
   55.89 +            else:
   55.90 +                return self.long
   55.91 +        else:
   55.92 +            return None
   55.93 +
   55.94 +    def show(self):
   55.95 +        sep = ''
   55.96 +        for x in self.optkeys:
   55.97 +            print sep, x,
   55.98 +            sep = ','
   55.99 +        if self.val:
  55.100 +            print self.val,
  55.101 +        print
  55.102 +        if self.use:
  55.103 +            print '\t',
  55.104 +            print self.use
  55.105 +        if self.val:
  55.106 +            print '\tDefault', self.default or 'None'
  55.107 +
  55.108 +    def specify(self, k, v):
  55.109 +        """Specify the option. Called when the option is set
  55.110 +        from the command line.
  55.111 +
  55.112 +        k  option switch used
  55.113 +        v  optional value given (if any)
  55.114 +        """
  55.115 +        if k in self.optkeys:
  55.116 +            if self.val is None and v:
  55.117 +                self.opts.err("Option '%s' does not take a value" % k)
  55.118 +            self.specified_opt = k
  55.119 +            self.specified_val = v
  55.120 +            if self.fn:
  55.121 +                self.fn(self, k, v)
  55.122 +            return 1
  55.123 +        else:
  55.124 +            return 0
  55.125 +
  55.126 +    def specified(self):
  55.127 +        """Test whether the option has been specified: set
  55.128 +        from the command line.
  55.129 +        """
  55.130 +        return self.specified_opt
  55.131 +
  55.132 +class OptVals:
  55.133 +    """Class to hold option values.
  55.134 +    """
  55.135 +    pass
  55.136 +
  55.137 +class Opts:
  55.138 +    """Container for options.
  55.139 +    """
  55.140 +    def __init__(self, use=None):
  55.141 +        """Options constructor.
  55.142 +
  55.143 +        use  usage string
  55.144 +        """
  55.145 +        self.use = use
  55.146 +        # List of options.
  55.147 +        self.options = []
  55.148 +        # Options indexed by name.
  55.149 +        self.options_map = {}
  55.150 +        # Command-line arguments.
  55.151 +        self.argv = []
  55.152 +        # Option values.
  55.153 +        self.vals = OptVals()
  55.154 +        self.vals.quiet = 0
  55.155 +        # Variables for default scripts.
  55.156 +        self.vars = {}
  55.157 +
  55.158 +    def __repr__(self):
  55.159 +        return '\n'.join(map(str, self.options))
  55.160 +
  55.161 +    __str__ = __repr__
  55.162 +
  55.163 +    def opt(self, name, **args):
  55.164 +        """Add an option.
  55.165 +
  55.166 +        name    option name
  55.167 +        **args  keyword params for option constructor
  55.168 +        """
  55.169 +        x = Opt(self, name, **args)
  55.170 +        self.options.append(x)
  55.171 +        self.options_map[name] = x
  55.172 +        return x
  55.173 +
  55.174 +    def setvar(self, var, val):
  55.175 +        """Set a default script variable.
  55.176 +        """
  55.177 +        self.vars[var] = val
  55.178 +
  55.179 +    def getvar(self, var):
  55.180 +        """Get a default script variable.
  55.181 +        """
  55.182 +        return self.vars.get(var)
  55.183 +
  55.184 +    def option(self, name):
  55.185 +        """Get an option (object).
  55.186 +        """
  55.187 +        return self.options_map.get(name)
  55.188 +
  55.189 +    def setopt(self, name, val):
  55.190 +        """Set an option value.
  55.191 +        An option can also be set using 'opts.vals.name = val'.
  55.192 +        """
  55.193 +        setattr(self.vals, name, val)
  55.194 +
  55.195 +    def getopt(self, name):
  55.196 +        """Get an option value.
  55.197 +        An option value can also be got using 'opts.vals.name'.
  55.198 +        """
  55.199 +        getattr(self.vals, name)
  55.200 +
  55.201 +    def specified(self, name):
  55.202 +        """Test if an option has been specified.
  55.203 +        """
  55.204 +        opt = self.option(name)
  55.205 +        return opt and opt.specified()
  55.206 +
  55.207 +    def err(self, msg):
  55.208 +        """Print an error to stderr and exit.
  55.209 +        """
  55.210 +        print >>sys.stderr, "Error:", msg
  55.211 +        sys.exit(1)
  55.212 +
  55.213 +    def info(self, msg):
  55.214 +        """Print a message to stdout (unless quiet is set).
  55.215 +        """
  55.216 +        if self.vals.quiet: return
  55.217 +        print msg
  55.218 +
  55.219 +    def warn(self, msg):
  55.220 +        """Print a warning to stdout.
  55.221 +        """
  55.222 +        print >>sys.stderr, "Warning:", msg
  55.223 +
  55.224 +    def parse(self, argv):
  55.225 +        """Parse arguments argv using the options.
  55.226 +
  55.227 +        return remaining arguments
  55.228 +        """
  55.229 +        self.argv = argv
  55.230 +        (vals, args) = getopt(argv[1:], self.short_opts(), self.long_opts())
  55.231 +        self.args = args
  55.232 +        for (k, v) in vals:
  55.233 +            for opt in self.options:
  55.234 +                if opt.specify(k, v): break
  55.235 +            else:
  55.236 +                print >>sys.stderr, "Error: Unknown option:", k
  55.237 +                self.usage()
  55.238 +        return args
  55.239 +
  55.240 +    def short_opts(self):
  55.241 +        """Get short options specifier for getopt.
  55.242 +        """
  55.243 +        l = []
  55.244 +        for x in self.options:
  55.245 +            y = x.short_opt()
  55.246 +            if not y: continue
  55.247 +            l.append(y)
  55.248 +        return ''.join(l)
  55.249 +
  55.250 +    def long_opts(self):
  55.251 +        """Get long options specifier for getopt.
  55.252 +        """
  55.253 +        l = []
  55.254 +        for x in self.options:
  55.255 +            y = x.long_opt()
  55.256 +            if not y: continue
  55.257 +            l.append(y)
  55.258 +        return l
  55.259 +
  55.260 +    def usage(self):
  55.261 +        print 'Usage: ', self.argv[0], self.use or 'OPTIONS'
  55.262 +        for opt in self.options:
  55.263 +            opt.show()
  55.264 +
  55.265 +    def load_defaults(self):
  55.266 +        """Load a defaults script. Assumes these options set:
  55.267 +        'path'    search path
  55.268 +        'default' script name
  55.269 +        """
  55.270 +        for x in [ '' ] + self.vals.path.split(':'):
  55.271 +            if x:
  55.272 +                p = os.path.join(x, self.vals.defaults)
  55.273 +            else:
  55.274 +                p = self.vals.defaults
  55.275 +            if os.path.exists(p):
  55.276 +                self.load(p)
  55.277 +                break
  55.278 +        else:
  55.279 +            self.err("Cannot open defaults file %s" % self.vals.defaults)
  55.280 +
  55.281 +    def load(self, defaults, help=0):
  55.282 +        """Load a defaults file. Local variables in the file
  55.283 +        are used to set options with the same names.
  55.284 +        Variables are not used to set options that are already specified.
  55.285 +        """
  55.286 +        # Create global and lobal dicts for the file.
  55.287 +        # Initialize locals to the vars.
  55.288 +        # Use exec to do the standard imports and
  55.289 +        # define variables we are passing to the script.
  55.290 +        globals = {}
  55.291 +        locals = {}
  55.292 +        locals.update(self.vars)
  55.293 +        cmd = '\n'.join(["import sys",
  55.294 +                         "import os",
  55.295 +                         "import os.path",
  55.296 +                         "xm_file = '%s'" % defaults,
  55.297 +                         "xm_help = %d" % help ])
  55.298 +        exec cmd in globals, locals
  55.299 +        execfile(defaults, globals, locals)
  55.300 +        if help: return
  55.301 +        # Extract the values set by the script and set the corresponding
  55.302 +        # options, if not set on the command line.
  55.303 +        vtypes = [ types.StringType,
  55.304 +                   types.ListType,
  55.305 +                   types.IntType,
  55.306 +                   types.FloatType
  55.307 +                   ]
  55.308 +        for (k, v) in locals.items():
  55.309 +            if self.specified(k): continue
  55.310 +            if not(type(v) in vtypes): continue
  55.311 +            self.setopt(k, v)
  55.312 +
  55.313 +def set_true(opt, k, v):
  55.314 +    """Set an option true."""
  55.315 +    opt.set(1)
  55.316 +
  55.317 +def set_false(opt, k, v):
  55.318 +    """Set an option false."""
  55.319 +    opt.set(0)
  55.320 +
  55.321 +def set_value(opt, k, v):
  55.322 +    """Set an option to a valoue."""
  55.323 +    opt.set(v)
  55.324 +
  55.325 +def set_int(opt, k, v):
  55.326 +    """Set an option to an integer value."""
  55.327 +    try:
  55.328 +        v = int(v)
  55.329 +    except:
  55.330 +        opt.opts.err('Invalid value: ' + str(v))
  55.331 +    opt.set(v)
  55.332 +
  55.333 +def append_value(opt, k, v):
  55.334 +    """Append a value to a list option."""
  55.335 +    opt.append(v)
  55.336 +
  55.337 +def set_var(opt, k, v):
  55.338 +    """Set a default script variable.
  55.339 +    """
  55.340 +    (var, val) = v.strip().split('=')
  55.341 +    opt.opts.setvar(var.strip(), val.strip())
  55.342 +
    56.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.2 +++ b/tools/xen/lib/xm/shutdown.py	Fri Jun 25 15:10:48 2004 +0000
    56.3 @@ -0,0 +1,75 @@
    56.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    56.5 +"""Domain shutdown.
    56.6 +"""
    56.7 +import string
    56.8 +import sys
    56.9 +import time
   56.10 +
   56.11 +from xen.xend.XendClient import server
   56.12 +from xen.xend.xm.opts import *
   56.13 +
   56.14 +gopts = Opts(use="""[options] [DOM]
   56.15 +
   56.16 +Shutdown one or more domains gracefully.""")
   56.17 +
   56.18 +gopts.opt('help', short='h',
   56.19 +         fn=set_true, default=0,
   56.20 +         use="Print this help.")
   56.21 +
   56.22 +gopts.opt('all', short='a',
   56.23 +         fn=set_true, default=0,
   56.24 +         use="Shutdown all domains.")
   56.25 +
   56.26 +gopts.opt('wait', short='w',
   56.27 +         fn=set_true, default=0,
   56.28 +         use='Wait for shutdown to complete.')
   56.29 +
   56.30 +gopts.opt('norestart', short='n',
   56.31 +          fn=set_true, default=0,
   56.32 +          use='Prevent domain restart.')
   56.33 +
   56.34 +def shutdown(opts, doms, wait):
   56.35 +    def domains():
   56.36 +        return [ int(a) for a in server.xend_domains() ]
   56.37 +    if doms == None: doms = domains()
   56.38 +    if 0 in doms:
   56.39 +        doms.remove(0)
   56.40 +    for d in doms:
   56.41 +        server.xend_domain_shutdown(d)
   56.42 +    if wait:
   56.43 +        while doms:
   56.44 +            alive = domains()
   56.45 +            dead = []
   56.46 +            for d in doms:
   56.47 +                if d in alive: continue
   56.48 +                dead.append(d)
   56.49 +            for d in dead:
   56.50 +                opts.info("Domain %d terminated" % d)
   56.51 +                doms.remove(d)
   56.52 +            time.sleep(1)
   56.53 +        opts.info("All domains terminated")
   56.54 +
   56.55 +def main_all(opts, args):
   56.56 +    shutdown(opts, None, opts.vals.wait)
   56.57 +
   56.58 +def main_dom(opts, args):
   56.59 +    if len(args) < 1: opts.err('Missing domain')
   56.60 +    dom = args[0]
   56.61 +    try:
   56.62 +        domid = int(dom)
   56.63 +    except:
   56.64 +        opts.err('Invalid domain: ' + dom)
   56.65 +    shutdown(opts, [ domid ], opts.vals.wait)
   56.66 +    
   56.67 +def main(argv):
   56.68 +    opts = gopts
   56.69 +    args = opts.parse(argv)
   56.70 +    if opts.vals.help:
   56.71 +        opts.usage()
   56.72 +        return
   56.73 +    print 'shutdown.main>', len(args), args
   56.74 +    if opts.vals.all:
   56.75 +        main_all(opts, args)
   56.76 +    else:
   56.77 +        main_dom(opts, args)
   56.78 +        
    57.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.2 +++ b/tools/xen/netfix	Fri Jun 25 15:10:48 2004 +0000
    57.3 @@ -0,0 +1,61 @@
    57.4 +#!/usr/bin/python
    57.5 +#  -*- mode: python; -*-
    57.6 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    57.7 +#============================================================================
    57.8 +# Move the IP address from eth0 onto the Xen bridge (nbe-br).
    57.9 +# Only works if the bridge control utils (brctl) have been installed.
   57.10 +#============================================================================
   57.11 +
   57.12 +from getopt import getopt
   57.13 +from xen.xend.XendBridge import *
   57.14 +
   57.15 +short_options = 'hvqni:b:c'
   57.16 +long_options  = ['help', 'verbose', 'quiet',
   57.17 +                 'interface=', 'bridge=', 'create']
   57.18 +
   57.19 +def usage():
   57.20 +    print """Usage:
   57.21 +    %s [options]
   57.22 +
   57.23 +    Reconfigure routing so that <bridge> has the IP address from
   57.24 +    <interface>. This lets IP carry on working when <interface>
   57.25 +    is attached to <bridge> for virtual networking.
   57.26 +    Uses brctl to add <interface> to <bridge>,
   57.27 +    so this can be run before any domains have been created.
   57.28 +    """ % sys.argv[0]
   57.29 +    print """
   57.30 +    -i, --interface <interface>    interface, default %(interface)s.
   57.31 +    -b, --bridge <bridge>          bridge, default %(bridge)s.
   57.32 +    -c, --create                   create the bridge.
   57.33 +    -v, --verbose                  Print commands.
   57.34 +    -q, --quiet                    Don't print commands.
   57.35 +    -n, --dry-run                  Don't execute commands.
   57.36 +    -h, --help                     Print this help.
   57.37 +    """ % defaults
   57.38 +    sys.exit(1)
   57.39 +
   57.40 +
   57.41 +def main():
   57.42 +    lopts = set_opts(Opts(defaults))
   57.43 +    lopts.dryrun = 0
   57.44 +    (options, args) = getopt(sys.argv[1:], short_options, long_options)
   57.45 +    if args: usage()
   57.46 +    for k, v in options:
   57.47 +        if k in ['-h', '--help']:
   57.48 +            usage()
   57.49 +        elif k in ['-c', '--create']:
   57.50 +            lopts.create = 1
   57.51 +        elif k in ['-i', '--interface']:
   57.52 +            lopts.interface = v
   57.53 +        elif k in ['-b', '--bridge']:
   57.54 +            lopts.bridge = v
   57.55 +        elif k in ['-q', '--quiet']:
   57.56 +            lopts.verbose = 0
   57.57 +        elif k in ['-v', '--verbose']:
   57.58 +            lopts.verbose = 1
   57.59 +        elif k in ['-n', '--dry-run']:
   57.60 +            lopts.dryrun = 1
   57.61 +    reconfigure(lopts.interface, lopts.bridge)
   57.62 +
   57.63 +if __name__ == '__main__':
   57.64 +    main()
    58.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.2 +++ b/tools/xen/setup.py	Fri Jun 25 15:10:48 2004 +0000
    58.3 @@ -0,0 +1,16 @@
    58.4 +
    58.5 +from distutils.core import setup, Extension
    58.6 +
    58.7 +setup(name            = 'xen',
    58.8 +      version         = '1.0',
    58.9 +      description     = 'Xen',
   58.10 +      author          = 'Mike Wray',
   58.11 +      author_email    = 'mike.wray@hp.com',
   58.12 +      packages        = ['xen',
   58.13 +                         'xen.ext',
   58.14 +                         'xen.xend',
   58.15 +                         'xen.xend.server',
   58.16 +                         'xen.xm',
   58.17 +                         ],
   58.18 +      package_dir     = { 'xen': 'lib' },
   58.19 +      )
    59.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.2 +++ b/tools/xen/xend	Fri Jun 25 15:10:48 2004 +0000
    59.3 @@ -0,0 +1,41 @@
    59.4 +#!/usr/bin/python
    59.5 +#  -*- mode: python; -*-
    59.6 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    59.7 +
    59.8 +"""Xen management daemon. Lives in /usr/sbin.
    59.9 +   Provides console server and HTTP management api.
   59.10 +
   59.11 +   Run:
   59.12 +
   59.13 +   xend start
   59.14 +
   59.15 +   The daemon is stopped with:
   59.16 +
   59.17 +   xend stop
   59.18 +
   59.19 +   Unfortunately restarting it upsets the channel to dom0 and
   59.20 +   domain management stops working - needs a reboot to fix.
   59.21 +"""
   59.22 +import os
   59.23 +import sys
   59.24 +from xen.xend.server import SrvDaemon
   59.25 +
   59.26 +def main():
   59.27 +    daemon = SrvDaemon.instance()
   59.28 +    if not sys.argv[1:]:
   59.29 +        print 'usage: %s {start|stop|restart}' % sys.argv[0]
   59.30 +    elif os.fork():
   59.31 +        pid, status = os.wait()
   59.32 +        return status >> 8
   59.33 +    elif sys.argv[1] == 'start':
   59.34 +        return daemon.start()
   59.35 +    elif sys.argv[1] == 'stop':
   59.36 +        return daemon.stop()
   59.37 +    elif sys.argv[1] == 'restart':
   59.38 +        return daemon.stop() or daemon.start()
   59.39 +    else:
   59.40 +        print 'not an option:', sys.argv[1]
   59.41 +    return 1
   59.42 +
   59.43 +if __name__ == '__main__':
   59.44 +    sys.exit(main())
    60.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.2 +++ b/tools/xen/xm	Fri Jun 25 15:10:48 2004 +0000
    60.3 @@ -0,0 +1,6 @@
    60.4 +#!/usr/bin/python
    60.5 +#  -*- mode: python; -*-
    60.6 +import sys
    60.7 +from xen.xm import main
    60.8 +
    60.9 +main.main(sys.argv)
    61.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    61.2 +++ b/tools/xend-old/Makefile	Fri Jun 25 15:10:48 2004 +0000
    61.3 @@ -0,0 +1,17 @@
    61.4 +
    61.5 +all:
    61.6 +	python setup.py build
    61.7 +
    61.8 +install: all
    61.9 +	if [ "$(prefix)" = "" ]; then                   \
   61.10 +	    python setup.py install;                    \
   61.11 +	elif [ "$(dist)" = "yes" ]; then                \
   61.12 +	    python setup.py install --home="$(prefix)"; \
   61.13 +	else                                            \
   61.14 +	    python setup.py install --root="$(prefix)"; \
   61.15 +	fi
   61.16 +	mkdir -p $(prefix)/usr/sbin
   61.17 +	install -m0755 xend $(prefix)/usr/sbin
   61.18 +
   61.19 +clean:
   61.20 +	rm -rf build *.pyc *.pyo *.a *.so *.o *~ *.rpm 
    63.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.2 +++ b/tools/xend-old/lib/blkif.py	Fri Jun 25 15:10:48 2004 +0000
    63.3 @@ -0,0 +1,214 @@
    63.4 +
    63.5 +#################################################################
    63.6 +## xend/blkif.py -- Block-interface management functions for Xend
    63.7 +## Copyright (c) 2004, K A Fraser (University of Cambridge)
    63.8 +#################################################################
    63.9 +
   63.10 +import errno, re, os, select, signal, socket, sys
   63.11 +import xend.main, xend.console, xend.manager, xend.utils, Xc
   63.12 +
   63.13 +CMSG_BLKIF_BE = 1
   63.14 +CMSG_BLKIF_FE = 2
   63.15 +CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED =  0
   63.16 +CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED    = 32
   63.17 +CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED    = 32
   63.18 +CMSG_BLKIF_FE_INTERFACE_CONNECT        = 33
   63.19 +CMSG_BLKIF_FE_INTERFACE_DISCONNECT     = 34
   63.20 +CMSG_BLKIF_BE_CREATE      = 0
   63.21 +CMSG_BLKIF_BE_DESTROY     = 1
   63.22 +CMSG_BLKIF_BE_CONNECT     = 2
   63.23 +CMSG_BLKIF_BE_DISCONNECT  = 3
   63.24 +CMSG_BLKIF_BE_VBD_CREATE  = 4
   63.25 +CMSG_BLKIF_BE_VBD_DESTROY = 5
   63.26 +CMSG_BLKIF_BE_VBD_GROW    = 6
   63.27 +CMSG_BLKIF_BE_VBD_SHRINK  = 7
   63.28 +
   63.29 +BLKIF_DRIVER_STATUS_DOWN  = 0
   63.30 +BLKIF_DRIVER_STATUS_UP    = 1
   63.31 +
   63.32 +pendmsg = None
   63.33 +pendaddr = None
   63.34 +
   63.35 +recovery = False # Is a recovery in progress? (if so we'll need to notify guests)
   63.36 +be_port  = None  # Port object for backend domain
   63.37 +
   63.38 +def backend_tx_req(msg):
   63.39 +    port = xend.blkif.be_port
   63.40 +    if not port:
   63.41 +        print "BUG: attempt to transmit request to non-existant blkif driver"
   63.42 +    if port.space_to_write_request():
   63.43 +        port.write_request(msg)
   63.44 +        port.notify()
   63.45 +    else:
   63.46 +        xend.blkif.pendmsg = msg
   63.47 +
   63.48 +def backend_rx_req(port, msg):
   63.49 +    port.write_response(msg)
   63.50 +    subtype = (msg.get_header())['subtype']
   63.51 +    print "Received blkif-be request, subtype %d" % subtype
   63.52 +    if subtype == CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED:
   63.53 +        status = (msg.get_payload())['status']
   63.54 +        if status == BLKIF_DRIVER_STATUS_UP:
   63.55 +            if xend.blkif.recovery:
   63.56 +                # Nasty hack: we count the number of VBDs we reattach so that
   63.57 +                # we'll know when to notify the guests.  Must make this better!
   63.58 +                interface.rebuilt_so_far = 0
   63.59 +                interface.nr_to_rebuild  = 0
   63.60 +                print "New blkif backend now UP, rebuilding VBDs:"
   63.61 +                for blkif_key in interface.list.keys():
   63.62 +                    blkif = interface.list[blkif_key]
   63.63 +                    blkif.create()
   63.64 +                    for vdev in blkif.devices.keys():
   63.65 +                        blkif.reattach_device(vdev)
   63.66 +                        interface.nr_to_rebuild += 1
   63.67 +        else:
   63.68 +            print "Unexpected block backend driver status: %d" % status
   63.69 +
   63.70 +
   63.71 +def backend_rx_rsp(port, msg):
   63.72 +    subtype = (msg.get_header())['subtype']
   63.73 +    print "Received blkif-be response, subtype %d" % subtype
   63.74 +    if subtype == CMSG_BLKIF_BE_CREATE:
   63.75 +        rsp = { 'success': True }
   63.76 +        xend.main.send_management_response(rsp, xend.blkif.pendaddr)
   63.77 +    elif subtype == CMSG_BLKIF_BE_CONNECT:
   63.78 +        pl = msg.get_payload()
   63.79 +        (dom, hnd, frame, evtchn, st) = (pl['domid'], pl['blkif_handle'],
   63.80 +                                         pl['shmem_frame'], pl['evtchn'],
   63.81 +                                         pl['status'])
   63.82 +        blkif = interface.list[xend.main.port_from_dom(dom).local_port]
   63.83 +        msg = xend.utils.message(CMSG_BLKIF_FE,
   63.84 +                                 CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED, 0,
   63.85 +                                 { 'handle' : 0, 'status' : 2,
   63.86 +                                   'evtchn' : blkif.evtchn['port2'] })
   63.87 +        blkif.ctrlif_tx_req(xend.main.port_list[blkif.key], msg)
   63.88 +    elif subtype == CMSG_BLKIF_BE_VBD_CREATE:
   63.89 +        pl = msg.get_payload()
   63.90 +        (dom, hnd, vdev, ro, st) = (pl['domid'], pl['blkif_handle'],
   63.91 +                                    pl['vdevice'], pl['readonly'],
   63.92 +                                    pl['status'])
   63.93 +        blkif = interface.list[xend.main.port_from_dom(dom).local_port]
   63.94 +        (pdev, start_sect, nr_sect, readonly) = blkif.devices[vdev]
   63.95 +        msg = xend.utils.message(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW, 0,
   63.96 +                                 { 'domid' : dom, 'blkif_handle' : 0,
   63.97 +                                   'vdevice' : vdev,
   63.98 +                                   'extent.sector_start' : start_sect,
   63.99 +                                   'extent.sector_length' : nr_sect,
  63.100 +                                   'extent.device' : pdev })
  63.101 +        backend_tx_req(msg)
  63.102 +    elif subtype == CMSG_BLKIF_BE_VBD_GROW:
  63.103 +       if not xend.blkif.recovery:
  63.104 +           rsp = { 'success': True }
  63.105 +           xend.main.send_management_response(rsp, xend.blkif.pendaddr)
  63.106 +       else:
  63.107 +           interface.rebuilt_so_far += 1
  63.108 +           if interface.rebuilt_so_far == interface.nr_to_rebuild:
  63.109 +               print "Rebuilt VBDs, notifying guests:"
  63.110 +               for blkif_key in interface.list.keys():
  63.111 +                   blkif = interface.list[blkif_key]
  63.112 +                   print "  Notifying %d" % blkif.dom
  63.113 +                   msg = xend.utils.message(CMSG_BLKIF_FE,
  63.114 +                                            CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED,
  63.115 +                                            0, { 'handle' : 0, 'status' : 1 })
  63.116 +                   blkif.ctrlif_tx_req(xend.main.port_from_dom(blkif.dom),msg)
  63.117 +               xend.blkif.recovery = False
  63.118 +               print "Done notifying guests"
  63.119 +
  63.120 +
  63.121 +def backend_do_work(port):
  63.122 +    global pendmsg
  63.123 +    if pendmsg and port.space_to_write_request():
  63.124 +        port.write_request(pendmsg)
  63.125 +        pendmsg = None
  63.126 +        return True
  63.127 +    return False
  63.128 +
  63.129 +
  63.130 +class interface:
  63.131 +
  63.132 +    # Dictionary of all block-device interfaces.
  63.133 +    list = {}
  63.134 +
  63.135 +    # NB. 'key' is an opaque value that has no meaning in this class.
  63.136 +    def __init__(self, dom, key):
  63.137 +        self.dom     = dom
  63.138 +        self.key     = key
  63.139 +        self.devices = {}
  63.140 +        self.pendmsg = None
  63.141 +        interface.list[key] = self
  63.142 +        self.create()
  63.143 +
  63.144 +    def create(self):
  63.145 +        msg = xend.utils.message(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE, 0,
  63.146 +                                 { 'domid' : self.dom, 'blkif_handle' : 0 })
  63.147 +        xend.blkif.pendaddr = xend.main.mgmt_req_addr
  63.148 +        backend_tx_req(msg)
  63.149 +
  63.150 +    # Attach a device to the specified interface
  63.151 +    def attach_device(self, vdev, pdev, start_sect, nr_sect, readonly):
  63.152 +        if self.devices.has_key(vdev):
  63.153 +            return False
  63.154 +        self.devices[vdev] = (pdev, start_sect, nr_sect, readonly)
  63.155 +        msg = xend.utils.message(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE, 0,
  63.156 +                                 { 'domid' : self.dom, 'blkif_handle' : 0,
  63.157 +                                   'vdevice' : vdev, 'readonly' : readonly })
  63.158 +        xend.blkif.pendaddr = xend.main.mgmt_req_addr
  63.159 +        backend_tx_req(msg)
  63.160 +        return True
  63.161 +
  63.162 +    def reattach_device(self, vdev):
  63.163 +        (pdev, start_sect, nr_sect, readonly) = self.devices[vdev]
  63.164 +        msg = xend.utils.message(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE,
  63.165 +                                 0, { 'domid' : self.dom,
  63.166 +                                      'blkif_handle' : 0,
  63.167 +                                      'vdevice' : vdev,
  63.168 +                                      'readonly' : readonly })
  63.169 +        xend.blkif.pendaddr = xend.main.mgmt_req_addr
  63.170 +        backend_tx_req(msg)
  63.171 +
  63.172 +    # Completely destroy this interface.
  63.173 +    def destroy(self):
  63.174 +        del interface.list[self.key]
  63.175 +        msg = xend.utils.message(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY, 0,
  63.176 +                                 { 'domid' : self.dom, 'blkif_handle' : 0 })
  63.177 +        backend_tx_req(msg)        
  63.178 +
  63.179 +
  63.180 +    # The parameter @port is the control-interface event channel. This method
  63.181 +    # returns True if messages were written to the control interface.
  63.182 +    def ctrlif_transmit_work(self, port):
  63.183 +        if self.pendmsg and port.space_to_write_request():
  63.184 +            port.write_request(self.pendmsg)
  63.185 +            self.pendmsg = None
  63.186 +            return True
  63.187 +        return False
  63.188 +
  63.189 +    def ctrlif_tx_req(self, port, msg):
  63.190 +        if port.space_to_write_request():
  63.191 +            port.write_request(msg)
  63.192 +            port.notify()
  63.193 +        else:
  63.194 +            self.pendmsg = msg
  63.195 +
  63.196 +    def ctrlif_rx_req(self, port, msg):
  63.197 +        port.write_response(msg)
  63.198 +        subtype = (msg.get_header())['subtype']
  63.199 +        if subtype == CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
  63.200 +            msg = xend.utils.message(CMSG_BLKIF_FE,
  63.201 +                                     CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED,
  63.202 +                                     0,
  63.203 +                                     { 'handle' : 0, 'status' : 1 })
  63.204 +            self.ctrlif_tx_req(port, msg)
  63.205 +        elif subtype == CMSG_BLKIF_FE_INTERFACE_CONNECT:
  63.206 +            pl = msg.get_payload()
  63.207 +            (hnd, frame) = (pl['handle'], pl['shmem_frame'])
  63.208 +            xc = Xc.new()
  63.209 +            self.evtchn = xc.evtchn_bind_interdomain(
  63.210 +                                            dom1=xend.blkif.be_port.remote_dom,
  63.211 +                                            dom2=self.dom)
  63.212 +            msg = xend.utils.message(CMSG_BLKIF_BE,
  63.213 +                                     CMSG_BLKIF_BE_CONNECT, 0,
  63.214 +                                     { 'domid' : self.dom, 'blkif_handle' : 0