Esempio n. 1
0
    def start(self):
        """Tasklet entry point"""
        super(RestconfTasklet, self).start()

        self._initialized = False
        self._tasklet_name = "RwRestconf"
        self.get_stats = 0
        self.schema_name = "rw-restconf"  #
        self._schema_state = SchemaState.initializing

        self._dynamic_schema_publish = (
            "D,/rw-mgmt-schema:rw-mgmt-schema-state/rw-mgmt-schema:listening-apps[name='%s']" % self._tasklet_name
        )
        self._dynamic_schema_response = RwMgmtSchemaYang.YangData_RwMgmtSchema_RwMgmtSchemaState_ListeningApps()
        self._dynamic_schema_response.app_type = "nb_interface"
        self._dynamic_schema_response.name = self._tasklet_name
        self._dynamic_schema_response.state = self._schema_state.value
        self._manifest = self.tasklet_info.get_pb_manifest()
        self._pending_modules = dict()
        self._ssl_cert = self._manifest.bootstrap_phase.rwsecurity.cert
        self._ssl_key = self._manifest.bootstrap_phase.rwsecurity.key
        self._stats_pb = RwRestconfYang.Restconfstats()

        self._dts = rift.tasklets.DTS(
            self.tasklet_info, RwRestconfYang.get_schema(), self.loop, self.on_dts_state_change
        )
Esempio n. 2
0
    def start(self):
        """Tasklet entry point"""
        super(RestconfTasklet, self).start()

        self._initialized = False
        self._tasklet_name = "RwRestconf"
        self.get_stats = 0
        self.schema_name = "rw-restconf"  #
        self._schema_state = SchemaState.initializing

        self._dynamic_schema_publish = "D,/rw-mgmt-schema:rw-mgmt-schema-state/rw-mgmt-schema:listening-apps[name='%s']" % self._tasklet_name
        self._dynamic_schema_response = RwMgmtSchemaYang.YangData_RwMgmtSchema_RwMgmtSchemaState_ListeningApps(
        )
        self._dynamic_schema_response.app_type = "nb_interface"
        self._dynamic_schema_response.name = self._tasklet_name
        self._dynamic_schema_response.state = self._schema_state.value
        self._manifest = self.tasklet_info.get_pb_manifest()
        self._pending_modules = dict()
        self._ssl_cert = self._manifest.bootstrap_phase.rwsecurity.cert
        self._ssl_key = self._manifest.bootstrap_phase.rwsecurity.key
        self._stats_pb = RwRestconfYang.Restconfstats()

        self._dts = rift.tasklets.DTS(self.tasklet_info,
                                      RwRestconfYang.get_schema(), self.loop,
                                      self.on_dts_state_change)
Esempio n. 3
0
    def test_conversion_url_to_dts_xpath_2(self):
        self.maxDiff = None
        url = "/api/running/rwrestconf-configuration/"  # trailing / on purpose
        expected = ""

        schema = load_multiple_schema_root(["rw-restconf"])

        actual = create_dts_xpath_from_url(url, schema)

        value = RwKeyspec.path_from_xpath(RwRestconfYang.get_schema(), actual, RwKeyspec.RwXpathType.KEYSPEC, None)
Esempio n. 4
0
    def test_conversion_url_to_dts_xpath_2(self):
        self.maxDiff = None
        url = "/api/running/rwrestconf-configuration/"  # trailing / on purpose
        expected = ""

        schema = load_multiple_schema_root(["rw-restconf"])

        actual = create_dts_xpath_from_url(url, schema)

        value = RwKeyspec.path_from_xpath(RwRestconfYang.get_schema(), actual,
                                          RwKeyspec.RwXpathType.KEYSPEC, None)
