def _do_delete_children(self):
        child_promises = []

        for child in self.resource.childResource:
            request = OneM2MRequest(OneM2MOperation.delete, child.path, fr=None,
                                    rqi=self.request.rqi)
            request.cascading = True
            child_promises.append(self.handle_onem2m_request(request))

        async_all(child_promises, fulfill_with_none=True).get()
Beispiel #2
0
    def _start(self):
        def retrieve_remote_cse_list():
            def get_collection(session):
                p = session.get_collection(None, RemoteCSE,
                                           CSEBase(path="/onem2m"))
                session.commit()
                return p

            return self.api.db.start_session().then(get_collection)

        def get_cse(cse):
            cse_req = OneM2MRequest(OneM2MOperation.retrieve, cse, None,
                                    MetaInformation(None))
            return (self.api.handle_onem2m_request(cse_req)
                    .then(lambda r: r.resource))

        def handle_remote_cse_list(remote_cse_list):
            self.logger.debug("Loaded RemoteCSE list is %s" % remote_cse_list)
            for cse in remote_cse_list:
                self.logger.debug("Adding CSE %s in the list" % cse)
                self._cse_links[cse.path] = cse.link

        return retrieve_remote_cse_list() \
            .then(
            lambda remote_cse_list: async_all(map(get_cse, remote_cse_list))) \
            .then(handle_remote_cse_list) \
            .then(self._started)
    def _handle_deleted(self, instance, req_ind):

        poc_path = instance.path
        scl_path = poc_path.rpartition('/')[0].rpartition('/')[0]

        self.logger.debug("_handle_deleted: instance: %s %s", poc_path,
                          scl_path)

        promises = []

        del (self.pocs_info[scl_path][poc_path])  #delete m2mpoc from list
        if len(self.pocs_info[scl_path]) <= 1:  #check if the scl has more pocs
            del (self.pocs_info[scl_path])  #delete scl from the list

            onlinestatus_path = scl_path + "/onlineStatus"
            online_status = {"onlineStatus": "OFFLINE"}
            rq = UpdateRequestIndication(onlinestatus_path,
                                         resource=online_status,
                                         typename="scl")
            rq.internal = True

            serverCapability_path = scl_path + "/serverCapability"
            serverCapability = {"serverCapability": "FALSE"}
            rq2 = UpdateRequestIndication(serverCapability_path,
                                          resource=serverCapability,
                                          typename="scl")
            rq2.internal = True
            promises = [
                self.api.handle_request_indication(rq),
                self.api.handle_request_indication(rq2)
            ]

        promises.append(self._update_scl(scl_path, self.pocs_info[scl_path]))

        return async_all(promises, fulfill_with_none=True)
 def handle_items(items):
     if not items:
         p = Promise()
         return p.fulfill(None)
     promises = []
     for path, pocs in items:
         promises.append(self._do_handle_pocs(path, pocs, shelve))
     return async_all(promises, fulfill_with_none=True)
    def _handle_updated(self, instance, req_ind):
        """
        #example:
        instance:M2mPoc(path='/m2m/scls/gscl/m2mPocs/m2mPoc1qvr4rUOGJAKEPFK', name='m2mPoc1qvr4rUOGJAKEPFK')
        req_ind:RequestIndication: {
            path: /m2m/scls/gscl/m2mPocs/m2mPoc1qvr4rUOGJAKEPFK,
            method: update,
            typename: m2mPoc,
            resource: {
                'expirationTime': '2014-07-11T17:05:09.004744+00:00',
                'contactInfo': 'https://[2001:638:806:65:f4bf:ccb0:cad5:a203]:6000',
                'onlineStatus': 'ONLINE'
            }
        }
        """
        self.logger.debug("_handle_updated: instance:%s req_ind:%s", instance,
                          req_ind)

        resource = req_ind.resource
        poc_path = instance.path
        scl_path = poc_path.rpartition('/')[0].rpartition('/')[0]

        online_status = resource['onlineStatus']
        self.logger.debug("_handle_updated: pocs_info:%s", self.pocs_info)

        self.pocs_info[scl_path][poc_path] = {'onlineStatus': online_status}
        has_offline = False
        has_online = False
        for key, value in self.pocs_info.get(scl_path).items():
            if key != 'onlineStatus':
                if value['onlineStatus'] == 'ONLINE':
                    has_online = True
                elif value['onlineStatus'] == 'OFFLINE':
                    has_offline = True
        if has_online:
            self.pocs_info[scl_path]['onlineStatus'] = "ONLINE"
        elif has_offline:
            self.pocs_info[scl_path]['onlineStatus'] = "OFFLINE"
        else:
            self.pocs_info[scl_path]['onlineStatus'] = "NOT_REACHABLE"

        onlinestatus_path = scl_path + "/onlineStatus"
        online_status = {
            "onlineStatus": self.pocs_info[scl_path]['onlineStatus']
        }

        rq = UpdateRequestIndication(onlinestatus_path,
                                     resource=online_status,
                                     typename="scl")
        rq.internal = True
        promises = [
            self._update_scl(scl_path, self.pocs_info[scl_path]),
            self.api.handle_request_indication(rq)
        ]
        return async_all(promises, fulfill_with_none=True)
