Ejemplo n.º 1
0
    def on_message_cb(self, client, obj, msg):
        """
        This method will invoke the specified callback handler by the client app
        when a notification is received by the app based on the notification type.

        @param client: the client instance for this callback
        @param obj: the private user data as set in Client() or userdata_set()
        @param msg: an instance of Message. This is a class with members topic, payload, qos, retain

        """
        payload = msg.payload
        topic = msg.topic
        json_data = None
        json_data, end = decoder.raw_decode(payload)
        if json_data is None:
            LOG.info('Received event has invalid JSON format')
            LOG.info('Received payload: %s' % payload)
        if len(payload) != end:
            LOG.info('Received event has additional invalid JSON format')
            LOG.info('It has the following additional content: %s' %
                     payload[end:])
        callback_called = False
        for cbs in self.handlers:
            if cbs != '#':
                if mqtt.topic_matches_sub(cbs, topic):
                    for cb in self.handlers.get(cbs, []):
                        cb(json_data)
                        callback_called = True

        if callback_called == False:
            for cb in self.handlers.get('#', []):
                LOG.info('Sending data to callback %s' % cb)
                cb(json_data)
Ejemplo n.º 2
0
    def on_stream_message_cb(self, client, obj, msg):
        """
        This callback function will be used for Thrift streaming messages
        and won't be encoded in JSON Format but the thrift wire format.
        The read method corresponding to this data structure needs to be used
        to decode the data

        @param client: the client instance for this callback
        @param obj: the private user data as set in Client() or userdata_set()
        @param msg: an instance of Message. This is a class with members topic, payload, qos, retain

        """

        payload = msg.payload
        topic = msg.topic

        callback_called = False
        for cbs in self.handlers:
            if cbs != '#':
                if mqtt.topic_matches_sub(cbs, topic):
                    for cb in self.handlers.get(cbs, []):
                        cb(payload)
                        callback_called = True
        if callback_called == False:
            for cb in self.handlers.get('#', []):
                LOG.info('Sending data to callback %s' % cb)
                cb(payload)
Ejemplo n.º 3
0
 def myget(dictitem,key):
     for keys in dictitem.keys():
         if keys.split(':')[-1] == key:
             value = dictitem.get(keys)
             return value
     LOG.info('Key %s not present' % str(key))
     return None
Ejemplo n.º 4
0
    def cfgAction(self, instance_id=None, restart_action=True):
        # Find the specific snabb instance or all depending on instance_id argument
        # Kill the relevant instances
        signal_sent = False
        if instance_id is not None and restart_action is False:
            cfg_file_name = SNABB_FILENAME + str(instance_id) + '.cfg'
            conf_file_name = SNABB_FILENAME + str(instance_id) + '.conf'
            try:
                os.remove(cfg_file_name)
                os.remove(conf_file_name)
            except OSError:
                pass
            LOG.info(
                "Removed the file %s and %s as the instance %d was deleted" %
                (cfg_file_name, conf_file_name, int(instance_id)))

        p = subprocess.Popen(['ps', '-axw'], stdout=subprocess.PIPE)
        out, err = p.communicate()
        if instance_id is not None:
            snabb_search_string = SNABB_PROCESS_SEARCH_STRING + \
                str(instance_id)
        else:
            snabb_search_string = SNABB_PROCESS_SEARCH_STRING
        for lines in out.splitlines():
            if snabb_search_string in lines:
                pid = int(lines.split(None, 1)[0])
                os.kill(pid, signal.SIGTERM)
                LOG.info("Successfully sent SIGTERM to the snabb instance %s" %
                         str(lines.split(None, 1)[1]))
                signal_sent = True

        return signal_sent
Ejemplo n.º 5
0
 def __call__(self):
     LOG.info("Entered ParseNotification")
     global dispQ
     while True:
         # process the notification message
         config_dict = dispQ.get()
         dispQ.task_done()
         LOG.info("dequeued %s" % str(config_dict))
         self.parse_snabb_config(config_dict)