Esempio n. 5
0
    def init(self):
        self._configuration = Configuration()
        self._configuration.use_https = self._manifest.bootstrap_phase.rwsecurity.use_ssl
        self._configuration.use_netconf = self._manifest.bootstrap_phase.rwmgmt.agent_mode == "CONFD"

        self._statistics = Statistics()
        self._messages = {}
        self._agent_is_ready = False
        self._agent_wait_timeout_secs = 360

        @asyncio.coroutine
        def on_prepare(dts, acg, xact, xact_info, ksp, msg, scratch):
            self._messages[xact.id] = msg
            acg.handle.prepare_complete_ok(xact_info.handle)

        @asyncio.coroutine
        def on_prepare_config_state(xact_info, action, path, msg):
            self._log.info("Agent is ready to receive requests")
            self._agent_is_ready = True
            xact_info.respond_xpath(RwDts.XactRspCode.ACK, path.create_string())

        def on_apply(dts, acg, xact, action, scratch):
            if action == RwDts.AppconfAction.INSTALL and xact.id is None:
                return

            if xact.id not in self._messages:
                raise KeyError("No stashed configuration found with transaction id [{}]".format(xact.id))

            toggles = self._messages[xact.id]

            if toggles.has_field("log_timing"):
                self._configuration.log_timing = toggles.log_timing

            if toggles.has_field("use_https"):
                self._configuration.use_https = toggles.use_https

            del self._messages[xact.id]

            if self._initialized:
                self._start_server()

        def agent_config_ready_cb(dts, acg, xact, action, scratch):
            # ATTN: Config ready needs to be handled here
            if action == RwDts.AppconfAction.INSTALL and xact.id is None:
                return
            self._log.info("Agent is ready to receive requests")
            self._agent_is_ready = True

            if xact.id in self._messages:
                del self._messages[xact.id]

        def agent_ready_read_cb(xact, xact_status, user_data):
            self._log.debug("agent_ready_cb")
            if self._agent_is_ready:
                return

            if xact is None:
                self._log.debug("xact is none")
                return

            query_result = xact.query_result()
            while query_result is not None:
                pbcm = query_result.protobuf
                data = RwMgmtagtYang.State_ConfigState.from_pbcm(pbcm)
                if data.ready:
                    self._agent_is_ready = True
                else:
                    self._agent_is_ready = False
                break

        with self._dts.appconf_group_create(handler=rift.tasklets.AppConfGroup.Handler(on_apply=on_apply)) as acg:
            acg.register(
                xpath="C,/rw-restconf:rwrestconf-configuration", flags=RwDts.Flag.SUBSCRIBER, on_prepare=on_prepare
            )

        yield from self._dts.register(
            flags=RwDts.Flag.SUBSCRIBER,
            xpath="D,/rw-mgmtagt:uagent/rw-mgmtagt:state/rw-mgmtagt:config-state",
            handler=rift.tasklets.DTS.RegistrationHandler(on_prepare=on_prepare_config_state),
        )
        # Check for agent's state in case of restart
        xact = self._dts.handle.query(
            "D,/rw-mgmtagt:uagent/rw-mgmtagt:state/rw-mgmtagt:config-state",
            RwDts.QueryAction.READ,
            0,
            agent_ready_read_cb,
            self,
        )

        self._ready_for_schema = False

        # start waiting for the agent
        self.loop.create_task(self.start_server())

        @asyncio.coroutine
        def dynamic_schema_state(xact_info, action, ks_path, msg):
            self._dynamic_schema_response.state = self._schema_state.value
            xact_info.respond_xpath(RwDts.XactRspCode.ACK, self._dynamic_schema_publish, self._dynamic_schema_response)

        yield from self._dts.register(
            flags=RwDts.Flag.PUBLISHER,
            xpath=(self._dynamic_schema_publish),
            handler=rift.tasklets.DTS.RegistrationHandler(on_prepare=dynamic_schema_state),
        )

        @asyncio.coroutine
        def load_modules_prepare(xact_info, action, path, msg):
            if msg.state != "loading_nb_interfaces":
                xact_info.respond_xpath(RwDts.XactRspCode.ACK, path.create_string())
                return

            self._schema_state = SchemaState.working

            module_name = msg.name

            so_filename = self._pending_modules[module_name]

            del self._pending_modules[module_name]

            new_schema = RwYang.Model.load_and_merge_schema(self._schema, so_filename, module_name)
            self._schema = new_schema

            yang_model = RwYang.Model.create_libncx()
            yang_model.load_schema_ypbc(new_schema)

            new_root = yang_model.get_root_node()

            self._schema_root = new_root
            self._confd_url_converter._schema = new_root
            self._confd_url_converter_v2._schema = new_root
            self._xml_to_json_translator._schema = new_root
            self._connection_manager._schema_root = new_root

            self._schema_state = SchemaState.ready
            xact_info.respond_xpath(RwDts.XactRspCode.ACK, path.create_string())

        yield from self._dts.register(
            flags=RwDts.Flag.SUBSCRIBER,
            xpath="D,/rw-mgmt-schema:rw-mgmt-schema-state/rw-mgmt-schema:dynamic-modules",
            handler=rift.tasklets.DTS.RegistrationHandler(on_prepare=load_modules_prepare),
        )

        def on_copy(shard, key, ctx):
            self._stats_pb.get_req = self._statistics.get_req
            self._stats_pb.put_req = self._statistics.put_req
            self._stats_pb.post_req = self._statistics.post_req
            self._stats_pb.del_req = self._statistics.del_req
            self._stats_pb.get_200_rsp = self._statistics.get_200_rsp
            self._stats_pb.get_404_rsp = self._statistics.get_404_rsp
            self._stats_pb.get_204_rsp = self._statistics.get_204_rsp
            self._stats_pb.get_500_rsp = self._statistics.get_500_rsp
            self._stats_pb.put_200_rsp = self._statistics.put_200_rsp
            self._stats_pb.put_404_rsp = self._statistics.put_404_rsp
            self._stats_pb.put_500_rsp = self._statistics.put_500_rsp
            self._stats_pb.post_200_rsp = self._statistics.post_200_rsp
            self._stats_pb.post_404_rsp = self._statistics.post_404_rsp
            self._stats_pb.post_500_rsp = self._statistics.post_500_rsp
            self._stats_pb.del_405_rsp = self._statistics.del_405_rsp
            self._stats_pb.del_404_rsp = self._statistics.del_404_rsp
            self._stats_pb.del_500_rsp = self._statistics.del_500_rsp
            self._stats_pb.del_200_rsp = self._statistics.del_200_rsp
            self._stats_pb.put_409_rsp = self._statistics.put_409_rsp
            self._stats_pb.put_405_rsp = self._statistics.put_405_rsp
            self._stats_pb.put_201_rsp = self._statistics.put_201_rsp
            self._stats_pb.post_409_rsp = self._statistics.post_409_rsp
            self._stats_pb.post_405_rsp = self._statistics.post_405_rsp
            self._stats_pb.post_201_rsp = self._statistics.post_201_rsp
            self._stats_pb.req_401_rsp = self._statistics.req_401_rsp

            evtsrc = self._stats_pb.eventsource_statistics
            evtsrc.websocket_stream_open = self._statistics.websocket_stream_open
            evtsrc.websocket_stream_close = self._statistics.websocket_stream_close
            evtsrc.websocket_events = self._statistics.websocket_events
            evtsrc.http_stream_open = self._statistics.http_stream_open
            evtsrc.http_stream_close = self._statistics.http_stream_close
            evtsrc.http_events = self._statistics.http_events

            return rwtypes.RwStatus.SUCCESS, self._stats_pb.to_pbcm()

        @asyncio.coroutine
        def get_prepare(xact_info, action, ks_path, msg):
            xact_info.respond_xpath(rwdts.XactRspCode.NA, xpath="D,/rw-restconf:rwrestconf-statistics")

        @asyncio.coroutine
        def get_restconf_state(xact_info, action, ks_path, msg):
            """Provides the RestConf state to the DTS.

            Invoked when UAgent requests DTS to provide the restconf-state.
            """
            xpath = "D,/rcmon:restconf-state"
            if self._state_provider is None:
                self._log.error("restconf-state provider not initialized")
                xact_info.send_error_xpath(rwtypes.RwStatus.FAILURE, xpath, "RW.RESTCONF not ready")
                xact_info.respond_xpath(RwDts.XactRspCode.NACK, xpath)
                return

            try:
                restconf_state = yield from self._state_provider.get_state()
                xact_info.respond_xpath(RwDts.XactRspCode.ACK, xpath, restconf_state)
            except:
                self._log.exception("Fetching state failed")
                xact_info.send_error_xpath(rwtypes.RwStatus.FAILURE, xpath, "RW.RESTCONF internal error")
                xact_info.respond_xpath(RwDts.XactRspCode.NACK, xpath)

        reg = yield from self._dts.register(
            flags=RwDts.Flag.PUBLISHER | RwDts.Flag.NO_PREP_READ,
            xpath="D,/rw-restconf:rwrestconf-statistics",
            handler=rift.tasklets.DTS.RegistrationHandler(on_prepare=get_prepare),
        )

        shard = yield from reg.shard_init(flags=RwDts.Flag.PUBLISHER)
        shard.appdata_register_queue_key(copy=on_copy)

        # Register with DTS for providing restconf-state operational data
        yield from self._dts.register(
            flags=RwDts.Flag.PUBLISHER,
            xpath="D,/rcmon:restconf-state",
            handler=rift.tasklets.DTS.RegistrationHandler(on_prepare=get_restconf_state),
        )

        self._schema = RwRestconfYang.get_schema()

        self._dynamic_schema_registration = RwDynSchema.rwdynschema_instance_register(
            self._dts.handle, dyn_schema_callback, "RwRestconf", RwDynSchema.RwdynschemaAppType.NORTHBOUND, self
        )
