#!/usr/bin/env python
# -*- coding: utf-8 -*-
-class AttributesMap(object):
- """AttributesMap is the base class for every object whose attributes
- are going to be manipulated by the end-user in a script or GUI.
- """
- def __init__(self):
- self._attributes = dict()
-
- @property
- def attributes(self):
- return self._attributes.values()
-
- @property
- def attributes_name(self):
- return self._attributes.keys()
-
- def set_attribute_value(self, name, value):
- self._attributes[name].value = value
-
- def set_attribute_readonly(self, name, readonly = True):
- self._attributes[name].readonly = (readonly == True)
-
- def get_attribute_value(self, name):
- return self._attributes[name].value
-
- def get_attribute_help(self, name):
- return self._attributes[name].help
-
- def get_attribute_type(self, name):
- return self._attributes[name].type
-
- def get_attribute_range(self, name):
- if not self._attributes[name].range:
- return (None, None)
- return self._attributes[name].range
-
- def get_attribute_allowed(self, name):
- return self._attributes[name].allowed
-
- def get_attribute_readonly(self, name):
- return self._attributes[name].readonly
-
- def get_attribute_visible(self, name):
- return self._attributes[name].visible
-
- def is_attribute_modified(self, name):
- return self._attributes[name].modified
-
- def add_attribute(self, name, help, type, value = None, range = None,
- allowed = None, readonly = False, visible = True,
- validation_function = None):
- if name in self._attributes:
- raise AttributeError("Attribute %s already exists" % name)
- attribute = Attribute(name, help, type, value, range, allowed, readonly,
- visible, validation_function)
- self._attributes[name] = attribute
-
- def del_attribute(self, name):
- del self._attributes[name]
-
- def has_attribute(self, name):
- return name in self._attributes
-
- def destroy(self):
- self._attributes = dict()
-
class Attribute(object):
+ ### Attribute types
STRING, BOOL, ENUM, DOUBLE, INTEGER = (
"STRING", "BOOL", "ENUM", "DOUBLE", "INTEGER")
-
types = [STRING, BOOL, ENUM, DOUBLE, INTEGER]
+ ### Attribute Flags
+ NoFlags = 0x00
+ # Attribute is only modifiable during experiment design
+ DesignOnly = 0x01
+ # Attribute is read only and can't be modified by the user
+ # Note: ReadOnly implies DesignOnly
+ ReadOnly = 0x03
+ # Attribute is invisible to the user
+ # Note: Invisible implies ReadOnly and DesignOnly
+ Invisible = 0x07
+ # Attribute has no default value in the testbed instance.
+ # So it needs to be set explicitely
+ HasNoDefaultValue = 0x08
+
def __init__(self, name, help, type, value = None, range = None,
- allowed = None, readonly = False, visible = True,
- validation_function = None):
+ allowed = None, flags = NoFlags, validation_function = None):
if not type in Attribute.types:
raise AttributeError("invalid type %s " % type)
self.name = name
self._type = type
self._help = help
self._value = value
- self._validation_function = validation_function
- # readonly attributes can be seen but not changed by users
- self._readonly = (readonly == True)
- # invisible attributes cannot be seen or changed by users
- self._visible = (visible == True)
- self._modified = False
+ self._flags = flags
# range: max and min possible values
self._range = range
# list of possible values
self._allowed = allowed
+ self._validation_function = validation_function
+ self._modified = False
@property
def type(self):
return self._help
@property
- def visible(self):
- return self._visible
+ def flags(self):
+ return self._flags
@property
- def readonly(self):
- return self._readonly
+ def invsible(self):
+ return (self._flags & Attribute.Invisible) == Attribute.Invisible
+
+ @property
+ def read_only(self):
+ return (self._flags & Attribute.ReadOnly) == Attribute.ReadOnly
+
+ @property
+ def has_no_default_value(self):
+ return (self._flags & Attribute.HasNoDefaultValue) == \
+ Attribute.HasNoDefaultValue
+
+ @property
+ def design_only(self):
+ return (self._flags & Attribute.DesignOnly) == Attribute.DesignOnly
@property
def modified(self):
def _is_valid(self, value):
return not self._validation_function or self._validation_function(value)
+class AttributesMap(object):
+ """AttributesMap is the base class for every object whose attributes
+ are going to be manipulated by the end-user in a script or GUI.
+ """
+ def __init__(self):
+ self._attributes = dict()
+
+ @property
+ def attributes(self):
+ return self._attributes.values()
+
+ @property
+ def attributes_name(self):
+ return self._attributes.keys()
+
+ def set_attribute_value(self, name, value):
+ self._attributes[name].value = value
+
+ def get_attribute_value(self, name):
+ return self._attributes[name].value
+
+ def get_attribute_help(self, name):
+ return self._attributes[name].help
+
+ def get_attribute_type(self, name):
+ return self._attributes[name].type
+
+ def get_attribute_range(self, name):
+ if not self._attributes[name].range:
+ return (None, None)
+ return self._attributes[name].range
+
+ def get_attribute_allowed(self, name):
+ return self._attributes[name].allowed
+
+ def is_attribute_read_only(self, name):
+ return self._attributes[name].read_only
+
+ def is_attribute_invisible(self, name):
+ return self._attributes[name].invisible
+
+ def is_attribute_design_only(self, name):
+ return self._attributes[name].design_only
+
+ def has_attribute_no_default_value(self, name):
+ return self._attributes[name].has_no_default_value
+
+ def is_attribute_modified(self, name):
+ return self._attributes[name].modified
+
+ def add_attribute(self, name, help, type, value = None, range = None,
+ allowed = None, flags = Attribute.NoFlags, validation_function = None):
+ if name in self._attributes:
+ raise AttributeError("Attribute %s already exists" % name)
+ attribute = Attribute(name, help, type, value, range, allowed, flags,
+ validation_function)
+ self._attributes[name] = attribute
+
+ def del_attribute(self, name):
+ del self._attributes[name]
+
+ def has_attribute(self, name):
+ return name in self._attributes
+
+ def destroy(self):
+ self._attributes = dict()
+
help = "If set, this address will automatically be assigned",
type = Attribute.BOOL,
value = False,
+ flags = Attribute.DesignOnly,
validation_function = validation.is_bool)
self.add_attribute(name = "Family",
help = "Address family type: AF_INET, AFT_INET6",
type = Attribute.INTEGER,
value = family,
- readonly = True)
+ flags = Attribute.ReadOnly | Attribute.HasNoDefaultValue,
+ validation_function = validation.is_integer)
address_validation = validation.is_ip4_address if family == AF_INET \
else validation.is_ip6_address
self.add_attribute(name = "Address",
help = "Address number",
type = Attribute.STRING,
+ flags = Attribute.HasNoDefaultValue,
validation_function = address_validation)
prefix_range = (0, 32) if family == AF_INET else (0, 128)
self.add_attribute(name = "NetPrefix",
type = Attribute.INTEGER,
range = prefix_range,
value = 24 if family == AF_INET else 64,
+ flags = Attribute.HasNoDefaultValue,
validation_function = validation.is_integer)
if family == AF_INET:
self.add_attribute(name = "Broadcast",
help = "Address family type: AF_INET, AFT_INET6",
type = Attribute.INTEGER,
value = family,
- readonly = True)
+ flags = Attribute.ReadOnly | Attribute.HasNoDefaultValue,
+ validation_function = validation.is_integer)
address_validation = validation.is_ip4_address if family == AF_INET \
else validation.is_ip6_address
self.add_attribute(name = "Destination",
self.add_attribute(name = "NetPrefix",
help = "Network destination prefix",
type = Attribute.INTEGER,
+ flags = Attribute.HasNoDefaultValue,
prefix_range = prefix_range,
validation_function = validation.is_integer)
self.add_attribute(name = "NextHop",
help = "Address for the next hop",
type = Attribute.STRING,
+ flags = Attribute.HasNoDefaultValue,
validation_function = address_validation)
class Box(AttributesMap):
self._traces[trace.trace_id] = tr
for attr in factory.box_attributes:
self.add_attribute(attr.name, attr.help, attr.type, attr.value,
- attr.range, attr.allowed, attr.readonly, attr.visible,
+ attr.range, attr.allowed, attr.flags,
attr.validation_function)
for attr in factory.attributes:
if attr.modified:
self._traces.append(trace)
def add_box_attribute(self, name, help, type, value = None, range = None,
- allowed = None, readonly = False, visible = True,
- validation_function = None):
- attribute = Attribute(name, help, type, value, range, allowed, readonly,
- visible, validation_function)
+ allowed = None, flags = Attribute.NoFlags, validation_function = None):
+ attribute = Attribute(name, help, type, value, range, allowed, flags,
+ validation_function)
self._box_attributes.append(attribute)
def create(self, guid, testbed_description):
metadata = Metadata(provider.testbed_id, provider.testbed_version)
for attr in metadata.testbed_attributes().attributes:
self.add_attribute(attr.name, attr.help, attr.type, attr.value,
- attr.range, attr.allowed, attr.readonly, attr.visible,
+ attr.range, attr.allowed, attr.flags,
attr.validation_function)
@property
for (autoconf, address, family, netprefix, broadcast) in \
data.get_address_data(guid):
if address != None:
- # TODO: BUG!!! Hardcodeado!!!!!! XXXXXXXXX CORREGIR!!!
- family = 0
- netprefix = 24
instance.add_adddress(guid, family, address, netprefix,
broadcast)
for (family, destination, netprefix, nexthop) in \
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-from nepi.core.attributes import AttributesMap
+from nepi.core.attributes import Attribute, AttributesMap
import sys
class VersionedMetadataInfo(object):
"value": default attribute value,
"range": (maximum, minimun) values else None if not defined,
"allowed": array of posible values,
- "readonly": whether the attribute is read only for the user,
- "visible": whether the attribute is visible for the user,
+ "flags": attributes flags,
"validation_function": validation function for the attribute
})
"""
"value": default attribute value,
"range": (maximum, minimun) values else None if not defined,
"allowed": array of posible values,
- "readonly": whether the attribute is read only for the user,
- "visible": whether the attribute is visible for the user,
+ "flags": attributes flags,
"validation_function": validation function for the attribute
})
]
value = attribute_info["value"]
range = attribute_info["range"]
allowed = attribute_info["allowed"]
- readonly = attribute_info["readonly"]
- visible = attribute_info["visible"]
+ flags = attribute_info["flags"] if "flags" in attribute_info \
+ else Attribute.NoFlags
validation_function = attribute_info["validation_function"]
attributes.add_attribute(name, help, type, value,
- range, allowed, readonly, visible, validation_function)
+ range, allowed, flags, validation_function)
return attributes
def build_design_factories(self):
value = attribute_info["value"]
range = attribute_info["range"]
allowed = attribute_info["allowed"]
- readonly = attribute_info["readonly"]
- visible = attribute_info["visible"]
+ flags = attribute_info["flags"] if "flags" in attribute_info \
+ else Attribute.NoFlags
validation_function = attribute_info["validation_function"]
if box_attributes:
factory.add_box_attribute(name, help, type, value, range,
- allowed, readonly, visible, validation_function)
+ allowed, flags, validation_function)
else:
factory.add_attribute(name, help, type, value, range,
- allowed, readonly, visible, validation_function)
+ allowed, flags, validation_function)
def _add_design_traces(self, factory, info):
if "traces" in info:
class TestbedInstance(execute.TestbedInstance):
def __init__(self, testbed_id, testbed_version):
super(TestbedInstance, self).__init__(testbed_id, testbed_version)
+ self._started = False
# testbed attributes for validation
self._attributes = None
# element factories for validation
if not factory.has_attribute(name):
raise RuntimeError("Invalid attribute %s for element type %s" %
(name, factory_id))
+ if self._started and factory.is_attribute_design_only(name):
+ raise RuntimeError("Attribute %s can only be modified during experiment design" % name)
factory.set_attribute_value(name, value)
if guid not in self._set:
self._set[guid] = dict()
parameters = dict() if guid not in self._create_set else \
self._create_set[guid]
start_function(self, guid, parameters, traces)
+ self._started = True
def action(self, time, guid, action):
raise NotImplementedError
"value": False,
"range": None,
"allowed": None,
- "readonly": False,
- "visible": True,
+ "flags": Attribute.DesignOnly,
"validation_function": validation.is_bool
}),
"lladdr": dict({
"value": None,
"range": None,
"allowed": None,
- "readonly": False,
- "visible": True,
+ "flags": Attribute.DesignOnly,
"validation_function": validation.is_mac_address
}),
"up": dict({
"value": False,
"range": None,
"allowed": None,
- "readonly": False,
- "visible": True,
"validation_function": validation.is_bool
}),
"device_name": dict({
"value": None,
"range": None,
"allowed": None,
- "readonly": False,
- "visible": True,
+ "flags": Attribute.DesignOnly,
"validation_function": validation.is_string
}),
"mtu": dict({
"value": None,
"range": None,
"allowed": None,
- "readonly": False,
- "visible": True,
"validation_function": validation.is_integer
}),
"broadcast": dict({
"value": None,
"range": None,
"allowed": None,
- "readonly": False,
- "visible": True,
"validation_function": validation.is_string # TODO: should be is address!
}),
"multicast": dict({
"value": False,
"range": None,
"allowed": None,
- "readonly": False,
- "visible": True,
"validation_function": validation.is_bool
}),
"arp": dict({
"value": False,
"range": None,
"allowed": None,
- "readonly": False,
- "visible": True,
"validation_function": validation.is_bool
}),
"command": dict({
"value": None,
"range": None,
"allowed": None,
- "readonly": False,
- "visible": True,
+ "flags": Attribute.DesignOnly,
"validation_function": validation.is_string
}),
"user": dict({
"value": None,
"range": None,
"allowed": None,
- "readonly": False,
- "visible": True,
+ "flags": Attribute.DesignOnly,
"validation_function": validation.is_string
}),
"stdin": dict({
"value": None,
"range": None,
"allowed": None,
- "readonly": False,
- "visible": True,
+ "flags": Attribute.DesignOnly,
"validation_function": validation.is_string
}),
"max_addresses": dict({
"value": None,
"range": None,
"allowed": None,
- "readonly": True,
- "visible": False,
+ "flags": Attribute.Invisible,
"validation_function": validation.is_integer
}),
"family": dict({
"value": AF_INET,
"range": None,
"allowed": None,
- "readonly": True,
- "visible": False,
+ "flags": Attribute.Invisible,
"validation_function": validation.is_integer
}),
})
"value": False,
"range": None,
"allowed": None,
- "readonly": False,
- "visible": True,
"validation_function": validation.is_bool
}),
"home_directory": dict({
"value": False,
"range": None,
"allowed": None,
- "readonly": False,
- "visible": True,
+ "flags": Attribute.DesignOnly,
"validation_function": validation.is_string
})
})
address_tag.setAttribute("AutoConfigure", str(autoconf))
if address:
address_tag.setAttribute("Address", str(address))
- if family:
- address_tag.setAttribute("Family", str(family))
- if netprefix:
- address_tag.setAttribute("NetPrefix", str(netprefix))
+ address_tag.setAttribute("Family", str(family))
+ address_tag.setAttribute("NetPrefix", str(netprefix))
if broadcast:
address_tag.setAttribute("Broadcast", str(broadcast))
if addresses_tag.hasChildNodes():
address_data["AutoConfigure"] = autoconf
if address:
address_data["Address"] = address
- if family:
- address_data["Family"] = family
- if netprefix:
- address_data["NetPrefix"] = netprefix
+ address_data["Family"] = family
+ address_data["NetPrefix"] = netprefix
if broadcast:
address_data["Broadcast"] = broadcast
addresses_data.append(address_data)
def attributes_to_data(self, data, guid, attributes):
for attribute in attributes:
- if attribute.modified:
+ if attribute.modified or attribute.has_no_default_value:
data.add_attribute_data(guid, attribute.name, attribute.value)
def traces_to_data(self, data, guid, traces):
def addresses_to_data(self, data, guid, addresses):
for addr in addresses:
- autoconf = addr.get_attribute_value("AutoConfigure") \
- if addr.is_attribute_modified("AutoConfigure") else None
- address = addr.get_attribute_value("Address") \
- if addr.is_attribute_modified("Address") else None
- netprefix = addr.get_attribute_value("NetPrefix") \
- if addr.is_attribute_modified("NetPrefix") else None
- family = addr.get_attribute_value("Family") \
- if addr.is_attribute_modified("Family") else None
+ autoconf = addr.get_attribute_value("AutoConfigure")
+ address = addr.get_attribute_value("Address")
+ netprefix = addr.get_attribute_value("NetPrefix")
+ family = addr.get_attribute_value("Family")
broadcast = addr.get_attribute_value("Broadcast") \
if addr.has_attribute("Broadcast") and \
- addr.is_attribute_modified("Broadcast") else None
+ addr.is_attribute_modified("Broadcast") else None
data.add_address_data(guid, autoconf, address, family, netprefix,
broadcast)
addr.set_attribute_value("AutoConfigure", autoconf)
if address:
addr.set_attribute_value("Address", address)
- if family:
+ if family != None:
addr.set_attribute_value("Family", family)
- if netprefix:
+ if netprefix != None:
addr.set_attribute_value("NetPrefix", netprefix)
if broadcast:
addr.set_attribute_value("Broadcast", broadcast)