2 # -*- coding: utf-8 -*-
4 from nepi.core.attributes import Attribute, AttributesMap
5 from nepi.core.connector import ConnectorTypeBase
6 from nepi.util import validation
7 from nepi.util.constants import ApplicationStatus as AS, TIME_NOW
8 from nepi.util.parser._xml import XmlExperimentParser
17 ATTRIBUTE_PATTERN_BASE = re.compile(r"\{#\[(?P<label>[-a-zA-Z0-9._]*)\](?P<expr>(?P<component>\.addr\[[0-9]+\]|\.route\[[0-9]+\]|\.trace\[[0-9]+\])?.\[(?P<attribute>[-a-zA-Z0-9._]*)\])#}")
18 ATTRIBUTE_PATTERN_GUID_SUB = r"{#[%(guid)s]%(expr)s#}"
19 COMPONENT_PATTERN = re.compile(r"(?P<kind>[a-z]*)\[(?P<index>.*)\]")
21 class ConnectorType(ConnectorTypeBase):
22 def __init__(self, testbed_id, factory_id, name, max = -1, min = 0):
23 super(ConnectorType, self).__init__(testbed_id, factory_id, name, max, min)
24 # from_connections -- connections where the other connector is the "From"
25 # to_connections -- connections where the other connector is the "To"
26 # keys in the dictionary correspond to the
27 # connector_type_id for possible connections. The value is a tuple:
28 # (can_cross, connect)
29 # can_cross: indicates if the connection is allowed accros different
31 # code: is the connection function to be invoked when the elements
33 self._from_connections = dict()
34 self._to_connections = dict()
36 def add_from_connection(self, testbed_id, factory_id, name, can_cross,
37 init_code, compl_code):
38 type_id = self.make_connector_type_id(testbed_id, factory_id, name)
39 self._from_connections[type_id] = (can_cross, init_code, compl_code)
41 def add_to_connection(self, testbed_id, factory_id, name, can_cross,
42 init_code, compl_code):
43 type_id = self.make_connector_type_id(testbed_id, factory_id, name)
44 self._to_connections[type_id] = (can_cross, init_code, compl_code)
46 def can_connect(self, testbed_id, factory_id, name, count,
48 connector_type_id = self.make_connector_type_id(testbed_id, factory_id, name)
49 for lookup_type_id in self._type_resolution_order(connector_type_id):
50 if lookup_type_id in self._from_connections:
51 (can_cross, init_code, compl_code) = self._from_connections[lookup_type_id]
52 elif lookup_type_id in self._to_connections:
53 (can_cross, init_code, compl_code) = self._to_connections[lookup_type_id]
57 return not must_cross or can_cross
61 def _connect_to_code(self, testbed_id, factory_id, name,
63 connector_type_id = self.make_connector_type_id(testbed_id, factory_id, name)
64 for lookup_type_id in self._type_resolution_order(connector_type_id):
65 if lookup_type_id in self._to_connections:
66 (can_cross, init_code, compl_code) = self._to_connections[lookup_type_id]
67 if not must_cross or can_cross:
68 return (init_code, compl_code)
72 def connect_to_init_code(self, testbed_id, factory_id, name, must_cross):
73 return self._connect_to_code(testbed_id, factory_id, name, must_cross)[0]
75 def connect_to_compl_code(self, testbed_id, factory_id, name, must_cross):
76 return self._connect_to_code(testbed_id, factory_id, name, must_cross)[1]
78 class Factory(AttributesMap):
79 def __init__(self, factory_id, create_function, start_function,
80 stop_function, status_function,
81 configure_function, preconfigure_function,
83 allow_addresses = False, has_addresses = False,
84 allow_routes = False, has_routes = False):
85 super(Factory, self).__init__()
86 self._factory_id = factory_id
87 self._allow_addresses = bool(allow_addresses)
88 self._allow_routes = bool(allow_routes)
89 self._has_addresses = bool(has_addresses) or self._allow_addresses
90 self._has_routes = bool(has_routes) or self._allow_routes
91 self._create_function = create_function
92 self._start_function = start_function
93 self._stop_function = stop_function
94 self._status_function = status_function
95 self._configure_function = configure_function
96 self._preconfigure_function = preconfigure_function
97 self._prestart_function = prestart_function
98 self._connector_types = dict()
101 self._box_attributes = AttributesMap()
104 def factory_id(self):
105 return self._factory_id
108 def allow_addresses(self):
109 return self._allow_addresses
112 def allow_routes(self):
113 return self._allow_routes
116 def has_addresses(self):
117 return self._has_addresses
120 def has_routes(self):
121 return self._has_routes
124 def box_attributes(self):
125 return self._box_attributes
128 def create_function(self):
129 return self._create_function
132 def prestart_function(self):
133 return self._prestart_function
136 def start_function(self):
137 return self._start_function
140 def stop_function(self):
141 return self._stop_function
144 def status_function(self):
145 return self._status_function
148 def configure_function(self):
149 return self._configure_function
152 def preconfigure_function(self):
153 return self._preconfigure_function
163 def connector_type(self, name):
164 return self._connector_types[name]
166 def add_connector_type(self, connector_type):
167 self._connector_types[connector_type.name] = connector_type
169 def add_trace(self, trace_id):
170 self._traces.append(trace_id)
172 def add_tag(self, tag_id):
173 self._tags.append(tag_id)
175 def add_box_attribute(self, name, help, type, value = None, range = None,
176 allowed = None, flags = Attribute.NoFlags, validation_function = None,
178 self._box_attributes.add_attribute(name, help, type, value, range,
179 allowed, flags, validation_function, category)
181 class TestbedController(object):
182 def __init__(self, testbed_id, testbed_version):
183 self._testbed_id = testbed_id
184 self._testbed_version = testbed_version
187 def testbed_id(self):
188 return self._testbed_id
191 def testbed_version(self):
192 return self._testbed_version
196 raise NotImplementedError
198 def defer_configure(self, name, value):
199 """Instructs setting a configuartion attribute for the testbed instance"""
200 raise NotImplementedError
202 def defer_create(self, guid, factory_id):
203 """Instructs creation of element """
204 raise NotImplementedError
206 def defer_create_set(self, guid, name, value):
207 """Instructs setting an initial attribute on an element"""
208 raise NotImplementedError
210 def defer_factory_set(self, guid, name, value):
211 """Instructs setting an attribute on a factory"""
212 raise NotImplementedError
214 def defer_connect(self, guid1, connector_type_name1, guid2,
215 connector_type_name2):
216 """Instructs creation of a connection between the given connectors"""
217 raise NotImplementedError
219 def defer_cross_connect(self,
220 guid, connector_type_name,
221 cross_guid, cross_testbed_guid,
222 cross_testbed_id, cross_factory_id,
223 cross_connector_type_name):
225 Instructs creation of a connection between the given connectors
226 of different testbed instances
228 raise NotImplementedError
230 def defer_add_trace(self, guid, trace_id):
231 """Instructs the addition of a trace"""
232 raise NotImplementedError
234 def defer_add_address(self, guid, address, netprefix, broadcast):
235 """Instructs the addition of an address"""
236 raise NotImplementedError
238 def defer_add_route(self, guid, destination, netprefix, nexthop, metric = 0):
239 """Instructs the addition of a route"""
240 raise NotImplementedError
243 """After do_setup the testbed initial configuration is done"""
244 raise NotImplementedError
248 After do_create all instructed elements are created and
251 raise NotImplementedError
253 def do_connect_init(self):
255 After do_connect_init all internal connections between testbed elements
258 raise NotImplementedError
260 def do_connect_compl(self):
262 After do_connect all internal connections between testbed elements
265 raise NotImplementedError
267 def do_preconfigure(self):
269 Done just before resolving netrefs, after connection, before cross connections,
270 useful for early stages of configuration, for setting up stuff that might be
271 required for netref resolution.
273 raise NotImplementedError
275 def do_configure(self):
276 """After do_configure elements are configured"""
277 raise NotImplementedError
279 def do_prestart(self):
280 """Before do_start elements are prestart-configured"""
281 raise NotImplementedError
283 def do_cross_connect_init(self, cross_data):
285 After do_cross_connect_init initiation of all external connections
286 between different testbed elements is performed
288 raise NotImplementedError
290 def do_cross_connect_compl(self, cross_data):
292 After do_cross_connect_compl completion of all external connections
293 between different testbed elements is performed
295 raise NotImplementedError
298 raise NotImplementedError
301 raise NotImplementedError
303 def set(self, guid, name, value, time = TIME_NOW):
304 raise NotImplementedError
306 def get(self, guid, name, time = TIME_NOW):
307 raise NotImplementedError
309 def get_route(self, guid, index, attribute):
313 guid: guid of box to query
314 index: number of routing entry to fetch
315 attribute: one of Destination, NextHop, NetPrefix
317 raise NotImplementedError
319 def get_address(self, guid, index, attribute='Address'):
323 guid: guid of box to query
324 index: number of inteface to select
325 attribute: one of Address, NetPrefix, Broadcast
327 raise NotImplementedError
329 def get_attribute_list(self, guid):
330 raise NotImplementedError
332 def get_factory_id(self, guid):
333 raise NotImplementedError
335 def action(self, time, guid, action):
336 raise NotImplementedError
338 def status(self, guid):
339 raise NotImplementedError
341 def trace(self, guid, trace_id, attribute='value'):
342 raise NotImplementedError
344 def traces_info(self):
345 """ dictionary of dictionaries:
351 filesize = size in bytes,
355 raise NotImplementedError
358 raise NotImplementedError
360 class ExperimentController(object):
361 def __init__(self, experiment_xml, root_dir):
362 self._experiment_xml = experiment_xml
363 self._testbeds = dict()
364 self._deployment_config = dict()
365 self._netrefs = collections.defaultdict(set)
366 self._testbed_netrefs = collections.defaultdict(set)
367 self._cross_data = dict()
368 self._root_dir = root_dir
369 self._netreffed_testbeds = set()
370 self._guids_in_testbed_cache = dict()
372 self.persist_experiment_xml()
375 def experiment_xml(self):
376 return self._experiment_xml
381 for testbed_guid in self._testbeds.keys():
382 _guids = self._guids_in_testbed(testbed_guid)
387 def persist_experiment_xml(self):
388 xml_path = os.path.join(self._root_dir, "experiment.xml")
389 f = open(xml_path, "w")
390 f.write(self._experiment_xml)
393 def trace(self, guid, trace_id, attribute='value'):
394 testbed = self._testbed_for_guid(guid)
396 return testbed.trace(guid, trace_id, attribute)
397 raise RuntimeError("No element exists with guid %d" % guid)
399 def traces_info(self):
401 for guid, testbed in self._testbeds.iteritems():
402 tinfo = testbed.traces_info()
404 traces_info[guid] = testbed.traces_info()
408 def _parallel(callables):
411 @functools.wraps(callable)
412 def wrapped(*p, **kw):
417 traceback.print_exc(file=sys.stderr)
418 excs.append(sys.exc_info())
420 threads = [ threading.Thread(target=wrap(callable)) for callable in callables ]
421 for thread in threads:
423 for thread in threads:
426 eTyp, eVal, eLoc = exc
427 raise eTyp, eVal, eLoc
430 parser = XmlExperimentParser()
431 data = parser.from_xml_to_data(self._experiment_xml)
433 self._init_testbed_controllers(data)
435 # persist testbed connection data, for potential recovery
436 self._persist_testbed_proxies()
438 def steps_to_configure(self, allowed_guids):
439 # perform setup in parallel for all test beds,
440 # wait for all threads to finish
441 self._parallel([testbed.do_setup
442 for guid,testbed in self._testbeds.iteritems()
443 if guid in allowed_guids])
445 # perform create-connect in parallel, wait
446 # (internal connections only)
447 self._parallel([testbed.do_create
448 for guid,testbed in self._testbeds.iteritems()
449 if guid in allowed_guids])
451 self._parallel([testbed.do_connect_init
452 for guid,testbed in self._testbeds.iteritems()
453 if guid in allowed_guids])
455 self._parallel([testbed.do_connect_compl
456 for guid,testbed in self._testbeds.iteritems()
457 if guid in allowed_guids])
459 self._parallel([testbed.do_preconfigure
460 for guid,testbed in self._testbeds.iteritems()
461 if guid in allowed_guids])
464 steps_to_configure(self, self._testbeds)
466 if self._netreffed_testbeds:
467 # initally resolve netrefs
468 self.do_netrefs(data, fail_if_undefined=False)
470 # rinse and repeat, for netreffed testbeds
471 netreffed_testbeds = set(self._netreffed_testbeds)
473 self._init_testbed_controllers(data)
475 # persist testbed connection data, for potential recovery
476 self._persist_testbed_proxies()
478 # configure dependant testbeds
479 steps_to_configure(self, netreffed_testbeds)
481 # final netref step, fail if anything's left unresolved
482 self.do_netrefs(data, fail_if_undefined=True)
484 self._program_testbed_cross_connections(data)
486 # perform do_configure in parallel for al testbeds
487 # (it's internal configuration for each)
488 self._parallel([testbed.do_configure
489 for testbed in self._testbeds.itervalues()])
493 #print >>sys.stderr, "DO IT"
497 # cross-connect (cannot be done in parallel)
498 for guid, testbed in self._testbeds.iteritems():
499 cross_data = self._get_cross_data(guid)
500 testbed.do_cross_connect_init(cross_data)
501 for guid, testbed in self._testbeds.iteritems():
502 cross_data = self._get_cross_data(guid)
503 testbed.do_cross_connect_compl(cross_data)
507 # Last chance to configure (parallel on all testbeds)
508 self._parallel([testbed.do_prestart
509 for testbed in self._testbeds.itervalues()])
513 # start experiment (parallel start on all testbeds)
514 self._parallel([testbed.start
515 for testbed in self._testbeds.itervalues()])
519 def _clear_caches(self):
520 # Cleaning cache for safety.
521 self._guids_in_testbed_cache = dict()
523 def _persist_testbed_proxies(self):
524 TRANSIENT = ('Recover',)
526 # persist access configuration for all testbeds, so that
527 # recovery mode can reconnect to them if it becomes necessary
528 conf = ConfigParser.RawConfigParser()
529 for testbed_guid, testbed_config in self._deployment_config.iteritems():
530 testbed_guid = str(testbed_guid)
531 conf.add_section(testbed_guid)
532 for attr in testbed_config.attributes_list:
533 if attr not in TRANSIENT:
534 conf.set(testbed_guid, attr,
535 testbed_config.get_attribute_value(attr))
537 f = open(os.path.join(self._root_dir, 'deployment_config.ini'), 'w')
541 def _load_testbed_proxies(self):
546 BOOLEAN : 'getboolean',
549 # deferred import because proxy needs
550 # our class definitions to define proxies
551 import nepi.util.proxy as proxy
553 conf = ConfigParser.RawConfigParser()
554 conf.read(os.path.join(self._root_dir, 'deployment_config.ini'))
555 for testbed_guid in conf.sections():
556 testbed_config = proxy.AccessConfiguration()
557 for attr in conf.options(testbed_guid):
558 testbed_config.set_attribute_value(attr,
559 conf.get(testbed_guid, attr) )
561 testbed_guid = str(testbed_guid)
562 conf.add_section(testbed_guid)
563 for attr in testbed_config.attributes_list:
564 if attr not in TRANSIENT:
565 getter = getattr(conf, TYPEMAP.get(
566 testbed_config.get_attribute_type(attr),
568 testbed_config.set_attribute_value(
569 testbed_guid, attr, getter(attr))
571 def _unpersist_testbed_proxies(self):
573 os.remove(os.path.join(self._root_dir, 'deployment_config.ini'))
575 # Just print exceptions, this is just cleanup
577 ######## BUG ##########
578 #BUG: If the next line is uncomented pyQt explodes when shutting down the experiment !!!!!!!!
579 #traceback.print_exc(file=sys.stderr)
582 for testbed in self._testbeds.values():
584 self._unpersist_testbed_proxies()
587 # reload perviously persisted testbed access configurations
588 self._load_testbed_proxies()
590 # recreate testbed proxies by reconnecting only
591 self._init_testbed_controllers(recover = True)
593 # another time, for netrefs
594 self._init_testbed_controllers(recover = True)
596 def is_finished(self, guid):
597 testbed = self._testbed_for_guid(guid)
599 return testbed.status(guid) == AS.STATUS_FINISHED
600 raise RuntimeError("No element exists with guid %d" % guid)
602 def set(self, guid, name, value, time = TIME_NOW):
603 testbed = self._testbed_for_guid(guid)
605 testbed.set(guid, name, value, time)
607 raise RuntimeError("No element exists with guid %d" % guid)
609 def get(self, guid, name, time = TIME_NOW):
610 testbed = self._testbed_for_guid(guid)
612 return testbed.get(guid, name, time)
613 raise RuntimeError("No element exists with guid %d" % guid)
615 def get_deferred(self, guid, name, time = TIME_NOW):
616 testbed = self._testbed_for_guid(guid)
618 return testbed.get_deferred(guid, name, time)
619 raise RuntimeError("No element exists with guid %d" % guid)
621 def get_factory_id(self, guid):
622 testbed = self._testbed_for_guid(guid)
624 return testbed.get_factory_id(guid)
625 raise RuntimeError("No element exists with guid %d" % guid)
627 def get_testbed_id(self, guid):
628 testbed = self._testbed_for_guid(guid)
630 return testbed.testbed_id
631 raise RuntimeError("No element exists with guid %d" % guid)
633 def get_testbed_version(self, guid):
634 testbed = self._testbed_for_guid(guid)
636 return testbed.testbed_version
637 raise RuntimeError("No element exists with guid %d" % guid)
641 for testbed in self._testbeds.values():
645 exceptions.append(sys.exc_info())
646 for exc_info in exceptions:
647 raise exc_info[0], exc_info[1], exc_info[2]
649 def _testbed_for_guid(self, guid):
650 for testbed_guid in self._testbeds.keys():
651 if guid in self._guids_in_testbed(testbed_guid):
652 return self._testbeds[testbed_guid]
655 def _guids_in_testbed(self, testbed_guid):
656 if testbed_guid not in self._testbeds:
658 if testbed_guid not in self._guids_in_testbed_cache:
659 self._guids_in_testbed_cache[testbed_guid] = \
660 set(self._testbeds[testbed_guid].guids)
661 return self._guids_in_testbed_cache[testbed_guid]
664 def _netref_component_split(component):
665 match = COMPONENT_PATTERN.match(component)
667 return match.group("kind"), match.group("index")
669 return component, None
671 _NETREF_COMPONENT_GETTERS = {
673 lambda testbed, guid, index, name:
674 testbed.get_address(guid, int(index), name),
676 lambda testbed, guid, index, name:
677 testbed.get_route(guid, int(index), name),
679 lambda testbed, guid, index, name:
680 testbed.trace(guid, index, name),
682 lambda testbed, guid, index, name:
683 testbed.get(guid, name),
686 def resolve_netref_value(self, value, failval = None):
687 match = ATTRIBUTE_PATTERN_BASE.search(value)
689 label = match.group("label")
690 if label.startswith('GUID-'):
691 ref_guid = int(label[5:])
693 expr = match.group("expr")
694 component = (match.group("component") or "")[1:] # skip the dot
695 attribute = match.group("attribute")
697 # split compound components into component kind and index
698 # eg: 'addr[0]' -> ('addr', '0')
699 component, component_index = self._netref_component_split(component)
701 # find object and resolve expression
702 for ref_testbed_guid, ref_testbed in self._testbeds.iteritems():
703 if component not in self._NETREF_COMPONENT_GETTERS:
704 raise ValueError, "Malformed netref: %r - unknown component" % (expr,)
705 elif ref_guid not in self._guids_in_testbed(ref_testbed_guid):
708 ref_value = self._NETREF_COMPONENT_GETTERS[component](
709 ref_testbed, ref_guid, component_index, attribute)
711 return value.replace(match.group(), ref_value)
712 # couldn't find value
715 def do_netrefs(self, data, fail_if_undefined = False):
717 for (testbed_guid, guid), attrs in self._netrefs.items():
718 testbed = self._testbeds.get(testbed_guid)
719 if testbed is not None:
720 for name in set(attrs):
721 value = testbed.get(guid, name)
722 if isinstance(value, basestring):
723 ref_value = self.resolve_netref_value(value)
724 if ref_value is not None:
725 testbed.set(guid, name, ref_value)
727 elif fail_if_undefined:
728 raise ValueError, "Unresolvable netref in: %r=%r" % (name,value,)
730 del self._netrefs[(testbed_guid, guid)]
733 for testbed_guid, attrs in self._testbed_netrefs.items():
734 tb_data = dict(data.get_attribute_data(testbed_guid))
736 for name in set(attrs):
737 value = tb_data.get(name)
738 if isinstance(value, basestring):
739 ref_value = self.resolve_netref_value(value)
740 if ref_value is not None:
741 data.set_attribute_data(testbed_guid, name, ref_value)
743 elif fail_if_undefined:
744 raise ValueError, "Unresolvable netref in: %r" % (value,)
746 del self._testbed_netrefs[testbed_guid]
749 def _init_testbed_controllers(self, data, recover = False):
750 blacklist_testbeds = set(self._testbeds)
751 element_guids = list()
753 data_guids = data.guids
755 # create testbed controllers
756 for guid in data_guids:
757 if data.is_testbed_data(guid):
758 if guid not in self._testbeds:
759 self._create_testbed_controller(guid, data, element_guids,
762 (testbed_guid, factory_id) = data.get_box_data(guid)
763 if testbed_guid not in blacklist_testbeds:
764 element_guids.append(guid)
765 label = data.get_attribute_data(guid, "label")
766 if label is not None:
767 if label in label_guids:
768 raise RuntimeError, "Label %r is not unique" % (label,)
769 label_guids[label] = guid
771 # replace references to elements labels for its guid
772 self._resolve_labels(data, data_guids, label_guids)
774 # program testbed controllers
776 self._program_testbed_controllers(element_guids, data)
778 def _resolve_labels(self, data, data_guids, label_guids):
779 netrefs = self._netrefs
780 testbed_netrefs = self._testbed_netrefs
781 for guid in data_guids:
782 for name, value in data.get_attribute_data(guid):
783 if isinstance(value, basestring):
784 match = ATTRIBUTE_PATTERN_BASE.search(value)
786 label = match.group("label")
787 if not label.startswith('GUID-'):
788 ref_guid = label_guids.get(label)
789 if ref_guid is not None:
790 value = ATTRIBUTE_PATTERN_BASE.sub(
791 ATTRIBUTE_PATTERN_GUID_SUB % dict(
792 guid = 'GUID-%d' % (ref_guid,),
793 expr = match.group("expr"),
796 data.set_attribute_data(guid, name, value)
798 # memorize which guid-attribute pairs require
799 # postprocessing, to avoid excessive controller-testbed
800 # communication at configuration time
801 # (which could require high-latency network I/O)
802 if not data.is_testbed_data(guid):
803 (testbed_guid, factory_id) = data.get_box_data(guid)
804 netrefs[(testbed_guid, guid)].add(name)
806 testbed_netrefs[guid].add(name)
808 def _create_testbed_controller(self, guid, data, element_guids, recover):
809 (testbed_id, testbed_version) = data.get_testbed_data(guid)
810 deployment_config = self._deployment_config.get(guid)
812 # deferred import because proxy needs
813 # our class definitions to define proxies
814 import nepi.util.proxy as proxy
816 if deployment_config is None:
818 deployment_config = proxy.AccessConfiguration()
820 for (name, value) in data.get_attribute_data(guid):
821 if value is not None and deployment_config.has_attribute(name):
822 # if any deployment config attribute has a netref, we can't
823 # create this controller yet
824 if isinstance(value, basestring) and ATTRIBUTE_PATTERN_BASE.search(value):
825 # remember to re-issue this one
826 self._netreffed_testbeds.add(guid)
829 # copy deployment config attribute
830 deployment_config.set_attribute_value(name, value)
833 self._deployment_config[guid] = deployment_config
835 if deployment_config is not None:
836 # force recovery mode
837 deployment_config.set_attribute_value("recover",recover)
839 testbed = proxy.create_testbed_controller(testbed_id,
840 testbed_version, deployment_config)
841 for (name, value) in data.get_attribute_data(guid):
842 testbed.defer_configure(name, value)
843 self._testbeds[guid] = testbed
844 if guid in self._netreffed_testbeds:
845 self._netreffed_testbeds.remove(guid)
847 def _program_testbed_controllers(self, element_guids, data):
848 for guid in element_guids:
849 (testbed_guid, factory_id) = data.get_box_data(guid)
850 testbed = self._testbeds.get(testbed_guid)
852 testbed.defer_create(guid, factory_id)
853 for (name, value) in data.get_attribute_data(guid):
854 # Try to resolve create-time netrefs, if possible
855 if isinstance(value, basestring) and ATTRIBUTE_PATTERN_BASE.search(value):
857 nuvalue = self.resolve_netref_value(value)
859 # Any trouble means we're not in shape to resolve the netref yet
861 if nuvalue is not None:
862 # Only if we succeed we remove the netref deferral entry
864 data.set_attribute_data(guid, name, value)
865 if (testbed_guid, guid) in self._netrefs:
866 self._netrefs[(testbed_guid, guid)].discard(name)
867 testbed.defer_create_set(guid, name, value)
869 for guid in element_guids:
870 (testbed_guid, factory_id) = data.get_box_data(guid)
871 testbed = self._testbeds.get(testbed_guid)
873 for (connector_type_name, cross_guid, cross_connector_type_name) \
874 in data.get_connection_data(guid):
875 (testbed_guid, factory_id) = data.get_box_data(guid)
876 (cross_testbed_guid, cross_factory_id) = data.get_box_data(
878 if testbed_guid == cross_testbed_guid:
879 testbed.defer_connect(guid, connector_type_name,
880 cross_guid, cross_connector_type_name)
881 for trace_id in data.get_trace_data(guid):
882 testbed.defer_add_trace(guid, trace_id)
883 for (address, netprefix, broadcast) in \
884 data.get_address_data(guid):
886 testbed.defer_add_address(guid, address, netprefix,
888 for (destination, netprefix, nexthop, metric) in data.get_route_data(guid):
889 testbed.defer_add_route(guid, destination, netprefix, nexthop, metric)
891 def _program_testbed_cross_connections(self, data):
892 data_guids = data.guids
894 for guid in data_guids:
895 if not data.is_testbed_data(guid):
896 (testbed_guid, factory_id) = data.get_box_data(guid)
897 testbed = self._testbeds.get(testbed_guid)
899 for (connector_type_name, cross_guid, cross_connector_type_name) \
900 in data.get_connection_data(guid):
901 (testbed_guid, factory_id) = data.get_box_data(guid)
902 (cross_testbed_guid, cross_factory_id) = data.get_box_data(
904 if testbed_guid != cross_testbed_guid:
905 cross_testbed = self._testbeds[cross_testbed_guid]
906 cross_testbed_id = cross_testbed.testbed_id
907 testbed.defer_cross_connect(guid, connector_type_name, cross_guid,
908 cross_testbed_guid, cross_testbed_id, cross_factory_id,
909 cross_connector_type_name)
910 # save cross data for later
911 self._add_crossdata(testbed_guid, guid, cross_testbed_guid,
914 def _add_crossdata(self, testbed_guid, guid, cross_testbed_guid, cross_guid):
915 if testbed_guid not in self._cross_data:
916 self._cross_data[testbed_guid] = dict()
917 if cross_testbed_guid not in self._cross_data[testbed_guid]:
918 self._cross_data[testbed_guid][cross_testbed_guid] = set()
919 self._cross_data[testbed_guid][cross_testbed_guid].add(cross_guid)
921 def _get_cross_data(self, testbed_guid):
923 if not testbed_guid in self._cross_data:
925 for cross_testbed_guid, guid_list in \
926 self._cross_data[testbed_guid].iteritems():
927 cross_data[cross_testbed_guid] = dict()
928 cross_testbed = self._testbeds[cross_testbed_guid]
929 for cross_guid in guid_list:
930 elem_cross_data = dict(
932 _testbed_guid = cross_testbed_guid,
933 _testbed_id = cross_testbed.testbed_id,
934 _testbed_version = cross_testbed.testbed_version)
935 cross_data[cross_testbed_guid][cross_guid] = elem_cross_data
936 attributes_list = cross_testbed.get_attribute_list(cross_guid)
937 for attr_name in attributes_list:
938 attr_value = cross_testbed.get(cross_guid, attr_name)
939 elem_cross_data[attr_name] = attr_value