Exemplo n.º 1
0
 def _create_delete_paths(self) -> List[Path]:
     paths: List[Path] = []
     if not self.ascii_mode:
         for path in self._features.keys():
             if not path == "":
                 paths.append(create_gnmi_path(path))
         return paths
Exemplo n.º 2
0
    def subscribe(
        self, encoding: str, requests: List[str], sample_rate: int, stream_mode: str, subscribe_mode: str,
    ) -> Iterable[ParsedResponse]:
        """Subscribe to sensor path(s) and poll them at a given interval on a gNMI device

                :param encoding: The encoding to use when you subscribe to a gNMI device
                :type encoding: str
                :param requests: A list of sensor path(s) to subscribe to
                :type requests: List[str]
                :param sample_rate: How often to poll the subscription in seconds
                :type sample_rate: int
                :param stream_mode: The way to stream off the data either STREAM, ONCE, POLL
                :type stream_mode: str
                :param subscribe_mode: Either can be SAMPLE or ON_CHANGE to either do MDT at a sample interval or EDT
                :type subscribe_mode: str

                :returns: An iterable of ParsedResponse of the streaming data

                """
        subs = []
        sample_rate = sample_rate * 1000000000
        for request in requests:
            subs.append(
                Subscription(
                    path=create_gnmi_path(request),
                    mode=SubscriptionMode.Value(subscribe_mode),
                    sample_interval=sample_rate,
                )
            )
        sub_list = SubscriptionList(
            subscription=subs, mode=SubscriptionList.Mode.Value(stream_mode), encoding=Encoding.Value(encoding),
        )
        sub_request = SubscribeRequest(subscribe=sub_list)
        try:
            stub = self._get_stub()
            for response in stub.Subscribe(self.sub_to_path(sub_request), metadata=self.metadata):
                if not response.sync_response:
                    keys, start_yang_path = self.process_header(response.update)
                    for update in response.update.update:
                        update_keys, update_yang_path = self.process_update_header(update)
                        total_yang_path = f"{start_yang_path}/{update_yang_path}"
                        value = self.get_value(update.val)
                        parsed_dict = {
                            "@timestamp": (int(response.update.timestamp) / 1000000),
                            "byte_size": response.ByteSize(),
                            "ip": self.host,
                        }
                        keys.update(update_keys)
                        parsed_dict["keys"] = keys
                        leaf = "-".join(total_yang_path.split("/")[-2:])
                        parsed_dict[leaf] = value
                        parsed_dict["index"] = yang_path_to_es_index(total_yang_path)
                        parsed_dict["yang_path"] = total_yang_path
                        yield ParsedResponse(parsed_dict, self.version, self.hostname)
        except Exception as e:
            raise GNMIException(f"Failed to complete Subscription:\n {e}")
Exemplo n.º 3
0
 def _split_full_config(response: GetResponse) -> List[GetResponse]:
     responses: List[GetResponse] = []
     full_config_json: Dict[str, Any] = {}
     timestamp = [n.timestamp for n in response.notification][0]
     for notification in response.notification:
         for update in notification.update:
             full_config_json = json.loads(update.val.json_ietf_val)
     models: List[str] = []
     for model, config in full_config_json.items():
         str_config: str = json.dumps(config)
         type_config_val: TypedValue = TypedValue(json_ietf_val=str_config.encode())
         up: Update = Update(path=create_gnmi_path(model), val=type_config_val)
         notification: Notification = Notification(update=[up], timestamp=timestamp)
         responses.append(GetResponse(notification=[notification]))
         models.append(model)
     model_str_config: str = json.dumps({"configs": models})
     model_type_config_val: TypedValue = TypedValue(json_ietf_val=model_str_config.encode())
     up: Update = Update(path=create_gnmi_path("router-configs"), val=model_type_config_val)
     notification: Notification = Notification(update=[up], timestamp=timestamp)
     responses.append(GetResponse(notification=[notification]))
     return responses
Exemplo n.º 4
0
    def get_config(self, encoding: str, config_models: List[str] = None, raw: bool = False) -> List[ParsedResponse]:
        """Get configuration of the gNMI device

        :param encoding: The encoding to use to for the Get Config operation
        :type encoding: str
        :param config_models: Yang model(s) of a specific configuration to get
        :type config_models: str
        :returns: A List of ParsedResponse of configuration data

        """
        try:
            stub: gNMIStub = self._get_stub()
            responses: List[ParsedResponse] = []
            if config_models:
                for config_model in config_models:
                    split_full_config_response = []
                    get_message: GetRequest = GetRequest(
                        path=[create_gnmi_path(config_model)],
                        type=GetRequest.DataType.Value("CONFIG"),
                        encoding=Encoding.Value(encoding),
                    )
                    response: GetResponse = stub.Get(get_message, metadata=self.metadata)
                    if raw:
                        return response
                    else: 
                        split_full_config_response.append(response)
            else:
                get_message: GetRequest = GetRequest(
                    path=[Path()], type=GetRequest.DataType.Value("CONFIG"), encoding=Encoding.Value(encoding),
                )
                full_config_response: GetResponse = stub.Get(get_message, metadata=self.metadata)
                if raw:
                    return full_config_response
                else:
                    split_full_config_response: List[Dict[str, Any]] = self._split_full_config(full_config_response)
            for response in split_full_config_response:
                parsed_dict: Dict[str, Any] = {
                    "@timestamp": (int(response.notification[0].timestamp) / 1000000),
                    "byte_size": response.ByteSize(),
                }
                model = response.notification[0].update[0].path.elem[0].name
                parsed_dict["model"] = model
                parsed_dict["index"] = yang_path_to_es_index(model)
                parsed_dict["ip"] = self.host
                parsed_dict["config"] = json.loads(response.notification[0].update[0].val.json_ietf_val)
                responses.append(ParsedResponse(parsed_dict, self.version, self.hostname))
            return responses
        except Exception as e:
            raise GNMIException(f"Failed to complete the Get Config:\n {e}")