Ejemplo n.º 6
0
    def close_notification_session(self):
        """
        This method closes the JET Notification channel.

        """

        self.notifier.Close()
        LOG.info('JET notification channel closed by user.')
        pass
    def create_config_update_topic(self):
        """
        This method creates a topic to subscribe config-update events.

        @return: Returns the config-update topic object

        """
        data = {}
        data['subscribed'] = 0
        data['topic'] = '%s/%s' % (GENPUB_TOPIC_HEADER, CONFIG_UPDATE)
        self.topics_subscribed.append(data['topic'])
        LOG.info('Successfully appended the topic %s' % data['topic'])
        return type('Topic', (), data)
Ejemplo n.º 8
0
 def get_binding_file(self, remote_filename, local_filename):
     try:
         localfd = open(local_filename, 'w+')
         ftp = FTP(self._dev._host)
         ftp.login(user=self._dev._auth_user, passwd=self._dev._auth_pwd)
         LOG.info("FTP get the file %s" % remote_filename)
         ftp.retrbinary('RETR %s' % remote_filename, localfd.write)
     except Exception as e:
         LOG.critical(
             'Failed to connect to the device: exception: %s' % e.message)
         return False
     LOG.info('Successfully copied the file %s' % remote_filename)
     return True
Ejemplo n.º 9
0
    def __init__(self,
                 device=DEFAULT_USER_NAME,
                 port=DEFAULT_NOTIFICATION_PORT,
                 user=None,
                 password=None,
                 tls=None,
                 keepalive=DEFAULT_MQTT_TIMEOUT,
                 bind_address="",
                 is_stream=False):
        """
        Create a request response session with the  JET server. Raises exception in case
        of invalid arguments or when JET notification server is not accessible.

        @param device: JET Server IP address. Default is localhost
        @param port: JET Notification port number. Default is 1883
        @param user: Username on the JET server, used for authentication and authorization.
        @param password: Password to access the JET server, used for authentication and authorization.
        @param keepalive: Maximum period in seconds between communications with the broker. Default is 60.
        @param bind_address: Client source address to bind. Can be used to control access at broker side.

        @return: JET Notification object.
        """

        try:
            self.notifier = NotifierMqtt()
            LOG.info('Connecting to JET notification server')
            self.notifier.mqtt_client.connect(device, port, keepalive,
                                              bind_address)
            self.notifier.mqtt_client.loop_start()
            self.notifier.handlers = collections.defaultdict(set)
            if is_stream == True:
                self.notifier.mqtt_client.on_message = self.notifier.on_stream_message_cb
            else:
                self.notifier.mqtt_client.on_message = self.notifier.on_message_cb

        except struct.error as err:
            message = err.message
            err.message = 'Invalid argument value passed in %s at line no. %s\nError: %s' \
                          % (traceback.extract_stack()[0][0], traceback.extract_stack()[0][1], message)
            LOG.error('%s' % (err.message))
            raise err
        except Exception, tx:
            tx.message = 'Could not connect to the JET notification server'
            LOG.error('%s' % (tx.message))
            raise Exception(tx.message)
Ejemplo n.º 10
0
 def write_file(self, filename, templatename, dictitems):
     PATH = os.path.dirname(os.path.abspath(__file__))
     TEMPLATE_ENVIRONMENT = Environment(
         autoescape=True,
         loader=FileSystemLoader(os.path.join(PATH, 'template')),
         trim_blocks=True,
         lstrip_blocks=False)
     try:
         with open(filename, 'w') as f:
             btext = TEMPLATE_ENVIRONMENT.get_template(
                 templatename).render(context=dictitems)
             f.write(btext)
             LOG.info("Successfully written %s" % str(filename))
         return True
     except Exception as e:
         LOG.critical("Failed to write the file %s, exception: %s" %
                      (str(filename), e.message))
         return False
Ejemplo n.º 11
0
    def Subscribe(self, subscriptionType, handler=None, qos=0):
        """
        This method subscribes to a specific topic the client app is interested
        in. This takes subscription type and the callback function as parameters.
        When the notification for the subscribed topic is received, user passed
        callback function will be called. Callback function receives the
        notification message in json format.

        @param subscriptionType : Type of notification user wants to subscribe to
        @param handler: Callback function for each notification

        """
        topic = subscriptionType.topic
        self.mqtt_client.subscribe(topic, qos)
        subscriptionType.subscribed = 1

        if(handler):
            self.handlers[topic].add(handler)
        LOG.info('Successfully subscribed to event:%s' %
                 subscriptionType.topic)