Beispiel #6
0
    def _start(self):
        def retrieve_scl_list():
            scls_req_ind = RetrieveRequestIndication(self._scl_base + '/scls')
            return (self.api.handle_request_indication(scls_req_ind)
                    .then(lambda r: r.resource.sclCollection))

        def get_scl(scl):
            scl_req_ind = RetrieveRequestIndication(scl)
            return (self.api.handle_request_indication(scl_req_ind)
                    .then(lambda r: r.resource))

        def handle_scl_list(scl_list):
            for scl in scl_list:
                self._scl_links[scl.path] = scl.link

        return retrieve_scl_list().then(
            lambda scls_list: async_all(map(get_scl, scls_list))).then(
            handle_scl_list).then(
            self._started)
    def _register_pocs(self):
        def send_update(m2mpoc, fields):
            uri = self.nscl_uri + "/" + "scls/" + self.gscl_id\
                + "/" + "m2mPocs" + "/" + m2mpoc.id
            rq = UpdateRequestIndication(uri, m2mpoc)
            rq.requestingEntity = self.config.get("requesting_entity")
            # TODO: add restore function in case of 404 or something
            return self.api.send_request_indication(rq)

        def _start_endpoint_refresher(response, m2mpoc):
            m2mpoc.set_path(response.resourceURI)
            self.poc_refresher.start(m2mpoc, [])

        def _register_endpoint(endpoint):

            # create a M2mPoc with the endpoint as contact info in the NSCL
            # (onlineStatus=ONLINE)
            uri = self.nscl_uri + "/" + "scls/" + self.gscl_id + "/" + "m2mPocs"
            m2mpoc = M2mPoc()
            m2mpoc.onlineStatus = "ONLINE"
            m2mpoc.contactInfo = endpoint.base_uri
            m2mpoc.expirationTime = self._gscl.expirationTime

            rq = CreateRequestIndication(uri, m2mpoc)
            rq.requestingEntity = self.config.get("requesting_entity")
            p = self.api.send_request_indication(rq).then(
                lambda evt, m2mpoc=m2mpoc: _start_endpoint_refresher(
                    evt, m2mpoc))

            return p

        # we use a separate refresher for pocs,
        # because refresher is specifically for Scl (see send_update)
        self.poc_refresher = ExpTimeUpdater(self.api,
                                            send_update,
                                            interval=self.interval,
                                            offset=self.offset)

        promise_list = map(_register_endpoint, self.api.get_mid_endpoints())
        return async_all(promise_list, True)
    def _check_notification_uri(self):
        # TODO(rst): TS-004 7.3.8.2.1
        # 5. If the notificationURI is not the Originator, the Hosting CSE
        # should send a Notify request primitive to the notificationURI with
        # verificationRequest parameter set as TRUE (clause 7.4.1.2.2).

        # debug only
        if self.request.originator is None:
            return

        try:
            self.logger.debug("Checking notificationURI: %s",
                              self.request.content.notificationURI)
            uris = [uri for uri in
                    self.request.content.notificationURI if
                    not uri.startswith(self.request.originator)]
            # TODO(rst): change the check that it should be a valid AE-ID
            # for uri in uris:
            #     if not urlparse(uri).scheme:
            #         raise CSESyntaxError("Invalid notificationURI")
        except KeyError:
            raise CSESyntaxError("Invalid notificationURI")

        # a. If the Hosting CSE cannot send the Notify request primitive, the
        # Hosting CSE shall return the Notify response primitive with a Response
        # Status Code indicating "SUBSCRIPTION_VERIFICATION_INITIATION_FAILED"
        # error.

        def send_verification(notify_uri):
            notification = Notification(
                verificationRequest=True,
                creator=self.request.originator
            )

            send_notify_request = OneM2MRequest(OneM2MOperation.notify,
                                                notify_uri, None,
                                                MetaInformation(None),
                                                notification)
            return self.api.send_onem2m_request(send_notify_request)

        # b. If the Hosting CSE sent the primitive, the Hosting CSE shall
        # check if the Notify response primitive contains a Response Status Code
        # indicating "SUBSCRIPTION_CREATOR_HAS_NO_PRIVILEGE" or
        # "SUBSCRIPTION_HOST_HAS_NO_PRIVILEGE" error. If so, the Hosting CSE
        # shall return the Create response primitive with a Response Status Code
        # indicating the same error from the Notify response primitive to the
        # Originator.

        def handle_error(error):
            self.logger.info("Subscription verification failed: %s", error)
            raise CSEError
            # TODO(rst): check subscription error
            # if error.status_code in [
            #     STATUS_REQUEST_TIMEOUT,
            #     STATUS_BAD_GATEWAY,
            #     STATUS_SERVICE_UNAVAILABLE,
            #     STATUS_GATEWAY_TIMEOUT
            # ]:
            #     raise CannotInitiateSubscriptionVerification(error)
            # elif error.status_code == STATUS_SUBSCRIPTION_VERIFICATION_FAILED:
            #     raise SubscriptionVerificationFailed(error)
            # else:
            #     raise CSEBadGateway(error)

        try:
            async_all(map(send_verification, uris),
                      fulfill_with_none=True).get()
        except Exception as error:
            handle_error(error)
    def _handle_created(self, instance, req_ind):
        """
        #example:
        instance:M2mPoc(path='/m2m/scls/gscl/m2mPocs/m2mPocnRIjsAAZmqm1U49j', name='m2mPocnRIjsAAZmqm1U49j')
        req_ind:RequestIndication: {
            path: /m2m/scls/gscl/m2mPocs,
            method: create,
            typename: m2mPoc,
            resource: {
                'creationTime': datetime.datetime(2014, 7, 11, 13, 37, 40, 385438,
                    tzinfo=<openmtc.util.Utc object at 0x7f4d9bf68e50>),
                'expirationTime': datetime.datetime(2014, 7, 11, 13, 43, 40,
                    tzinfo=<FixedOffset '+00:00'>),
                'onlineStatus': 'ONLINE',
                'contactInfo': 'http://[2001:638:806:65:f4bf:ccb0:cad5:a203]:5000',
                'lastModifiedTime': datetime.datetime(2014, 7, 11, 13, 37, 40, 385438,
                    tzinfo=<openmtc.util.Utc object at 0x7f4d9bf68e50>)
            }
        }
        """

        self.logger.debug("_handle_created: instance:%s req_ind:%s", instance,
                          req_ind)

        resource = req_ind.resource
        poc_path = instance.path
        scl_path = req_ind.path[:-8]
        online_status = resource['onlineStatus']

        if self.pocs_info.get(scl_path) is None:

            self.pocs_info[scl_path] = {'onlineStatus': online_status}
            self.pocs_info[scl_path][poc_path] = {
                'onlineStatus': online_status
            }
        else:
            self.pocs_info[scl_path][poc_path] = {
                'onlineStatus': online_status
            }
            has_offline = False
            has_online = False
            for key, value in self.pocs_info.get(scl_path).items():
                if key != 'onlineStatus':
                    if value['onlineStatus'] == 'ONLINE':
                        has_online = True
                    elif value['onlineStatus'] == 'OFFLINE':
                        has_offline = True
            if has_online:
                self.pocs_info[scl_path]['onlineStatus'] = "ONLINE"
            elif has_offline:
                self.pocs_info[scl_path]['onlineStatus'] = "OFFLINE"
            else:
                self.pocs_info[scl_path]['onlineStatus'] = "NOT_REACHABLE"

        self.logger.debug("_handle_created: self.pocs_info: %s",
                          self.pocs_info)

        onlinestatus_path = scl_path + "/onlineStatus"
        online_status = {
            "onlineStatus": self.pocs_info[scl_path]['onlineStatus']
        }
        rq = UpdateRequestIndication(onlinestatus_path,
                                     resource=online_status,
                                     typename="scl")
        rq.internal = True

        serverCapability_path = scl_path + "/serverCapability"
        serverCapability = {"serverCapability": True}
        rq2 = UpdateRequestIndication(serverCapability_path,
                                      resource=serverCapability,
                                      typename="scl")
        rq2.internal = True

        promises = [self._update_scl(scl_path, self.pocs_info[scl_path]), self.api.handle_request_indication(rq), \
            self.api.handle_request_indication(rq2)]
        return async_all(promises, fulfill_with_none=True)
