direct-io.hg
changeset 1564:46d2220a5d07
bitkeeper revision 1.1011.1.1 (40dac272gGtMUxrtDr9Jr2GTujO_-w)
Merge ssh://xenbk@gandalf.hpl.hp.com//var/bk/xeno-unstable.bk
into labyrinth.cl.cam.ac.uk:/auto/groups/xeno/BK/xeno.bk
Merge ssh://xenbk@gandalf.hpl.hp.com//var/bk/xeno-unstable.bk
into labyrinth.cl.cam.ac.uk:/auto/groups/xeno/BK/xeno.bk
line diff
1.1 --- a/docs/xen_config.html Thu Jun 24 10:28:58 2004 +0000 1.2 +++ b/docs/xen_config.html Thu Jun 24 12:00:50 2004 +0000 1.3 @@ -86,13 +86,13 @@ Defines a netbsd kernel image and its co 1.4 <li>args: string, optional. Extra kernel args. 1.5 </ul> 1.6 1.7 -<h2>(controller (block)) element</h2> 1.8 -Define that the vm is a block device controller backend. 1.9 +<h2>(backend (blkif)) element</h2> 1.10 +The vm is a block device backend. 1.11 The vm can have pci devices configured, but no virtual 1.12 block devices. 1.13 1.14 -<h2>(controller (net)) element</h2> 1.15 -Define that the vm is a net device controller backend. 1.16 +<h2>(backend (netif)) element</h2> 1.17 +The vm is a net device backend. 1.18 The domain may not have virtual network interfaces (vifs) configured. 1.19 1.20 <h2>(device (vif)) element</h2>
2.1 --- a/tools/xenmgr/lib/EventTypes.py Thu Jun 24 10:28:58 2004 +0000 2.2 +++ b/tools/xenmgr/lib/EventTypes.py Thu Jun 24 12:00:50 2004 +0000 2.3 @@ -8,7 +8,7 @@ 2.4 ## xend.domain.unpause: dom 2.5 ## xend.domain.pause: dom 2.6 ## xend.domain.shutdown: dom 2.7 -## xend.domain.halt: dom 2.8 +## xend.domain.destroy: dom 2.9 2.10 ## xend.domain.migrate.begin: dom, to 2.11 ## Begin tells: src host, src domain uri, dst host. Dst id known?
3.1 --- a/tools/xenmgr/lib/XendClient.py Thu Jun 24 10:28:58 2004 +0000 3.2 +++ b/tools/xenmgr/lib/XendClient.py Thu Jun 24 12:00:50 2004 +0000 3.3 @@ -199,9 +199,9 @@ class Xend: 3.4 return xend_call(self.domainurl(id), 3.5 {'op' : 'shutdown'}) 3.6 3.7 - def xend_domain_halt(self, id): 3.8 + def xend_domain_destroy(self, id): 3.9 return xend_call(self.domainurl(id), 3.10 - {'op' : 'halt'}) 3.11 + {'op' : 'destroy'}) 3.12 3.13 def xend_domain_save(self, id, filename): 3.14 return xend_call(self.domainurl(id),
4.1 --- a/tools/xenmgr/lib/XendDomain.py Thu Jun 24 10:28:58 2004 +0000 4.2 +++ b/tools/xenmgr/lib/XendDomain.py Thu Jun 24 12:00:50 2004 +0000 4.3 @@ -6,6 +6,8 @@ 4.4 """ 4.5 import sys 4.6 4.7 +from twisted.internet import defer 4.8 + 4.9 import Xc; xc = Xc.new() 4.10 import xenctl.ip 4.11 4.12 @@ -59,21 +61,26 @@ class XendDomain: 4.13 for d in domlist: 4.14 domid = str(d['dom']) 4.15 doms[domid] = d 4.16 + dlist = [] 4.17 for config in self.domain_db.values(): 4.18 domid = str(sxp.child_value(config, 'id')) 4.19 print "dom=", domid, "config=", config 4.20 if domid in doms: 4.21 print "dom=", domid, "new" 4.22 - self._new_domain(config) 4.23 + deferred = self._new_domain(config, doms[domid]) 4.24 + dlist.append(deferred) 4.25 else: 4.26 print "dom=", domid, "del" 4.27 self._delete_domain(domid) 4.28 - print "doms:" 4.29 - for d in self.domain.values(): print 'dom', d 4.30 - print "refresh..." 4.31 - self.refresh() 4.32 - print "doms:" 4.33 - for d in self.domain.values(): print 'dom', d 4.34 + deferred = defer.DeferredList(dlist, fireOnOneErrback=1) 4.35 + def cbok(val): 4.36 + print "doms:" 4.37 + for d in self.domain.values(): print 'dom', d 4.38 + print "refresh..." 4.39 + self.refresh() 4.40 + print "doms:" 4.41 + for d in self.domain.values(): print 'dom', d 4.42 + deferred.addCallback(cbok) 4.43 4.44 def sync(self): 4.45 """Sync domain db to disk. 4.46 @@ -90,31 +97,36 @@ class XendDomain: 4.47 def close(self): 4.48 pass 4.49 4.50 - def _new_domain(self, info): 4.51 + def _new_domain(self, savedinfo, info): 4.52 """Create a domain entry from saved info. 4.53 """ 4.54 - console = None 4.55 - kernel = None 4.56 - id = sxp.child_value(info, 'id') 4.57 - dom = int(id) 4.58 - name = sxp.child_value(info, 'name') 4.59 - memory = int(sxp.child_value(info, 'memory')) 4.60 - consoleinfo = sxp.child(info, 'console') 4.61 - if consoleinfo: 4.62 - consoleid = sxp.child_value(consoleinfo, 'id') 4.63 - console = self.xconsole.console_get(consoleid) 4.64 - if dom and console is None: 4.65 - # Try to connect a console. 4.66 - console = self.xconsole.console_create(dom) 4.67 - config = sxp.child(info, 'config') 4.68 - if config: 4.69 - image = sxp.child(info, 'image') 4.70 - if image: 4.71 - image = sxp.child0(image) 4.72 - kernel = sxp.child_value(image, 'kernel') 4.73 - dominfo = XendDomainInfo.XendDomainInfo( 4.74 - config, dom, name, memory, kernel, console) 4.75 - self.domain[id] = dominfo 4.76 +## console = None 4.77 +## kernel = None 4.78 +## id = sxp.child_value(info, 'id') 4.79 +## dom = int(id) 4.80 +## name = sxp.child_value(info, 'name') 4.81 +## memory = int(sxp.child_value(info, 'memory')) 4.82 +## consoleinfo = sxp.child(info, 'console') 4.83 +## if consoleinfo: 4.84 +## consoleid = sxp.child_value(consoleinfo, 'id') 4.85 +## console = self.xconsole.console_get(consoleid) 4.86 +## if dom and console is None: 4.87 +## # Try to connect a console. 4.88 +## console = self.xconsole.console_create(dom) 4.89 +## config = sxp.child(info, 'config') 4.90 +## if config: 4.91 +## image = sxp.child(info, 'image') 4.92 +## if image: 4.93 +## image = sxp.child0(image) 4.94 +## kernel = sxp.child_value(image, 'kernel') 4.95 +## dominfo = XendDomainInfo.XendDomainInfo( 4.96 +## config, dom, name, memory, kernel, console) 4.97 + config = sxp.child_value(savedinfo, 'config') 4.98 + deferred = XendDomainInfo.vm_recreate(config, info) 4.99 + def fn(dominfo): 4.100 + self.domain[dominfo.id] = dominfo 4.101 + deferred.addCallback(fn) 4.102 + return deferred 4.103 4.104 def _add_domain(self, id, info, notify=1): 4.105 self.domain[id] = info 4.106 @@ -143,10 +155,13 @@ class XendDomain: 4.107 doms[id] = d 4.108 if id not in self.domain: 4.109 config = None 4.110 - image = None 4.111 - newinfo = XendDomainInfo.XendDomainInfo( 4.112 - config, d['dom'], d['name'], d['mem_kb']/1024, image=image, info=d) 4.113 - self._add_domain(newinfo.id, newinfo) 4.114 + #image = None 4.115 + #newinfo = XendDomainInfo.XendDomainInfo( 4.116 + # config, d['dom'], d['name'], d['mem_kb']/1024, image=image, info=d) 4.117 + deferred = XendDomainInfo.vm_recreate(config, d) 4.118 + def fn(dominfo): 4.119 + self._add_domain(dominfo.id, dominfo) 4.120 + deferred.addCallback(fn) 4.121 # Remove entries for domains that no longer exist. 4.122 for d in self.domain.values(): 4.123 dominfo = doms.get(d.id) 4.124 @@ -217,13 +232,13 @@ class XendDomain: 4.125 self.refresh() 4.126 return val 4.127 4.128 - def domain_halt(self, id): 4.129 + def domain_destroy(self, id): 4.130 """Terminate domain immediately. 4.131 """ 4.132 dom = int(id) 4.133 if dom <= 0: 4.134 return 0 4.135 - eserver.inject('xend.domain.halt', id) 4.136 + eserver.inject('xend.domain.destroy', id) 4.137 val = xc.domain_destroy(dom=dom) 4.138 self.refresh() 4.139 return val 4.140 @@ -235,14 +250,14 @@ class XendDomain: 4.141 pass 4.142 4.143 def domain_save(self, id, dst, progress=0): 4.144 - """Save domain state to file, halt domain. 4.145 + """Save domain state to file, destroy domain. 4.146 """ 4.147 dom = int(id) 4.148 self.domain_pause(id) 4.149 eserver.inject('xend.domain.save', id) 4.150 rc = xc.linux_save(dom=dom, state_file=dst, progress=progress) 4.151 if rc == 0: 4.152 - self.domain_halt(id) 4.153 + self.domain_destroy(id) 4.154 return rc 4.155 4.156 def domain_restore(self, src, config, progress=0):
5.1 --- a/tools/xenmgr/lib/XendDomainInfo.py Thu Jun 24 10:28:58 2004 +0000 5.2 +++ b/tools/xenmgr/lib/XendDomainInfo.py Thu Jun 24 12:00:50 2004 +0000 5.3 @@ -60,160 +60,6 @@ class VmError(ValueError): 5.4 return self.value 5.5 5.6 5.7 -class XendDomainInfo: 5.8 - """Virtual machine object.""" 5.9 - 5.10 - def __init__(self, config, dom, name, memory, image=None, console=None, info=None): 5.11 - """Construct a virtual machine object. 5.12 - 5.13 - config configuration 5.14 - dom domain id 5.15 - name name 5.16 - memory memory size (in MB) 5.17 - image image object 5.18 - """ 5.19 - #todo: add info: runtime, state, ... 5.20 - self.config = config 5.21 - self.id = str(dom) 5.22 - self.dom = dom 5.23 - self.name = name 5.24 - self.memory = memory 5.25 - self.image = image 5.26 - self.console = console 5.27 - self.devices = {} 5.28 - self.configs = [] 5.29 - self.info = info 5.30 - self.ipaddrs = [] 5.31 - self.block_controller = 0 5.32 - self.net_controller = 0 5.33 - 5.34 - #todo: state: running, suspended 5.35 - self.state = 'running' 5.36 - #todo: set to migrate info if migrating 5.37 - self.migrate = None 5.38 - 5.39 - def update(self, info): 5.40 - """Update with info from xc.domain_getinfo(). 5.41 - """ 5.42 - self.info = info 5.43 - 5.44 - def __str__(self): 5.45 - s = "domain" 5.46 - s += " id=" + self.id 5.47 - s += " name=" + self.name 5.48 - s += " memory=" + str(self.memory) 5.49 - if self.console: 5.50 - s += " console=" + self.console.id 5.51 - if self.image: 5.52 - s += " image=" + self.image 5.53 - s += "" 5.54 - return s 5.55 - 5.56 - __repr__ = __str__ 5.57 - 5.58 - def sxpr(self): 5.59 - sxpr = ['domain', 5.60 - ['id', self.id], 5.61 - ['name', self.name], 5.62 - ['memory', self.memory] ] 5.63 - if self.info: 5.64 - run = (self.info['running'] and 'R') or 'r' 5.65 - block = (self.info['blocked'] and 'B') or 'b' 5.66 - stop = (self.info['paused'] and 'P') or 'p' 5.67 - susp = (self.info['shutdown'] and 'S') or 's' 5.68 - crash = (self.info['crashed'] and 'C') or 'c' 5.69 - state = run + block + stop + susp + crash 5.70 - sxpr.append(['state', state]) 5.71 - if self.info['shutdown']: 5.72 - reasons = ["poweroff", "reboot", "suspend"] 5.73 - reason = reasons[self.info['shutdown_reason']] 5.74 - sxpr.append(['shutdown_reason', reason]) 5.75 - sxpr.append(['cpu', self.info['cpu']]) 5.76 - sxpr.append(['cpu_time', self.info['cpu_time']/1e9]) 5.77 - if self.console: 5.78 - sxpr.append(self.console.sxpr()) 5.79 - if self.config: 5.80 - sxpr.append(['config', self.config]) 5.81 - return sxpr 5.82 - 5.83 - def add_device(self, type, dev): 5.84 - """Add a device to a virtual machine. 5.85 - 5.86 - dev device to add 5.87 - """ 5.88 - dl = self.devices.get(type, []) 5.89 - dl.append(dev) 5.90 - self.devices[type] = dl 5.91 - 5.92 - def get_devices(self, type): 5.93 - val = self.devices.get(type, []) 5.94 - print 'get_devices', type; sxp.show(val); print 5.95 - return val 5.96 - 5.97 - def get_device_by_id(self, type, id): 5.98 - """Get the device with the given id. 5.99 - 5.100 - id device id 5.101 - 5.102 - returns device or None 5.103 - """ 5.104 - return sxp.child_with_id(self.get_devices(type), id) 5.105 - 5.106 - def get_device_by_index(self, type, idx): 5.107 - """Get the device with the given index. 5.108 - 5.109 - idx device index 5.110 - 5.111 - returns device or None 5.112 - """ 5.113 - dl = self.get_devices(type) 5.114 - if 0 <= idx < len(dl): 5.115 - return dl[idx] 5.116 - else: 5.117 - return None 5.118 - 5.119 - def add_config(self, val): 5.120 - """Add configuration data to a virtual machine. 5.121 - 5.122 - val data to add 5.123 - """ 5.124 - self.configs.append(val) 5.125 - 5.126 - def destroy(self): 5.127 - if self.dom <= 0: 5.128 - return 0 5.129 - return xc.domain_destroy(dom=self.dom) 5.130 - 5.131 - def died(self): 5.132 - print 'died>', self.dom 5.133 - self.release_vifs() 5.134 - 5.135 - def release_vifs(self): 5.136 - print 'release_vifs>', self.dom 5.137 - vifs = self.get_devices('vif') 5.138 - for v in vifs: 5.139 - vif = sxp.child_value(v, 'vif') 5.140 - bridge = sxp.child_value(v, 'bridge') 5.141 - XendBridge.vif_bridge_rem(self.dom, vif, bridge) 5.142 - 5.143 - def show(self): 5.144 - """Print virtual machine info. 5.145 - """ 5.146 - print "[VM dom=%d name=%s memory=%d" % (self.dom, self.name, self.memory) 5.147 - print "image:" 5.148 - sxp.show(self.image) 5.149 - print 5.150 - for dl in self.devices: 5.151 - for dev in dl: 5.152 - print "device:" 5.153 - sxp.show(dev) 5.154 - print 5.155 - for val in self.configs: 5.156 - print "config:" 5.157 - sxp.show(val) 5.158 - print 5.159 - print "]" 5.160 - 5.161 def blkdev_name_to_number(name): 5.162 """Take the given textual block-device name (e.g., '/dev/sda1', 5.163 'hda') and return the device number used by the OS. """ 5.164 @@ -264,7 +110,7 @@ def lookup_raw_partn(partition): 5.165 5.166 return None 5.167 5.168 -def lookup_disk_uname( uname ): 5.169 +def lookup_disk_uname(uname): 5.170 """Lookup a list of segments for a physical device. 5.171 uname [string]: name of the device in the format \'phy:dev\' for a physical device 5.172 returns [list of dicts]: list of extents that make up the named device 5.173 @@ -277,7 +123,7 @@ def lookup_disk_uname( uname ): 5.174 segments = None 5.175 return segments 5.176 5.177 -def make_disk(dom, uname, dev, mode): 5.178 +def make_disk(dom, uname, dev, mode, recreate=0): 5.179 """Create a virtual disk device for a domain. 5.180 5.181 @returns Deferred 5.182 @@ -289,21 +135,21 @@ def make_disk(dom, uname, dev, mode): 5.183 raise VmError("vbd: Multi-segment vdisk: uname=%s" % uname) 5.184 segment = segments[0] 5.185 vdev = blkdev_name_to_number(dev) 5.186 - ctrl = xend.blkif_create(dom) 5.187 + ctrl = xend.blkif_create(dom, recreate=recreate) 5.188 5.189 def fn(ctrl): 5.190 - return xend.blkif_dev_create(dom, vdev, mode, segment) 5.191 + return xend.blkif_dev_create(dom, vdev, mode, segment, recreate=recreate) 5.192 ctrl.addCallback(fn) 5.193 return ctrl 5.194 5.195 -def make_vif(dom, vif, vmac): 5.196 +def make_vif(dom, vif, vmac, recreate=0): 5.197 """Create a virtual network device for a domain. 5.198 5.199 5.200 @returns Deferred 5.201 """ 5.202 - xend.netif_create(dom) 5.203 - d = xend.netif_dev_create(dom, vif, vmac) 5.204 + xend.netif_create(dom, recreate=recreate) 5.205 + d = xend.netif_dev_create(dom, vif, vmac, recreate=recreate) 5.206 return d 5.207 5.208 def vif_up(iplist): 5.209 @@ -338,49 +184,6 @@ def vif_up(iplist): 5.210 finally: 5.211 if not nlb: set_ip_nonlocal_bind(0) 5.212 5.213 -def xen_domain_create(config, ostype, name, memory, kernel, ramdisk, cmdline, vifs_n): 5.214 - """Create a domain. Builds the image but does not configure it. 5.215 - 5.216 - config configuration 5.217 - ostype OS type 5.218 - name domain name 5.219 - memory domain memory (MB) 5.220 - kernel kernel image 5.221 - ramdisk kernel ramdisk 5.222 - cmdline kernel commandline 5.223 - vifs_n number of network interfaces 5.224 - returns vm 5.225 - """ 5.226 - flags = 0 5.227 - if not os.path.isfile(kernel): 5.228 - raise VmError('Kernel image does not exist: %s' % kernel) 5.229 - if ramdisk and not os.path.isfile(ramdisk): 5.230 - raise VMError('Kernel ramdisk does not exist: %s' % ramdisk) 5.231 - 5.232 - cpu = int(sxp.child_value(config, 'cpu', '-1')) 5.233 - print 'xen_domain_create> create ', memory, name, cpu 5.234 - dom = xc.domain_create(mem_kb= memory * 1024, name= name, cpu= cpu) 5.235 - if dom <= 0: 5.236 - raise VmError('Creating domain failed: name=%s memory=%d kernel=%s' 5.237 - % (name, memory, kernel)) 5.238 - console = xendConsole.console_create(dom) 5.239 - buildfn = getattr(xc, '%s_build' % ostype) 5.240 - 5.241 - print 'xen_domain_create> build ', ostype, dom, kernel, cmdline, ramdisk 5.242 - if len(cmdline) >= 256: 5.243 - print 'Warning: kernel cmdline too long' 5.244 - err = buildfn(dom = dom, 5.245 - image = kernel, 5.246 - control_evtchn = console.port2, 5.247 - cmdline = cmdline, 5.248 - ramdisk = ramdisk, 5.249 - flags = flags) 5.250 - if err != 0: 5.251 - raise VmError('Building domain failed: type=%s dom=%d err=%d' 5.252 - % (ostype, dom, err)) 5.253 - vm = XendDomainInfo(config, dom, name, memory, kernel, console) 5.254 - return vm 5.255 - 5.256 config_handlers = {} 5.257 5.258 def add_config_handler(name, h): 5.259 @@ -450,34 +253,27 @@ def vm_create(config): 5.260 returns Deferred 5.261 raises VmError for invalid configuration 5.262 """ 5.263 - # todo - add support for scheduling params? 5.264 print 'vm_create>' 5.265 - vm = None 5.266 - try: 5.267 - name = sxp.child_value(config, 'name') 5.268 - memory = int(sxp.child_value(config, 'memory', '128')) 5.269 - image = sxp.child_value(config, 'image') 5.270 - 5.271 - image_name = sxp.name(image) 5.272 - image_handler = get_image_handler(image_name) 5.273 - if image_handler is None: 5.274 - raise VmError('unknown image type: ' + image_name) 5.275 - vm = image_handler(config, name, memory, image) 5.276 - deferred = vm_configure(vm, config) 5.277 - except StandardError, ex: 5.278 - # Catch errors, cleanup and re-raise. 5.279 - if vm: 5.280 - vm.destroy() 5.281 - raise 5.282 - def cbok(x): 5.283 - print 'vm_create> cbok', x 5.284 - return x 5.285 - deferred.addCallback(cbok) 5.286 - print 'vm_create<' 5.287 - return deferred 5.288 + vm = XendDomainInfo() 5.289 + return vm.construct(config) 5.290 + 5.291 +def vm_recreate(config, info): 5.292 + """Create the VM object for an existing domain. 5.293 + """ 5.294 + vm = XendDomainInfo() 5.295 + vm.recreate = 1 5.296 + vm.setdom(info['dom']) 5.297 + vm.name = info['name'] 5.298 + vm.memory = info['mem_kb']/1024 5.299 + if config: 5.300 + d = vm.construct(config) 5.301 + else: 5.302 + d = defer.Deferred() 5.303 + d.callback(vm) 5.304 + return d 5.305 5.306 def vm_restore(src, config, progress=0): 5.307 - """Restore a VM. 5.308 + """Restore a VM from a disk image. 5.309 5.310 src saved state to restore 5.311 config configuration 5.312 @@ -485,11 +281,14 @@ def vm_restore(src, config, progress=0): 5.313 returns deferred 5.314 raises VmError for invalid configuration 5.315 """ 5.316 + vm = XendDomainInfo() 5.317 + vm.config = config 5.318 ostype = "linux" #todo set from config 5.319 restorefn = getattr(xc, "%s_restore" % ostype) 5.320 dom = restorefn(state_file=src, progress=progress) 5.321 - if dom < 0: return dom 5.322 - deferred = dom_configure(dom, config) 5.323 + if dom < 0: 5.324 + raise VMError('restore failed') 5.325 + deferred = vm.dom_configure(dom) 5.326 def vifs_cb(val, vm): 5.327 vif_up(vm.ipaddrs) 5.328 deferred.addCallback(vifs_cb, vm) 5.329 @@ -501,115 +300,25 @@ def dom_get(dom): 5.330 return domlist[0] 5.331 return None 5.332 5.333 -def dom_configure(dom, config): 5.334 - """Configure a domain. 5.335 - 5.336 - dom domain id 5.337 - config configuration 5.338 - returns deferred 5.339 - """ 5.340 - d = dom_get(dom) 5.341 - if not d: 5.342 - raise VMError("Domain not found: %d" % dom) 5.343 - try: 5.344 - name = d['name'] 5.345 - memory = d['memory']/1024 5.346 - image = None 5.347 - vm = VM(config, dom, name, memory, image) 5.348 - deferred = vm_configure(vm, config) 5.349 - except StandardError, ex: 5.350 - if vm: 5.351 - vm.destroy() 5.352 - raise 5.353 - return deferred 5.354 5.355 def append_deferred(dlist, v): 5.356 if isinstance(v, defer.Deferred): 5.357 dlist.append(v) 5.358 5.359 -def vm_create_devices(vm, config): 5.360 - """Create the devices for a vm. 5.361 - 5.362 - vm virtual machine 5.363 - config configuration 5.364 - 5.365 - returns Deferred 5.366 - raises VmError for invalid devices 5.367 - """ 5.368 - print '>vm_create_devices' 5.369 - dlist = [] 5.370 - devices = sxp.children(config, 'device') 5.371 - index = {} 5.372 - for d in devices: 5.373 - dev = sxp.child0(d) 5.374 - if dev is None: 5.375 - raise VmError('invalid device') 5.376 - dev_name = sxp.name(dev) 5.377 - dev_index = index.get(dev_name, 0) 5.378 - dev_handler = get_device_handler(dev_name) 5.379 - if dev_handler is None: 5.380 - raise VmError('unknown device type: ' + dev_name) 5.381 - v = dev_handler(vm, dev, dev_index) 5.382 - append_deferred(dlist, v) 5.383 - index[dev_name] = dev_index + 1 5.384 - deferred = defer.DeferredList(dlist, fireOnOneErrback=1) 5.385 - print '<vm_create_devices' 5.386 - return deferred 5.387 - 5.388 -def config_controllers(vm, config): 5.389 - for c in sxp.children(config, 'controller'): 5.390 - name = sxp.name(c) 5.391 - if name == 'block': 5.392 - vm.block_controller = 1 5.393 - xend.blkif_set_control_domain(vm.dom) 5.394 - elif name == 'net': 5.395 - vm.net_controller = 1 5.396 - xend.netif_set_control_domain(vm.dom) 5.397 - else: 5.398 - raise VmError('invalid controller type:' + str(name)) 5.399 - 5.400 -def vm_configure(vm, config): 5.401 - """Configure a vm. 5.402 - 5.403 - vm virtual machine 5.404 - config configuration 5.405 - 5.406 - returns Deferred - calls callback with vm 5.407 - """ 5.408 - config_controllers(vm, config) 5.409 - if vm.block_controller: 5.410 - d = defer.Deferred() 5.411 - d.callback(1) 5.412 - else: 5.413 - d = xend.blkif_create(vm.dom) 5.414 - d.addCallback(_vm_configure1, vm, config) 5.415 - return d 5.416 - 5.417 -def _vm_configure1(val, vm, config): 5.418 - d = vm_create_devices(vm, config) 5.419 +def _vm_configure1(val, vm): 5.420 + d = vm.create_devices() 5.421 print '_vm_configure1> made devices...' 5.422 def cbok(x): 5.423 print '_vm_configure1> cbok', x 5.424 return x 5.425 d.addCallback(cbok) 5.426 - d.addCallback(_vm_configure2, vm, config) 5.427 + d.addCallback(_vm_configure2, vm) 5.428 print '_vm_configure1<' 5.429 return d 5.430 5.431 -def _vm_configure2(val, vm, config): 5.432 +def _vm_configure2(val, vm): 5.433 print '>callback _vm_configure2...' 5.434 - dlist = [] 5.435 - index = {} 5.436 - for field in sxp.children(config): 5.437 - field_name = sxp.name(field) 5.438 - field_index = index.get(field_name, 0) 5.439 - field_handler = get_config_handler(field_name) 5.440 - # Ignore unknown fields. Warn? 5.441 - if field_handler: 5.442 - v = field_handler(vm, config, field, field_index) 5.443 - append_deferred(dlist, v) 5.444 - index[field_name] = field_index + 1 5.445 - d = defer.DeferredList(dlist, fireOnOneErrback=1) 5.446 + d = vm.configure_fields() 5.447 def cbok(results): 5.448 print '_vm_configure2> cbok', results 5.449 return vm 5.450 @@ -622,22 +331,369 @@ def _vm_configure2(val, vm, config): 5.451 print '<_vm_configure2' 5.452 return d 5.453 5.454 -def config_devices(config, name): 5.455 - """Get a list of the 'device' nodes of a given type from a config. 5.456 +class XendDomainInfo: 5.457 + """Virtual machine object.""" 5.458 + 5.459 + def __init__(self): 5.460 + self.recreate = 0 5.461 + self.config = None 5.462 + self.id = None 5.463 + self.dom = None 5.464 + self.name = None 5.465 + self.memory = None 5.466 + self.image = None 5.467 + self.ramdisk = None 5.468 + self.cmdline = None 5.469 + self.console = None 5.470 + self.devices = {} 5.471 + self.configs = [] 5.472 + self.info = None 5.473 + self.ipaddrs = [] 5.474 + self.blkif_backend = 0 5.475 + self.netif_backend = 0 5.476 + #todo: state: running, suspended 5.477 + self.state = 'running' 5.478 + #todo: set to migrate info if migrating 5.479 + self.migrate = None 5.480 + 5.481 + def setdom(self, dom): 5.482 + self.dom = int(dom) 5.483 + self.id = str(dom) 5.484 + 5.485 + def update(self, info): 5.486 + """Update with info from xc.domain_getinfo(). 5.487 + """ 5.488 + self.info = info 5.489 + 5.490 + def __str__(self): 5.491 + s = "domain" 5.492 + s += " id=" + self.id 5.493 + s += " name=" + self.name 5.494 + s += " memory=" + str(self.memory) 5.495 + if self.console: 5.496 + s += " console=" + self.console.id 5.497 + if self.image: 5.498 + s += " image=" + self.image 5.499 + s += "" 5.500 + return s 5.501 + 5.502 + __repr__ = __str__ 5.503 + 5.504 + def sxpr(self): 5.505 + sxpr = ['domain', 5.506 + ['id', self.id], 5.507 + ['name', self.name], 5.508 + ['memory', self.memory] ] 5.509 + if self.info: 5.510 + run = (self.info['running'] and 'r') or '-' 5.511 + block = (self.info['blocked'] and 'b') or '-' 5.512 + stop = (self.info['paused'] and 'p') or '-' 5.513 + susp = (self.info['shutdown'] and 's') or '-' 5.514 + crash = (self.info['crashed'] and 'c') or '-' 5.515 + state = run + block + stop + susp + crash 5.516 + sxpr.append(['state', state]) 5.517 + if self.info['shutdown']: 5.518 + reasons = ["poweroff", "reboot", "suspend"] 5.519 + reason = reasons[self.info['shutdown_reason']] 5.520 + sxpr.append(['shutdown_reason', reason]) 5.521 + sxpr.append(['cpu', self.info['cpu']]) 5.522 + sxpr.append(['cpu_time', self.info['cpu_time']/1e9]) 5.523 + if self.console: 5.524 + sxpr.append(self.console.sxpr()) 5.525 + if self.config: 5.526 + sxpr.append(['config', self.config]) 5.527 + return sxpr 5.528 + 5.529 + def construct(self, config): 5.530 + # todo - add support for scheduling params? 5.531 + self.config = config 5.532 + try: 5.533 + self.name = sxp.child_value(config, 'name') 5.534 + self.memory = int(sxp.child_value(config, 'memory', '128')) 5.535 + self.configure_backends() 5.536 + image = sxp.child_value(config, 'image') 5.537 + image_name = sxp.name(image) 5.538 + image_handler = get_image_handler(image_name) 5.539 + if image_handler is None: 5.540 + raise VmError('unknown image type: ' + image_name) 5.541 + image_handler(self, image) 5.542 + deferred = self.configure() 5.543 + except StandardError, ex: 5.544 + # Catch errors, cleanup and re-raise. 5.545 + self.destroy() 5.546 + raise 5.547 + def cbok(x): 5.548 + print 'vm_create> cbok', x 5.549 + return x 5.550 + deferred.addCallback(cbok) 5.551 + print 'vm_create<' 5.552 + return deferred 5.553 + 5.554 + def config_devices(self, name): 5.555 + """Get a list of the 'device' nodes of a given type from the config. 5.556 + 5.557 + name device type 5.558 + return list of device configs 5.559 + """ 5.560 + devices = [] 5.561 + for d in sxp.children(self.config, 'device'): 5.562 + dev = sxp.child0(d) 5.563 + if dev is None: continue 5.564 + if name == sxp.name(dev): 5.565 + devices.append(dev) 5.566 + return devices 5.567 + 5.568 + def add_device(self, type, dev): 5.569 + """Add a device to a virtual machine. 5.570 + 5.571 + dev device to add 5.572 + """ 5.573 + dl = self.devices.get(type, []) 5.574 + dl.append(dev) 5.575 + self.devices[type] = dl 5.576 + 5.577 + def get_devices(self, type): 5.578 + val = self.devices.get(type, []) 5.579 + return val 5.580 + 5.581 + def get_device_by_id(self, type, id): 5.582 + """Get the device with the given id. 5.583 + 5.584 + id device id 5.585 + 5.586 + returns device or None 5.587 + """ 5.588 + dl = self.get_devices(type) 5.589 + for d in dl: 5.590 + if d.getprop('id') == id: 5.591 + return d 5.592 + return None 5.593 + 5.594 + def get_device_by_index(self, type, idx): 5.595 + """Get the device with the given index. 5.596 + 5.597 + idx device index 5.598 + 5.599 + returns device or None 5.600 + """ 5.601 + dl = self.get_devices(type) 5.602 + if 0 <= idx < len(dl): 5.603 + return dl[idx] 5.604 + else: 5.605 + return None 5.606 + 5.607 + def add_config(self, val): 5.608 + """Add configuration data to a virtual machine. 5.609 + 5.610 + val data to add 5.611 + """ 5.612 + self.configs.append(val) 5.613 + 5.614 + def destroy(self): 5.615 + if self.dom <= 0: 5.616 + return 0 5.617 + return xc.domain_destroy(dom=self.dom) 5.618 + 5.619 + def died(self): 5.620 + print 'died>', self.dom 5.621 + self.release_devices() 5.622 + 5.623 + def release_devices(self): 5.624 + print 'release_devices>', self.dom 5.625 + self.release_vifs() 5.626 + self.release_vbds() 5.627 + self.devices = {} 5.628 + 5.629 + def release_vifs(self): 5.630 + print 'release_vifs>', self.dom 5.631 + if self.dom is None: return 5.632 + ctrl = xend.netif_get(self.dom) 5.633 + if ctrl: 5.634 + ctrl.destroy() 5.635 5.636 - config configuration 5.637 - name device type 5.638 - return list of device configs 5.639 - """ 5.640 - devices = [] 5.641 - for d in sxp.children(config, 'device'): 5.642 - dev = sxp.child0(d) 5.643 - if dev is None: continue 5.644 - if name == sxp.name(dev): 5.645 - devices.append(dev) 5.646 - return devices 5.647 - 5.648 -def vm_image_linux(config, name, memory, image): 5.649 + def release_vbds(self): 5.650 + print 'release_vbds>', self.dom 5.651 + if self.dom is None: return 5.652 + ctrl = xend.blkif_get(self.dom) 5.653 + if ctrl: 5.654 + ctrl.destroy() 5.655 + 5.656 + def show(self): 5.657 + """Print virtual machine info. 5.658 + """ 5.659 + print "[VM dom=%d name=%s memory=%d" % (self.dom, self.name, self.memory) 5.660 + print "image:" 5.661 + sxp.show(self.image) 5.662 + print 5.663 + for dl in self.devices: 5.664 + for dev in dl: 5.665 + print "device:" 5.666 + sxp.show(dev) 5.667 + print 5.668 + for val in self.configs: 5.669 + print "config:" 5.670 + sxp.show(val) 5.671 + print 5.672 + print "]" 5.673 + 5.674 + def init_domain(self): 5.675 + """Initialize the domain memory. 5.676 + """ 5.677 + if self.recreate: return 5.678 + memory = self.memory 5.679 + name = self.name 5.680 + cpu = int(sxp.child_value(self.config, 'cpu', '-1')) 5.681 + print 'init_domain>', memory, name, cpu 5.682 + dom = xc.domain_create(mem_kb= memory * 1024, name= name, cpu= cpu) 5.683 + if dom <= 0: 5.684 + raise VmError('Creating domain failed: name=%s memory=%d' 5.685 + % (name, memory)) 5.686 + self.setdom(dom) 5.687 + 5.688 + def build_domain(self, ostype, kernel, ramdisk, cmdline, vifs_n): 5.689 + """Build the domain boot image. 5.690 + """ 5.691 + if self.recreate: return 5.692 + if len(cmdline) >= 256: 5.693 + print 'Warning: kernel cmdline too long' 5.694 + dom = self.dom 5.695 + buildfn = getattr(xc, '%s_build' % ostype) 5.696 + print 'build_domain>', ostype, dom, kernel, cmdline, ramdisk 5.697 + flags = 0 5.698 + if self.netif_backend: flags |= SIF_NET_BE_DOMAIN 5.699 + if self.blkif_backend: flags |= SIF_BLK_BE_DOMAIN 5.700 + err = buildfn(dom = dom, 5.701 + image = kernel, 5.702 + control_evtchn = self.console.port2, 5.703 + cmdline = cmdline, 5.704 + ramdisk = ramdisk, 5.705 + flags = flags) 5.706 + if err != 0: 5.707 + raise VmError('Building domain failed: type=%s dom=%d err=%d' 5.708 + % (ostype, dom, err)) 5.709 + 5.710 + def create_domain(self, ostype, kernel, ramdisk, cmdline, vifs_n): 5.711 + """Create a domain. Builds the image but does not configure it. 5.712 + 5.713 + ostype OS type 5.714 + kernel kernel image 5.715 + ramdisk kernel ramdisk 5.716 + cmdline kernel commandline 5.717 + vifs_n number of network interfaces 5.718 + """ 5.719 + print 'create_domain>', ostype, kernel 5.720 + if not self.recreate: 5.721 + if not os.path.isfile(kernel): 5.722 + raise VmError('Kernel image does not exist: %s' % kernel) 5.723 + if ramdisk and not os.path.isfile(ramdisk): 5.724 + raise VMError('Kernel ramdisk does not exist: %s' % ramdisk) 5.725 + print 'create-domain> init_domain...' 5.726 + self.init_domain() 5.727 + print 'create_domain>', 'dom=', self.dom 5.728 + self.console = xendConsole.console_create(self.dom) 5.729 + self.build_domain(ostype, kernel, ramdisk, cmdline, vifs_n) 5.730 + self.image = kernel 5.731 + self.ramdisk = ramdisk 5.732 + self.cmdline = cmdline 5.733 + 5.734 + def create_devices(self): 5.735 + """Create the devices for a vm. 5.736 + 5.737 + returns Deferred 5.738 + raises VmError for invalid devices 5.739 + """ 5.740 + print '>create_devices' 5.741 + dlist = [] 5.742 + devices = sxp.children(self.config, 'device') 5.743 + index = {} 5.744 + for d in devices: 5.745 + dev = sxp.child0(d) 5.746 + if dev is None: 5.747 + raise VmError('invalid device') 5.748 + dev_name = sxp.name(dev) 5.749 + dev_index = index.get(dev_name, 0) 5.750 + dev_handler = get_device_handler(dev_name) 5.751 + if dev_handler is None: 5.752 + raise VmError('unknown device type: ' + dev_name) 5.753 + v = dev_handler(self, dev, dev_index) 5.754 + append_deferred(dlist, v) 5.755 + index[dev_name] = dev_index + 1 5.756 + deferred = defer.DeferredList(dlist, fireOnOneErrback=1) 5.757 + print '<create_devices' 5.758 + return deferred 5.759 + 5.760 + def configure_backends(self): 5.761 + """Set configuration flags if the vm is a backend for netif of blkif. 5.762 + """ 5.763 + for c in sxp.children(self.config, 'backend'): 5.764 + name = sxp.name(c) 5.765 + if name == 'blkif': 5.766 + self.blkif_backend = 1 5.767 + elif name == 'netif': 5.768 + self.netif_backend = 1 5.769 + else: 5.770 + raise VmError('invalid backend type:' + str(name)) 5.771 + 5.772 + def create_backends(self): 5.773 + """Setup the netif and blkif backends. 5.774 + """ 5.775 + if self.blkif_backend: 5.776 + xend.blkif_set_control_domain(self.dom, recreate=self.recreate) 5.777 + if self.netif_backend: 5.778 + xend.netif_set_control_domain(self.dom, recreate=self.recreate) 5.779 + 5.780 + def configure(self): 5.781 + """Configure a vm. 5.782 + 5.783 + vm virtual machine 5.784 + config configuration 5.785 + 5.786 + returns Deferred - calls callback with vm 5.787 + """ 5.788 + if self.blkif_backend: 5.789 + d = defer.Deferred() 5.790 + d.callback(1) 5.791 + else: 5.792 + d = xend.blkif_create(self.dom, recreate=self.recreate) 5.793 + d.addCallback(_vm_configure1, self) 5.794 + return d 5.795 + 5.796 + def dom_configure(self, dom): 5.797 + """Configure a domain. 5.798 + 5.799 + dom domain id 5.800 + returns deferred 5.801 + """ 5.802 + d = dom_get(dom) 5.803 + if not d: 5.804 + raise VMError("Domain not found: %d" % dom) 5.805 + try: 5.806 + self.setdom(dom) 5.807 + self.name = d['name'] 5.808 + self.memory = d['memory']/1024 5.809 + deferred = self.configure() 5.810 + except StandardError, ex: 5.811 + self.destroy() 5.812 + raise 5.813 + return deferred 5.814 + 5.815 + def configure_fields(self): 5.816 + dlist = [] 5.817 + index = {} 5.818 + for field in sxp.children(self.config): 5.819 + field_name = sxp.name(field) 5.820 + field_index = index.get(field_name, 0) 5.821 + field_handler = get_config_handler(field_name) 5.822 + # Ignore unknown fields. Warn? 5.823 + if field_handler: 5.824 + v = field_handler(self, self.config, field, field_index) 5.825 + append_deferred(dlist, v) 5.826 + index[field_name] = field_index + 1 5.827 + d = defer.DeferredList(dlist, fireOnOneErrback=1) 5.828 + return d 5.829 + 5.830 + 5.831 +def vm_image_linux(vm, image): 5.832 """Create a VM for a linux image. 5.833 5.834 name vm name 5.835 @@ -658,12 +714,11 @@ def vm_image_linux(config, name, memory, 5.836 if args: 5.837 cmdline += " " + args 5.838 ramdisk = sxp.child_value(image, "ramdisk", '') 5.839 - vifs = config_devices(config, "vif") 5.840 - vm = xen_domain_create(config, "linux", name, memory, kernel, 5.841 - ramdisk, cmdline, len(vifs)) 5.842 + vifs = vm.config_devices("vif") 5.843 + vm.create_domain("linux", kernel, ramdisk, cmdline, len(vifs)) 5.844 return vm 5.845 5.846 -def vm_image_netbsd(config, name, memory, image): 5.847 +def vm_image_netbsd(vm, image): 5.848 """Create a VM for a bsd image. 5.849 5.850 name vm name 5.851 @@ -685,9 +740,8 @@ def vm_image_netbsd(config, name, memory 5.852 if args: 5.853 cmdline += " " + args 5.854 ramdisk = sxp.child_value(image, "ramdisk") 5.855 - vifs = config_devices(config, "vif") 5.856 - vm = xen_domain_create(config, "netbsd", name, memory, kernel, 5.857 - ramdisk, cmdline, len(vifs)) 5.858 + vifs = vm.config_devices("vif") 5.859 + vm.create_domain("netbsd", kernel, ramdisk, cmdline, len(vifs)) 5.860 return vm 5.861 5.862 5.863 @@ -698,18 +752,18 @@ def vm_dev_vif(vm, val, index): 5.864 val vif config 5.865 index vif index 5.866 """ 5.867 - if vm.net_controller: 5.868 - raise VmError('vif: vif in control domain') 5.869 + if vm.netif_backend: 5.870 + raise VmError('vif: vif in netif backend domain') 5.871 vif = index #todo 5.872 vmac = sxp.child_value(val, "mac") 5.873 - defer = make_vif(vm.dom, vif, vmac) 5.874 + defer = make_vif(vm.dom, vif, vmac, vm.recreate) 5.875 def fn(id): 5.876 + dev = xend.netif_dev(vm.dom, vif) 5.877 + devid = sxp.attribute(val, 'id') 5.878 + if devid: 5.879 + dev.setprop('id', devid) 5.880 bridge = sxp.child_value(val, "bridge") 5.881 - bridge = XendBridge.vif_bridge_add(vm.dom, vif, bridge) 5.882 - dev = ['vif', ['vif', vif], ['bridge', bridge] ] 5.883 - netdev = xend.netif_dev(vm.dom, vif) 5.884 - if netdev and netdev.mac: 5.885 - dev += [ 'mac', netdev.mac ] 5.886 + dev.bridge_add(bridge) 5.887 vm.add_device('vif', dev) 5.888 print 'vm_dev_vif> created', dev 5.889 return id 5.890 @@ -723,8 +777,9 @@ def vm_dev_vbd(vm, val, index): 5.891 val vbd config 5.892 index vbd index 5.893 """ 5.894 - if vm.block_controller: 5.895 - raise VmError('vbd: vbd in control domain') 5.896 + if vm.blkif_backend: 5.897 + raise VmError('vbd: vbd in blkif backend domain') 5.898 + vdev = index 5.899 uname = sxp.child_value(val, 'uname') 5.900 if not uname: 5.901 raise VMError('vbd: Missing uname') 5.902 @@ -732,9 +787,10 @@ def vm_dev_vbd(vm, val, index): 5.903 if not dev: 5.904 raise VMError('vbd: Missing dev') 5.905 mode = sxp.child_value(val, 'mode', 'r') 5.906 - defer = make_disk(vm.dom, uname, dev, mode) 5.907 + defer = make_disk(vm.dom, uname, dev, mode, vm.recreate) 5.908 def fn(vbd): 5.909 - vm.add_device('vbd', val) 5.910 + dev = xend.blkif_dev(vm.dom, vdev) 5.911 + vm.add_device('vbd', dev) 5.912 return vbd 5.913 defer.addCallback(fn) 5.914 return defer 5.915 @@ -765,7 +821,8 @@ def vm_dev_pci(vm, val, index): 5.916 func = parse_pci(func) 5.917 except: 5.918 raise VMError('pci: invalid parameter') 5.919 - rc = xc.physdev_pci_access_modify(dom=vm.dom, bus=bus, dev=dev, func=func, enable=1) 5.920 + rc = xc.physdev_pci_access_modify(dom=vm.dom, bus=bus, dev=dev, 5.921 + func=func, enable=1) 5.922 if rc < 0: 5.923 #todo non-fatal 5.924 raise VMError('pci: Failed to configure device: bus=%s dev=%s func=%s' % 5.925 @@ -833,13 +890,11 @@ def vm_field_vnet(vm, config, val, index 5.926 if id is None: 5.927 raise VmError('vnet: missing vif id') 5.928 dev = vm.get_device_by_id('vif', id) 5.929 - if not sxp.elementp(dev, 'vif'): 5.930 - raise VmError('vnet: invalid vif id %s' % id) 5.931 - vnet = sxp.child_value(v, 'vnet', 1) 5.932 - mac = sxp.child_value(dev, 'mac') 5.933 - vif = sxp.child_value(dev, 'vif') 5.934 - vnet_bridge(vnet, mac, vm.dom, 0) 5.935 - vm.add_config([ 'vif.vnet', ['id', id], ['vnet', vnet], ['mac', mac]]) 5.936 + #vnet = sxp.child_value(v, 'vnet', 1) 5.937 + #mac = sxp.child_value(dev, 'mac') 5.938 + #vif = sxp.child_value(dev, 'vif') 5.939 + #vnet_bridge(vnet, mac, vm.dom, 0) 5.940 + #vm.add_config([ 'vif.vnet', ['id', id], ['vnet', vnet], ['mac', mac]]) 5.941 5.942 # Register image handlers for linux and bsd. 5.943 add_image_handler('linux', vm_image_linux)
6.1 --- a/tools/xenmgr/lib/server/SrvConsoleServer.py Thu Jun 24 10:28:58 2004 +0000 6.2 +++ b/tools/xenmgr/lib/server/SrvConsoleServer.py Thu Jun 24 12:00:50 2004 +0000 6.3 @@ -584,28 +584,31 @@ class Daemon: 6.4 reactor.diconnectAll() 6.5 sys.exit(0) 6.6 6.7 - def blkif_set_control_domain(self, dom): 6.8 + def blkif_set_control_domain(self, dom, recreate=0): 6.9 """Set the block device backend control domain. 6.10 """ 6.11 - return self.blkifCF.setControlDomain(dom) 6.12 + return self.blkifCF.setControlDomain(dom, recreate=recreate) 6.13 6.14 def blkif_get_control_domain(self, dom): 6.15 """Get the block device backend control domain. 6.16 """ 6.17 return self.blkifCF.getControlDomain() 6.18 6.19 - def blkif_create(self, dom): 6.20 + def blkif_create(self, dom, recreate=0): 6.21 """Create a block device interface controller. 6.22 6.23 Returns Deferred 6.24 """ 6.25 - d = self.blkifCF.createInstance(dom) 6.26 + d = self.blkifCF.createInstance(dom, recreate=recreate) 6.27 return d 6.28 6.29 + def blkif_get(self, dom): 6.30 + return self.blkifCF.getInstanceByDom(dom) 6.31 + 6.32 def blkif_dev(self, dom, vdev): 6.33 return self.blkifCF.getDomainDevice(dom, vdev) 6.34 6.35 - def blkif_dev_create(self, dom, vdev, mode, segment): 6.36 + def blkif_dev_create(self, dom, vdev, mode, segment, recreate=0): 6.37 """Create a block device. 6.38 6.39 Returns Deferred 6.40 @@ -614,26 +617,29 @@ class Daemon: 6.41 if not ctrl: 6.42 raise ValueError('No blkif controller: %d' % dom) 6.43 print 'blkif_dev_create>', dom, vdev, mode, segment 6.44 - d = ctrl.attach_device(vdev, mode, segment) 6.45 + d = ctrl.attachDevice(vdev, mode, segment, recreate=recreate) 6.46 return d 6.47 6.48 - def netif_set_control_domain(self, dom): 6.49 + def netif_set_control_domain(self, dom, recreate=0): 6.50 """Set the network interface backend control domain. 6.51 """ 6.52 - return self.netifCF.setControlDomain(dom) 6.53 + return self.netifCF.setControlDomain(dom, recreate=recreate) 6.54 6.55 def netif_get_control_domain(self, dom): 6.56 """Get the network interface backend control domain. 6.57 """ 6.58 return self.netifCF.getControlDomain() 6.59 6.60 - def netif_create(self, dom): 6.61 + def netif_create(self, dom, recreate=0): 6.62 """Create a network interface controller. 6.63 6.64 """ 6.65 - return self.netifCF.createInstance(dom) 6.66 + return self.netifCF.createInstance(dom, recreate=recreate) 6.67 6.68 - def netif_dev_create(self, dom, vif, vmac): 6.69 + def netif_get(self, dom): 6.70 + return self.netifCF.getInstanceByDom(dom) 6.71 + 6.72 + def netif_dev_create(self, dom, vif, vmac, recreate=0): 6.73 """Create a network device. 6.74 6.75 todo 6.76 @@ -641,7 +647,7 @@ class Daemon: 6.77 ctrl = self.netifCF.getInstanceByDom(dom) 6.78 if not ctrl: 6.79 raise ValueError('No netif controller: %d' % dom) 6.80 - d = ctrl.attach_device(vif, vmac) 6.81 + d = ctrl.attachDevice(vif, vmac, recreate=recreate) 6.82 return d 6.83 6.84 def netif_dev(self, dom, vif):
7.1 --- a/tools/xenmgr/lib/server/SrvDomain.py Thu Jun 24 10:28:58 2004 +0000 7.2 +++ b/tools/xenmgr/lib/server/SrvDomain.py Thu Jun 24 12:00:50 2004 +0000 7.3 @@ -32,8 +32,8 @@ class SrvDomain(SrvDir): 7.4 req.setHeader("Location", "%s/.." % req.prePathURL()) 7.5 return val 7.6 7.7 - def op_halt(self, op, req): 7.8 - val = self.xd.domain_halt(self.dom.id) 7.9 + def op_destroy(self, op, req): 7.10 + val = self.xd.domain_destroy(self.dom.id) 7.11 req.setHeader("Location", "%s/.." % req.prePathURL()) 7.12 return val 7.13 7.14 @@ -196,7 +196,7 @@ class SrvDomain(SrvDir): 7.15 req.write('<input type="submit" name="op" value="unpause">') 7.16 req.write('<input type="submit" name="op" value="pause">') 7.17 req.write('<input type="submit" name="op" value="shutdown">') 7.18 - req.write('<input type="submit" name="op" value="halt">') 7.19 + req.write('<input type="submit" name="op" value="destroy">') 7.20 req.write('<br><input type="submit" name="op" value="migrate">') 7.21 req.write('To: <input type="text" name="destination">') 7.22 req.write('</form>')
8.1 --- a/tools/xenmgr/lib/server/blkif.py Thu Jun 24 10:28:58 2004 +0000 8.2 +++ b/tools/xenmgr/lib/server/blkif.py Thu Jun 24 12:00:50 2004 +0000 8.3 @@ -1,3 +1,5 @@ 8.4 +from twisted.internet import defer 8.5 + 8.6 import channel 8.7 import controller 8.8 from messages import * 8.9 @@ -22,7 +24,7 @@ class BlkifControllerFactory(controller. 8.10 self.attached = 1 8.11 self.registerChannel() 8.12 8.13 - def createInstance(self, dom): 8.14 + def createInstance(self, dom, recreate=0): 8.15 d = self.addDeferred() 8.16 blkif = self.getInstanceByDom(dom) 8.17 if blkif: 8.18 @@ -30,7 +32,10 @@ class BlkifControllerFactory(controller. 8.19 else: 8.20 blkif = BlkifController(self, dom) 8.21 self.addInstance(blkif) 8.22 - blkif.send_be_create() 8.23 + if recreate: 8.24 + self.callDeferred(blkif) 8.25 + else: 8.26 + blkif.send_be_create() 8.27 return d 8.28 8.29 def getDomainDevices(self, dom): 8.30 @@ -41,10 +46,11 @@ class BlkifControllerFactory(controller. 8.31 blkif = self.getInstanceByDom(dom) 8.32 return (blkif and blkif.getDevice(vdev)) or None 8.33 8.34 - def setControlDomain(self, dom): 8.35 + def setControlDomain(self, dom, recreate=0): 8.36 if self.dom == dom: return 8.37 self.deregisterChannel() 8.38 - self.attached = 0 8.39 + if not recreate: 8.40 + self.attached = 0 8.41 self.dom = dom 8.42 self.registerChannel() 8.43 # 8.44 @@ -55,6 +61,28 @@ class BlkifControllerFactory(controller. 8.45 def getControlDomain(self): 8.46 return self.dom 8.47 8.48 + def reattachDevice(self, dom, vdev): 8.49 + blkif = self.getInstanceByDom(dom) 8.50 + if blkif: 8.51 + blkif.reattachDevice(vdev) 8.52 + self.attached = self.devicesAttached() 8.53 + if self.attached: 8.54 + self.reattached() 8.55 + 8.56 + def devicesAttached(self): 8.57 + """Check if all devices are attached. 8.58 + """ 8.59 + attached = 1 8.60 + for blkif in self.getInstances(): 8.61 + if not blkif.attached: 8.62 + attached = 0 8.63 + break 8.64 + return attached 8.65 + 8.66 + def reattached(self): 8.67 + for blkif in self.getInstances(): 8.68 + blkif.reattached() 8.69 + 8.70 def recv_be_create(self, msg, req): 8.71 #print 'recv_be_create>' 8.72 val = unpackMsg('blkif_be_create_t', msg) 8.73 @@ -86,29 +114,7 @@ class BlkifControllerFactory(controller. 8.74 if self.attached: 8.75 self.callDeferred(0) 8.76 else: 8.77 - self.reattach_device(val['domid'], val['vdevice']) 8.78 - 8.79 - def reattach_device(self, dom, vdev): 8.80 - blkif = self.getInstanceByDom(dom) 8.81 - if blkif: 8.82 - blkif.reattach_device(vdev) 8.83 - self.attached = self.devices_attached() 8.84 - if self.attached: 8.85 - self.reattached() 8.86 - 8.87 - def devices_attached(self): 8.88 - """Check if all devices are attached. 8.89 - """ 8.90 - attached = 1 8.91 - for blkif in self.getInstances(): 8.92 - if not blkif.attached: 8.93 - attached = 0 8.94 - break 8.95 - return attached 8.96 - 8.97 - def reattached(self): 8.98 - for blkif in self.getInstances(): 8.99 - blkif.reattached() 8.100 + self.reattachDevice(val['domid'], val['vdevice']) 8.101 8.102 def recv_be_driver_status_changed(self, msg, req): 8.103 val = unpackMsg('blkif_be_driver_status_changed_t', msg) 8.104 @@ -117,11 +123,12 @@ class BlkifControllerFactory(controller. 8.105 for blkif in self.getInstances(): 8.106 blkif.detach() 8.107 8.108 -class BlkDev: 8.109 +class BlkDev(controller.Dev): 8.110 """Info record for a block device. 8.111 """ 8.112 8.113 - def __init__(self, vdev, mode, segment): 8.114 + def __init__(self, ctrl, vdev, mode, segment): 8.115 + controller.Dev.__init__(self, ctrl) 8.116 self.vdev = vdev 8.117 self.mode = mode 8.118 self.device = segment['device'] 8.119 @@ -131,6 +138,14 @@ class BlkDev: 8.120 8.121 def readonly(self): 8.122 return 'w' not in self.mode 8.123 + 8.124 + def sxpr(self): 8.125 + print 'BlkDev>sxpr>', vars(self) 8.126 + val = ['blkif', ['vdev', self.vdev], ['mode', self.mode] ] 8.127 + return val 8.128 + 8.129 + def destroy(self): 8.130 + self.controller.send_be_vbd_destroy(self.vdev) 8.131 8.132 class BlkifController(controller.Controller): 8.133 """Block device interface controller. Handles all block devices 8.134 @@ -154,21 +169,43 @@ class BlkifController(controller.Control 8.135 self.registerChannel() 8.136 #print 'BlkifController<', 'dom=', self.dom, 'idx=', self.idx 8.137 8.138 + def lostChannel(self): 8.139 + print 'BlkifController>lostChannel>', 'dom=', self.dom 8.140 + #self.destroyDevices() 8.141 + controller.Controller.lostChannel(self) 8.142 + 8.143 def getDevices(self): 8.144 return self.devices.values() 8.145 8.146 def getDevice(self, vdev): 8.147 return self.devices.get(vdev) 8.148 8.149 - def attach_device(self, vdev, mode, segment): 8.150 + def addDevice(self, vdev, mode, segment): 8.151 + if vdev in self.devices: return None 8.152 + dev = BlkDev(self, vdev, mode, segment) 8.153 + self.devices[vdev] = dev 8.154 + return dev 8.155 + 8.156 + def attachDevice(self, vdev, mode, segment, recreate=0): 8.157 """Attach a device to the specified interface. 8.158 """ 8.159 #print 'BlkifController>attach_device>', self.dom, vdev, mode, segment 8.160 - if vdev in self.devices: return -1 8.161 - dev = BlkDev(vdev, mode, segment) 8.162 - self.devices[vdev] = dev 8.163 - self.send_be_vbd_create(vdev) 8.164 - return self.factory.addDeferred() 8.165 + dev = self.addDevice(vdev, mode, segment) 8.166 + if not dev: return -1 8.167 + if recreate: 8.168 + d = defer.Deferred() 8.169 + d.callback(self) 8.170 + else: 8.171 + self.send_be_vbd_create(vdev) 8.172 + d = self.factory.addDeferred() 8.173 + return d 8.174 + 8.175 + def destroy(self): 8.176 + self.destroyDevices() 8.177 + 8.178 + def destroyDevices(self): 8.179 + for dev in self.getDevices(): 8.180 + dev.destroy() 8.181 8.182 def detach(self): 8.183 """Detach all devices, when the back-end control domain has changed. 8.184 @@ -178,7 +215,7 @@ class BlkifController(controller.Control 8.185 dev.attached = 0 8.186 self.send_be_vbd_create(vdev) 8.187 8.188 - def reattach_device(self, vdev): 8.189 + def reattachDevice(self, vdev): 8.190 """Reattach a device, when the back-end control domain has changed. 8.191 """ 8.192 dev = self.devices[vdev] 8.193 @@ -254,4 +291,13 @@ class BlkifController(controller.Control 8.194 'extent.sector_start' : dev.start_sector, 8.195 'extent.sector_length' : dev.nr_sectors }) 8.196 self.factory.writeRequest(msg) 8.197 + 8.198 + def send_be_vbd_destroy(self, vdev): 8.199 + dev = self.devices[vdev] 8.200 + msg = packMsg('blkif_be_vbd_destroy_t', 8.201 + { 'domid' : self.dom, 8.202 + 'blkif_handle' : 0, 8.203 + 'vdevice' : dev.vdev }) 8.204 + del self.devices[vdev] 8.205 + self.factory.writeRequest(msg) 8.206
9.1 --- a/tools/xenmgr/lib/server/controller.py Thu Jun 24 10:28:58 2004 +0000 9.2 +++ b/tools/xenmgr/lib/server/controller.py Thu Jun 24 12:00:50 2004 +0000 9.3 @@ -95,7 +95,7 @@ class ControllerFactory(CtrlMsgRcvr): 9.4 if instance.idx in self.instances: 9.5 del self.instances[instance.idx] 9.6 9.7 - def createInstance(self, dom): 9.8 + def createInstance(self, dom, recreate=0): 9.9 raise NotImplementedError() 9.10 9.11 def instanceClosed(self, instance): 9.12 @@ -136,3 +136,30 @@ class Controller(CtrlMsgRcvr): 9.13 9.14 def lostChannel(self): 9.15 self.factory.instanceClosed(self) 9.16 + 9.17 +class Dev: 9.18 + 9.19 + def __init__(self, controller): 9.20 + self.controller = controller 9.21 + self.props = {} 9.22 + 9.23 + def setprop(self, k, v): 9.24 + self.props[k] = v 9.25 + 9.26 + def getprop(self, k, v=None): 9.27 + return self.props.get(k, v) 9.28 + 9.29 + def hasprop(self, k): 9.30 + return k in self.props 9.31 + 9.32 + def delprop(self, k): 9.33 + if k in self.props: 9.34 + del self.props[k] 9.35 + 9.36 + #def __repr__(self): 9.37 + # return str(self.sxpr()) 9.38 + 9.39 + def sxpr(self): 9.40 + raise NotImplementedError() 9.41 + 9.42 +
10.1 --- a/tools/xenmgr/lib/server/messages.py Thu Jun 24 10:28:58 2004 +0000 10.2 +++ b/tools/xenmgr/lib/server/messages.py Thu Jun 24 12:00:50 2004 +0000 10.3 @@ -76,6 +76,9 @@ blkif_formats = { 10.4 'blkif_be_vbd_grow_t': 10.5 (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW), 10.6 10.7 + 'blkif_be_vbd_destroy_t': 10.8 + (CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY), 10.9 + 10.10 'blkif_fe_interface_status_changed_t': 10.11 (CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED), 10.12
11.1 --- a/tools/xenmgr/lib/server/netif.py Thu Jun 24 10:28:58 2004 +0000 11.2 +++ b/tools/xenmgr/lib/server/netif.py Thu Jun 24 12:00:50 2004 +0000 11.3 @@ -1,5 +1,9 @@ 11.4 import random 11.5 11.6 +from twisted.internet import defer 11.7 + 11.8 +from xenmgr import XendBridge 11.9 + 11.10 import channel 11.11 import controller 11.12 from messages import * 11.13 @@ -22,7 +26,7 @@ class NetifControllerFactory(controller. 11.14 self.attached = 1 11.15 self.registerChannel() 11.16 11.17 - def createInstance(self, dom): 11.18 + def createInstance(self, dom, recreate=0): 11.19 """Create or find the network interface controller for a domain. 11.20 """ 11.21 #print 'netif>createInstance> dom=', dom 11.22 @@ -40,12 +44,13 @@ class NetifControllerFactory(controller. 11.23 netif = self.getInstanceByDom(dom) 11.24 return (netif and netif.getDevice(vif)) or None 11.25 11.26 - def setControlDomain(self, dom): 11.27 + def setControlDomain(self, dom, recreate=0): 11.28 """Set the 'back-end' device driver domain. 11.29 """ 11.30 if self.dom == dom: return 11.31 self.deregisterChannel() 11.32 - self.attached = 0 11.33 + if not recreate: 11.34 + self.attached = 0 11.35 self.dom = dom 11.36 self.registerChannel() 11.37 # 11.38 @@ -98,20 +103,38 @@ class NetifControllerFactory(controller. 11.39 ## print "Done notifying guests" 11.40 ## recovery = False 11.41 11.42 -class NetDev: 11.43 +class NetDev(controller.Dev): 11.44 """Info record for a network device. 11.45 """ 11.46 11.47 - def __init__(self, vif, mac): 11.48 + def __init__(self, ctrl, vif, mac): 11.49 + controller.Dev.__init__(self, ctrl) 11.50 self.vif = vif 11.51 self.mac = mac 11.52 self.evtchn = None 11.53 + self.bridge = None 11.54 11.55 def sxpr(self): 11.56 vif = str(self.vif) 11.57 mac = ':'.join(map(lambda x: "%x" % x, self.mac)) 11.58 - return ['netif', ['vif', vif], ['mac', mac]] 11.59 - 11.60 + val = ['netif', ['vif', vif], ['mac', mac]] 11.61 + if self.bridge: 11.62 + val += ['bridge', self.bridge] 11.63 + return val 11.64 + 11.65 + def bridge_add(self, bridge): 11.66 + self.bridge = XendBridge.vif_bridge_add(self.controller.dom, self.vif, bridge) 11.67 + 11.68 + def bridge_rem(self): 11.69 + if not self.bridge: return 11.70 + XendBridge.vif_bridge_rem(self.controller.dom, self.vif, self.bridge) 11.71 + self.bridge = None 11.72 + 11.73 + def destroy(self): 11.74 + self.bridge_rem() 11.75 + self.controller.send_be_destroy(self.vif) 11.76 + 11.77 + 11.78 class NetifController(controller.Controller): 11.79 """Network interface controller. Handles all network devices for a domain. 11.80 """ 11.81 @@ -150,8 +173,7 @@ class NetifController(controller.Control 11.82 11.83 def lostChannel(self): 11.84 print 'NetifController>lostChannel>', 'dom=', self.dom 11.85 - #for vif in self.devices: 11.86 - # self.send_be_destroy(vif) 11.87 + #self.destroyDevices() 11.88 controller.Controller.lostChannel(self) 11.89 11.90 def getDevices(self): 11.91 @@ -167,11 +189,18 @@ class NetifController(controller.Control 11.92 mac = [ int(x, 16) for x in vmac.split(':') ] 11.93 if len(mac) != 6: raise ValueError("invalid mac") 11.94 #print "attach_device>", "vif=", vif, "mac=", mac 11.95 - dev = NetDev(vif, mac) 11.96 + dev = NetDev(self, vif, mac) 11.97 self.devices[vif] = dev 11.98 return dev 11.99 11.100 - def attach_device(self, vif, vmac): 11.101 + def destroy(self): 11.102 + self.destroyDevices() 11.103 + 11.104 + def destroyDevices(self): 11.105 + for dev in self.getDevices(): 11.106 + dev.destroy() 11.107 + 11.108 + def attachDevice(self, vif, vmac, recreate=0): 11.109 """Attach a network device. 11.110 If vmac is None a random mac address is assigned. 11.111 11.112 @@ -179,8 +208,12 @@ class NetifController(controller.Control 11.113 @param vmac mac address (string) 11.114 """ 11.115 self.addDevice(vif, vmac) 11.116 - d = self.factory.addDeferred() 11.117 - self.send_be_create(vif) 11.118 + if recreate: 11.119 + d = defer.Deferred() 11.120 + d.callback(self) 11.121 + else: 11.122 + d = self.factory.addDeferred() 11.123 + self.send_be_create(vif) 11.124 return d 11.125 11.126 def reattach_devices(self):
12.1 --- a/tools/xenmgr/lib/xm/create.py Thu Jun 24 10:28:58 2004 +0000 12.2 +++ b/tools/xenmgr/lib/xm/create.py Thu Jun 24 12:00:50 2004 +0000 12.3 @@ -1,3 +1,6 @@ 12.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 12.5 +"""Domain creation. 12.6 +""" 12.7 import string 12.8 import sys 12.9 12.10 @@ -13,7 +16,7 @@ Create a domain. 12.11 """) 12.12 12.13 gopts.opt('help', short='h', 12.14 - fn=set_value, default=0, 12.15 + fn=set_true, default=0, 12.16 use="Print this help.") 12.17 12.18 gopts.opt('quiet', short='q', 12.19 @@ -36,21 +39,19 @@ gopts.opt('load', short='L', val='FILE', 12.20 fn=set_value, default=None, 12.21 use='Domain saved state to load.') 12.22 12.23 -def set_var(opt, k, v): 12.24 - opt.set(v) 12.25 - for d in string.split(v, ';' ): 12.26 - (k, v) = string.split(d, '=') 12.27 - opt.opts.setvar(k, v) 12.28 - 12.29 gopts.opt('define', short='D', val='VAR=VAL', 12.30 fn=set_var, default=None, 12.31 - use="""Set variables before loading defaults, e.g. '-D vmid=3;ip=1.2.3.4' 12.32 - to set vmid and ip.""") 12.33 + use="""Set a variable before loading defaults, e.g. '-D vmid=3' 12.34 + to set vmid. May be repeated to set more thanone variable.""") 12.35 12.36 gopts.opt('dryrun', short='n', 12.37 fn=set_true, default=0, 12.38 use="Dry run - print the config but don't create the domain.") 12.39 12.40 +gopts.opt('name', short='N', val='NAME', 12.41 + fn=set_value, default=None, 12.42 + use="Domain name.") 12.43 + 12.44 gopts.opt('console', short='c', 12.45 fn=set_true, default=0, 12.46 use="Connect to console after domain is created.") 12.47 @@ -71,34 +72,48 @@ gopts.opt('memory', short='m', val='MEMO 12.48 fn=set_value, default=128, 12.49 use="Domain memory in MB.") 12.50 12.51 +gopts.opt('blkif', 12.52 + fn=set_true, default=0, 12.53 + use="Make the domain a block device backend.") 12.54 + 12.55 +gopts.opt('netif', 12.56 + fn=set_true, default=0, 12.57 + use="Make the domain a network interface backend.") 12.58 + 12.59 gopts.opt('disk', short='d', val='phy:DEV,VDEV,MODE', 12.60 fn=append_value, default=[], 12.61 use="""Add a disk device to a domain. The physical device is DEV, which 12.62 - is exported to the domain as VDEV. The disk is read-only if MODE is r, 12.63 - read-write if mode is 'w'.""") 12.64 + is exported to the domain as VDEV. The disk is read-only if MODE 12.65 + is 'r', read-write if MODE is 'w'. 12.66 + The option may be repeated to add more than one disk. 12.67 + """) 12.68 12.69 gopts.opt('pci', val='BUS,DEV,FUNC', 12.70 fn=append_value, default=[], 12.71 - use="""Add a PCI device to a domain, using given params (in hex).""") 12.72 + use="""Add a PCI device to a domain, using given params (in hex). 12.73 + For example '-pci c0,02,1a'. 12.74 + The option may be repeated to add more than one pci device. 12.75 + """) 12.76 12.77 gopts.opt('ipaddr', short='i', val="IPADDR", 12.78 fn=append_value, default=[], 12.79 use="Add an IP address to the domain.") 12.80 12.81 -gopts.opt('mac', short='M', val="MAC", 12.82 +gopts.opt('vif', val="mac=MAC,bridge=BRIDGE", 12.83 fn=append_value, default=[], 12.84 - use="""Add a network interface with the given mac address to the domain. 12.85 - More than one interface may be specified. Interfaces with unspecified MAC addresses 12.86 - are allocated a random address.""") 12.87 + use="""Add a network interface with the given MAC address and bridge. 12.88 + If mac is not specified a random MAC address is used. 12.89 + If bridge is not specified the default bridge is used. 12.90 + This option may be repeated to add more than one vif. 12.91 + Specifying vifs will increase the number of interfaces as needed. 12.92 + """) 12.93 12.94 -gopts.opt('nics', val="N", 12.95 +gopts.opt('nics', val="NUM", 12.96 fn=set_int, default=1, 12.97 - use="Set the number of network interfaces.") 12.98 - 12.99 -gopts.opt('vnet', val='VNET', 12.100 - fn=append_value, default=[], 12.101 - use="""Define the vnets for the network interfaces. 12.102 - More than one vnet may be given, they are used in order. 12.103 + use="""Set the number of network interfaces. 12.104 + Use the vif option to define interface parameters, otherwise 12.105 + defaults are used. Specifying vifs will increase the 12.106 + number of interfaces as needed. 12.107 """) 12.108 12.109 gopts.opt('root', short='R', val='DEVICE', 12.110 @@ -116,15 +131,15 @@ gopts.opt('ip', short='I', val='IPADDR', 12.111 12.112 gopts.opt('gateway', val="IPADDR", 12.113 fn=set_value, default='', 12.114 - use="Set kernel IP gateway.") 12.115 + use="Set the kernel IP gateway.") 12.116 12.117 gopts.opt('netmask', val="MASK", 12.118 fn=set_value, default = '', 12.119 - use="Set kernel IP netmask.") 12.120 + use="Set the kernel IP netmask.") 12.121 12.122 gopts.opt('hostname', val="NAME", 12.123 fn=set_value, default='', 12.124 - use="Set kernel IP hostname.") 12.125 + use="Set the kernel IP hostname.") 12.126 12.127 gopts.opt('interface', val="INTF", 12.128 fn=set_value, default="eth0", 12.129 @@ -132,7 +147,7 @@ gopts.opt('interface', val="INTF", 12.130 12.131 gopts.opt('dhcp', val="off|dhcp", 12.132 fn=set_value, default='off', 12.133 - use="Set kernel dhcp option.") 12.134 + use="Set the kernel dhcp option.") 12.135 12.136 gopts.opt('nfs_server', val="IPADDR", 12.137 fn=set_value, default=None, 12.138 @@ -143,19 +158,16 @@ gopts.opt('nfs_root', val="PATH", 12.139 use="Set the path of the root NFS directory.") 12.140 12.141 def strip(pre, s): 12.142 + """Strip prefix 'pre' if present. 12.143 + """ 12.144 if s.startswith(pre): 12.145 return s[len(pre):] 12.146 else: 12.147 return s 12.148 12.149 -def make_config(opts): 12.150 - 12.151 - config = ['config', 12.152 - ['name', opts.name ], 12.153 - ['memory', opts.memory ] ] 12.154 - if opts.cpu: 12.155 - config.append(['cpu', opts.cpu]) 12.156 - 12.157 +def configure_image(config, opts): 12.158 + """Create the image config. 12.159 + """ 12.160 config_image = [ opts.builder ] 12.161 config_image.append([ 'kernel', os.path.abspath(opts.kernel) ]) 12.162 if opts.ramdisk: 12.163 @@ -169,8 +181,10 @@ def make_config(opts): 12.164 if opts.extra: 12.165 config_image.append(['args', opts.extra]) 12.166 config.append(['image', config_image ]) 12.167 - 12.168 - config_devs = [] 12.169 + 12.170 +def configure_disks(config_devs, opts): 12.171 + """Create the config for disks (virtual block devices). 12.172 + """ 12.173 for (uname, dev, mode) in opts.disk: 12.174 config_vbd = ['vbd', 12.175 ['uname', uname], 12.176 @@ -178,18 +192,34 @@ def make_config(opts): 12.177 ['mode', mode ] ] 12.178 config_devs.append(['device', config_vbd]) 12.179 12.180 +def configure_pci(config_devs, opts): 12.181 + """Create the config for pci devices. 12.182 + """ 12.183 for (bus, dev, func) in opts.pci: 12.184 config_pci = ['pci', ['bus', bus], ['dev', dev], ['func', func]] 12.185 config_devs.append(['device', config_pci]) 12.186 12.187 - for idx in range(0, opts.nics): 12.188 - config_vif = ['vif', ['@', ['id', 'vif%d' % idx]]] 12.189 - if idx < len(opts.mac): 12.190 - config_vif.append(['mac', opts.mac[idx]]) 12.191 +def configure_vifs(config_devs, opts): 12.192 + """Create the config for virtual network interfaces. 12.193 + """ 12.194 + vifs = opts.vif 12.195 + vifs_n = max(opts.nics, len(vifs)) 12.196 + 12.197 + for idx in range(0, vifs_n): 12.198 + if idx < len(vifs): 12.199 + d = vifs[idx] 12.200 + mac = d.get('mac') 12.201 + bridge = d.get('bridge') 12.202 + else: 12.203 + mac = None 12.204 + bridge = None 12.205 + config_vif = ['vif'] 12.206 + if mac: 12.207 + config_vif.append(['mac', mac]) 12.208 + if bridge: 12.209 + config_vif.append(['bridge', bridge]) 12.210 config_devs.append(['device', config_vif]) 12.211 12.212 - config += config_devs 12.213 - 12.214 ## if vfr_ipaddr: 12.215 ## config_vfr = ['vfr'] 12.216 ## idx = 0 # No way of saying which IP is for which vif? 12.217 @@ -197,15 +227,27 @@ def make_config(opts): 12.218 ## config_vfr.append(['vif', ['id', idx], ['ip', ip]]) 12.219 ## config.append(config_vfr) 12.220 12.221 - if opts.vnet: 12.222 - config_vnet = ['vnet'] 12.223 - idx = 0 12.224 - for vnet in opts.vnet: 12.225 - config_vif = ['vif', ['id', 'vif%d' % idx], ['vnet', vnet]] 12.226 - config_vnet.append(config_vif) 12.227 - idx += 1 12.228 - config.append(config_vnet) 12.229 - 12.230 + 12.231 +def make_config(opts): 12.232 + """Create the domain configuration. 12.233 + """ 12.234 + 12.235 + config = ['vm', 12.236 + ['name', opts.name ], 12.237 + ['memory', opts.memory ] ] 12.238 + if opts.cpu: 12.239 + config.append(['cpu', opts.cpu]) 12.240 + if opts.blkif: 12.241 + config.append(['backend', ['blkif']]) 12.242 + if opts.netif: 12.243 + config.append(['backend', ['netif']]) 12.244 + 12.245 + configure_image(config, opts) 12.246 + config_devs = [] 12.247 + configure_disks(config_devs, opts) 12.248 + configure_pci(config_devs, opts) 12.249 + configure_vifs(config_devs, opts) 12.250 + config += config_devs 12.251 return config 12.252 12.253 def preprocess_disk(opts): 12.254 @@ -213,7 +255,6 @@ def preprocess_disk(opts): 12.255 disk = [] 12.256 for v in opts.disk: 12.257 d = v.split(',') 12.258 - print 'disk', v, d 12.259 if len(d) != 3: 12.260 opts.err('Invalid disk specifier: ' + v) 12.261 disk.append(d) 12.262 @@ -231,6 +272,22 @@ def preprocess_pci(opts): 12.263 pci.append(hexd) 12.264 opts.pci = pci 12.265 12.266 +def preprocess_vifs(opts): 12.267 + if not opts.vif: return 12.268 + vifs = [] 12.269 + for vif in opts.vif: 12.270 + d = {} 12.271 + a = vif.split(',') 12.272 + for b in a: 12.273 + (k, v) = b.strip().split('=') 12.274 + k = k.strip() 12.275 + v = v.strip() 12.276 + if k not in ['mac', 'bridge']: 12.277 + opts.err('Invalid vif specifier: ' + vif) 12.278 + d[k] = v 12.279 + vifs.append(d) 12.280 + opts.vif = vifs 12.281 + 12.282 def preprocess_ip(opts): 12.283 setip = (opts.hostname or opts.netmask 12.284 or opts.gateway or opts.dhcp or opts.interface) 12.285 @@ -259,6 +316,7 @@ def preprocess(opts): 12.286 opts.err("No kernel specified") 12.287 preprocess_disk(opts) 12.288 preprocess_pci(opts) 12.289 + preprocess_vifs(opts) 12.290 preprocess_ip(opts) 12.291 preprocess_nfs(opts) 12.292 12.293 @@ -266,8 +324,8 @@ def make_domain(opts, config): 12.294 """Create, build and start a domain. 12.295 Returns: [int] the ID of the new domain. 12.296 """ 12.297 - if opts.load: 12.298 - filename = os.path.abspath(opts.load) 12.299 + if opts.vals.load: 12.300 + filename = os.path.abspath(opts.vals.load) 12.301 dominfo = server.xend_domain_restore(filename, config) 12.302 else: 12.303 dominfo = server.xend_domain_create(config) 12.304 @@ -280,7 +338,7 @@ def make_domain(opts, config): 12.305 console_port = None 12.306 12.307 if server.xend_domain_unpause(dom) < 0: 12.308 - server.xend_domain_halt(dom) 12.309 + server.xend_domain_destroy(dom) 12.310 opts.err("Failed to start domain %d" % dom) 12.311 opts.info("Started domain %d, console on port %d" 12.312 % (dom, console_port)) 12.313 @@ -289,16 +347,16 @@ def make_domain(opts, config): 12.314 def main(argv): 12.315 opts = gopts 12.316 args = opts.parse(argv) 12.317 - if opts.help: 12.318 + if opts.vals.help: 12.319 opts.usage() 12.320 return 12.321 - if opts.config: 12.322 + if opts.vals.config: 12.323 pass 12.324 else: 12.325 opts.load_defaults() 12.326 - preprocess(opts) 12.327 - config = make_config(opts) 12.328 - if opts.dryrun: 12.329 + preprocess(opts.vals) 12.330 + config = make_config(opts.vals) 12.331 + if opts.vals.dryrun: 12.332 PrettyPrint.prettyprint(config) 12.333 else: 12.334 make_domain(opts, config)
13.1 --- a/tools/xenmgr/lib/xm/main.py Thu Jun 24 10:28:58 2004 +0000 13.2 +++ b/tools/xenmgr/lib/xm/main.py Thu Jun 24 12:00:50 2004 +0000 13.3 @@ -10,27 +10,72 @@ from xenmgr import sxp 13.4 from xenmgr.XendClient import server 13.5 from xenmgr.xm import create, shutdown 13.6 13.7 +class Prog: 13.8 + """Base class for sub-programs. 13.9 + """ 13.10 + 13.11 + """Program group it belongs to""" 13.12 + group = 'all' 13.13 + """Program name.""" 13.14 + name = '??' 13.15 + """Short program info.""" 13.16 + info = '' 13.17 + 13.18 + def __init__(self, xm): 13.19 + self.xm = xm 13.20 + 13.21 + def err(self, msg): 13.22 + self.xm.err(msg) 13.23 + 13.24 + def help(self, args): 13.25 + self.shortHelp(args) 13.26 + 13.27 + def shortHelp(self, args): 13.28 + print "%-14s %s" % (self.name, self.info) 13.29 + 13.30 + def main(self, args): 13.31 + """Program main entry point. 13.32 + """ 13.33 + pass 13.34 + 13.35 + 13.36 +class ProgUnknown(Prog): 13.37 + 13.38 + name = 'unknown' 13.39 + info = '' 13.40 + 13.41 + def help(self, args): 13.42 + self.xm.err("Unknown command: %s\nTry '%s help' for more information." 13.43 + % (args[0], self.xm.name)) 13.44 + 13.45 + main = help 13.46 + 13.47 class Xm: 13.48 + """Main application. 13.49 + """ 13.50 13.51 def __init__(self): 13.52 - self.prog = 'xm' 13.53 - pass 13.54 + self.name = 'xm' 13.55 + self.unknown = ProgUnknown(self) 13.56 + self.progs = {} 13.57 13.58 def err(self, msg): 13.59 print >>sys.stderr, "Error:", msg 13.60 sys.exit(1) 13.61 13.62 def main(self, args): 13.63 - """Main entry point. Dispatches to the xm_ methods. 13.64 + """Main entry point. Dispatches to the progs. 13.65 """ 13.66 - self.prog = args[0] 13.67 + self.name = args[0] 13.68 if len(args) < 2: 13.69 self.err("Missing command\nTry '%s help' for more information." 13.70 - % self.prog) 13.71 - prog = 'xm_' + args[1] 13.72 + % self.name) 13.73 help = self.helparg(args) 13.74 - fn = getattr(self, prog, self.unknown) 13.75 - fn(help, args[1:]) 13.76 + p = self.getprog(args[1], self.unknown) 13.77 + if help: 13.78 + p.help(args[1:]) 13.79 + else: 13.80 + p.main(args[1:]) 13.81 13.82 def helparg(self, args): 13.83 for a in args: 13.84 @@ -38,39 +83,87 @@ class Xm: 13.85 return 1 13.86 return 0 13.87 13.88 - def unknown(self, help, args): 13.89 - if help and len(args) == 1: 13.90 - self.xm_help(help, args) 13.91 - else: 13.92 - self.err("Unknown command: %s\nTry '%s help' for more information." 13.93 - % (args[0], self.prog)) 13.94 + def prog(self, pklass): 13.95 + """Add a sub-program. 13.96 13.97 - def help(self, meth, args): 13.98 - """Print help on an xm_ method. 13.99 - Uses the method documentation string if there is one. 13.100 + pklass program class (Prog subclass) 13.101 + """ 13.102 + p = pklass(self) 13.103 + self.progs[p.name] = p 13.104 + return p 13.105 + 13.106 + def getprog(self, name, val=None): 13.107 + """Get a sub-program. 13.108 + """ 13.109 + return self.progs.get(name, val) 13.110 + 13.111 + def proglist(self): 13.112 + """Get a list of sub-programs, ordered by group. 13.113 """ 13.114 - name = meth[3:] 13.115 - f = getattr(self, meth) 13.116 - print "%-14s %s" % (name, f.__doc__ or '') 13.117 + groups = {} 13.118 + for p in self.progs.values(): 13.119 + l = groups.get(p.group, []) 13.120 + l.append(p) 13.121 + groups[p.group] = l 13.122 + kl = groups.keys() 13.123 + kl.sort() 13.124 + pl = [] 13.125 + for k in kl: 13.126 + l = groups[k] 13.127 + l.sort() 13.128 + pl += l 13.129 + return pl 13.130 + 13.131 +# Create the application object, then add the sub-program classes. 13.132 +xm = Xm() 13.133 + 13.134 +class ProgHelp(Prog): 13.135 13.136 - def xm_help(self, help, args): 13.137 - """Print help.""" 13.138 - for k in dir(self): 13.139 - if not k.startswith('xm_'): continue 13.140 - self.help(k, args) 13.141 - print "\nTry '%s CMD -h' for help on CMD" % self.prog 13.142 - 13.143 - def xm_create(self, help, args): 13.144 - """Create a domain.""" 13.145 + name = "help" 13.146 + info = "Print help." 13.147 + 13.148 + def help(self, args): 13.149 + if len(args) == 2: 13.150 + name = args[1] 13.151 + p = self.xm.getprog(name) 13.152 + if p: 13.153 + p.help(args) 13.154 + else: 13.155 + print '%s: Unknown command: %s' % (self.name, name) 13.156 + else: 13.157 + for p in self.xm.proglist(): 13.158 + p.shortHelp(args) 13.159 + print "\nTry '%s help CMD' for help on CMD" % self.xm.name 13.160 + 13.161 + main = help 13.162 + 13.163 +xm.prog(ProgHelp) 13.164 + 13.165 +class ProgCreate(Prog): 13.166 + 13.167 + group = 'domain' 13.168 + name = "create" 13.169 + info = """Create a domain.""" 13.170 + 13.171 + def help(self, args): 13.172 + create.main([args[0], '-h']) 13.173 + 13.174 + def main(self, args): 13.175 create.main(args) 13.176 13.177 - def xm_save(self, help, args): 13.178 - """Save domain state (and config) to file.""" 13.179 - if help: 13.180 - print args[0], "DOM FILE [CONFIG]" 13.181 - print """\nSave domain with id DOM to FILE. 13.182 - Optionally save config to CONFIG.""" 13.183 - return 13.184 +xm.prog(ProgCreate) 13.185 + 13.186 +class ProgSave(Prog): 13.187 + group = 'domain' 13.188 + name = "save" 13.189 + info = """Save domain state (and config) to file.""" 13.190 + 13.191 + def help(self, args): 13.192 + print args[0], "DOM FILE [CONFIG]" 13.193 + print """\nSave domain with id DOM to FILE. 13.194 + Optionally save config to CONFIG.""" 13.195 + 13.196 + def main(self, args): 13.197 if len(args) < 3: self.err("%s: Missing arguments" % args[0]) 13.198 dom = args[1] 13.199 savefile = os.path.abspath(args[2]) 13.200 @@ -83,23 +176,45 @@ class Xm: 13.201 PrettyPrint.prettyprint(config, out=out) 13.202 out.close() 13.203 server.xend_domain_save(dom, savefile) 13.204 - 13.205 - def xm_restore(self, help, args): 13.206 - """Create a domain from a saved state.""" 13.207 - if help: 13.208 - print args[0], "FILE CONFIG" 13.209 - print "\nRestore a domain from FILE using configuration CONFIG." 13.210 - return 13.211 + 13.212 +xm.prog(ProgSave) 13.213 + 13.214 +class ProgRestore(Prog): 13.215 + group = 'domain' 13.216 + name = "restore" 13.217 + info = """Create a domain from a saved state.""" 13.218 + 13.219 + def help(self, args): 13.220 + print args[0], "FILE CONFIG" 13.221 + print "\nRestore a domain from FILE using configuration CONFIG." 13.222 + 13.223 + def main(self, help, args): 13.224 if len(args) < 3: self.err("%s: Missing arguments" % args[0]) 13.225 savefile = os.path.abspath(args[1]) 13.226 configfile = os.path.abspath(args[2]) 13.227 info = server.xend_domain_restore(savefile, configfile) 13.228 PrettyPrint.prettyprint(info) 13.229 13.230 - def xm_domains(self, help, args): 13.231 - """List domains.""" 13.232 - if help: self.help('xm_' + args[0], args); return 13.233 - doms = server.xend_domains() 13.234 +xm.prog(ProgRestore) 13.235 + 13.236 +class ProgList(Prog): 13.237 + group = 'domain' 13.238 + name = "list" 13.239 + info = """List info about domains.""" 13.240 + 13.241 + def help(self, args): 13.242 + if help: 13.243 + print args[0], '[DOM...]' 13.244 + print """\nGet information about domains. 13.245 + Either all domains or the domains given.""" 13.246 + return 13.247 + 13.248 + def main(self, args): 13.249 + n = len(args) 13.250 + if n == 1: 13.251 + doms = server.xend_domains() 13.252 + else: 13.253 + doms = map(int, args[1:]) 13.254 doms.sort() 13.255 print 'Dom Name Mem(MB) CPU State Time(s)' 13.256 for dom in doms: 13.257 @@ -113,111 +228,167 @@ class Xm: 13.258 d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0')) 13.259 print ("%(dom)-4d %(name)-16s %(mem)7d %(cpu)3d %(state)5s %(cpu_time)7.1f" % d) 13.260 13.261 - def xm_domain(self, help, args): 13.262 - """Get information about a domain.""" 13.263 - if help: 13.264 - print args[0], 'DOM' 13.265 - print '\nGet information about domain DOM.' 13.266 - return 13.267 +xm.prog(ProgList) 13.268 + 13.269 +class ProgDestroy(Prog): 13.270 + group = 'domain' 13.271 + name = "destroy" 13.272 + info = """Terminate a domain immediately.""" 13.273 + 13.274 + def help(self, args): 13.275 + print args[0], 'DOM' 13.276 + print '\nTerminate domain DOM immediately.' 13.277 + 13.278 + def main(self, args): 13.279 if len(args) < 2: self.err("%s: Missing domain" % args[0]) 13.280 dom = args[1] 13.281 - info = server.xend_domain(dom) 13.282 - PrettyPrint.prettyprint(info) 13.283 - print 13.284 + server.xend_domain_destroy(dom) 13.285 + 13.286 +xm.prog(ProgDestroy) 13.287 13.288 - def xm_halt(self, help, args): 13.289 - """Terminate a domain immediately.""" 13.290 - if help: 13.291 - print args[0], 'DOM' 13.292 - print '\nTerminate domain DOM immediately.' 13.293 - return 13.294 - if len(args) < 2: self.err("%s: Missing domain" % args[0]) 13.295 - dom = args[1] 13.296 - server.xend_domain_halt(dom) 13.297 +class ProgShutdown(Prog): 13.298 + group = 'domain' 13.299 + name = "shutdown" 13.300 + info = """Shutdown a domain.""" 13.301 13.302 - def xm_shutdown(self, help, args): 13.303 - """Shutdown a domain.""" 13.304 + def help(self, args): 13.305 + print args[0], 'DOM' 13.306 + print '\nSignal domain DOM to shutdown.' 13.307 + 13.308 + def main(self, args): 13.309 shutdown.main(args) 13.310 13.311 - def xm_pause(self, help, args): 13.312 - """Pause execution of a domain.""" 13.313 - if help: 13.314 - print args[0], 'DOM' 13.315 - print '\nPause execution of domain DOM.' 13.316 - return 13.317 +xm.prog(ProgShutdown) 13.318 + 13.319 +class ProgPause(Prog): 13.320 + group = 'domain' 13.321 + name = "pause" 13.322 + info = """Pause execution of a domain.""" 13.323 + 13.324 + def help(self, args): 13.325 + print args[0], 'DOM' 13.326 + print '\nPause execution of domain DOM.' 13.327 + 13.328 + def main(self, args): 13.329 if len(args) < 2: self.err("%s: Missing domain" % args[0]) 13.330 dom = args[1] 13.331 server.xend_domain_pause(dom) 13.332 13.333 - def xm_unpause(self, help, args): 13.334 - """Unpause a paused domain.""" 13.335 - if help: 13.336 - print args[0], 'DOM' 13.337 - print '\nUnpause execution of domain DOM.' 13.338 - return 13.339 +xm.prog(ProgPause) 13.340 + 13.341 +class ProgUnpause(Prog): 13.342 + group = 'domain' 13.343 + name = "unpause" 13.344 + info = """Unpause a paused domain.""" 13.345 + 13.346 + def help(self, args): 13.347 + print args[0], 'DOM' 13.348 + print '\nUnpause execution of domain DOM.' 13.349 + 13.350 + def main(self, args): 13.351 if len(args) < 2: self.err("%s: Missing domain" % args[0]) 13.352 dom = args[1] 13.353 server.xend_domain_unpause(dom) 13.354 13.355 - def xm_pincpu(self, help, args): 13.356 - """Pin a domain to a cpu. """ 13.357 - if help: 13.358 - print args[0],'DOM CPU' 13.359 - print '\nPin domain DOM to cpu CPU.' 13.360 - return 13.361 +xm.prog(ProgUnpause) 13.362 + 13.363 +class ProgPincpu(Prog): 13.364 + group = 'domain' 13.365 + name = "pincpu" 13.366 + info = """Pin a domain to a cpu. """ 13.367 + 13.368 + def help(self, args): 13.369 + print args[0],'DOM CPU' 13.370 + print '\nPin domain DOM to cpu CPU.' 13.371 + 13.372 + def main(self, args): 13.373 if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0]) 13.374 v = map(int, args[1:3]) 13.375 server.xend_domain_pincpu(*v) 13.376 13.377 - def xm_bvt(self, help, args): 13.378 - """Set BVT scheduler parameters.""" 13.379 - if help: 13.380 - print args[0], "DOM MCUADV WARP WARPL WARPU" 13.381 - print '\nSet Borrowed Virtual Time scheduler parameters.' 13.382 - return 13.383 +xm.prog(ProgPincpu) 13.384 + 13.385 +class ProgBvt(Prog): 13.386 + group = 'scheduler' 13.387 + name = "bvt" 13.388 + info = """Set BVT scheduler parameters.""" 13.389 + 13.390 + def help(self, args): 13.391 + print args[0], "DOM MCUADV WARP WARPL WARPU" 13.392 + print '\nSet Borrowed Virtual Time scheduler parameters.' 13.393 + 13.394 + def main(self, args): 13.395 if len(args) != 6: self.err("%s: Invalid argument(s)" % args[0]) 13.396 v = map(int, args[1:6]) 13.397 server.xend_domain_cpu_bvt_set(*v) 13.398 13.399 - def xm_bvtslice(self, help, args): 13.400 - """Set the BVT scheduler slice.""" 13.401 - if help: 13.402 - print args[0], 'SLICE' 13.403 - print '\nSet Borrowed Virtual Time scheduler slice.' 13.404 - return 13.405 +xm.prog(ProgBvt) 13.406 + 13.407 +class ProgBvtslice(Prog): 13.408 + group = 'scheduler' 13.409 + name = "bvtslice" 13.410 + info = """Set the BVT scheduler slice.""" 13.411 + 13.412 + def help(self, args): 13.413 + print args[0], 'SLICE' 13.414 + print '\nSet Borrowed Virtual Time scheduler slice.' 13.415 + 13.416 + def main(self, args): 13.417 if len(args) < 2: self.err('%s: Missing slice' % args[0]) 13.418 server.xend_node_cpu_bvt_slice_set(slice) 13.419 13.420 - def xm_atropos(self, help, args): 13.421 - """Set atropos parameters.""" 13.422 - if help: 13.423 - print args[0], "DOM PERIOD SLICE LATENCY XTRATIME" 13.424 - print "\nSet atropos parameters." 13.425 - return 13.426 +xm.prog(ProgBvtslice) 13.427 + 13.428 +class ProgAtropos(Prog): 13.429 + group = 'scheduler' 13.430 + name= "atropos" 13.431 + info = """Set atropos parameters.""" 13.432 + 13.433 + def help(self, args): 13.434 + print args[0], "DOM PERIOD SLICE LATENCY XTRATIME" 13.435 + print "\nSet atropos parameters." 13.436 + 13.437 + def main(self, args): 13.438 if len(args) != 5: self.err("%s: Invalid argument(s)" % args[0]) 13.439 v = map(int, args[1:5]) 13.440 server.xend_domain_cpu_atropos_set(*v) 13.441 13.442 - def xm_rrobin(self, help, args): 13.443 - """Set round robin slice.""" 13.444 - if help: 13.445 - print args[0], "SLICE" 13.446 - print "\nSet round robin scheduler slice." 13.447 - return 13.448 +xm.prog(ProgAtropos) 13.449 + 13.450 +class ProgRrobin(Prog): 13.451 + group = 'scheduler' 13.452 + name = "rrobin" 13.453 + info = """Set round robin slice.""" 13.454 + 13.455 + def help(self, args): 13.456 + print args[0], "SLICE" 13.457 + print "\nSet round robin scheduler slice." 13.458 + 13.459 + def main(self, args): 13.460 if len(args) != 2: self.err("%s: Invalid argument(s)" % args[0]) 13.461 rrslice = int(args[1]) 13.462 server.xend_node_rrobin_set(rrslice) 13.463 13.464 - def xm_info(self, help, args): 13.465 - """Get information about the xen host.""" 13.466 - if help: self.help('xm_' + args[0], args); return 13.467 +xm.prog(ProgRrobin) 13.468 + 13.469 +class ProgInfo(Prog): 13.470 + group = 'host' 13.471 + name = "info" 13.472 + info = """Get information about the xen host.""" 13.473 + 13.474 + def main(self, args): 13.475 info = server.xend_node() 13.476 for x in info[1:]: 13.477 print "%-23s:" % x[0], x[1] 13.478 13.479 - def xm_consoles(self, help, args): 13.480 - """Get information about domain consoles.""" 13.481 - if help: self.help('xm_' + args[0], args); return 13.482 +xm.prog(ProgInfo) 13.483 + 13.484 +class ProgConsoles(Prog): 13.485 + group = 'console' 13.486 + name = "consoles" 13.487 + info = """Get information about domain consoles.""" 13.488 + 13.489 + def main(self, args): 13.490 l = server.xend_consoles() 13.491 print "Dom Port Id" 13.492 for x in l: 13.493 @@ -228,12 +399,18 @@ class Xm: 13.494 d['id'] = sxp.child_value(info, 'id', '?') 13.495 print "%(dom)3s %(port)4s %(id)3s" % d 13.496 13.497 - def xm_console(self, help, args): 13.498 - """Open a console to a domain.""" 13.499 - if help: 13.500 - print "console DOM" 13.501 - print "\nOpen a console to domain DOM." 13.502 - return 13.503 +xm.prog(ProgConsoles) 13.504 + 13.505 +class ProgConsole(Prog): 13.506 + group = 'console' 13.507 + name = "console" 13.508 + info = """Open a console to a domain.""" 13.509 + 13.510 + def help(self, args): 13.511 + print "console DOM" 13.512 + print "\nOpen a console to domain DOM." 13.513 + 13.514 + def main(self, args): 13.515 if len(args) < 2: self.err("%s: Missing domain" % args[0]) 13.516 dom = args[1] 13.517 info = server.xend_domain(dom) 13.518 @@ -244,6 +421,7 @@ class Xm: 13.519 from xenctl import console_client 13.520 console_client.connect("localhost", int(port)) 13.521 13.522 +xm.prog(ProgConsole) 13.523 + 13.524 def main(args): 13.525 - xm = Xm() 13.526 xm.main(args)
14.1 --- a/tools/xenmgr/lib/xm/opts.py Thu Jun 24 10:28:58 2004 +0000 14.2 +++ b/tools/xenmgr/lib/xm/opts.py Thu Jun 24 12:00:50 2004 +0000 14.3 @@ -1,3 +1,6 @@ 14.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 14.5 +"""Object-oriented command-line option support. 14.6 +""" 14.7 from getopt import getopt 14.8 import os 14.9 import os.path 14.10 @@ -5,8 +8,22 @@ import sys 14.11 import types 14.12 14.13 class Opt: 14.14 + """An individual option. 14.15 + """ 14.16 def __init__(self, opts, name, short=None, long=None, 14.17 val=None, fn=None, use=None, default=None): 14.18 + """Create an option. 14.19 + 14.20 + opts parent options object 14.21 + name name of the field it controls 14.22 + short short (1-char) command line switch (optional) 14.23 + long long command-line switch. Defaults to option name. 14.24 + val string used to print option args in help. 14.25 + If val is not specified the option has no arg. 14.26 + fn function to call when the option is specified. 14.27 + use usage (help) string 14.28 + default default value if not specified on command-line 14.29 + """ 14.30 self.opts = opts 14.31 self.name = name 14.32 self.short = short 14.33 @@ -24,18 +41,34 @@ class Opt: 14.34 self.fn = fn 14.35 self.specified_opt = None 14.36 self.specified_val = None 14.37 + self.value = None 14.38 self.set(default) 14.39 14.40 + def __repr__(self): 14.41 + return self.name + '=' + str(self.specified_val) 14.42 + 14.43 + __str__ = __repr__ 14.44 + 14.45 def set(self, value): 14.46 - setattr(self.opts, self.name, value) 14.47 + """Set the option value. 14.48 + """ 14.49 + self.opts.setopt(self.name, value) 14.50 14.51 def get(self): 14.52 - return getattr(self.opts, self.name) 14.53 + """Get the option value. 14.54 + """ 14.55 + return self.opts.getopt(self.name) 14.56 14.57 def append(self, value): 14.58 - self.set(self.get().append(value)) 14.59 + """Append a value to the option value. 14.60 + """ 14.61 + v = self.get() or [] 14.62 + v.append(value) 14.63 + self.set(v) 14.64 14.65 def short_opt(self): 14.66 + """Short option spec. 14.67 + """ 14.68 if self.short: 14.69 if self.val: 14.70 return self.short + ':' 14.71 @@ -45,6 +78,8 @@ class Opt: 14.72 return None 14.73 14.74 def long_opt(self): 14.75 + """Long option spec. 14.76 + """ 14.77 if self.long: 14.78 if self.val: 14.79 return self.long + '=' 14.80 @@ -68,6 +103,12 @@ class Opt: 14.81 print '\tDefault', self.default or 'None' 14.82 14.83 def specify(self, k, v): 14.84 + """Specify the option. Called when the option is set 14.85 + from the command line. 14.86 + 14.87 + k option switch used 14.88 + v optional value given (if any) 14.89 + """ 14.90 if k in self.optkeys: 14.91 if self.val is None and v: 14.92 self.opts.err("Option '%s' does not take a value" % k) 14.93 @@ -80,52 +121,113 @@ class Opt: 14.94 return 0 14.95 14.96 def specified(self): 14.97 + """Test whether the option has been specified: set 14.98 + from the command line. 14.99 + """ 14.100 return self.specified_opt 14.101 14.102 +class OptVals: 14.103 + """Class to hold option values. 14.104 + """ 14.105 + pass 14.106 + 14.107 class Opts: 14.108 + """Container for options. 14.109 + """ 14.110 def __init__(self, use=None): 14.111 - self._usage = use 14.112 - self._options = [] 14.113 - self._options_map = {} 14.114 - self._argv = [] 14.115 - self._vals = {} 14.116 - self._globals = {} 14.117 - self._locals = {} 14.118 - self.quiet = 0 14.119 + """Options constructor. 14.120 + 14.121 + use usage string 14.122 + """ 14.123 + self.use = use 14.124 + # List of options. 14.125 + self.options = [] 14.126 + # Options indexed by name. 14.127 + self.options_map = {} 14.128 + # Command-line arguments. 14.129 + self.argv = [] 14.130 + # Option values. 14.131 + self.vals = OptVals() 14.132 + self.vals.quiet = 0 14.133 + # Variables for default scripts. 14.134 + self.vars = {} 14.135 + 14.136 + def __repr__(self): 14.137 + return '\n'.join(map(str, self.options)) 14.138 + 14.139 + __str__ = __repr__ 14.140 14.141 def opt(self, name, **args): 14.142 + """Add an option. 14.143 + 14.144 + name option name 14.145 + **args keyword params for option constructor 14.146 + """ 14.147 x = Opt(self, name, **args) 14.148 - self._options.append(x) 14.149 - self._options_map[name] = x 14.150 + self.options.append(x) 14.151 + self.options_map[name] = x 14.152 return x 14.153 14.154 + def setvar(self, var, val): 14.155 + """Set a default script variable. 14.156 + """ 14.157 + self.vars[var] = val 14.158 + 14.159 + def getvar(self, var): 14.160 + """Get a default script variable. 14.161 + """ 14.162 + return self.vars.get(var) 14.163 + 14.164 + def option(self, name): 14.165 + """Get an option (object). 14.166 + """ 14.167 + return self.options_map.get(name) 14.168 + 14.169 + def setopt(self, name, val): 14.170 + """Set an option value. 14.171 + An option can also be set using 'opts.vals.name = val'. 14.172 + """ 14.173 + setattr(self.vals, name, val) 14.174 + 14.175 def getopt(self, name): 14.176 - return self._options_map.get(name) 14.177 + """Get an option value. 14.178 + An option value can also be got using 'opts.vals.name'. 14.179 + """ 14.180 + getattr(self.vals, name) 14.181 14.182 def specified(self, name): 14.183 - opt = self.getopt(name) 14.184 + """Test if an option has been specified. 14.185 + """ 14.186 + opt = self.option(name) 14.187 return opt and opt.specified() 14.188 14.189 - def setvar(self, name, val): 14.190 - self._globals[name] = val 14.191 - 14.192 def err(self, msg): 14.193 + """Print an error to stderr and exit. 14.194 + """ 14.195 print >>sys.stderr, "Error:", msg 14.196 sys.exit(1) 14.197 14.198 def info(self, msg): 14.199 - if self.quiet: return 14.200 + """Print a message to stdout (unless quiet is set). 14.201 + """ 14.202 + if self.vals.quiet: return 14.203 print msg 14.204 14.205 def warn(self, msg): 14.206 + """Print a warning to stdout. 14.207 + """ 14.208 print >>sys.stderr, "Warning:", msg 14.209 14.210 def parse(self, argv): 14.211 - self._argv = argv 14.212 + """Parse arguments argv using the options. 14.213 + 14.214 + return remaining arguments 14.215 + """ 14.216 + self.argv = argv 14.217 (vals, args) = getopt(argv[1:], self.short_opts(), self.long_opts()) 14.218 - self._args = args 14.219 + self.args = args 14.220 for (k, v) in vals: 14.221 - for opt in self._options: 14.222 + for opt in self.options: 14.223 if opt.specify(k, v): break 14.224 else: 14.225 print >>sys.stderr, "Error: Unknown option:", k 14.226 @@ -133,63 +235,92 @@ class Opts: 14.227 return args 14.228 14.229 def short_opts(self): 14.230 + """Get short options specifier for getopt. 14.231 + """ 14.232 l = [] 14.233 - for x in self._options: 14.234 + for x in self.options: 14.235 y = x.short_opt() 14.236 if not y: continue 14.237 l.append(y) 14.238 return ''.join(l) 14.239 14.240 def long_opts(self): 14.241 + """Get long options specifier for getopt. 14.242 + """ 14.243 l = [] 14.244 - for x in self._options: 14.245 + for x in self.options: 14.246 y = x.long_opt() 14.247 if not y: continue 14.248 l.append(y) 14.249 - return ''.join(l) 14.250 + return l 14.251 14.252 def usage(self): 14.253 - print 'Usage: ', self._argv[0], self._usage or 'OPTIONS' 14.254 - for opt in self._options: 14.255 + print 'Usage: ', self.argv[0], self.use or 'OPTIONS' 14.256 + for opt in self.options: 14.257 opt.show() 14.258 14.259 def load_defaults(self): 14.260 - for x in [ '' ] + self.path.split(':'): 14.261 + """Load a defaults script. Assumes these options set: 14.262 + 'path' search path 14.263 + 'default' script name 14.264 + """ 14.265 + for x in [ '' ] + self.vals.path.split(':'): 14.266 if x: 14.267 - p = os.path.join(x, self.defaults) 14.268 + p = os.path.join(x, self.vals.defaults) 14.269 else: 14.270 - p = self.defaults 14.271 + p = self.vals.defaults 14.272 if os.path.exists(p): 14.273 self.load(p) 14.274 break 14.275 else: 14.276 self.err("Cannot open defaults file %s" % self.defaults) 14.277 14.278 - def load(self, defaults): 14.279 - self._globals['sys'] = sys 14.280 - self._globals['config_file'] = defaults 14.281 - execfile(defaults, self._globals, self._locals) 14.282 + def load(self, defaults, help=0): 14.283 + """Load a defaults file. Local variables in the file 14.284 + are used to set options with the same names. 14.285 + Variables are not used to set options that are already specified. 14.286 + """ 14.287 + # Create global and lobal dicts for the file. 14.288 + # Initialize locals to the vars. 14.289 + # Use exec to do the standard imports and 14.290 + # define variables we are passing to the script. 14.291 + globals = {} 14.292 + locals = {} 14.293 + locals.update(self.vars) 14.294 + cmd = '\n'.join(["import sys", 14.295 + "import os", 14.296 + "import os.path", 14.297 + "xm_file = '%s'" % defaults, 14.298 + "xm_help = %d" % help ]) 14.299 + exec cmd in globals, locals 14.300 + execfile(defaults, globals, locals) 14.301 + if help: return 14.302 + # Extract the values set by the script and set the corresponding 14.303 + # options, if not set on the command line. 14.304 vtypes = [ types.StringType, 14.305 types.ListType, 14.306 types.IntType, 14.307 types.FloatType 14.308 ] 14.309 - for (k, v) in self._locals.items(): 14.310 + for (k, v) in locals.items(): 14.311 if self.specified(k): continue 14.312 if not(type(v) in vtypes): continue 14.313 - print 'SET ', k, v 14.314 - setattr(self, k, v) 14.315 + self.setopt(k, v) 14.316 14.317 def set_true(opt, k, v): 14.318 + """Set an option true.""" 14.319 opt.set(1) 14.320 14.321 def set_false(opt, k, v): 14.322 + """Set an option false.""" 14.323 opt.set(0) 14.324 14.325 def set_value(opt, k, v): 14.326 + """Set an option to a valoue.""" 14.327 opt.set(v) 14.328 14.329 def set_int(opt, k, v): 14.330 + """Set an option to an integer value.""" 14.331 try: 14.332 v = int(v) 14.333 except: 14.334 @@ -197,4 +328,12 @@ def set_int(opt, k, v): 14.335 opt.set(v) 14.336 14.337 def append_value(opt, k, v): 14.338 + """Append a value to a list option.""" 14.339 opt.append(v) 14.340 + 14.341 +def set_var(opt, k, v): 14.342 + """Set a default script variable. 14.343 + """ 14.344 + (var, val) = v.strip().split('=') 14.345 + opt.opts.setvar(var.strip(), val.strip()) 14.346 +
15.1 --- a/tools/xenmgr/lib/xm/shutdown.py Thu Jun 24 10:28:58 2004 +0000 15.2 +++ b/tools/xenmgr/lib/xm/shutdown.py Thu Jun 24 12:00:50 2004 +0000 15.3 @@ -1,3 +1,6 @@ 15.4 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com> 15.5 +"""Domain shutdown. 15.6 +""" 15.7 import string 15.8 import sys 15.9 import time