Esempio n. 1
0
    def disable_interface(self, interface_disable_id=None, dpid=None):
        """Administratively disable interfaces in the topology."""
        error_list = []  # List of interfaces that were not deactivated.
        msg_error = "Some interfaces couldn't be found and deactivated: "
        if dpid is None:
            dpid = ":".join(interface_disable_id.split(":")[:-1])
        try:
            switch = self.controller.switches[dpid]
        except KeyError as exc:
            return jsonify(f"Switch not found: {exc}"), 404

        if interface_disable_id:
            interface_number = int(interface_disable_id.split(":")[-1])

            try:
                switch.interfaces[interface_number].disable()
            except KeyError as exc:
                error_list.append(f"Switch {dpid} Interface {exc}")
        else:
            for interface in switch.interfaces.values():
                interface.disable()
        if not error_list:
            log.info(f"Storing administrative state for disabled interfaces.")
            self.save_status_on_storehouse()
            return jsonify("Operation successful"), 200
        return jsonify({msg_error: error_list}), 409
Esempio n. 2
0
    def _email_send(self, **kwargs):
        """
        Send an email through SMTP
        """
        try:

            d = {
                'm_from': settings.m_from,
                'm_to': settings.m_to,
                'm_subject': settings.m_subject,
                'm_body': settings.m_body,
                'm_server_fqdn': settings.m_server_fqdn,
                'm_server_port': settings.m_server_port
            }

            # overrides global setting values
            for k, v in kwargs.items():
                d[k] = v

            msg = MIMEText(d['m_body'])
            msg['Subject'] = d['m_subject']
            msg['From'] = d['m_from']
            msg['To'] = d['m_to']

            s = smtplib.SMTP(host=d['m_server_fqdn'], port=d['m_server_port'])
            # m_to has to be a list in case of multiple destinations
            s.sendmail(d['m_from'], d['m_to'].split(", "), msg.as_string())
            s.quit()
            log.info('An email was sent to: {0}'.format(d['m_to']))

        except smtplib.SMTPException as e:
            log.error(str(e))
            raise
Esempio n. 3
0
    def _save_status_callback(self, _event, data, error):
        """Display the saved network status in the log."""
        if error:
            log.error(f'Can\'t update persistence box {data.box_id}.')

        log.info('Network administrative status saved in '
                 f'{self.namespace}.{data.box_id}')
Esempio n. 4
0
 def execute(self) -> None:
     """Execute."""
     log.info("Starting uvloop")
     self.loop = uvloop.new_event_loop()
     asyncio.set_event_loop(self.loop)
     self._wait_all_dpids(self.dpids)
     self.loop.run_until_complete(self.main_coroutine())
Esempio n. 5
0
    def _get_box_callback(self, event, data, error):
        """Handle get_box method saving the box or logging with the error."""
        if error:
            log.error(f'Box {data.box_id} not found in {data.namespace}.')

        self.box = data
        log.info(f'Box {self.box.box_id} was load from storehouse.')
Esempio n. 6
0
 def _send(self, d):
     """
     Sends this 'd' dict via slacker
     """
     try:
         # if settings wasn't properly setup in the first place
         if not self.has_failed:
             if not d.get('payload'):
                 raise ValueError(
                     "The dictionary should contain at least the 'payload' key-value"
                 )
             slack_msg = ""
             for k in ['source', 'tag', 'payload']:
                 slack_msg = self._parse_str(slack_msg, d.get(k))
             # fallback to #general
             ch = d.get('channel') if d.get('channel') else 'general'
             log.info('channel:{0} msg:{1}'.format(ch, slack_msg))
             self.slack.chat.post_message(ch, slack_msg)
     except requests.exceptions.ConnectionError as e:
         err = "ConnectionError to Slack API. Make sure you are connected and can reach Slack API."
         log.error(err)
         raise ValueError(err)
     except self.error as e:
         err = "This slack channel {0} doesn't exist".format(ch)
         log.error(err)
         raise ValueError(err)