Beispiel #10
0
    def _update_announcements(self, resource, add_list):
        old_resource = self._announcements[resource.path]['resource']
        uris = self._announcements[resource.path]['uris']

        attributes_changed = False

        try:
            if (resource.expirationTime != old_resource.expirationTime or
                    resource.searchStrings != old_resource.searchStrings or
                    resource.accessRightID != old_resource.accessRightID):
                attributes_changed = True
        except AttributeError:
            if (resource.expirationTime != old_resource.expirationTime or
                    resource.searchStrings != old_resource.searchStrings):
                attributes_changed = True

        if attributes_changed:

            annc_model = get_resource_type(resource.typename + "Annc")

            def send_update_annc_pre(scl_uri):
                try:
                    if not resource.accessRightID:
                        return send_update_annc(scl_uri)
                except AttributeError:
                    return send_update_annc(scl_uri)

                return send_update_annc(scl_uri, self.api.is_local_path(
                    resource.accessRightID))

            def send_update_annc(scl_uri, local_ar=False):
                endpoint = self.api.get_mid_uri(urlparse(scl_uri).scheme)

                annc = annc_model()

                # link hast to be set
                annc.link = urljoin(endpoint, resource.path)

                # * searchStrings from the original resource;
                annc.searchStrings = resource.searchStrings

                # * accessRightID from the original resource;
                if local_ar:
                    annc.accessRightID = urljoin(endpoint, urlparse(
                        resource.accessRightID).path)
                else:
                    annc.accessRightID = resource.accessRightID

                # * expirationTime handling is to the discretion of the SCL
                # implementation. It is the responsibility of the local SCL to
                # keep the announced resource in sync with the lifetime of the
                # original resource, as long as the announcement is active. One
                # strategy to minimize signalling would be to request the same
                # expiration from the original resource. If this is accepted by
                # the remote SCL, then no explicit de-announce is needed in case
                # of expiration of the original resource;
                annc.expirationTime = resource.expirationTime

                update_req_ind = UpdateRequestIndication(
                    uris[scl_uri], annc, requestingEntity=endpoint)

                # todo investigate response for not accepted expirationTime
                return self.api.send_request_indication(update_req_ind)

            old_resource.searchStrings = resource.searchStrings
            try:
                old_resource.accessRightID = resource.accessRightID
            except AttributeError:
                pass
            old_resource.expirationTime = resource.expirationTime

            scl_list = resource.announceTo.sclList
            # TODO: conversion to set()  is questionable
            update_list = [x for x in scl_list if x not in set(add_list)]

            return async_all(map(send_update_annc_pre, update_list))

        return None