Ejemplo n.º 12
0
 def deleteAction(self):
     # Delete the cfg files
     snabb_search_string = SNABB_PROCESS_SEARCH_STRING
     for f in os.listdir('/tmp'):
         if snabb_search_string in f:
             LOG.info('Deleting the file %s' % str(f))
             try:
                 os.remove(os.path.join('/tmp/', f))
             except OSError:
                 pass
     signal_sent = False
     p = subprocess.Popen(['ps', '-axw'], stdout=subprocess.PIPE)
     out, err = p.communicate()
     for lines in out.splitlines():
         if snabb_search_string in lines:
             pid = int(lines.split(None, 1)[0])
             os.kill(pid, signal.SIGTERM)
             LOG.info("Successfully sent SIGTERM to the snabb instance %s" %
                      str(lines.split(None, 1)[1]))
             signal_sent = True
     return signal_sent
Ejemplo n.º 13
0
    def Unsubscribe(self, subscriptionType=None):
        """
        This method takes the topic as argument and unsubscribes to the given topic.
        If topic name is not given as argument (no arguments), this method
        unsubscribes to all the topics which app already subscribed for.

        @param subscriptionType: Notification type that user wants to unsubscribe from.
        @return 0 on successful unsubscription and -1 on failure

        """
        if subscriptionType is None:
            self.mqtt_client.unsubscribe(self.topics_subscribed)
            self.handlers = collections.defaultdict(set)
            LOG.info('Successfully unsubscribed from all notifications')
            return 0
        elif not isinstance(subscriptionType, type):
            message = 'Invalid subscription topic: ' + subscriptionType
            LOG.info(message)
            raise Exception(message)

        else:
            for item in self.topics_subscribed:
                if (item == subscriptionType.topic and subscriptionType.subscribed == 1):
                    self.mqtt_client.unsubscribe(subscriptionType.topic)
                    self.mqtt_client.unsubscribe(subscriptionType.topic)
                    self.handlers.pop(str(subscriptionType.topic), None)
                    LOG.info('Successfully unsubscribed %s' %
                             subscriptionType.topic)
                    return 0

            # Failed case
            LOG.error('You have not subscribed to %s. Failed to unsubscribe' %
                      subscriptionType.topic)
            return -1
Ejemplo n.º 14
0
    def start_snabb_instance(self, instance_id):
        s = SNABB_INSTANCE_LAUNCH_TEMPLATE
        config_file_name = SNABB_FILENAME + str(instance_id) + '.cfg'
        pci_path = SNABB_PCI_PATH + str(instance_id)
        mac_path = SNABB_MAC_PATH + str(instance_id)
        # Read the files
        mac_id = ''
        pci_id = ''
        try:
            with open(pci_path) as f:
                pci_id = f.read().strip().split('/')[0]
        except Exception as e:
            LOG.info('Failed to read the file %s due to exception: %s' %
                     (pci_path, e.message))
            return False
        try:
            with open(mac_path) as f:
                mac_id = f.read().strip()
        except Exception as e:
            LOG.info('Failed to read the file %s due to exception: %s' %
                     (mac_path, e.message))
            return False

        cmd = s.substitute(cfg=config_file_name,
                           id=instance_id,
                           pci=pci_id,
                           mac=mac_id)
        # TODO launch the process if required
        output = 0
        try:
            pid = subprocess.Popen(["sudo", cmd],
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.STDOUT).pid
            LOG.info('Tried to restart the snabb instance id %s, returned %s' %
                     (str(instance_id), str(pid)))
        except Exception as e:
            LOG.info("Failed to start the snabb instance, exception %s" %
                     e.message)

        return output