Esempio n. 6
0
    def init(self):
        self._configuration = Configuration()
        self._configuration.use_https = self._manifest.bootstrap_phase.rwsecurity.use_ssl
        self._configuration.use_netconf = self._manifest.bootstrap_phase.rwmgmt.agent_mode == "CONFD"

        self._statistics = Statistics()
        self._messages = {}
        self._agent_is_ready = False
        self._agent_wait_timeout_secs = 360

        @asyncio.coroutine
        def on_prepare(dts, acg, xact, xact_info, ksp, msg, scratch):
            self._messages[xact.id] = msg
            acg.handle.prepare_complete_ok(xact_info.handle)

        def on_apply(dts, acg, xact, action, scratch):
            if action == RwDts.AppconfAction.INSTALL and xact.id is None:
                return

            if xact.id not in self._messages:
                raise KeyError(
                    "No stashed configuration found with transaction id [{}]".
                    format(xact.id))

            toggles = self._messages[xact.id]

            if toggles.has_field("log_timing"):
                self._configuration.log_timing = toggles.log_timing

            if toggles.has_field("use_https"):
                self._configuration.use_https = toggles.use_https

            del self._messages[xact.id]

            if self._initialized:
                self._start_server()

        def agent_config_ready_cb(dts, acg, xact, action, scratch):
            # ATTN: Config ready needs to be handled here
            if action == RwDts.AppconfAction.INSTALL and xact.id is None:
                return
            self._log.info("Agent is ready to receive requests")
            self._agent_is_ready = True

            if xact.id in self._messages:
                del self._messages[xact.id]

        def agent_ready_read_cb(xact, xact_status, user_data):
            self._log.debug("agent_ready_cb")
            if self._agent_is_ready:
                return

            if xact is None:
                self._log.debug("xact is none")
                return

            query_result = xact.query_result()
            while query_result is not None:
                pbcm = query_result.protobuf
                data = RwMgmtagtYang.State_ConfigState.from_pbcm(pbcm)
                if data.ready:
                    self._agent_is_ready = True
                else:
                    self._agent_is_ready = False
                break

        with self._dts.appconf_group_create(
                handler=rift.tasklets.AppConfGroup.Handler(
                    on_apply=on_apply)) as acg:
            acg.register(xpath="C,/rw-restconf:rwrestconf-configuration",
                         flags=RwDts.Flag.SUBSCRIBER,
                         on_prepare=on_prepare)

        with self._dts.appconf_group_create(
                handler=rift.tasklets.AppConfGroup.Handler(
                    on_apply=agent_config_ready_cb)) as acg:
            acg.register(
                xpath=
                "D,/rw-mgmtagt:uagent/rw-mgmtagt:state/rw-mgmtagt:config-state",
                flags=RwDts.Flag.SUBSCRIBER,
                on_prepare=on_prepare)

        # Check for agent's state in case of restart
        xact = self._dts.handle.query(
            "D,/rw-mgmtagt:uagent/rw-mgmtagt:state/rw-mgmtagt:config-state",
            RwDts.QueryAction.READ, 0, agent_ready_read_cb, self)

        self._ready_for_schema = False

        #start waiting for the agent
        self.loop.create_task(self.start_server())

        @asyncio.coroutine
        def dynamic_schema_state(xact_info, action, ks_path, msg):
            self._dynamic_schema_response.state = self._schema_state.value
            xact_info.respond_xpath(RwDts.XactRspCode.ACK,
                                    self._dynamic_schema_publish,
                                    self._dynamic_schema_response)

        yield from self._dts.register(
            flags=RwDts.Flag.PUBLISHER,
            xpath=(self._dynamic_schema_publish),
            handler=rift.tasklets.DTS.RegistrationHandler(
                on_prepare=dynamic_schema_state))

        @asyncio.coroutine
        def load_modules_prepare(xact_info, action, path, msg):
            if msg.state != "loading_nb_interfaces":
                xact_info.respond_xpath(RwDts.XactRspCode.ACK,
                                        path.create_string())
                return

            self._schema_state = SchemaState.working

            module_name = msg.name

            so_filename = self._pending_modules[module_name]

            del self._pending_modules[module_name]

            new_schema = RwYang.Model.load_and_merge_schema(
                self._schema, so_filename, module_name)
            self._schema = new_schema

            yang_model = RwYang.Model.create_libncx()
            yang_model.load_schema_ypbc(new_schema)

            new_root = yang_model.get_root_node()

            self._schema_root = new_root
            self._confd_url_converter._schema = new_root
            self._xml_to_json_translator._schema = new_root
            self._connection_manager._schema_root = new_root

            self._schema_state = SchemaState.ready
            xact_info.respond_xpath(RwDts.XactRspCode.ACK,
                                    path.create_string())

        yield from self._dts.register(
            flags=RwDts.Flag.SUBSCRIBER,
            xpath=
            "D,/rw-mgmt-schema:rw-mgmt-schema-state/rw-mgmt-schema:dynamic-modules",
            handler=rift.tasklets.DTS.RegistrationHandler(
                on_prepare=load_modules_prepare))

        def on_copy(shard, key, ctx):
            self._stats_pb.get_req = self._statistics.get_req
            self._stats_pb.put_req = self._statistics.put_req
            self._stats_pb.post_req = self._statistics.post_req
            self._stats_pb.del_req = self._statistics.del_req
            self._stats_pb.get_200_rsp = self._statistics.get_200_rsp
            self._stats_pb.get_404_rsp = self._statistics.get_404_rsp
            self._stats_pb.get_204_rsp = self._statistics.get_204_rsp
            self._stats_pb.get_500_rsp = self._statistics.get_500_rsp
            self._stats_pb.put_200_rsp = self._statistics.put_200_rsp
            self._stats_pb.put_404_rsp = self._statistics.put_404_rsp
            self._stats_pb.put_500_rsp = self._statistics.put_500_rsp
            self._stats_pb.post_200_rsp = self._statistics.post_200_rsp
            self._stats_pb.post_404_rsp = self._statistics.post_404_rsp
            self._stats_pb.post_500_rsp = self._statistics.post_500_rsp
            self._stats_pb.del_405_rsp = self._statistics.del_405_rsp
            self._stats_pb.del_404_rsp = self._statistics.del_404_rsp
            self._stats_pb.del_500_rsp = self._statistics.del_500_rsp
            self._stats_pb.del_200_rsp = self._statistics.del_200_rsp
            self._stats_pb.put_409_rsp = self._statistics.put_409_rsp
            self._stats_pb.put_405_rsp = self._statistics.put_405_rsp
            self._stats_pb.put_201_rsp = self._statistics.put_201_rsp
            self._stats_pb.post_409_rsp = self._statistics.post_409_rsp
            self._stats_pb.post_405_rsp = self._statistics.post_405_rsp
            self._stats_pb.post_201_rsp = self._statistics.post_201_rsp

            evtsrc = self._stats_pb.eventsource_statistics
            evtsrc.websocket_stream_open = self._statistics.websocket_stream_open
            evtsrc.websocket_stream_close = self._statistics.websocket_stream_close
            evtsrc.websocket_events = self._statistics.websocket_events
            evtsrc.http_stream_open = self._statistics.http_stream_open
            evtsrc.http_stream_close = self._statistics.http_stream_close
            evtsrc.http_events = self._statistics.http_events

            return rwtypes.RwStatus.SUCCESS, self._stats_pb.to_pbcm()

        @asyncio.coroutine
        def get_prepare(xact_info, action, ks_path, msg):
            xact_info.respond_xpath(
                rwdts.XactRspCode.NA,
                xpath="D,/rw-restconf:rwrestconf-statistics")

        @asyncio.coroutine
        def get_restconf_state(xact_info, action, ks_path, msg):
            """Provides the RestConf state to the DTS.

            Invoked when UAgent requests DTS to provide the restconf-state.
            """
            xpath = "D,/rcmon:restconf-state"
            if self._state_provider is None:
                self._log.error("restconf-state provider not initialized")
                xact_info.send_error_xpath(rwtypes.RwStatus.FAILURE, xpath,
                                           "RW.RESTCONF not ready")
                xact_info.respond_xpath(RwDts.XactRspCode.NACK, xpath)
                return

            try:
                restconf_state = yield from self._state_provider.get_state()
                xact_info.respond_xpath(RwDts.XactRspCode.ACK, xpath,
                                        restconf_state)
            except:
                self._log.exception("Fetching state failed")
                xact_info.send_error_xpath(rwtypes.RwStatus.FAILURE, xpath,
                                           "RW.RESTCONF internal error")
                xact_info.respond_xpath(RwDts.XactRspCode.NACK, xpath)

        reg = yield from self._dts.register(
            flags=RwDts.Flag.PUBLISHER | RwDts.Flag.NO_PREP_READ,
            xpath="D,/rw-restconf:rwrestconf-statistics",
            handler=rift.tasklets.DTS.RegistrationHandler(
                on_prepare=get_prepare))

        shard = yield from reg.shard_init(flags=RwDts.Flag.PUBLISHER)
        shard.appdata_register_queue_key(copy=on_copy)

        # Register with DTS for providing restconf-state operational data
        yield from self._dts.register(
            flags=RwDts.Flag.PUBLISHER,
            xpath="D,/rcmon:restconf-state",
            handler=rift.tasklets.DTS.RegistrationHandler(
                on_prepare=get_restconf_state))

        self._schema = RwRestconfYang.get_schema()

        self._dynamic_schema_registration = RwDynSchema.rwdynschema_instance_register(
            self._dts.handle, dyn_schema_callback, "RwRestconf",
            RwDynSchema.RwdynschemaAppType.NORTHBOUND, self)