Esempio n. 7
0
    def handle_features_reply(self, event):
        """Handle kytos/of_core.messages.in.ofpt_features_reply event.

        This is the end of the Handshake workflow of the OpenFlow Protocol.

        Args:
            event (KytosEvent): Event with features reply message.
        """
        connection = event.source
        version_utils = self.of_core_version_utils[connection.protocol.version]
        switch = version_utils.handle_features_reply(self.controller, event)

        if (connection.is_during_setup() and
                connection.protocol.state == 'waiting_features_reply'):
            connection.protocol.state = 'handshake_complete'
            connection.set_established_state()
            version_utils.send_desc_request(self.controller, switch)
            if settings.SEND_SET_CONFIG:
                version_utils.send_set_config(self.controller, switch)
            log.info('Connection %s, Switch %s: OPENFLOW HANDSHAKE COMPLETE',
                     connection.id, switch.dpid)
            event_raw = KytosEvent(
                name='kytos/of_core.handshake.completed',
                content={'switch': switch})
            self.controller.buffers.app.put(event_raw)
Esempio n. 8
0
    def deploy_to_path(self, path=None):
        """Install the flows for this circuit.

        Procedures to deploy:

        0. Remove current flows installed
        1. Decide if will deploy "path" or discover a new path
        2. Choose vlan
        3. Install NNI flows
        4. Install UNI flows
        5. Activate
        6. Update current_path
        7. Update links caches(primary, current, backup)

        """
        self.remove_current_flows()
        if not self.should_deploy(path):
            path = self.discover_new_path()
            if not path:
                return False

        path.choose_vlans()
        self._install_nni_flows(path)
        self._install_uni_flows(path)
        self.activate()
        self.current_path = path
        self.sync()
        log.info(f"{self} was deployed.")
        return True
Esempio n. 9
0
    def setup(self):
        """Replace the '__init__' method for the KytosNApp subclass.

        The setup method is automatically called by the controller when your
        application is loaded.

        So, if you have any setup routine, insert it here.
        """
        # self.nodes = dict(settings.HOST_NODE)
        # self.edges = dict(settings.HOST_EDGE)
        # self.topology_not_set = True
        self.trident = TridentServer()
        self.trident.set_ctx_controller(self.controller)
        sa_name = 'authenticated'
        # pkt = TridentPacket('10.0.0.2', '*', 0, 0, '*')
        # self.trident.update_sa(sa_name, pkt, 'Accept')
        # self.interface2DirLink = {}

        self.debug = False
        # self._system_ready = False
        self.lock = threading.Lock()
        self.sw_nodes = {}
        self.sw_links = {}  # {(swid, port):(swid, port)}

        log.info('Main setup')
Esempio n. 10
0
    def run_important_traces(self):
        try:
            important_circuits = settings.IMPORTANT_CIRCUITS
        except AttributeError:
            return

        for circuit in important_circuits:
            entries = {
                'trace': {
                    'switch': {
                        'dpid': circuit['dpid_a'],
                        'in_port': circuit['port_a']
                    },
                    'eth': {
                        'dl_vlan': circuit['vlan_a']
                    }
                }
            }
            result = requests.put(
                'http://localhost:8181/api/amlight/sdntrace/trace',
                json=entries)
            trace = result.json()
            trace_id = trace['result']['trace_id']
            type = None
            while type != 'last':
                time.sleep(5)
                result = requests.get(
                    'http://localhost:8181/api/amlight/sdntrace/trace/%s' %
                    trace_id)
                trace = result.json()
                type = trace['result'][-1]['type']
            log.info(trace)
Esempio n. 11
0
    def _create_box_callback(self, _event, data, error):
        """Execute the callback to handle create_box."""
        if error:
            log.error(f'Can\'t create box with namespace {self.namespace}')

        self.box = data
        log.info(f'Box {self.box.box_id} was created in {self.namespace}.')