Exemplo n.º 5
0
 def _get_version(self) -> str:
     stub = self._get_stub()
     get_message: GetRequest = GetRequest(
         path=[create_gnmi_path("Cisco-IOS-XR-install-oper:install/version")],
         type=GetRequest.DataType.Value("STATE"),
         encoding=Encoding.Value("JSON_IETF")
     )
     response: GetResponse = stub.Get(get_message, metadata=self.metadata)
     def _parse_version(version: GetResponse) -> str:
         rc = ""
         for notification in version.notification:
             for update in notification.update:
                 rc = json.loads(update.val.json_ietf_val)
                 return rc["package"][0]["version"]
     return _parse_version(response)
Exemplo n.º 6
0
    def _get_hostname(self) -> str:
        stub = self._get_stub()
        get_message: GetRequest = GetRequest(
            path=[create_gnmi_path("Cisco-IOS-XR-shellutil-cfg:host-names")],
            type=GetRequest.DataType.Value("CONFIG"),
            encoding=Encoding.Value("JSON_IETF"),
        )
        response: GetResponse = stub.Get(get_message, metadata=self.metadata)

        def _parse_hostname(hostname_response: GetResponse) -> str:
            for notification in hostname_response.notification:
                for update in notification.update:
                    rc = update.val.json_ietf_val
                    if not rc:
                        return ""
                    else:
                        return json.loads(rc)["host-name"]

        return _parse_hostname(response)
Exemplo n.º 7
0
 def _create_updates(self) -> List[Update]:
     updates: List[Update] = []
     if self.ascii_mode:
         type_config_val: TypedValue = TypedValue(
             ascii_val=self.ascii_config)
         updates.append(Update(path=self.path, val=type_config_val))
         return updates
     else:
         for path, config in self._features.items():
             str_config: str = json.dumps(config)
             type_config_val: TypedValue = TypedValue(
                 json_ietf_val=str_config.encode())
             if path == "":
                 updates.append(Update(path=Path(), val=type_config_val))
             else:
                 updates.append(
                     Update(path=create_gnmi_path(path),
                            val=type_config_val))
         return updates
Exemplo n.º 8
0
    def get(self, encoding: str, oper_models: List[str], raw: bool = False) -> List[ParsedResponse]:
        """Get oper data of a gNMI device

        :param encoding: The encoding to use to for the Get operation
        :type encoding: str
        :param oper_models: The yang model of the operational data to get
        :type oper_models: List[str]
        :returns: A list of ParsedResponse of the flatten operational data

        """
        try:
            stub: gNMIStub = self._get_stub()
            paths: List[Path] = []
            for oper_model in oper_models:
                paths.append(create_gnmi_path(oper_model))
            get_message: GetRequest = GetRequest(
                path=paths,
                type=GetRequest.DataType.Value("OPERATIONAL"),
                encoding=Encoding.Value(encoding),
            )
            response: GetResponse = stub.Get(get_message, metadata=self.metadata)
            if raw:
                return response
            else:
                rc: List[ParsedResponse] = []
                for notification in response.notification:
                    start_yang_path: List[str] = []
                    start_yang_keys: Dict[str, str] = {}
                    sub_yang_path: List[str] = []
                    sub_yang_info: List[Dict[str, Any]] = []
                    for update in notification.update:
                        for elem in update.path.elem:
                            start_yang_path.append(elem.name)
                            if elem.key:
                                for key, value in elem.key.items():
                                    if isinstance(value, str):
                                        start_yang_keys[key] = value.replace('"', "").replace("'", "")
                                    else:
                                        start_yang_keys[key] = value
                        keywords = self.yang_keywords[start_yang_path[0].split(":")[0]]["keys"]
                        start_yang_path_str: str = "/".join(start_yang_path)
                        response_value: Any = self.get_value(update.val)
                        if update.val.WhichOneof("value") in ["json_val", "json_ietf_val"]:
                            if response_value == "":
                                rc.append(ParsedResponse({}, self.version, self.hostname))
                                return rc
                            if isinstance(response_value, list):
                                for sub_response_value in response_value:
                                    for key, value in sub_response_value.items():
                                        self._walk_yang_data(
                                            sub_yang_path, key, value, keywords, start_yang_keys, sub_yang_info,
                                        )
                            else:
                                for key, value in response_value.items():
                                    self._walk_yang_data(
                                        sub_yang_path, key, value, keywords, start_yang_keys, sub_yang_info,
                                    )
                            for sub_yang in sub_yang_info:
                                parsed_dict = {
                                    "@timestamp": (int(notification.timestamp) / 1000000),
                                    "byte_size": response.ByteSize(),
                                    "keys": sub_yang["keys"],
                                }
                                yang_path = sub_yang["yang_path"]
                                parsed_dict["yang_path"] = f"{start_yang_path_str}/{yang_path}"
                                leaf = "-".join(parsed_dict["yang_path"].split("/")[-2:])
                                parsed_dict[leaf] = sub_yang["value"]
                                parsed_dict["ip"] = self.host
                                parsed_dict["index"] = yang_path_to_es_index(parsed_dict["yang_path"])
                                rc.append(ParsedResponse(parsed_dict, self.version, self.hostname))
                        else:
                            raise GNMIException("Unsupported Get encoding")
            return rc
        except Exception as error:
            raise GNMIException(f"Failed to complete the Get:\n {error}")