bitkeeper revision 1.1159.1.164 (41503abcmVn6L0phzf-BOxlxa3zgxw)

Add support for reconfiguring an existing device,
including support for changing the bridge of a vif.
Treat bridge "null" as meaning no bridge.
This commit is contained in:
mjw@wray-m-3.hpl.hp.com committed 2004-09-21 14:29:16 +00:00
1 parent eb7bd4c6c6
commit a23e4c0121
9 files changed
+230 -34

No files matched your search

+6
View File
@@ -550,6 +550,12 @@ class Xend:
'type' : type,
'idx' : idx })
def xend_domain_device_configure(self, id, config, idx):
return self.xendPost(self.domainurl(id),
{'op' : 'device_configure',
'idx' : idx,
'config' : fileof(config) })
def xend_consoles(self):
return self.xendGet(self.consoleurl())
+16 -2
View File
@@ -684,12 +684,27 @@ class XendDomain:
self.update_domain(dominfo.id)
return val
def domain_device_configure(self, id, devconfig, idx):
"""Configure an existing device for a domain.
@param id: domain id
@param devconfig: device configuration
@param idx: device index
@return: updated device configuration
"""
dominfo = self.domain_lookup(id)
self.refresh_schedule()
val = dominfo.device_configure(devconfig, idx)
self.update_domain(dominfo.id)
return val
def domain_device_destroy(self, id, type, idx):
"""Destroy a device.
@param id: domain id
@param type: device type
@param idx: device index
@param type: device type
"""
dominfo = self.domain_lookup(id)
self.refresh_schedule()
@@ -706,7 +721,6 @@ class XendDomain:
"""
dominfo = self.domain_lookup(id)
devs = dominfo.get_devices(type)
#return range(0, len(devs))
return devs
def domain_devtype_get(self, id, type, idx):
+24
View File
@@ -825,6 +825,30 @@ class XendDomainInfo:
d = dev_handler(self, dev_config, dev_index, change=1)
return d
def device_configure(self, dev_config, idx):
"""Configure an existing device.
@param dev_config: device configuration
@param idx: device index
"""
type = sxp.name(dev_config)
dev = self.get_device_by_index(type, idx)
if not dev:
raise VmError('invalid device: %s %s' % (type, idx))
new_config = dev.configure(dev_config, change=1)
devs = self.devices.get(type)
index = devs.index(dev)
# Patch new config into device configs.
dev_configs = self.config_devices(type)
old_config = dev_configs[index]
dev_configs[index] = new_config
# Patch new config into vm config.
new_full_config = ['device', new_config]
old_full_config = ['device', old_config]
old_index = self.config.index(old_full_config)
self.config[old_index] = new_full_config
return new_config
def device_destroy(self, type, idx):
"""Destroy a device.
@@ -164,6 +164,14 @@ class SrvDomain(SrvDir):
val = fn(req.args, {'dom': self.dom.id})
return val
def op_device_configure(self, op, req):
fn = FormFn(self.xd.domain_device_configure,
[['dom', 'str'],
['config', 'sxpr'],
['idx', 'str']])
d = fn(req.args, {'dom': self.dom.id})
return d
def op_vifs(self, op, req):
devs = self.xd.domain_vif_ls(self.dom.id)
return [ dev.sxpr() for dev in devs ]
@@ -617,6 +617,9 @@ class Dev:
"""
raise NotImplementedError()
def configure(self, config, change=0):
raise NotImplementedError()
class SplitDev(Dev):
def __init__(self, idx, controller):
+62 -11
View File
@@ -104,31 +104,82 @@ class NetDev(controller.SplitDev):
self.evtchn = None
self.configure(config)
def configure(self, config):
def _get_config_mac(self, config):
vmac = sxp.child_value(config, 'mac')
if not vmac: return None
mac = [ int(x, 16) for x in vmac.split(':') ]
if len(mac) != 6: raise XendError("invalid mac")
return mac
def _get_config_ipaddr(self, config):
ips = sxp.children(config, elt='ip')
if ips:
val = []
for ipaddr in ips:
val.append(sxp.child0(ipaddr))
else:
val = None
return val
def configure(self, config, change=0):
if change:
return self.reconfigure(config)
self.config = config
self.mac = None
self.bridge = None
self.script = None
self.ipaddr = []
vmac = sxp.child_value(config, 'mac')
if not vmac: raise XendError("invalid mac")
mac = [ int(x, 16) for x in vmac.split(':') ]
if len(mac) != 6: raise XendError("invalid mac")
self.mac = mac
mac = self._get_config_mac(config)
if mac is None:
raise XendError("invalid mac")
self.mac = mac
self.bridge = sxp.child_value(config, 'bridge')
self.script = sxp.child_value(config, 'script')
ipaddrs = sxp.children(config, elt='ip')
for ipaddr in ipaddrs:
self.ipaddr.append(sxp.child0(ipaddr))
self.ipaddr = self._get_config_ipaddr(config) or []
try:
self.backendDomain = int(sxp.child_value(config, 'backend', '0'))
except:
raise XendError('invalid backend domain')
def reconfigure(self, config):
"""Reconfigure the interface with new values.
Not all configuration parameters can be changed:
bridge, script and ip addresses can,
backend and mac cannot.
To leave a parameter unchanged, omit it from the changes.
@param config configuration changes
@return updated interface configuration
@raise XendError on errors
"""
changes = {}
mac = self._get_config_mac(config)
bridge = sxp.child_value(config, 'bridge')
script = sxp.child_value(config, 'script')
ipaddr = self._get_config_ipaddr(config)
backendDomain = sxp.child_value(config, 'backend', '0')
if (mac is not None) and (mac != self.mac):
raise XendError("cannot change mac")
if (backendDomain is not None) and (backendDomain != str(self.backendDomain)):
raise XendError("cannot change backend")
if (bridge is not None) and (bridge != self.bridge):
changes['bridge'] = bridge
if (script is not None) and (script != self.script):
changes['script'] = script
if (ipaddr is not None) and (ipaddr != self.ipaddr):
changes['ipaddr'] = ipaddr
if changes:
self.vifctl("down")
for (k, v) in changes.items():
setattr(self, k, v)
self.config = sxp.merge(config, self.config)
self.vifctl("up")
return self.config
def sxpr(self):
vif = str(self.vif)
mac = self.get_mac()
+73 -1
View File
@@ -41,7 +41,8 @@ __all__ = [
"has_id",
"with_id",
"child_with_id",
"elements",
"elements",
"merge",
"to_string",
"from_string",
"all_from_string",
@@ -595,6 +596,77 @@ def elements(sxpr, ctxt=None):
yield v
i += 1
def merge(s1, s2):
"""Merge sxprs s1 and s2.
Returns an sxpr containing all the fields from s1 and s2, with
entries in s1 overriding s2. Recursively merges fields.
@param s1 sxpr
@param s2 sxpr
@return merged sxpr
"""
if s1 is None:
val = s2
elif s2 is None:
val = s1
elif elementp(s1):
name1 = name(s1)
(m1, v1) = child_map(s1)
(m2, v2) = child_map(s2)
val = [name1]
for (k1, f1) in m1.items():
merge_list(val, f1, m2.get(k1, []))
for (k2, f2) in m2.items():
if k2 in m1: continue
val.extend(f2)
val.extend(v1)
else:
val = s1
return val
def merge_list(sxpr, l1, l2):
"""Merge element lists l1 and l2 into sxpr.
The lists l1 and l2 are all element with the same name.
Values from l1 are merged with values in l2 and stored in sxpr.
If one list is longer than the other the excess values are used
as they are.
@param sxpr to merge into
@param l1 sxpr list
@param l2 sxpr list
@return modified sxpr
"""
n1 = len(l1)
n2 = len(l2)
nmin = min(n1, n2)
for i in range(0, nmin):
sxpr.append(merge(l1[i], l2[i]))
for i in range(nmin, n1):
sxpr.append(l1[i])
for i in range(nmin, n2):
sxpr.append(l2[i])
return sxpr
def child_map(sxpr):
"""Get a dict of the elements in sxpr and a list of its values.
The dict maps element name to the list of elements with that name,
and the list is the non-element children.
@param sxpr
@return (dict, list)
"""
m = {}
v = []
for x in children(sxpr):
if elementp(x):
n = name(x)
l = m.get(n, [])
l.append(x)
m[n] = l
else:
v.append(x)
return (m, v)
def to_string(sxpr):
"""Convert an sxpr to a string.
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.