Esempio n. 12
0
    def delete_circuit(self, circuit_id):
        """Remove a circuit.

        First, the flows are removed from the switches, and then the EVC is
        disabled.
        """
        log.debug('delete_circuit /v2/evc/%s', circuit_id)
        try:
            evc = self.circuits[circuit_id]
        except KeyError:
            result = f'circuit_id {circuit_id} not found'
            log.debug('delete_circuit result %s %s', result, 404)
            raise NotFound(result)

        if evc.archived:
            result = f'Circuit {circuit_id} already removed'
            log.debug('delete_circuit result %s %s', result, 404)
            raise NotFound(result)

        log.info('Removing %s', evc)
        evc.remove_current_flows()
        evc.deactivate()
        evc.disable()
        self.sched.remove(evc)
        evc.archive()
        evc.sync()
        log.info('EVC removed. %s', evc)
        result = {'response': f'Circuit {circuit_id} removed'}
        status = 200

        log.debug('delete_circuit result %s %s', result, status)
        return jsonify(result), status
Esempio n. 13
0
    def shutdown(self):
        """This method is executed when your napp is unloaded.

        If you have some cleanup procedure, insert it here.
        """
        self.plugin.stop()
        log.info("stop")
Esempio n. 14
0
    def _restore_status(self, switches_status, interfaces_status):
        """Restore the network administrative status saved in StoreHouse."""
        # restore Switches
        for switch_id, state in switches_status.items():
            try:
                if state:
                    self.controller.switches[switch_id].enable()
                else:
                    self.controller.switches[switch_id].disable()
            except KeyError:
                error = ('Error while restoring switches status. The '
                         f'{switch_id} does not exist.')
                raise KeyError(error)
        # restore interfaces
        for interface_id, state in interfaces_status.items():
            switch_id = ":".join(interface_id.split(":")[:-1])
            interface_number = int(interface_id.split(":")[-1])
            try:
                switch = self.controller.switches[switch_id]
                if state:
                    switch.interfaces[interface_number].enable()
                else:
                    switch.interfaces[interface_number].disable()
            except KeyError:
                error = ('Error while restoring interface status. The '
                         f'interface {interface_id} does not exist.')
                raise KeyError(error)

        log.info('Network status restored.')
Esempio n. 15
0
 def handle_link_down(self, event):
     """Change circuit when link is down or under_mantenance."""
     log.debug("Event handle_link_down %s", event)
     for evc in self.circuits.values():
         if evc.is_affected_by_link(event.content['link']):
             log.info('handling evc %s' % evc)
             evc.handle_link_down()
Esempio n. 16
0
    def _load_network_status(self):
        """Load network status saved in storehouse."""
        try:
            status = self.storehouse.get_data()
        except FileNotFoundError as error:
            log.info(error)
            return
        if status:
            switches = status['network_status']['switches']
            self.links_state = status['network_status']['links']

            for switch_id, switch_att in switches.items():
                # get switches status
                self.switches_state[switch_id] = switch_att['enabled']
                iface = switch_att['interfaces']
                # get interface status
                for iface_id, iface_att in iface.items():
                    enabled_value = iface_att['enabled']
                    lldp_value = iface_att['lldp']
                    self.interfaces_state[iface_id] = (enabled_value,
                                                       lldp_value)

        else:
            error = 'There is no status saved to restore.'
            log.info(error)
Esempio n. 17
0
    def _slack_send(self, **kwargs):
        """
        Send some key value pairs via slacker
        """
        try:
            # if settings wasn't properly setup in the first place
            if not self.has_failed:
                if not kwargs.get('m_body'):
                    err = "Missing the 'm_body' argument"
                    log.error(err)
                    raise ValueError(err)
                slack_msg = ""
                for k in ['source', 'm_body']:
                    slack_msg = self._parse_str(slack_msg, kwargs.get(k))
                # fallback to #general
                ch = ''
                if kwargs.get('channel'):
                    ch = kwargs.get('channel')
                elif settings.slack_channel:
                    ch = settings.slack_channel
                else:
                    ch = 'general'

                log.info('channel:{0} msg:{1}'.format(ch, slack_msg))
                self.slack.chat.post_message(ch, slack_msg)
        except requests.exceptions.ConnectionError:
            err = "ConnectionError to Slack API."
            log.error(err)
            raise
        except self.slack_error as e:
            log.error(str(e))
            raise