Ejemplo n.º 15
0
 def bindAction(self, binding_file):
     # Compile the binding file
     signal_sent = False
     # Find the snabb instances and send sighup to all the instances
     p = subprocess.Popen(['ps', '-axw'], stdout=subprocess.PIPE)
     out, err = p.communicate()
     snabb_search_string = SNABB_PROCESS_SEARCH_STRING
     for lines in out.splitlines():
         if snabb_search_string in lines:
             pid = int(lines.split(None, 1)[0])
             cmd = r"/usr/local/bin/snabb lwaftr control " + str(
                 pid) + " reload"
             try:
                 output = subprocess.check_output(cmd, shell=True)
                 LOG.info('Sent SIGHUP to instance %d' % pid)
             except Exception as e:
                 LOG.info("Failed to send SIGHUP to instance %d" % pid)
             signal_sent = True
             LOG.info("Successfully sent SIGHUP to the snabb instance")
             break
     return signal_sent
Ejemplo n.º 16
0
    def parse_for_binding(self, config_dict):
        br_addresses = OrderedDict()
        br_address_idx = -1
        softwires = []
        addresses = {}
        remote_binding_table_filename = self.myget(config_dict['binding']['br'],'binding-table-file')
        # This section will take care of the binding files and binding table entries
        # Fetch this binding file from the device
        if remote_binding_table_filename is not None:
            # New binding table is provided by the user
            new_binding_file = r'/tmp/snabbvmx.binding.new'
            # touch the new file
            open(new_binding_file, 'w+').close()
            if self.get_binding_file(remote_binding_table_filename, new_binding_file):
                # Copy the remote file to new_binding_file and create the softwires, psid and br_address tables
                # Then add to these tables the new entries from the configuration
                # At the end compare the new binding file with the old one to see if binding entries have changed
                with open(new_binding_file, 'r') as f:
                    # Walk over the file to create the binding entries
                    regex_br_address = r"softwires_([\w:]+)"
                    regex_br_entries = r"([\w:]+)+\s+(\d+.\d+.\d+.\d+),(\d+),(\d+),(\d+)"
                    for lines in f.readlines():
                        if re.search(regex_br_address, lines):
                            match = re.search(regex_br_address, lines)
                            br_addresses[match.group(0).split(
                                '_')[1]] = br_address_idx + 1
                            br_address_idx += 1
                        elif re.search(regex_br_entries, lines):
                            match = re.search(regex_br_entries, lines)
                            shift = 16 - int(match.group(4)) - \
                                int(match.group(5))
                            softwires.append('{ ipv4=%s, psid=%s, b4=%s, aftr=%s }' %
                                             (match.group(2),match.group(3),
                                              match.group(1),br_address_idx))
                            if shift > 0:
                                addresses[str(match.group(2))] = "{psid_length=%s, shift=%d}" % (match.group(4),
                                                                                                 shift)
                            else:
                                addresses[
                                    str(match.group(2))] = "{psid_length=%s}" % match.group(4)

                        else:
                            LOG.info("Ignoring this line: %s" % lines)
                os.remove(new_binding_file)
            else:
                LOG.critical(
                    'Failed to copy remote binding file onto the local disk')
        else:
            LOG.info("No binding table info found in the config")

        # Now parse the snabb config to see if there is any binding table entry
        new_instance_list = config_dict['binding']['br']['br-instances']['br-instance']
        for instances in new_instance_list:
            bt = self.myget(instances,'binding-table')
            if bt is not None:
                bte = self.myget(bt,'binding-entry')
                if bte is not None:
                    for items in bte:
                        binding_ipv6_info = self.myget(items,"binding-ipv6info")
                        ipv4 = self.myget(items,"binding-ipv4-addr")
                        b4_address = self.myget(items,"br-ipv6-addr")
                        portset = self.myget(items,'port-set')
                        psid = self.myget(portset,"psid")
                        psid_len = self.myget(portset,"psid-len")
                        offset = self.myget(portset,"psid-offset")
                        shift = 16-psid_len-offset
                        if binding_ipv6_info is not None and ipv4 is not None and b4_address is not None:
                            if shift > 0:
                                addresses[ipv4] = "{psid_length=%s, shift=%d}" % (psid_len, shift)
                            else:
                                addresses[ipv4] = "{psid_length=%s}" %psid_len
                            if b4_address in br_addresses.keys():
                                aftr = br_addresses[b4_address]
                            else:
                                aftr = len(br_addresses)
                                br_addresses[b4_address] = aftr

                            softwires.append('{ ipv4=%s, psid=%s, b4=%s, aftr=%s }' % (
                                ipv4,psid,binding_ipv6_info,aftr))
                        else:
                            LOG.info("Incomplete binding table entry in the configuration %s" %str(items))
                else:
                    LOG.info("Empty binding table entry in the configuration")
            else:
                LOG.info("No binding table configuration present")

        # Write it into a file
        with open(SNABB_BINDING_FILENAME_TMP, 'w+') as nf:
            nf.write('psid_map {\n')
            for items in sorted(addresses.iterkeys()):
                nf.write("\t" + items + " " + addresses[items] + '\n')
            nf.write("}\nbr_addresses {\n")
            for items in br_addresses.keys():
                nf.write("\t" + items + ",\n")
            nf.write("}\nsoftwires {\n")
            for items in softwires:
                nf.write("\t" + items + "\n")
            nf.write("}")

        # Determine if this binding file is different from existing
        # file
        if self.old_binding_filename is None:
            self.old_binding_filename = SNABB_BINDING_FILENAME
            os.rename(SNABB_BINDING_FILENAME_TMP, self.old_binding_filename)
            self.binding_changed = True
            LOG.info("Old binding file not present, so creating a new binding file")
        elif not filecmp.cmp(self.old_binding_filename, SNABB_BINDING_FILENAME_TMP):
            os.rename(SNABB_BINDING_FILENAME_TMP, self.old_binding_filename)
            self.binding_changed = True
            LOG.info("Binding Table has changed")
        else:
            LOG.info("Binding Table has not changed")
        if (self.binding_changed):
	    cmd = r"/usr/local/bin/snabb lwaftr compile-binding-table " + \
		  str(self.old_binding_filename)
	    try:
		output = subprocess.check_output(cmd, shell=True)
		LOG.info("Compiled the binding file, returned %s" % str(output))
	    except Exception as e:
		LOG.critical("Failed to compile the binding file returned %s" % str(e.message))
		self.binding_changed = False
        return
