Пример #1
0
    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)
Пример #2
0
        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] = []
Пример #4
0
    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
Пример #5
0
 def reset(self):
     super(NetworkBackendBridgedPyroute2, self).reset()
     log.debug("stopping ipdb instance")
     if self.ipdb:
         self.ipdb.release()
         self.ipdb = None
Пример #6
0
    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)