Beispiel #11
0
        def send_anncs(scl_list):
            # i) For each unsuccessful
            # createXXXAnnouncementResourceResponseIndication, the remote SCL is
            # removed from the sclList in the announceTo attribute.
            def handle_create_err(res):
                return res.scl_uri

            # ii) For each successful
            # createXXXAnnouncementResourceResponseIndication, the local SCL
            # shall internally store the resourceURI of the created announced
            # resource. This URI is needed for delete the resource later on.
            def handle_create(res):
                if isinstance(res.res_con, ErrorResponse):
                    return handle_create_err(res)
                self._announcements[resource.path]['uris'][
                    res.scl_uri] = res.res_con.resourceURI
                return False

            # iii) For each unsuccessful
            # deleteXXXAnnouncementResourceRequestIndication with the statusCode
            # STATUS_NOT_FOUND, the remote SCL is removed from the sclList in
            # the announceTo attribute.
            # For all other statusCode value, no action is performed.
            def handle_delete_err(res):
                try:
                    if res.res_con.statusCode != 'STATUS_NOT_FOUND':
                        return res.scl_uri
                finally:
                    del self._announcements[resource.path]['uris'][res.scl_uri]
                    return False

            # iv) For each successful
            # deleteXXXAnnouncementResourceRequestIndication, the remote SCL is
            # removed from the sclList in the announceTo attribute.
            def handle_delete(res):
                if isinstance(res.res_con, ErrorResponse):
                    return handle_delete_err(res)
                del self._announcements[resource.path]['uris'][res.scl_uri]
                return False

            create_list = [x for x in scl_list if x not in set(old_scl_list)]
            delete_list = [x for x in old_scl_list if x not in set(scl_list)]

            filtered_scls = [x for x in db_scl_list if x not in set(scl_list)]

            # links the send funcs with the handle result funcs
            create_func = lambda s: send_create_annc_pre(s).then(
                lambda r: handle_create(AnncResult(s, r)),
                lambda r: handle_create_err(AnncResult(s, r)))
            delete_func = lambda s: send_delete_annc(s).then(
                lambda r: handle_delete(AnncResult(s, r)),
                lambda r: handle_delete_err(AnncResult(s, r)))

            # filters out all False in the list
            def filter_func(l):
                return filter(None, l)

            return async_all([
                (async_all(map(create_func, create_list)).then(filter_func)
                 .then(lambda l: l + filtered_scls)),
                async_all(map(delete_func, delete_list)).then(filter_func)
            ])