Ejemplo n.º 17
0
    def parse_snabb_config(self, config_dict):
        if config_dict.get('purge', None) is not None:
            # Call the confAction to kill all the Snabb applications after
            # deleting the cfg/conf/binding files
            self.old_cfg = []
            self.old_conf = []
            self.old_binding_filename = None
            self.instances = {}
	    LOG.info("Purging the snabb configuration files and terminating instances")
            ca = ConfAction()
            ca.deleteAction()
            return
        LOG.info("entered parse_snabb_config")
        # At first lets clear the present flag in all the instances
        for keys in self.instances:
            self.instances[keys] = 0

        # Action handler to commit actions for conf/cfg/binding changes
        action_handler = ConfAction()

        # First the binding entry changes
        self.binding_changed = self.parse_for_binding(config_dict)

        # description is same for all the instances in the YANG schema
        cfg_dict = {}
        conf_dict = {}
        # Parse the config and cfg changes
        descr = self.myget(config_dict,'description')
        new_instance_list = config_dict['binding']['br']['br-instances']['br-instance']
        for instances in new_instance_list:
            # TODO try except loop has to be implemented
            instance_id = self.myget(instances,'id')
            # Verify that the old config contains this instance, if not then we
            # need to delete this instance
            self.instances[instance_id] = 1
            cfg_dict['id'] = instance_id
            cfg_dict['cnf_file_name'] = SNABB_FILENAME + str(instance_id) + '.conf'

            cfg_dict['ipv4_address'] = self.myget(instances,'ipv4_address')
            cfg_dict['ipv4_desc'] = descr
            cfg_dict['ipv4_cache_rate'] = self.myget(instances,'cache_refresh_interval')
            cfg_dict['ipv4_ingress_filter'] = self.myget(instances, 'ipv4_ingress_filter')
            cfg_dict['ipv4_egress_filter'] = self.myget(instances, 'ipv4_egress_filter')
            cfg_dict['fragmentation'] = self.myget(instances, 'fragmentation')


            cfg_dict['ipv6_address'] = self.myget(instances,'ipv6_address')
            cfg_dict['ipv6_desc'] = descr
            cfg_dict['ipv6_cache_rate'] = self.myget(instances,'cache_refresh_interval')
            cfg_dict['ipv6_ingress_filter'] = self.myget(instances, 'ipv6_ingress_filter')
            cfg_dict['ipv6_egress_filter'] = self.myget(instances, 'ipv6_egress_filter')
            cfg_dict['fragmentation'] = self.myget(instances, 'fragmentation')

            cfg_dict['ingress_drop_interval'] = self.myget(instances,'ingress_drop_interval')
            cfg_dict['ingress_drop_monitor'] = self.myget(instances,'ingress_drop_monitor')
            cfg_dict['ingress_drop_threshold'] = self.myget(instances, 'ingress_drop_threshold')
            cfg_dict['ingress_drop_wait'] = self.myget(instances,'ingress_drop_wait')
            cfg_dict['ring_buffer_size'] = None

            # Parse the conf file attributes
            conf_dict['id'] = instance_id
            if self.old_binding_filename is not None:
                conf_dict['binding_table'] = str(self.old_binding_filename)
            else:
                conf_dict['binding_table'] = None

            mac_path = SNABB_MAC_PATH + str(instance_id)
            # Read the files
            mac_id = "00:00:00:00:00:00"
            try:
                with open(mac_path) as f:
                    mac_id = f.read().strip()
            except Exception as e:
                LOG.info('Failed to read the file %s due to exception: %s' %
                         (mac_path, e.message))

            conf_dict['v4_vlan_tag'] = self.myget(instances,'v4_vlan_tag')
            conf_dict['v6_vlan_tag'] = self.myget(instances, 'v6_vlan_tag')
            if self.myget(instances,'v4_vlan_tag') is not None or self.myget(instances, 'v6_vlan_tag') is not None:
                conf_dict['vlan_tagging'] = 'true'
            else:
                conf_dict['vlan_tagging'] = 'false'

            conf_dict['policy_icmpv4_incoming'] = self.myget(instances, 'policy_icmpv4_incoming')
            conf_dict['policy_icmpv4_outgoing'] = self.myget(instances, 'policy_icmpv4_outgoing')
            conf_dict['policy_icmpv6_incoming'] = self.myget(instances,'policy_icmpv6_incoming')
            conf_dict['policy_icmpv6_outgoing'] = self.myget(instances, 'policy_icmpv6_outgoing')
            conf_dict['max_fragments_per_reassembly_packet'] = self.myget(instances, 'max_fragments_per_reassembly_packet')
            conf_dict['max_ipv4_reassembly_packets'] = self.myget(instances, 'max_ipv4_reassembly_packets')
            conf_dict['max_ipv6_reassembly_packets'] = self.myget(instances, 'max_ipv6_reassembly_packets')
            conf_dict['icmpv6_rate_limiter_n_packets'] = self.myget(instances, 'icmpv6_rate_limiter_n_packets')
            conf_dict['icmpv6_rate_limiter_n_seconds'] = self.myget(instances, 'icmpv6_rate_limiter_n_seconds')
            conf_dict['ipv4_address'] = self.myget(instances, 'ipv4_address')
            conf_dict['ipv6_mtu'] = self.myget(instances,"tunnel-path-mru")
            conf_dict['ipv4_mtu'] = self.myget(instances,"tunnel-payload-mtu")
            conf_dict['hairpinning'] = self.myget(instances,"hairpinning")

            #TODO Why are the following values hardcoded
            conf_dict['ipv6_address'] = '2001:db8::1'
            conf_dict['inet_mac'] = '02:02:02:02:02:02'
            conf_dict['next_hop6_mac'] = '02:02:02:02:02:02'

            # TODO these parameters are not defined
            conf_dict['aftr_mac_inet_side'] = mac_id
            conf_dict['aftr_mac_b4_side'] = mac_id

            # Take action based on whether the cfg or conf files have changed
            # or not
            ret_cfg, ret_conf = False, False
            new_cfg_id_present = False
            new_conf_id_present = False
            cnt = 0
            cfg_changed = False
            LOG.debug('New cfg dict = %s' % str(cfg_dict))
            if self.old_cfg is None:
                ret_cfg = self.write_snabb_cfg_file(cfg_dict, instance_id)
                self.old_cfg.append(cfg_dict)
                if not ret_cfg:
                    LOG.critical("Failed to write the cfg file")
                    return
            else:
                # Add the new cfg to the old_cfg dictionary
                cnt = 0
                for cfg_instance in self.old_cfg:
                    if cfg_instance['id'] == cfg_dict['id']:
                        # Check if the configuration has changed for this new instance
                        if cmp(cfg_instance, cfg_dict) != 0:
                            cfg_changed = True
                            self.old_cfg[cnt] = cfg_dict
                            new_cfg_id_present = True
                            LOG.info("Cfg dictionary has changed")
                            break
                        else:
                            new_cfg_id_present = True
                            cfg_changed = False
                            LOG.info("Cfg dictionary has not changed")
                            break
                    cnt += 1
                # New cfg is not in the existing dict, add it
                if not new_cfg_id_present:
                    self.old_cfg.append(cfg_dict)
                    cfg_changed = True
                if (cfg_changed):
                    ret_cfg = self.write_snabb_cfg_file(cfg_dict, instance_id)
                    if not ret_cfg:
                        LOG.critical("Failed to write the cfg file")
                        return

            if self.old_conf is None:
                ret_conf = self.write_snabb_conf_file(conf_dict, instance_id)
                self.old_conf.append(conf_dict)
                if not ret_conf:
                    LOG.critical("Failed to write the conf file")
                    return
            else:
                cnt = 0
                conf_changed = False
                new_conf_id_present = False
                for conf_instance in self.old_conf:
                    if (conf_instance['id'] == conf_dict['id']):
                        if cmp(conf_instance, conf_dict) != 0:
                            conf_changed = True
                            self.old_conf[cnt] = conf_dict
                            new_conf_id_present = True
                            LOG.info("Conf dictionary has changed")
                            break
                        else:
                            new_conf_id_present = True
                            conf_changed = False
                            LOG.info("Conf dictionary has not changed")
                    cnt = + 1
                if not new_conf_id_present:
                    self.old_conf.append(conf_dict)
                    conf_changed = True
                if (conf_changed):
                    ret_conf = self.write_snabb_conf_file(
                        conf_dict, instance_id)
                    if not ret_conf:
                        LOG.critical("Failed to write the conf file")
                        return

            if ret_conf or ret_cfg:
                # Assume that the instances list is populated here
                if not new_cfg_id_present and not new_conf_id_present:
                    # It is a new instance, so start it
                    LOG.info("New id added, starting new instance")
                    ret = action_handler.start_snabb_instance(instance_id)
                else:
                    LOG.info("The configuration changed, restarting the snabb instance id %s" %instance_id)
                    ret = action_handler.cfgAction(instance_id)
                    if not ret:
                        LOG.critical("Failed to restart the Snabb instance")
	    elif self.binding_changed:
		# Only the binding table has changed.
		# Send SIGHUP to the instances
		LOG.info("Only binding table has changed, sending SIGHUP")
		ret = action_handler.bindAction(self.old_binding_filename)
		if not ret:
		    LOG.critical("Failed to reload the binding tables")
		self.binding_changed = False
            else:
                LOG.info("No config change hence did not restart Snabb instance %s id" %instance_id)

        # Few of the instances might have been deleted, we need to kill those
        # instances
        for keys in self.instances:
            if self.instances[keys] == 0:
                # Remove the old_cfg item which is for this id
                cnt = 0
                for cfg_instance in self.old_cfg:
                    if cfg_instance['id'] == keys:
                        del self.old_cfg[cnt]
                        break
                    cnt += 1

                cnt = 0
                for conf_instance in self.old_conf:
                    if conf_instance['id'] == keys:
                        del self.old_conf[cnt]
                        break
                    cnt += 1
		# Purge the files needed for this instance
                LOG.info(
                    "Instance id %d is not present, need to kill it" % int(keys))
                ret = action_handler.cfgAction(keys, False)
                if not ret:
                    LOG.critical(
                        "Failed to kill the Snabb instance %d" % int(keys))
        return
