def _build_qemu_nic_command(self): # TODO: ABSTRACT COMMAND GENERATION! cmd_setup_nics = [] def add_if(_if, _if_name, vlan): cmd_setup_nics.append( self._build_qemu_nic_command_internal(_if, _if_name, vlan)) cnt_normal_iface = 0 log.debug("using ifaces: '%s'", self.emulation_node.network_mixin.interfaces) # NOTE: sort the interfaces so that the Management interface is the last one for vlan, _if in enumerate( self.emulation_node.network_mixin.interfaces): _if_name = None if type(_if) in (Interface.HubWiFi, Interface.Management): _if_name = singletons.network_backend.get_tap_name( self.id, _if) else: # create for each connection a tap device # NOTE: for each new tap device we need to adjust the `nr_host_interface` # NOTE: otherwise we have duplicate interface names! # iterate over interfaces and connections _if_name = singletons.network_backend.get_tap_name( self.id, _if) cnt_normal_iface += 1 log.debug('add_if(%s,%s,%s)', repr(_if), _if_name, vlan) add_if(_if, _if_name, vlan) return '\n'.join(cmd_setup_nics)
def before_link_initial_start(self, network_backend, emulation_node_x, emulation_node_y, interface_x, interface_y, connection_info, start_activated=False, **kwargs): """ Check if a connection shall be created between the nodes and the interfaces. Create for ach new connection a bridge. """ connection = None # let the NetworkBackend decide whether the links really shall be connected connected, bridge = self.create_connection(emulation_node_x, emulation_node_y, interface_x, interface_y) if connected: # create connection connection = self.network_backend_bootstrapper.connection_type( emulation_node_x, emulation_node_y, interface_x, interface_y, connection_info) # TODO: does nothing atm connection.start(self) log.debug("created connection between: %s@%s, %s@%s", emulation_node_x, interface_x, emulation_node_y, interface_y) return connected, bridge, connection
def reset_simulation_scenario_state(self): from miniworld import log from miniworld.Config import config log.info("resetting simulation_scenario_state") # objects may require singletons, hence first garbage collect objects for obj in self[KEY_OBJECT]: log.debug("resetting '%s'", obj) try: obj.reset() except NotImplementedError: log.critical( "Object '%s@%s' did not implement the reset() method!", obj, obj.__class__) except Exception as e: if config.is_log_cleanup(): log.exception(e) for singleton in self[KEY_SINGLETON]: log.debug("resetting '%s'", singleton) try: singleton.reset() except Exception as e: if config.is_log_cleanup(): log.exception(e) log.info("clearing simulate state objects ...") self[KEY_OBJECT] = []
def create_n_connect_central_nodes(self, interfaces): """ Parameters ---------- interfaces Returns ------- dict<int, CentralNode> """ # create CentralNode s but only if there is a HubWiFi interface # TODO: REMOVE cnt = 0 central_nodes_dict = {} for _if in filter(lambda x: is_central_node_interface(x), interfaces): if cnt == 1: raise ValueError( "Only one '%s' interface support at the moment!" % HubWiFi) # TODO: REFACTOR! # TODO: #54: make amount of nodes configurable count_central_nodes = 1 # multiprocessing.cpu_count() network_backend_bootstrapper = NetworkBackends.get_current_network_backend_bootstrapper( ) for _ in range(0, count_central_nodes): # create an own network backend for each node # new_emulation_node_network_backend = network_backend_bootstrapper.emulation_node_network_backend_type(network_backend_bootstrapper) central_node = network_backend_bootstrapper.central_node_type( network_backend_bootstrapper) # TODO: #54 make configurable! log.debug("creating CentralNode with id: %s", central_node.id) central_node.start(switch=False) central_nodes_dict[central_node.id] = central_node # create a reference so that the :py:class:`.AbstractConnection` can access it # to make a connection self.switches[_if] = central_node.switch # connect CentralHub s pairwise to each other central_nodes = central_nodes_dict.values() log.info("connecting CentralHubs pairwise to each other ...") # for i1 in range(0, count_central_nodes): # for i2 in range(0, count_central_nodes): # if i1 != i2: for i1, i2 in zip(range(0, count_central_nodes), range(1, count_central_nodes)): node_x, node_y = central_nodes[i1], central_nodes[i2] node_x.connect_to_emu_node(self, node_y) cnt += 1 return central_nodes_dict
def reset(self): super(NetworkBackendBridgedPyroute2, self).reset() log.debug("stopping ipdb instance") if self.ipdb: self.ipdb.release() self.ipdb = None
def _start(self, path_qemu_base_image): """ Start the QEMU instance: 1. Set qemu process ownership 2. Try to load a snapshot, kill the old process and snapshot if it fails 3. Build the command line for Qemu 3.1 Check if KVM is available 3.2 Build NIC command 3.3 Create disk overlay 3.4 Include user command line additions 4. Start the Qemu process, take process ownership for snapshot mode (to keep the snapshots alive in the process) 5. Enter the Qemu Monitor first, then the serial console 6. Boot VM 7. Set event progress 8. Create snapshot 9. Store Qemu process in singleton map 10. Call after_start Parameters ---------- path_qemu_base_image : str Path to the base image used as read layer. Raises ------ QemuBootWaitTimeout Timeout while booting the vm. REPLTimeout Timeout while doing stuff on the shell. InvalidImage """ if os.path.getsize(path_qemu_base_image) == 0: raise self.InvalidImage() es = singletons.event_system self.process = None snapshot_load_failed = False if config.is_qemu_snapshot_boot(): self.process = singletons.qemu_process_singletons.get(self.id) take_process_ownership = False else: take_process_ownership = True def kill_qemu_snapshot_process(): # kill old qemu process and snapshot # terminate old qemu process self.process.kill() self.process.wait() self.process = None # check if a snapshot exists if self.process is not None: # only snapshot boot if scenario did not change # TODO: unit test if singletons.simulation_manager.scenario_changed: snapshot_load_failed = True log.info( 'scenario config changed -> no snapshot boot possible') else: id_snapshot = self.get_snapshot_id() self.nlog.info("loading vm snapshot %s", id_snapshot) t_start = time.time() try: self.monitor_repl.loadvm(id_snapshot) t_end = time.time() log.debug("loaded snapshot in %0.2f seconds", t_end - t_start) self.booted_from_snapshot = True except QemuMonitorSnapshotLoadError: snapshot_load_failed = True if snapshot_load_failed: kill_qemu_snapshot_process() if self.process is None or snapshot_load_failed: self.monitor_repl = QemuMonitorRepl(self) # build qemu shell command from template qemu_cmd = self._build_qemu_command(path_qemu_base_image) # run the qemu command self.process = singletons.shell_helper.run_shell_async( self.id, qemu_cmd, prefixes=[self.shell_prefix], # we are responsible ourselves for killing the process take_process_ownership=take_process_ownership) # we need to connect to both sockets once, first to the qemu monitor socket (this creates the serial shell socket) self.monitor_repl.run_commands_eager(StringIO("\n")) # NetUtil.wait_until_uds_reachable(self.path_uds_socket) booted_signal = scenario_config.get_signal_boot_completed( node_id=self.id) shell_prompt = scenario_config.get_shell_prompt(node_id=self.id) # boot signal and shell prompt supplied # use boot signal for boot and shell prompt for entering the shell if booted_signal is not None and shell_prompt is not None: func = NetUtil.wait_for_socket_result booted_signal = scenario_config.get_signal_boot_completed( node_id=self.id) else: booted_signal = scenario_config.get_shell_prompt( node_id=self.id) func = NetUtil.wait_for_boot if scenario_config.is_provisioning_boot_mode_selectors(): # connected via unix domain socket self.wait_until_qemu_booted( func, self.log_path_qemu_boot, booted_signal=booted_signal, # TODO: timeout=config.get_repl_timeout()) else: raise ValueError("Unknown boot mode!") # notify EventSystem that the VM booted successfully with es.event_no_init_finish(es.EVENT_VM_BOOT) as ev: ev.update([self.id], 1.0) if not self.booted_from_snapshot: # connect to the serial shell self.run_commands_eager(StringIO("\n")) # notify EventSystem that the VMs shell is ready with es.event_no_init_finish(es.EVENT_VM_SHELL_READY) as ev: ev.update([self.id], 1.0) self.nlog.info("qemu instance running ...") if config.is_qemu_snapshot_boot(): # store process singleton singletons.qemu_process_singletons[self.id] = self.process self.after_start()
def add_tmp_object_with_simulation_scenario_state(self, obj): # NOTE: str() might have unitialized variables log.debug("adding tmp %s to resettable objects with simulation state", type(obj)) # if not obj in self[KEY_OBJECT]: self[KEY_OBJECT].append(obj)
def add_singleton_with_simulation_scenario_state_(self, singleton_class): log.debug("adding %s to resettable singletons with simulation state", singleton_class) if singleton_class not in self[KEY_SINGLETON]: self[KEY_SINGLETON].append(singleton_class)