Esempio n. 18
0
    def delete_circuit(self, circuit_id):
        """Remove a circuit.

        First, the flows are removed from the switches, and then the EVC is
        disabled.
        """
        log.debug("delete_circuit /v2/evc/%s", circuit_id)
        try:
            evc = self.circuits[circuit_id]
        except KeyError:
            result = f"circuit_id {circuit_id} not found"
            log.debug("delete_circuit result %s %s", result, 404)
            raise NotFound(result) from NotFound

        if evc.archived:
            result = f"Circuit {circuit_id} already removed"
            log.debug("delete_circuit result %s %s", result, 404)
            raise NotFound(result) from NotFound

        log.info("Removing %s", evc)
        with evc.lock:
            evc.remove_current_flows()
            evc.deactivate()
            evc.disable()
            self.sched.remove(evc)
            evc.archive()
            evc.sync()
        log.info("EVC removed. %s", evc)
        result = {"response": f"Circuit {circuit_id} removed"}
        status = 200

        log.debug("delete_circuit result %s %s", result, status)
        emit_event(self.controller, "deleted", evc_id=evc.id)
        return jsonify(result), status
Esempio n. 19
0
 def match_to_dict(self):
     """Convert a match in OF 1.3 to a dictionary."""
     match = dict()
     for name in self.match:
         match[name] = self.match[name].value
     log.info('Match %s' % match)
     return match
Esempio n. 20
0
    def _build_lldp_packet_out(version, port_number, data):
        """Build a LLDP PacketOut message.

        Args:
            version (int): OpenFlow version
            port_number (int): Switch port number where the packet must be
                forwarded to.
            data (bytes): Binary data to be sent through the port.

        Returns:
            PacketOut message for the specific given OpenFlow version, if it
                is supported.
            None if the OpenFlow version is not supported.

        """
        if version == 0x01:
            action_output_class = AO10
            packet_out_class = PO10
        elif version == 0x04:
            action_output_class = AO13
            packet_out_class = PO13
        else:
            log.info('Openflow version %s is not yet supported.', version)
            return None

        output_action = action_output_class()
        output_action.port = port_number

        packet_out = packet_out_class()
        packet_out.data = data
        packet_out.actions.append(output_action)

        return packet_out
Esempio n. 21
0
    def delete_circuit(self, circuit_id):
        """Remove a circuit.

        First, the flows are removed from the switches, and then the EVC is
        disabled.
        """
        try:
            evc = self.circuits[circuit_id]
        except KeyError:
            result = {'response': f'circuit_id {circuit_id} not found'}
            status = 404
        else:
            log.info(f'Removing {circuit_id}')
            if evc.archived:
                result = {'response': f'Circuit {circuit_id} already removed'}
                status = 404
            else:
                evc.remove_current_flows()
                evc.deactivate()
                evc.disable()
                self.sched.remove(evc)
                evc.archive()
                evc.sync()
                result = {'response': f'Circuit {circuit_id} removed'}
                status = 200

        return jsonify(result), status
Esempio n. 22
0
    def get_json_topology(self):
        """Return a json with topology details.

        Method responsible to return a json in /kytos/topology route.
        Returns:
            topology (string): json with topology details.
        """
        log.info("trying to get the topology")
        nodes, links = [], []
        switches = self.controller.switches

        switches_mac_address = []
        for switch in switches.values():
            for interface in switch.interfaces.values():
                switches_mac_address.append(interface.address)

        for _, switch in switches.items():
            nodes.append(switch.as_dict())
            for _, interface in switch.interfaces.items():
                link = {
                    'source': switch.id,
                    'target': interface.id,
                    'type': 'interface'
                }
                nodes.append(interface.as_dict())
                links.append(link)

                for endpoint, _ in interface.endpoints:
                    if isinstance(endpoint, HWAddress):
                        if endpoint in switches_mac_address:
                            continue

                        link = {
                            'source': interface.id,
                            'target': endpoint.value,
                            'type': 'link',
                            'link_speed': interface.get_hr_speed()
                        }
                        host = {
                            "type": 'host',
                            "id": endpoint.value,
                            "name": endpoint.value,
                            "mac": endpoint.value
                        }
                        if host not in nodes:
                            nodes.append(host)
                        if not interface.is_link_between_switches():
                            links.append(link)
                    else:
                        link = {
                            'source': interface.id,
                            'target': endpoint.id,
                            'type': 'link',
                            'link_speed2': interface.get_hr_speed()
                        }
                        links.append(link)

        output = {'nodes': nodes, 'links': links}
        return json.dumps(output)