Ejemplo n.º 18
0
def Main():
    parser = argparse.ArgumentParser(
        prog=os.path.basename(__file__),
        description='Snabb VMX integration JET app')
    parser.add_argument("--host",
                        help="Host address of the JSD server",
                        type=str,
                        default=DEFAULT_RPC_HOST)
    parser.add_argument(
        "--user",
        help="Username for authentication by JET server (default:%(default)s)",
        type=str,
        default=DEFAULT_USER_NAME)
    parser.add_argument(
        "--password",
        help="Password for authentication by JET server (default:%(default)s",
        type=str,
        default=DEFAULT_PASSWORD)
    parser.add_argument(
        "--rpc_port",
        nargs='?',
        help="Port number of the JSD gRPC server. default: %(default)s",
        type=int,
        default=DEFAULT_RPC_PORT)
    parser.add_argument(
        "--notification_port",
        nargs='?',
        help="Port number of the JSD notification server. default: %(default)s",
        type=int,
        default=DEFAULT_NOTIFICATION_PORT)
    parser.add_argument("--config",
                        nargs='?',
                        help="JSON config file",
                        type=str,
                        default=None)

    args = parser.parse_args()
    if args.config is not None:
        try:
            json_cfg = {}
            with open(args.config) as json_cfg_file:
                json_cfg = json.load(json_cfg_file)
            device = Device(json_cfg['host'], json_cfg['user'],
                            json_cfg['password'], json_cfg['rpc_port'],
                            json_cfg['notification_port'])
        except Exception as e:
            LOG.error("exception :%s" % str(e.message))
            sys.exit(0)
    else:
        try:
            device = Device(args.host, args.user, args.password, args.rpc_port,
                            args.notification_port)
        except Exception as e:
            LOG.error("Exception:%s" % e.message)
            sys.exit(0)
    dispatchFunction = ParseNotification(device)
    dispatchThread = Thread(target=dispatchFunction)
    dispatchThread.setDaemon(True)
    dispatchThread.start()
    try:
        device.initialize()
        # log device initialized successfully
        print "Device initialized for the configuration updates"
        opw = OpServer()
        reactor.listenTCP(9191, server.Site(opw))
        LOG.info("Starting the reactor")
        reactor.run()

    except Exception as e:
        # log device initialization failed
        LOG.critical("JET app exiting due to exception: %s" % str(e.message))
        sys.exit(0)
    return