Beispiel #12
0
def start_plugins():
    logger.info("Starting plugins")
    async_all([plugin.start() for plugin in _plugins]).get()
Beispiel #13
0
def init_plugins():
    logger.info("Initializing plugins")
    async_all([plugin.initialize() for plugin in _plugins]).get()
Beispiel #14
0
    def _update_announcements(self, resource, add_list):
        old_resource = self._announcements[resource.path]['resource']
        uris = self._announcements[resource.path]['uris']

        attributes_changed = False

        try:
            if resource.expirationTime != old_resource.expirationTime or \
                            resource.labels != old_resource.labels or \
                            resource.accessRightID != old_resource.accessRightID:
                attributes_changed = True
        except AttributeError:
            if resource.expirationTime != old_resource.expirationTime or \
                            resource.labels != old_resource.labels:
                attributes_changed = True

        if attributes_changed:

            annc_model = get_onem2m_type(resource.typename + "Annc")

            def send_update_annc_pre(cse_uri):
                # TODO_oneM2M: Needs updating
                try:
                    if not resource.accessRightID:
                        return send_update_annc(cse_uri)
                except AttributeError:
                    return send_update_annc(cse_uri)

                return self.api.is_local_path(resource.accessRightID) \
                    .then(lambda local_ar: send_update_annc(cse_uri, local_ar))

            def send_update_annc(cse_uri, local_ar=None):
                # TODO_oneM2M: Update to oneM2M
                # endpoint = self.api.get_endpoint('mid',
                #                                 urlparse(cse_uri).scheme)
                endpoint = self.config.get('endpoint', '')

                annc = annc_model()

                # link hast to be set
                annc.link = urljoin(endpoint, resource.path)

                # * labels from the original resource;
                annc.labels = resource.labels

                # * accessRightID from the original resource;
                if local_ar:
                    annc.accessRightID = urljoin(endpoint, urlparse(
                        resource.accessRightID).path)
                elif local_ar is None:
                    annc.accessRightID = local_ar
                else:
                    annc.accessRightID = resource.accessRightID

                # * expirationTime handling is to the discretion of the CSE
                # implementation. It is the responsibility of the local CSE to
                # keep the announced resource in sync with the lifetime of the
                # original resource, as long as the announcement is active. One
                # strategy to minimize signalling would be to request the same
                # expiration from the original resource. If this is accepted by
                # the remote CSE, then no explicit de-announce is needed in case
                # of expiration of the original resource;
                annc.expirationTime = resource.expirationTime

                update_req_ind = UpdateRequestIndication(uris[cse_uri], annc)

                # todo investigate response for not accepted expirationTime
                return self.api.send_request_indication(update_req_ind)

            old_resource.labels = resource.labels
            try:
                old_resource.accessRightID = resource.accessRightID
            except AttributeError:
                pass
            old_resource.expirationTime = resource.expirationTime

            cse_list = resource.announceTo  # .get('cseList', {}).get('reference')
            # TODO: conversion to set()  is questionable
            update_list = [x for x in cse_list if x not in set(add_list)]

            return async_all(map(send_update_annc_pre, update_list))

        self.logger.debug('No attributes changed, returning None')
        return None