Esempio n. 23
0
    def setup(self):
        """Replace the '__init__' method for the KytosNApp subclass.

        Execute right after the NApp is loaded.
        """
        self.metadata_cache = {}
        self.create_cache()
        log.info("Storehouse NApp started.")
Esempio n. 24
0
File: main.py Progetto: kytos/kronos
    def setup(self):
        """Init method for the napp."""
        log.info("Kronos NApp started.")

        if settings.DEFAULT_BACKEND.lower() == 'influxdb':
            self.backend = InfluxBackend(settings)
        elif settings.DEFAULT_BACKEND.lower() == 'csv':
            self.backend = CSVBackend(settings)
Esempio n. 25
0
 def initREST(self):
     log.info("we are starting our own restful api")
     app = connexion.App(__name__, specification_dir='./swagger/')
     app.app.json_encoder = JSONEncoder
     app.add_api(
         'swagger.yaml',
         arguments={'title': 'Cross-domain path and resource discovery'})
     app.run(port=8080)
Esempio n. 26
0
    def _save_evc_callback(self, _event, data, error):
        """Display the save EVC result in the log."""
        self._lock.release()
        log.debug(f'Lock {self._lock} released.')
        if error:
            log.error(f'Can\'t update the {self.box.box_id}')

        log.info(f'Box {data.box_id} was updated.')
Esempio n. 27
0
 def create_box(self):
     """Create a new box."""
     content = {'namespace': self.namespace,
                'callback': self._create_box_callback,
                'data': {}}
     event = KytosEvent(name='kytos.storehouse.create', content=content)
     self.controller.buffers.app.put(event)
     log.info('Create box from storehouse.')
Esempio n. 28
0
 def storehouse_create(event, box, error=False):
     """Log the return of an object creation in storehouse."""
     # pylint: disable=unused-argument
     if error:
         msg = 'Flow info not installed'
     else:
         msg = 'Flow info installed sucessfully'
     log.info(msg)
Esempio n. 29
0
    def setup(self):
        """Init method for the napp."""
        log.info("Time Series NApp started.")

        if settings.DEFAULT_BACKEND == 'INFLUXDB':
            self.backend = InfluxBackend(settings)
        elif settings.DEFAULT_BACKEND == 'CSV':
            self.backend = CSVBackend(settings)
Esempio n. 30
0
 def verify_storehouse(self, entities):
     """Request a list of box saved by specific entity."""
     name = 'kytos.storehouse.list'
     content = {'namespace': f'kytos.topology.{entities}.metadata',
                'callback': self.request_retrieve_entities}
     event = KytosEvent(name=name, content=content)
     self.controller.buffers.app.put(event)
     log.info(f'verify data in storehouse for {entities}.')
Esempio n. 31
0
    def setup(self):
        """ Default Kytos/Napps setup call. """
        log.info("Starting Kytos SDNTrace App version %s!" % VERSION)

        # Create list of switches
        self.switches = Switches(self.controller.switches)  # noqa: E501  pylint: disable=attribute-defined-outside-init

        # Instantiate TraceManager
        self.tracing = TraceManager(self.controller)  # pylint: disable=W0201
Esempio n. 32
0
    def _spawn_trace(self, trace_id, trace_entries):
        """ Once a request is found by the run_traces method,
        instantiate a TracePath class and run the tracepath

        Args:
            trace_id: trace request id
            trace_entries: TraceEntries class
        """
        log.info("Creating thread to trace request id %s..." % trace_id)
        tracer = TracePath(self, trace_id, trace_entries)
        tracer.tracepath()
        del self._running_traces[trace_id]