Ejemplo n.º 19
0
    def __call__(self, message):
        global dispQ
        LOG.info("Inside Handle commit notifications")
        LOG.info("Received message: %s" % str(message))
        config_dict = message['commit-patch']
        print config_dict
        try:
            sw_present = False
            for keys in config_dict:
                if keys.endswith('softwire-config'):
                    sw_present = True
                    break
            if sw_present:
                purge_request = True
                # Push all the configuration into a new file
                stub = openconfig_service_pb2.beta_create_OpenconfigRpcApi_stub(
                    self._dev.getChannel())

                get_request = openconfig_service_pb2.GetRequestList(
                    operation_id="1001",
                    operation=1,
                    path="/configuration/ietf-softwire:softwire-config")
                request = openconfig_service_pb2.GetRequest(
                    request_id=1002, encoding=1, get_request=[get_request])
                response = stub.Get(request,
                                    common.app_globals.RPC_TIMEOUT_SECONDS)
                for rsp in response.response:
                    print rsp.value
                    if rsp.response_code == openconfig_service_pb2.OK and rsp.value != "":
                        print rsp

                        LOG.info(
                            "Invoked the getRequest for snabb configuration")
                        config_dict = json.loads(
                            rsp.value)["ietf-softwire:softwire-config"]
                        LOG.debug(
                            "Notification message contains the config %s" %
                            (str(config_dict)))
                        purge_request = False
                        dispQ.put(config_dict)
                if purge_request:
                    LOG.info("Softwire-config deleted in the config")
                    config_dict['purge'] = True
                    dispQ.put(config_dict)
            else:
                LOG.info("Softwire-config not present in the config")
        except Exception as e:
            LOG.critical("Exception: %s" % e.message)
            LOG.info('Exiting the JET app')
            os._exit(1)
        return