Example #1
0
    def _build_header(self, raw_msg):
        """
        Builds the header for this Process-level RPC conversation.
        https://confluence.oceanobservatories.org/display/syseng/CIAD+COI+OV+Common+Message+Format
        """

        context = self._process.get_context()
        log.debug('ProcessRPCRequestEndpointUnit._build_header has context of: %s', context)

        # conv-id/seq/protocol are set in the base class
        header = RPCRequestEndpointUnit._build_header(self, raw_msg)

        # add our process identity to the headers
        header.update({'sender-name'  : self._process.name or 'unnamed-process',     # @TODO
                       'sender'       : 'todo'})
        
        # use context to set security attributes forward
        if isinstance(context, dict):
            # fwd on ion-user-id and expiry, according to common message format spec
            user_id             = context.get('ion-user-id', None)
            expiry              = context.get('expiry', None)

            if user_id:         header['ion-user-id']   = user_id
            if expiry:          header['expiry']        = expiry

        return header
Example #2
0
    def _fetch_file(self, url):
        log.debug("Downloading: %s" % url)
        file_name = url.split('/')[-1]
        
        if(os.path.exists('/tmp/' + file_name)):
             log.debug(" -- file already downloaded")
             return '/tmp/' + file_name
            
        u = urllib2.urlopen(url)
        f = open('/tmp/' + file_name, 'wb')
        meta = u.info()
        file_size = int(meta.getheaders("Content-Length")[0])
        print "Downloading: %s Bytes: %s" % (file_name, file_size)

        file_size_dl = 0
        block_sz = 8192
        while True:
            buffer = u.read(block_sz)
            if not buffer:
                break

            file_size_dl += len(buffer)
            f.write(buffer)
            status = r"%10d  [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
            status = status + chr(8)*(len(status)+1)
            print status,

        f.close()
        return '/tmp/' + file_name
Example #3
0
    def stop(self):
        log.debug("ProcManager stopping ...")

        # Call quit on procs to give them ability to clean up in reverse order
        procs_list = sorted(self.procs.values(), key=lambda proc: proc._proc_start_time, reverse=True)
        for proc in procs_list:
            try:
                self.terminate_process(proc.id)
            except Exception as ex:
                log.warn("Failed to terminate process (%s): %s", proc.id, ex)

        # TODO: Have a choice of shutdown behaviors for waiting on children, timeouts, etc
        self.proc_sup.shutdown(CFG.get_safe("container.timeout.shutdown"))

        if self.procs:
            log.warn("ProcManager procs not empty: %s", self.procs)
        if self.procs_by_name:
            log.warn("ProcManager procs_by_name not empty: %s", self.procs_by_name)

        # Remove Resource registration
        if self.container.has_capability(self.container.CCAP.RESOURCE_REGISTRY):
            try:
                self.container.resource_registry.delete(self.cc_id, del_associations=True)
            except NotFound:
                # already gone, this is ok
                pass

        if self.pd_enabled:
            self._stop_process_dispatcher()

        log.debug("ProcManager stopped, OK.")
 def read_data_process(self, data_process_id=""):
     # Read DataProcess object with _id matching  id
     log.debug("Reading DataProcess object id: %s" % data_process_id)
     data_proc_obj = self.clients.resource_registry.read(data_process_id)
     if not data_proc_obj:
         raise NotFound("DataProcess %s does not exist" % data_process_id)
     return data_proc_obj
    def _link_resources_lowlevel(self, subject_id='', association_type='', object_id='', check_duplicates=True):
        """
        create an association
        @param subject_id the resource ID of the predefined type
        @param association_type the predicate
        @param object_id the resource ID of the type to be joined
        @param check_duplicates whether to check for an existing association of this exact subj-pred-obj
        @todo check for errors: does RR check for bogus ids?
        """

        assert(type("") == type(subject_id) == type(object_id))

        if check_duplicates:
            dups = self._resource_link_exists(subject_id, association_type, object_id)
            if dups:
                log.debug("Create %s Association from '%s': ALREADY EXISTS"
                          % (self._assn_name(association_type),
                             self._toplevel_call()))
                return dups

        associate_success = self.RR.create_association(subject_id,
                                                       association_type,
                                                       object_id)

        log.debug("Create %s Association from '%s': %s"
                  % (self._assn_name(association_type),
                     self._toplevel_call(),
                      str(associate_success)))

        return associate_success
def is_trusted_request():

    if request.remote_addr is not None:
        log.debug("%s from: %s: %s", request.method, request.remote_addr, request.url)

    if not service_gateway_instance.is_trusted_address(request.remote_addr):
        abort(403)
    def on_start(self):
        log.debug('EventAlertTransform.on_start()')
        super(EventAlertTransform, self).on_start()

        #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        # get the algorithm to use
        #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        self.timer_origin = self.CFG.get_safe('process.timer_origin', 'Interval Timer')
        self.instrument_origin = self.CFG.get_safe('process.instrument_origin', '')

        self.counter = 0
        self.event_times = []

        #-------------------------------------------------------------------------------------
        # Set up a listener for instrument events
        #-------------------------------------------------------------------------------------

        self.instrument_event_queue = gevent.queue.Queue()

        def instrument_event_received(message, headers):
            log.debug("EventAlertTransform received an instrument event here::: %s" % message)
            self.instrument_event_queue.put(message)

        self.instrument_event_subscriber = EventSubscriber(origin = self.instrument_origin,
            callback=instrument_event_received)

        self.instrument_event_subscriber.start()

        #-------------------------------------------------------------------------------------
        # Create the publisher that will publish the Alert message
        #-------------------------------------------------------------------------------------

        self.event_publisher = EventPublisher()
Example #8
0
    def _transform(self, obj):
        # Note: This check to detect an IonObject is a bit risky (only type_)
        if isinstance(obj, dict) and "type_" in obj:
            objc    = obj.copy()
            type    = objc.pop('type_')

            # don't supply a dict - we want the object to initialize with all its defaults intact,
            # which preserves things like IonEnumObject and invokes the setattr behavior we want there.
            ion_obj = self._obj_registry.new(type.encode('ascii'))
            for k, v in objc.iteritems():
                setattr(ion_obj, k, v)

            return ion_obj
        if _have_numpy:
            if isinstance(obj, dict):
                msg = obj.get('numpy',False)
                log.debug('message = %s', msg)
                if msg:
                    shape = msg.get('shape')
                    type = msg.get('type')
                    data = msg.get('body')
                    log.debug('Numpy Array Detected:\n  type: %s\n  shape: %s\n  body: %s',type,shape,data)
                    ret = np.fromstring(string=data,dtype=type).reshape(shape)
                    return np.array(ret)


        return obj
def send_email(event, msg_recipient, smtp_client, rr_client):
    """
    A common method to send email with formatting

    @param event              Event
    @param msg_recipient        str
    @param smtp_client          fake or real smtp client object

    """

    #log.debug("Got type of event to notify on: %s", event.type_)

    #------------------------------------------------------------------------------------
    # the 'from' email address for notification emails
    #------------------------------------------------------------------------------------

    ION_NOTIFICATION_EMAIL_ADDRESS = '*****@*****.**'
    smtp_sender = CFG.get_safe('server.smtp.sender', ION_NOTIFICATION_EMAIL_ADDRESS)

    msg = convert_events_to_email_message([event], rr_client)
    msg['From'] = smtp_sender
    msg['To'] = msg_recipient
    log.debug("UNS sending email from %s to %s for event type: %s", smtp_sender,msg_recipient, event.type_)
    #log.debug("UNS using the smtp client: %s", smtp_client)

    try:
        smtp_client.sendmail(smtp_sender, [msg_recipient], msg.as_string())
    except: # Can be due to a broken connection... try to create a connection
        smtp_client = setting_up_smtp_client()
        log.debug("Connect again...message received after ehlo exchange: %s", str(smtp_client.ehlo()))
        smtp_client.sendmail(smtp_sender, [msg_recipient], msg.as_string())
def process_oms_event():

    json_params = {}

    # oms direct request
    if request.data:
        json_params  = json_loads(str(request.data))
        log.debug('ServiceGatewayService:process_oms_event request.data:  %s', json_params)

    #validate payload
    if 'platform_id' not in json_params or 'message' not in json_params:
        log.warning('Invalid OMS event format. payload_data: %s', json_params)
        #return gateway_json_response(OMS_BAD_REQUEST_RESPONSE)

    #prepare the event information
    try:
        #create a publisher to relay OMS events into the system as DeviceEvents
        event_publisher = EventPublisher()

        event_publisher.publish_event(
            event_type='OMSDeviceStatusEvent',
            origin_type='OMS Platform',
            origin=json_params.get('platform_id', 'NOT PROVIDED'),
            sub_type='',
            description = json_params.get('message', ''),
            status_details = json_params)
    except Exception, e:
        log.error('Could not publish OMS  event: %s. Event data: %s', e.message, json_params)
    def find_events(self, origin='', type='', min_datetime=0, max_datetime=0, limit= -1, descending=False):
        """
        This method leverages couchdb view and simple filters. It does not use elastic search.

        Returns a list of events that match the specified search criteria. Will throw a not NotFound exception
        if no events exist for the given parameters.

        @param origin         str
        @param event_type     str
        @param min_datetime   int  seconds
        @param max_datetime   int  seconds
        @param limit          int         (integer limiting the number of results (0 means unlimited))
        @param descending     boolean     (if True, reverse order (of production time) is applied, e.g. most recent first)
        @retval event_list    []
        @throws NotFound    object with specified parameters does not exist
        @throws NotFound    object with specified parameters does not exist
        """
        event_tuples = []

        try:
            event_tuples = self.container.event_repository.find_events(event_type=type, origin=origin, start_ts=min_datetime, end_ts=max_datetime, limit=limit, descending=descending)
        except Exception as exc:
            log.warning("The UNS find_events operation for event origin = %s and type = %s failed. Error message = %s", origin, type, exc.message)

        events = [item[2] for item in event_tuples]
        log.debug("(find_events) UNS found the following relevant events: %s", events)

        return events
Example #12
0
    def overlay(self, transport, *methods):
        for m in methods:
            self._methods[m] = getattr(transport, m)

        log.debug("ComposableTransport.overlay(%s) %s %s (%s)", self.channel_number, type(transport), transport, transport.channel_number)

        self._transports.append(transport)
Example #13
0
    def stop_consume_impl(self, consumer_tag):
        """
        Stops consuming by consumer tag.
        """
        #log.debug("AMQPTransport.stop_consume_impl(%s): %s", self._client.channel_number, consumer_tag)
        self._sync_call(self._client.basic_cancel, 'callback', consumer_tag)

        # PIKA 0.9.5 / GEVENT interaction problem here
        # we get called back too early, the basic_cancel hasn't really finished processing yet. we need
        # to wait until our consumer tag is removed from the pika channel's consumers dict.
        # See: https://gist.github.com/3751870

        attempts = 6
        while attempts > 0:
            if consumer_tag not in self._client._consumers:
                break
            else:
                log.debug("stop_consume_impl waiting for ctag to be removed from consumers, attempts rem: %s", attempts)

            attempts -= 1

            sleep(1) if attempts < 4 else sleep(0.1)        # Wait shorter the first few times

        if consumer_tag in self._client._consumers:
            raise TransportError("stop_consume_impl did not complete in the expected amount of time, transport may be compromised")
Example #14
0
 def lookup(self, qualified_key='/'):
     """
     Read entry residing in directory at parent node level.
     """
     log.debug("Reading content at path %s" % qualified_key)
     direntry = self._safe_read(qualified_key)
     return direntry.attributes if direntry else None
Example #15
0
    def get_datastore(self, ds_name, profile=DataStore.DS_PROFILE.BASIC, config=None):
        """
        Factory method to get a datastore instance from given name, profile and config.
        @param ds_name  Logical name of datastore (will be scoped with sysname)
        @param profile  One of known constants determining the use of the store
        @param config  Override config to use
        """
        validate_true(ds_name, 'ds_name must be provided')
        if ds_name in self._datastores:
            log.debug("get_datastore(): Found instance of store '%s'" % ds_name)
            return self._datastores[ds_name]

        scoped_name = DatastoreManager.get_scoped_name(ds_name)

        # Create a datastore instance
        log.info("get_datastore(): Create instance of store '%s' as database=%s" % (ds_name, scoped_name))
        new_ds = DatastoreManager.get_datastore_instance(ds_name, profile)

        # Create store if not existing
        if not new_ds.datastore_exists(scoped_name):
            new_ds.create_datastore(scoped_name, create_indexes=True, profile=profile)
        else:
            # NOTE: This may be expensive if called more than once per container
            # If views exist and are dropped and recreated
            new_ds._define_views(profile=profile, keepviews=True)

        # Set a few standard datastore instance fields
        new_ds.local_name = ds_name
        new_ds.ds_profile = profile

        self._datastores[ds_name] = new_ds

        return new_ds
Example #16
0
    def find_res_by_attribute(self, restype, attr_name, attr_value=None, id_only=False, filter=None):
        log.debug("find_res_by_attribute(restype=%s, attr_name=%s, attr_value=%s)", restype, attr_name, attr_value)
        if not attr_name or type(attr_name) is not str:
            raise BadRequest('Argument attr_name illegal')
        if type(id_only) is not bool:
            raise BadRequest('id_only must be type bool, not %s' % type(id_only))
        filter = filter if filter is not None else {}
        qual_ds_name = self._get_datastore_name()
        if id_only:
            query = "SELECT id, type_, json_specialattr(doc) FROM " + qual_ds_name
        else:
            query = "SELECT id, type_, json_specialattr(doc), doc FROM " + qual_ds_name
        query_clause = " WHERE lcstate<>'DELETED' "
        query_args = dict(type_=restype, att=attr_name, val=attr_value)

        if attr_value:  # Note: cannot make None test here (and allow empty string because of default service args "")
            query_clause += "AND json_specialattr(doc)=%(spc)s"
            query_args['spc'] = "%s=%s" % (attr_name, attr_value)
        else:
            query_clause += "AND json_specialattr(doc) LIKE %(spc)s"
            query_args['spc'] = "%s=%%" % (attr_name, )
        if restype:
            query_clause += " AND type_=%(type_)s"

        query_clause = self._add_access_filter(filter, qual_ds_name, query_clause, query_args)
        extra_clause = filter.get("extra_clause", "")
        with self.pool.cursor(**self.cursor_args) as cur:
            cur.execute(query + query_clause + extra_clause, query_args)
            rows = cur.fetchall()

        res_assocs = [dict(id=self._prep_id(row[0]), type=row[1], attr_name=attr_name, attr_value=row[2].split("=",1)[-1]) for row in rows]
        log.debug("find_res_by_attribute() found %s objects", len(res_assocs))
        return self._prepare_find_return(rows, res_assocs, id_only=id_only)
    def get_data_process_subscriptions_count(self, data_process_id=""):
        if not data_process_id:
            raise BadRequest("The data_process_definition_id parameter is empty")

        subscription_ids, _ = self.clients.resource_registry.find_objects(subject=data_process_id, predicate=PRED.hasSubscription, id_only=True)
        log.debug("get_data_process_subscriptions_count(id=%s): %s subscriptions", data_process_id, len(subscription_ids))
        return len(subscription_ids)
Example #18
0
    def find_res_by_lcstate(self, lcstate, restype=None, id_only=False, filter=None):
        log.debug("find_res_by_lcstate(lcstate=%s, restype=%s)", lcstate, restype)
        if type(id_only) is not bool:
            raise BadRequest('id_only must be type bool, not %s' % type(id_only))
        if '_' in lcstate:
            log.warn("Search for compound lcstate restricted to maturity: %s", lcstate)
            lcstate,_ = lcstate.split("_", 1)
        filter = filter if filter is not None else {}
        qual_ds_name = self._get_datastore_name()
        if id_only:
            query = "SELECT id, name, type_, lcstate, availability FROM " + qual_ds_name
        else:
            query = "SELECT id, name, type_, lcstate, availability, doc FROM " + qual_ds_name
        query_clause = " WHERE "
        query_args = dict(type_=restype, lcstate=lcstate)

        is_maturity = lcstate not in AvailabilityStates
        if is_maturity:
            query_clause += "lcstate=%(lcstate)s"
        else:
            query_clause += "availability=%(lcstate)s"

        if restype:
            query_clause += " AND type_=%(type_)s"

        query_clause = self._add_access_filter(filter, qual_ds_name, query_clause, query_args)
        extra_clause = filter.get("extra_clause", "")
        with self.pool.cursor(**self.cursor_args) as cur:
            cur.execute(query + query_clause + extra_clause, query_args)
            rows = cur.fetchall()

        res_assocs = [dict(id=self._prep_id(row[0]), name=row[1], type=row[2], lcstate=row[3] if is_maturity else row[4]) for row in rows]
        log.debug("find_res_by_lcstate() found %s objects", len(res_assocs))
        return self._prepare_find_return(rows, res_assocs, id_only=id_only)
Example #19
0
    def find_res_by_nested_type(self, nested_type, restype=None, id_only=False, filter=None):
        log.debug("find_res_by_nested_type(nested_type=%s, restype=%s)", nested_type, restype)
        if not nested_type or type(nested_type) is not str:
            raise BadRequest('Argument nested_type illegal')
        if type(id_only) is not bool:
            raise BadRequest('id_only must be type bool, not %s' % type(id_only))
        filter = filter if filter is not None else {}
        qual_ds_name = self._get_datastore_name()
        if id_only:
            query = "SELECT id, type_ FROM " + qual_ds_name
        else:
            query = "SELECT id, type_, doc FROM " + qual_ds_name
        query_clause = " WHERE lcstate<>'DELETED' "
        query_args = dict(type_=restype, nest=[nested_type])

        query_clause += "AND %(nest)s <@ json_nested(doc)"
        if restype:
            query_clause += " AND type_=%(type_)s"

        query_clause = self._add_access_filter(filter, qual_ds_name, query_clause, query_args)
        extra_clause = filter.get("extra_clause", "")
        with self.pool.cursor(**self.cursor_args) as cur:
            cur.execute(query + query_clause + extra_clause, query_args)
            rows = cur.fetchall()

        res_assocs = [dict(id=self._prep_id(row[0]), type=row[1], nested_type=nested_type) for row in rows]
        log.debug("find_res_by_nested_type() found %s objects", len(res_assocs))
        return self._prepare_find_return(rows, res_assocs, id_only=id_only)
def setting_up_smtp_client():
    '''
    Sets up the smtp client
    '''

    #------------------------------------------------------------------------------------
    # the default smtp server
    #------------------------------------------------------------------------------------

    ION_SMTP_SERVER = 'mail.oceanobservatories.org'

    smtp_host = CFG.get_safe('server.smtp.host', ION_SMTP_SERVER)
    smtp_port = CFG.get_safe('server.smtp.port', 25)
    smtp_sender = CFG.get_safe('server.smtp.sender')
    smtp_password = CFG.get_safe('server.smtp.password')

    if CFG.get_safe('system.smtp',False): #Default is False - use the fake_smtp
        log.debug('Using the real SMTP library to send email notifications!')

        smtp_client = smtplib.SMTP(smtp_host)
        smtp_client.ehlo()
        smtp_client.starttls()
        smtp_client.login(smtp_sender, smtp_password)

    else:
        log.debug('Using a fake SMTP library to simulate email notifications!')

        smtp_client = fake_smtplib.SMTP(smtp_host)

    return smtp_client
Example #21
0
    def find_res_by_type(self, restype, lcstate=None, id_only=False, filter=None):
        log.debug("find_res_by_type(restype=%s, lcstate=%s)", restype, lcstate)
        if type(id_only) is not bool:
            raise BadRequest('id_only must be type bool, not %s' % type(id_only))
        if lcstate:
            raise BadRequest('lcstate not supported anymore in find_res_by_type')

        filter = filter if filter is not None else {}
        qual_ds_name = self._get_datastore_name()
        if id_only:
            query = "SELECT id, name, type_, lcstate FROM " + qual_ds_name
        else:
            query = "SELECT id, name, type_, lcstate, doc FROM " + qual_ds_name
        query_clause = " WHERE lcstate<>'DELETED' "
        query_args = dict(type_=restype, lcstate=lcstate)

        if restype:
            query_clause += "AND type_=%(type_)s"
        else:
            # Returns ALL documents, only limited by filter
            query_clause = ""

        query_clause = self._add_access_filter(filter, qual_ds_name, query_clause, query_args)
        extra_clause = filter.get("extra_clause", "")
        with self.pool.cursor(**self.cursor_args) as cur:
            cur.execute(query + query_clause + extra_clause, query_args)
            rows = cur.fetchall()

        res_assocs = [dict(id=self._prep_id(row[0]), name=row[1], type=row[2]) for row in rows]
        log.debug("find_res_by_type() found %s objects", len(res_assocs))
        return self._prepare_find_return(rows, res_assocs, id_only=id_only)
Example #22
0
    def find_res_by_lcstate(self, lcstate, restype=None, id_only=False):
        log.debug("find_res_by_lcstate(lcstate=%s, restype=%s)" % (lcstate, restype))
        if type(id_only) is not bool:
            raise BadRequest('id_only must be type bool, not %s' % type(id_only))
        db = self.server[self.datastore_name]
        view = db.view(self._get_viewname("resource","by_lcstate"), include_docs=(not id_only))
        is_hierarchical = (lcstate in ResourceLifeCycleSM.STATE_ALIASES)
        # lcstate is a hiearachical state and we need to treat the view differently
        if is_hierarchical:
            key = [1, lcstate]
        else:
            key = [0, lcstate]
        if restype:
            key.append(restype)
        endkey = list(key)
        endkey.append(END_MARKER)
        rows = view[key:endkey]

        if is_hierarchical:
            res_assocs = [dict(lcstate=row['key'][3], type=row['key'][2], name=row['key'][4], id=row.id) for row in rows]
        else:
            res_assocs = [dict(lcstate=row['key'][1], type=row['key'][2], name=row['key'][3], id=row.id) for row in rows]

        log.debug("find_res_by_lcstate() found %s objects" % (len(res_assocs)))
        if id_only:
            res_ids = [row.id for row in rows]
            return (res_ids, res_assocs)
        else:
            res_docs = [self._persistence_dict_to_ion_object(row.doc) for row in rows]
            return (res_docs, res_assocs)
Example #23
0
    def delete_doc(self, doc, datastore_name=""):
        if not datastore_name:
            datastore_name = self.datastore_name
        try:
            db = self.server[datastore_name]
        except ValueError:
            raise BadRequest("Data store name %s is invalid" % datastore_name)
        if type(doc) is str:
            log.info('Deleting object %s/%s' % (datastore_name, doc))
            if self._is_in_association(doc, datastore_name):
                obj = self.read(doc, datastore_name)
                log.warn("XXXXXXX Attempt to delete object %s that still has associations" % str(obj))
#                raise BadRequest("Object cannot be deleted until associations are broken")
            try:
                del db[doc]
            except ResourceNotFound:
                raise NotFound('Object with id %s does not exist.' % str(doc))
        else:
            log.info('Deleting object %s/%s' % (datastore_name, doc["_id"]))
            if self._is_in_association(doc["_id"], datastore_name):
                log.warn("XXXXXXX Attempt to delete object %s that still has associations" % str(doc))
#                raise BadRequest("Object cannot be deleted until associations are broken")
            try:
                res = db.delete(doc)
            except ResourceNotFound:
                raise NotFound('Object with id %s does not exist.' % str(doc["_id"]))
            log.debug('Delete result: %s' % str(res))
Example #24
0
 def test_comm_config_type_list(self):
     types = CommConfig.valid_type_list()
     log.debug( "types: %s" % types)
     
     known_types = ['ethernet']
     
     self.assertEqual(sorted(types), sorted(known_types))
Example #25
0
    def create_doc(self, doc, object_id=None, datastore_name=""):
        if not datastore_name:
            datastore_name = self.datastore_name
        if '_id' in doc:
            raise BadRequest("Doc must not have '_id'")
        if '_rev' in doc:
            raise BadRequest("Doc must not have '_rev'")

        if object_id:
            try:
                self.read(object_id, '', datastore_name)
                raise BadRequest("Object with id %s already exist" % object_id)
            except NotFound:
                pass

        # Assign an id to doc (recommended in CouchDB documentation)
        doc["_id"] = object_id or uuid4().hex
        log.info('Creating new object %s/%s' % (datastore_name, doc["_id"]))
        log.debug('create doc contents: %s', doc)

        # Save doc.  CouchDB will assign version to doc.
        try:
            res = self.server[datastore_name].save(doc)
        except ResourceNotFound:
            raise BadRequest("Data store %s does not exist" % datastore_name)
        except ResourceConflict:
            raise BadRequest("Object with id %s already exist" % doc["_id"])
        except ValueError:
            raise BadRequest("Data store name %s invalid" % datastore_name)
        log.debug('Create result: %s' % str(res))
        id, version = res
        return (id, version)
Example #26
0
    def start(self):

        log.debug("GovernanceController starting ...")

        self._CFG = CFG

        self.enabled = CFG.get_safe('interceptor.interceptors.governance.config.enabled', False)

        log.info("GovernanceInterceptor enabled: %s" % str(self.enabled))

        self.policy_event_subscriber = None

        #containers default to not Org Boundary and ION Root Org
        self._is_container_org_boundary = CFG.get_safe('container.org_boundary',False)
        self._container_org_name = CFG.get_safe('container.org_name', CFG.get_safe('system.root_org', 'ION'))
        self._container_org_id = None
        self._system_root_org_name = CFG.get_safe('system.root_org', 'ION')

        self._is_root_org_container = (self._container_org_name == self._system_root_org_name)

        if self.enabled:

            config = CFG.get_safe('interceptor.interceptors.governance.config')

            self.initialize_from_config(config)

            self.policy_event_subscriber = EventSubscriber(event_type=OT.PolicyEvent, callback=self.policy_event_callback)
            self.policy_event_subscriber.start()

            self.rr_client = ResourceRegistryServiceProcessClient(node=self.container.node, process=self.container)
            self.policy_client = PolicyManagementServiceProcessClient(node=self.container.node, process=self.container)
Example #27
0
    def launch(self):
        """
        Launches the simulator process as indicated by _COMMAND.

        @return (rsn_oms, uri) A pair with the CIOMSSimulator instance and the
                associated URI to establish connection with it.
        """
        log.debug("[OMSim] Launching: %s", _COMMAND)

        self._process = self._spawn(_COMMAND)

        if not self._process or not self.poll():
            msg = "[OMSim] Failed to launch simulator: %s" % _COMMAND
            log.error(msg)
            raise Exception(msg)

        log.debug("[OMSim] process started, pid: %s", self.getpid())

        # give it some time to start up
        sleep(5)

        # get URI:
        uri = None
        with open("logs/rsn_oms_simulator.yml", buffering=1) as f:
            # we expect one of the first few lines to be of the form:
            # rsn_oms_simulator_uri=xxxx
            # where xxxx is the uri -- see oms_simulator_server.
            while uri is None:
                line = f.readline()
                if line.index("rsn_oms_simulator_uri=") == 0:
                    uri = line[len("rsn_oms_simulator_uri="):].strip()

        self._rsn_oms = CIOMSClientFactory.create_instance(uri)
        return self._rsn_oms, uri
Example #28
0
    def __init__(self, host=None, port=None, datastore_name='prototype', options="", profile=DataStore.DS_PROFILE.BASIC):
        log.debug('__init__(host=%s, port=%s, datastore_name=%s, options=%s' % (host, port, datastore_name, options))
        self.host = host or CFG.server.couchdb.host
        self.port = port or CFG.server.couchdb.port
        # The scoped name of the datastore
        self.datastore_name = datastore_name
        self.auth_str = ""
        try:
            if CFG.server.couchdb.username and CFG.server.couchdb.password:
                self.auth_str = "%s:%s@" % (CFG.server.couchdb.username, CFG.server.couchdb.password)
                log.debug("Using username:password authentication to connect to datastore")
        except AttributeError:
            log.error("CouchDB username:password not configured correctly. Trying anonymous...")

        connection_str = "http://%s%s:%s" % (self.auth_str, self.host, self.port)
        #connection_str = "http://%s:%s" % (self.host, self.port)
        # TODO: Security risk to emit password into log. Remove later.
        log.info('Connecting to CouchDB server: %s' % connection_str)
        self.server = couchdb.Server(connection_str)

        # Datastore specialization
        self.profile = profile

        # serializers
        self._io_serializer     = IonObjectSerializer()
        self._io_deserializer   = IonObjectDeserializer(obj_registry=obj_registry)
Example #29
0
    def __init__(self, container):
        log.debug("ExchangeManager initializing ...")
        self.container = container

        # Define the callables that can be added to Container public API
        # @TODO: remove
        self.container_api = [self.create_xs,
                              self.create_xp,
                              self.create_xn_service,
                              self.create_xn_process,
                              self.create_xn_queue]

        # Add the public callables to Container
        for call in self.container_api:
            setattr(self.container, call.__name__, call)

        self.default_xs         = ExchangeSpace(self, ION_ROOT_XS)
        self._xs_cache          = {}        # caching of xs names to RR objects
        self._default_xs_obj    = None      # default XS registry object
        self.org_id             = None

        # mappings
        self.xs_by_name = { ION_ROOT_XS: self.default_xs }      # friendly named XS to XSO
        self.xn_by_name = {}                                    # friendly named XN to XNO
        # xn by xs is a property

        self._chan = None

        # @TODO specify our own to_name here so we don't get auto-behavior - tricky chicken/egg
        self._ems_client    = ExchangeManagementServiceProcessClient(process=self.container)
        self._rr_client     = ResourceRegistryServiceProcessClient(process=self.container)
Example #30
0
    def find_res_by_alternative_id(self, alt_id=None, alt_id_ns=None, id_only=False, filter=None):
        log.debug("find_res_by_alternative_id(restype=%s, alt_id_ns=%s)", alt_id, alt_id_ns)
        if alt_id and type(alt_id) is not str:
            raise BadRequest('Argument alt_id illegal')
        if alt_id_ns and type(alt_id_ns) is not str:
            raise BadRequest('Argument alt_id_ns illegal')
        if type(id_only) is not bool:
            raise BadRequest('id_only must be type bool, not %s' % type(id_only))
        filter = filter if filter is not None else {}
        ds, datastore_name = self._get_datastore()
        key = []
        if alt_id:
            key.append(alt_id)
            if alt_id_ns is not None:
                key.append(alt_id_ns)

        endkey = self._get_endkey(key)
        rows = ds.view(self._get_view_name("resource", "by_altid"), include_docs=(not id_only), start_key=key, end_key=endkey, **filter)

        if alt_id_ns and not alt_id:
            res_assocs = [dict(alt_id=row['key'][0], alt_id_ns=row['key'][1], id=row['id']) for row in rows if row['key'][1] == alt_id_ns]
        else:
            res_assocs = [dict(alt_id=row['key'][0], alt_id_ns=row['key'][1], id=row['id']) for row in rows]
        log.debug("find_res_by_alternative_id() found %s objects", len(res_assocs))
        self._count(find_res_by_altid_call=1, find_res_by_altid_obj=len(res_assocs))
        if id_only:
            res_ids = [row['id'] for row in res_assocs]
            return (res_ids, res_assocs)
        else:
            if alt_id_ns and not alt_id:
                res_docs = [self._persistence_dict_to_ion_object(self._get_row_doc(row)) for row in rows if row['key'][1] == alt_id_ns]
            else:
                res_docs = [self._persistence_dict_to_ion_object(self._get_row_doc(row)) for row in rows]
            return (res_docs, res_assocs)
Example #31
0
        self._url = 'http://%s:%s@%s:%d' % (username, password, server, port) \
                    if username else 'http://%s:%d' % (server, port)
        self._db_name = instance
        self._server_name = server
        self._max_retry = max_retry

        self._server = Server(self._url)
        if can_create or must_create:
            try:
                log.debug('creating %s on %s', instance, self._url)
                self._db = self._server.create(self._db_name)
            except Exception, e:
                if must_create:
                    raise self._wrap_error('initialize', self._db_name, e)
        else:
            log.debug('connecting to %s on %s', instance, server)
            self._db = self._server[self._db_name]

    def drop(self):
        log.debug('deleting %s from %s', self._db_name, self._server_name)
        self._server.delete(self._db_name)
        self._db = None

    def _is_list(self, op, target):
        # check that argument is string, dictionary or list of ONE of them
        if isinstance(target, str) or isinstance(target, dict):
            return False
        elif all(isinstance(t, str)
                 for t in target) or all(isinstance(t, dict) for t in target):
            return True
        else:
Example #32
0
 def add_to_white_list(self, root_cert_string):
     log.debug("Adding certificate <%s> to white list" % root_cert_string)
     self.white_list.append(root_cert_string)
Example #33
0
    def __init__(self):
        self.cont_cert = None
        self.cont_key = None
        self.root_cert = None
        self.white_list = []

        # Look for certificates and keys in "the usual places"
        certstore_path = self.certstore = CFG.get_safe(
            'authentication.certstore', CERTSTORE_PATH)
        log.debug("certstore_path: %s" % str(certstore_path))
        keystore_path = self.certstore = CFG.get_safe(
            'authentication.keystore', KEYSTORE_PATH)
        log.debug("keystore_path: %s" % str(keystore_path))

        if certstore_path and keystore_path:
            if certstore_path == 'directory':
                log.debug("Container.instance.directory: " %
                          str(Container.instance.directory))
                Container.instance.directory.load_authentication()
            else:
                cont_cert_path = os.path.join(certstore_path,
                                              CONTAINER_CERT_NAME)
                log.debug("cont_cert_path: %s" % cont_cert_path)
                cont_key_path = os.path.join(keystore_path, CONTAINER_KEY_NAME)
                log.debug("cont_key_path: %s" % cont_key_path)
                root_cert_path = os.path.join(certstore_path, ORG_CERT_NAME)
                log.debug("root_cert_path: %s" % root_cert_path)

                if os.path.exists(cont_cert_path) and os.path.exists(
                        cont_key_path) and os.path.exists(root_cert_path):
                    with open(cont_cert_path, 'r') as f:
                        self.cont_cert = f.read()
                    log.debug("cont_cert: %s" % self.cont_cert)
                    self.cont_key = EVP.load_key(cont_key_path)
                    with open(root_cert_path, 'r') as f:
                        self.root_cert = f.read()
                    log.debug("root_cert: %s" % self.root_cert)
                    self.add_to_white_list(self.root_cert)
    def process_batch(self, start_time = '', end_time = ''):
        """
        This method is launched when an process_batch event is received. The user info dictionary maintained
        by the User Notification Service is used to query the event repository for all events for a particular
        user that have occurred in a provided time interval, and then an email is sent to the user containing
        the digest of all the events.

        @param start_time int milliseconds
        @param end_time int milliseconds
        """
        self.smtp_client = setting_up_smtp_client()

        if end_time <= start_time:
            return

        for user_id, value in self.user_info.iteritems():

            notifications = value['notifications']
            notification_preferences = value['notification_preferences']

            # Ignore users who do NOT want batch notifications or who have disabled the delivery switch
            # However, if notification preferences have not been set for the user, use the default mechanism and do not bother
            if notification_preferences:
                if notification_preferences.delivery_mode != NotificationDeliveryModeEnum.BATCH \
                    or not notification_preferences.delivery_enabled:
                    continue

            events_for_message = []

            search_time = "SEARCH 'ts_created' VALUES FROM %s TO %s FROM 'events_index'" % (start_time, end_time)

            for notification in notifications:

                # If the notification request has expired, then do not use it in the search
                if notification.temporal_bounds.end_datetime:
                    continue

                if notification.origin:
                    search_origin = 'search "origin" is "%s" from "events_index"' % notification.origin
                else:
                    search_origin = 'search "origin" is "*" from "events_index"'

                if notification.origin_type:
                    search_origin_type= 'search "origin_type" is "%s" from "events_index"' % notification.origin_type
                else:
                    search_origin_type= 'search "origin_type" is "*" from "events_index"'

                if notification.event_type:
                    search_event_type = 'search "type_" is "%s" from "events_index"' % notification.event_type
                else:
                    search_event_type = 'search "type_" is "*" from "events_index"'

                search_string = search_time + ' and ' + search_origin + ' and ' + search_origin_type + ' and ' + search_event_type

                # get the list of ids corresponding to the events
                ret_vals = self.discovery.parse(search_string)

                events_for_message.extend(self.datastore.read_mult(ret_vals))

            log.debug("Found following events of interest to user, %s: %s", user_id, events_for_message)

            # send a notification email to each user using a _send_email() method
            if events_for_message:
                self.format_and_send_email(events_for_message = events_for_message,
                                            user_id = user_id,
                                            smtp_client=self.smtp_client)

        self.smtp_client.quit()
    def create_notification(self, notification=None, user_id=''):
        """
        Persists the provided NotificationRequest object for the specified Origin id.
        Associate the Notification resource with the user_id string.
        returned id is the internal id by which NotificationRequest will be identified
        in the data store.

        @param notification        NotificationRequest
        @param user_id             str
        @retval notification_id    str
        @throws BadRequest    if object passed has _id or _rev attribute

        """

        if not user_id:
            raise BadRequest("User id not provided.")

        log.debug("Create notification called for user_id: %s, and notification: %s", user_id, notification)

        #---------------------------------------------------------------------------------------------------
        # Persist Notification object as a resource if it has already not been persisted
        #---------------------------------------------------------------------------------------------------

        # if the notification has already been registered, simply use the old id
        notification_id = self._notification_in_notifications(notification, self.notifications)

        # since the notification has not been registered yet, register it and get the id

        temporal_bounds = TemporalBounds()
        temporal_bounds.start_datetime = get_ion_ts()
        temporal_bounds.end_datetime = ''

        if not notification_id:
            notification.temporal_bounds = temporal_bounds
            notification_id, _ = self.clients.resource_registry.create(notification)
            self.notifications[notification_id] = notification
        else:
            log.debug("Notification object has already been created in resource registry before. No new id to be generated. notification_id: %s", notification_id)
            # Read the old notification already in the resource registry
            notification = self.clients.resource_registry.read(notification_id)

            # Update the temporal bounds of the old notification resource
            notification.temporal_bounds = temporal_bounds

            # Update the notification in the resource registry
            self.clients.resource_registry.update(notification)

            log.debug("The temporal bounds for this resubscribed notification object with id: %s, is: %s", notification_id,notification.temporal_bounds)


        # Link the user and the notification with a hasNotification association
        assocs= self.clients.resource_registry.find_associations(subject=user_id,
                                                                    predicate=PRED.hasNotification,
                                                                    object=notification_id,
                                                                    id_only=True)
        if assocs:
            log.debug("Got an already existing association: %s, between user_id: %s, and notification_id: %s", assocs,user_id,notification_id)
            return notification_id
        else:
            log.debug("Creating association between user_id: %s, and notification_id: %s", user_id, notification_id )
            self.clients.resource_registry.create_association(user_id, PRED.hasNotification, notification_id)

        # read the registered notification request object because this has an _id and is more useful
        notification = self.clients.resource_registry.read(notification_id)

        # Update the user info object with the notification
        self.event_processor.add_notification_for_user(new_notification=notification, user_id=user_id)

        #-------------------------------------------------------------------------------------------------------------------
        # Generate an event that can be picked by a notification worker so that it can update its user_info dictionary
        #-------------------------------------------------------------------------------------------------------------------
        log.debug("(create notification) Publishing ReloadUserInfoEvent for notification_id: %s", notification_id)

        self.event_publisher.publish_event( event_type= "ReloadUserInfoEvent",
            origin="UserNotificationService",
            description= "A notification has been created.",
            notification_id = notification_id)

        return notification_id
Example #36
0
 def drop(self):
     log.debug('deleting %s from %s', self._db_name, self._server_name)
     self._server.delete(self._db_name)
     self._db = None
Example #37
0
    def update(self, target, force=False, _depth=0):
        """ update one or many entries

            if force is False and _rev is missing or not the latest, the update will fail.
            if force is True and _rev is missing or not the latest, will find the latest _rev and attempt to update.
            since others may be updating at the same time, this may still not be the latest!
            update will repeat up to max_retry times before giving up.

            return value for a single item update is a tuple (success, id, exception)
            return value when target is a list is a list of tuples indicating the outcome of each item updated.

            NOTE: updates may not made to DB in order.
        """
        if not isinstance(target, list):
            result = self.update([target], force=force)
            return result[0]

        # update the ones that already have revisions
        have_revisions = filter(lambda d: '_rev' in d.keys(), target)
        results = self._db.update(have_revisions) if len(
            have_revisions) else None

        # if missing or old _rev, retry update
        log.debug('update results: %s', repr(results))
        some_attempted = len(have_revisions) > 0
        some_failed = some_attempted and not reduce(lambda a, b: a and b,
                                                    [r[0] for r in results])
        some_not_updated = len(have_revisions) < len(target) or some_failed
        can_retry = force and _depth < self._max_retry
        if can_retry and some_not_updated:
            # start with elements that did not have _rev
            retry_target = filter(lambda d: '_rev' not in d.keys(), target)
            # now add elements that failed due to wrong _rev
            successful_results = []
            if results:
                doc_with_result = zip(have_revisions, results)
                failed_subset_with_result = filter(
                    lambda t: not t[1][0], doc_with_result
                )  # TODO: also check t[1][2] is correct exception type for bad _rev
                retry_target += [t[0] for t in failed_subset_with_result]
                successful_results = [
                    t[1] for t in filter(lambda t: t[1][0], doc_with_result)
                ]
            # search db and update these _rev values
            log.debug(' before %s', repr(retry_target))
            self._update_revision(retry_target)
            log.debug('  after %s', repr(retry_target))
            # some just aren't in the DB any more
            not_found_docs = filter(lambda t: '_rev' not in t, retry_target)
            not_found_results = [
                (False, t['_id'], Exception('not found in DB'))
                for t in not_found_docs
            ]  #TODO: use application exception
            # for otehrs, try again with udpated _rev
            found_rev = filter(lambda t: '_rev' in t, retry_target)
            retry_results = self.update(found_rev,
                                        force=True,
                                        _depth=_depth + 1)

            results = not_found_results + retry_results + successful_results

        # only need to sort once on final exit from recursive retry
        if _depth > 1:
            return results

        # sort results into original order of arguments
        out = []
        for d in target:
            id = d['_id']
            result = None
            if results:
                for t in results:
                    if t[1] == id:
                        result = t
                        break
            if not result:  # no revision?
                if force:  #   force: would have read latest from DB -- so _id was not found
                    result = (False, id,
                              Exception("udpate failed: _id was not found"))
                else:  #   no force: then cannot update
                    result = (False, id,
                              Exception("update failed without _rev or force"))
            out.append(result)
        return out
    def create_data_process(self,
                            data_process_definition_id=None,
                            in_data_product_ids='',
                            out_data_products=None,
                            configuration=None):
        """
        @param  data_process_definition_id: Object with definition of the
                    transform to apply to the input data product
        @param  in_data_product_ids: ID of the input data products
        @param  out_data_products: list of IDs of the output data products
        @retval data_process_id: ID of the newly created data process object
        """

        inform = "Input Data Product:       "+str(in_data_product_ids)+\
                 "Transformed by:           "+str(data_process_definition_id)+\
                 "To create output Product: "+str(out_data_products)
        log.debug("DataProcessManagementService:create_data_process()\n" +
                  inform)

        if configuration is None:
            configuration = {}

        # Create and store a new DataProcess with the resource registry
        log.debug(
            "DataProcessManagementService:create_data_process - Create and store a new DataProcess with the resource registry"
        )
        data_process_def_obj = self.read_data_process_definition(
            data_process_definition_id)

        data_process_name = "process_" + data_process_def_obj.name \
                             + time.ctime()
        self.data_process = IonObject(RT.DataProcess, name=data_process_name)
        data_process_id, version = self.clients.resource_registry.create(
            self.data_process)
        log.debug(
            "DataProcessManagementService:create_data_process - Create and store a new DataProcess with the resource registry  data_process_id: %s"
            + str(data_process_id))

        # Register the data process instance as a data producer with DataAcquisitionMgmtSvc
        #TODO: should this be outside this method? Called by orchestration?
        data_producer_id = self.clients.data_acquisition_management.register_process(
            data_process_id)
        log.debug(
            "DataProcessManagementService:create_data_process register process with DataAcquisitionMgmtSvc: data_producer_id: %s   (L4-CI-SA-RQ-181)",
            str(data_producer_id))

        self.output_stream_dict = {}
        #TODO: should this be outside this method? Called by orchestration?
        if out_data_products is None:
            raise BadRequest(
                "Data Process must have output product(s) specified %s",
                str(data_process_definition_id))
        for name, out_data_product_id in out_data_products.iteritems():

            # check that the product is not already associated with a producer
            producer_ids, _ = self.clients.resource_registry.find_objects(
                out_data_product_id, PRED.hasDataProducer, RT.DataProducer,
                True)
            if producer_ids:
                raise BadRequest(
                    "Data Product should not already be associated to a DataProducer %s hasDataProducer %s",
                    str(data_process_id), str(producer_ids[0]))

            #Assign each output Data Product to this producer resource
            out_data_product_obj = self.clients.resource_registry.read(
                out_data_product_id)
            if not out_data_product_obj:
                raise NotFound("Output Data Product %s does not exist" %
                               out_data_product_id)
            # Associate with DataProcess: register as an output product for this process
            log.debug(
                "DataProcessManagementService:create_data_process link data process %s and output out data product: %s    (L4-CI-SA-RQ-260)",
                str(data_process_id), str(out_data_product_id))
            self.clients.data_acquisition_management.assign_data_product(
                data_process_id, out_data_product_id, create_stream=False)

            # Retrieve the id of the OUTPUT stream from the out Data Product
            stream_ids, _ = self.clients.resource_registry.find_objects(
                out_data_product_id, PRED.hasStream, RT.Stream, True)

            log.debug(
                "DataProcessManagementService:create_data_process retrieve out data prod streams: %s",
                str(stream_ids))
            if not stream_ids:
                raise NotFound("No Stream created for output Data Product " +
                               str(out_data_product_id))
            if len(stream_ids) != 1:
                raise BadRequest(
                    "Data Product should only have ONE stream at this time" +
                    str(out_data_product_id))
            self.output_stream_dict[name] = stream_ids[0]
            log.debug(
                "DataProcessManagementService:create_data_process -Register the data process instance as a data producer with DataAcquisitionMgmtSvc, then retrieve the id of the OUTPUT stream  out_stream_id: "
                + str(self.output_stream_dict[name]))

        # Associate with dataProcess
        self.clients.resource_registry.create_association(
            data_process_id, PRED.hasProcessDefinition,
            data_process_definition_id)

        #check if data process has lookup tables attached
        self._find_lookup_tables(data_process_definition_id, configuration)

        #Todo: currently this is handled explicitly after creating the data product, that code then calls DMAS:assign_data_product
        log.debug(
            "DataProcessManagementService:create_data_process associate data process workflows with source data products %s hasInputProducts  %s   (L4-CI-SA-RQ-260)",
            str(data_process_id), str(in_data_product_ids))
        for in_data_product_id in in_data_product_ids:
            self.clients.resource_registry.create_association(
                data_process_id, PRED.hasInputProduct, in_data_product_id)

            #check if in data product is attached to an instrument, check instrumentDevice and InstrumentModel for lookup table attachments
            instdevice_ids, _ = self.clients.resource_registry.find_subjects(
                RT.InstrumentDevice, PRED.hasOutputProduct, in_data_product_id,
                True)
            for instdevice_id in instdevice_ids:
                log.debug(
                    "DataProcessManagementService:create_data_process instrument device_id assoc to the input data product of this data process: %s   (L4-CI-SA-RQ-231)",
                    str(instdevice_id))
                self._find_lookup_tables(instdevice_id, configuration)
                instmodel_ids, _ = self.clients.resource_registry.find_objects(
                    instdevice_id, PRED.hasModel, RT.InstrumentModel, True)
                for instmodel_id in instmodel_ids:
                    log.debug(
                        "DataProcessManagementService:create_data_process instmodel_id assoc to the instDevice: %s",
                        str(instmodel_id))
                    self._find_lookup_tables(instmodel_id, configuration)

        #-------------------------------
        # Create subscription from in_data_product, which should already be associated with a stream via the Data Producer
        #-------------------------------

#        # first - get the data producer associated with this IN data product
#        log.debug("DataProcessManagementService:create_data_process - get the data producer associated with this IN data product")
#        producer_ids, _ = self.clients.resource_registry.find_objects(in_data_product_id, PRED.hasDataProducer, RT.DataProducer, True)
#        if not producer_ids:
#            raise NotFound("No Data Producer created for this Data Product " + str(in_data_product_id))
#        if len(producer_ids) != 1:
#            raise BadRequest("Data Product should only have ONE Data Producers at this time" + str(in_data_product_id))
#        in_product_producer = producer_ids[0]
#        log.debug("DataProcessManagementService:create_data_process - get the data producer associated with this IN data product  in_product_producer: " +  str(in_product_producer))

# second - get the streams associated with this IN data products
        self.in_stream_ids = []
        for in_data_product_id in in_data_product_ids:
            log.debug(
                "DataProcessManagementService:create_data_process - get the stream associated with this IN data product"
            )
            stream_ids, _ = self.clients.resource_registry.find_objects(
                in_data_product_id, PRED.hasStream, RT.Stream, True)
            if not stream_ids:
                raise NotFound("No Stream created for this IN Data Product " +
                               str(in_data_product_id))
            if len(stream_ids) != 1:
                raise BadRequest(
                    "IN Data Product should only have ONE stream at this time"
                    + str(in_data_product_id))
            log.debug(
                "DataProcessManagementService:create_data_process - get the stream associated with this IN data product:  %s  in_stream_id: %s ",
                str(in_data_product_id), str(stream_ids[0]))
            self.in_stream_ids.append(stream_ids[0])

        # Finally - create a subscription to the input stream
        log.debug(
            "DataProcessManagementService:create_data_process - Finally - create a subscription to the input stream"
        )
        in_data_product_obj = self.clients.data_product_management.read_data_product(
            in_data_product_id)
        query = StreamQuery(stream_ids=self.in_stream_ids)
        #self.input_subscription_id = self.clients.pubsub_management.create_subscription(query=query, exchange_name=in_data_product_obj.name)
        self.input_subscription_id = self.clients.pubsub_management.create_subscription(
            query=query, exchange_name=data_process_name)
        log.debug(
            "DataProcessManagementService:create_data_process - Finally - create a subscription to the input stream   input_subscription_id"
            + str(self.input_subscription_id))

        # add the subscription id to the resource for clean up later
        data_process_obj = self.clients.resource_registry.read(data_process_id)
        data_process_obj.input_subscription_id = self.input_subscription_id
        self.clients.resource_registry.update(data_process_obj)

        procdef_ids, _ = self.clients.resource_registry.find_objects(
            data_process_definition_id,
            PRED.hasProcessDefinition,
            RT.ProcessDefinition,
            id_only=True)
        if not procdef_ids:
            raise BadRequest(
                "Cannot find associated ProcessDefinition for DataProcessDefinition id=%s"
                % data_process_definition_id)
        process_definition_id = procdef_ids[0]

        # Launch the transform process
        log.debug(
            "DataProcessManagementService:create_data_process - Launch the first transform process: "
        )
        log.debug(
            "DataProcessManagementService:create_data_process - input_subscription_id: "
            + str(self.input_subscription_id))
        log.debug(
            "DataProcessManagementService:create_data_process - out_stream_id: "
            + str(self.output_stream_dict))
        log.debug(
            "DataProcessManagementService:create_data_process - process_definition_id: "
            + str(process_definition_id))
        log.debug(
            "DataProcessManagementService:create_data_process - data_process_id: "
            + str(data_process_id))

        transform_id = self.clients.transform_management.create_transform(
            name=data_process_id,
            description=data_process_id,
            in_subscription_id=self.input_subscription_id,
            out_streams=self.output_stream_dict,
            process_definition_id=process_definition_id,
            configuration=configuration)

        log.debug(
            "DataProcessManagementService:create_data_process - transform_id: "
            + str(transform_id))

        self.clients.resource_registry.create_association(
            data_process_id, PRED.hasTransform, transform_id)
        log.debug(
            "DataProcessManagementService:create_data_process - Launch the first transform process   transform_id"
            + str(transform_id))

        # TODO: Flesh details of transform mgmt svc schedule method
        #        self.clients.transform_management_service.schedule_transform(transform_id)

        return data_process_id
Example #39
0
    def build_packet(self, *args, **kwargs):
        """
        Build and return a granule of data.
        @param taxonomy the taxonomy of the granule
        @data dictionary containing sample data.
        @return granule suitable for publishing
        """
        taxonomy_str = kwargs.get('taxonomy')
        data = kwargs.get('data')
        data_producer_id = kwargs.get('data_producer_id')

        if not data_producer_id:
            raise PacketFactoryException("data_producer_id parameter missing")

        if not taxonomy_str:
            raise PacketFactoryException("taxonomy parameter missing")

        if not data:
            raise PacketFactoryException("data parameter missing")

        taxonomy = self._get_taxy_tool(taxonomy_str)

        # the nick_names in the taxonomy:
        nick_names = self._get_nick_names_from_taxonomy(taxonomy)

        #
        # TODO in general, how are groups (and the individual values
        # belonging to the groups) to be determined?
        #

        # in this version, expect 'data' and 'coordinates' to be included in
        # the taxonomy -- TODO the idea would be to be more general here?

        ##############################################################
        # NOTE for the moment, using the flat data record dict 'rdt'
        ##############################################################

        #        if not 'data' in nick_names:
        #            raise PacketFactoryException("expected name 'data' in taxonomy")
        #        if not 'coordinates' in nick_names:
        #            raise PacketFactoryException("expected name 'coordinates' in taxonomy")

        rdt = RecordDictionaryTool(taxonomy=taxonomy)
        #        data_rdt = RecordDictionaryTool(taxonomy=taxonomy)
        #        coordinates_rdt = RecordDictionaryTool(taxonomy=taxonomy)
        #
        #        rdt['data'] = data_rdt
        #        rdt['coordinates'] = coordinates_rdt

        #        def is_coordinate(nick_name):
        #            # just an ad hoc check to determine which group the nick_names
        #            # belong to
        #            return nick_name in ['lat', 'lon', 'time', 'height']

        # now, assign the values to the corresp record dicts:
        for name, value in data.iteritems():
            handle = -1
            log.info("packetfactory: name: %s" % str(name))
            if name in nick_names:
                handle = taxonomy.get_handle(name)
                log.info("packetfactory: handle: %s" % str(handle))
            else:
                handles = taxonomy.get_handles(name)
                log.info("packetfactory: handles: %s" % str(handles))
                if len(handles) == 1:
                    handle = handles.pop()
                elif len(handles) > 1:
                    # TODO proper handling of this case
                    log.warn("Multiple handles found for '%s': %s" %
                             (name % handles))

            if handle >= 0:
                # ok, the nick_name has been found, either directly as a
                # nick_name or via an alias; set value (using nick_name):
                nick_name = taxonomy.get_nick_name(handle)

                assert isinstance(value, list)
                val = numpy.array(value)

                # NOTE for the moment, using the flat data record dict 'rdt':
                rdt[nick_name] = val


#                if is_coordinate(nick_name):
#                    coordinates_rdt[nick_name] = val
#                else:
#                    data_rdt[nick_name] = val

            else:
                # name not found.
                # In the current tests this is happening with 'stream_id'
                log.warning("No handle found for '%s'" % name)

        log.debug("dictionary created: %s" % rdt.pretty_print())

        return build_granule(data_producer_id=data_producer_id,
                             taxonomy=taxonomy,
                             record_dictionary=rdt)
Example #40
0
 def mark_bad_channel(self, ch_number):
     log.debug("Marking %d as a bad channel", ch_number)
     self._bad_channel_numbers.add(ch_number)
Example #41
0
 def send(self, data):
     # send data from parent (coming from the instrumment) to tcp client
     log.debug("DirectAccessServer.send(): data = " + str(data))
     if self.server:
         self.server.send(data)
class DataProcessManagementService(BaseDataProcessManagementService):
    def on_init(self):
        IonObject("Resource")  # suppress pyflakes error

        self.override_clients(self.clients)

    def override_clients(self, new_clients):
        """
        Replaces the service clients with a new set of them... and makes sure they go to the right places
        """

        #shortcut names for the import sub-services
        if hasattr(self.clients, "resource_registry"):
            self.RR = self.clients.resource_registry

        if hasattr(self.clients, "transform_management_service"):
            self.TMS = self.clients.transform_management_service

        #farm everything out to the impls

        self.data_process = DataProcessImpl(self.clients)

    def create_data_process_definition(self, data_process_definition=None):

        result, _ = self.clients.resource_registry.find_resources(
            RT.DataProcessDefinition, None, data_process_definition.name, True)
        if result:
            raise BadRequest(
                "A data process definition named '%s' already exists" %
                data_process_definition.name)

        #todo: determine validation checks for a data process def

        data_process_definition_id, version = self.clients.resource_registry.create(
            data_process_definition)

        #-------------------------------
        # Process Definition
        #-------------------------------
        # Create the underlying process definition
        process_definition = ProcessDefinition()
        process_definition.name = data_process_definition.name
        process_definition.description = data_process_definition.description

        process_definition.executable = {
            'module': data_process_definition.module,
            'class': data_process_definition.class_name
        }
        process_definition_id = self.clients.process_dispatcher.create_process_definition(
            process_definition=process_definition)

        self.clients.resource_registry.create_association(
            data_process_definition_id, PRED.hasProcessDefinition,
            process_definition_id)

        return data_process_definition_id

    def update_data_process_definition(self, data_process_definition=None):
        # TODO: If executable has changed, update underlying ProcessDefinition

        # Overwrite DataProcessDefinition object
        self.clients.resource_registry.update(data_process_definition)

    def read_data_process_definition(self, data_process_definition_id=''):
        # Read DataProcessDefinition object with _id matching id
        log.debug("Reading DataProcessDefinition object id: %s" %
                  data_process_definition_id)
        data_proc_def_obj = self.clients.resource_registry.read(
            data_process_definition_id)

        return data_proc_def_obj

    def delete_data_process_definition(self, data_process_definition_id=''):
        # Delete the data process
        self.clients.resource_registry.delete(data_process_definition_id)

    def find_data_process_definitions(self, filters=None):
        """
        @param      filters: dict of parameters to filter down
                        the list of possible data proc.
        @retval
        """
        #todo: add filtering
        data_process_def_list, _ = self.clients.resource_registry.find_resources(
            RT.DataProcessDefinition, None, None, True)
        return data_process_def_list

    def assign_input_stream_definition_to_data_process_definition(
            self, stream_definition_id='', data_process_definition_id=''):
        """Connect the input  stream with a data process definition
        """
        # Verify that both ids are valid, RR will throw if not found
        stream_definition_obj = self.clients.resource_registry.read(
            stream_definition_id)
        data_process_definition_obj = self.clients.resource_registry.read(
            data_process_definition_id)

        self.clients.resource_registry.create_association(
            data_process_definition_id, PRED.hasInputStreamDefinition,
            stream_definition_id)

    def unassign_input_stream_definition_from_data_process_definition(
            self, stream_definition_id='', data_process_definition_id=''):
        """
        Disconnect the Data Product from the Data Producer

        @param data_product_id    str
        @throws NotFound    object with specified id does not exist
        """

        # Remove the link between the Stream Definition resource and the Data Process Definition resource
        associations = self.clients.resource_registry.find_associations(
            data_process_definition_id,
            PRED.hasInputStreamDefinition,
            stream_definition_id,
            id_only=True)
        if not associations:
            raise NotFound(
                "No Input Stream Definitions associated with data process definition ID "
                + str(data_process_definition_id))
        for association in associations:
            self.clients.resource_registry.delete_association(association)

    def assign_stream_definition_to_data_process_definition(
            self, stream_definition_id='', data_process_definition_id=''):
        """Connect the output  stream with a data process definition
        """
        # Verify that both ids are valid, RR will throw if not found
        stream_definition_obj = self.clients.resource_registry.read(
            stream_definition_id)
        data_process_definition_obj = self.clients.resource_registry.read(
            data_process_definition_id)

        self.clients.resource_registry.create_association(
            data_process_definition_id, PRED.hasStreamDefinition,
            stream_definition_id)

    def unassign_stream_definition_from_data_process_definition(
            self, stream_definition_id='', data_process_definition_id=''):
        """
        Disconnect the Data Product from the Data Producer

        @param data_product_id    str
        @throws NotFound    object with specified id does not exist
        """

        # Remove the link between the Stream Definition resource and the Data Process Definition resource
        associations = self.clients.resource_registry.find_associations(
            data_process_definition_id,
            PRED.hasStreamDefinition,
            stream_definition_id,
            id_only=True)
        if not associations:
            raise NotFound(
                "No Stream Definitions associated with data process definition ID "
                + str(data_process_definition_id))
        for association in associations:
            self.clients.resource_registry.delete_association(association)

    # ------------------------------------------------------------------------------------------------
    # Working with DataProcess

    def create_data_process(self,
                            data_process_definition_id=None,
                            in_data_product_ids='',
                            out_data_products=None,
                            configuration=None):
        """
        @param  data_process_definition_id: Object with definition of the
                    transform to apply to the input data product
        @param  in_data_product_ids: ID of the input data products
        @param  out_data_products: list of IDs of the output data products
        @retval data_process_id: ID of the newly created data process object
        """

        inform = "Input Data Product:       "+str(in_data_product_ids)+\
                 "Transformed by:           "+str(data_process_definition_id)+\
                 "To create output Product: "+str(out_data_products)
        log.debug("DataProcessManagementService:create_data_process()\n" +
                  inform)

        if configuration is None:
            configuration = {}

        # Create and store a new DataProcess with the resource registry
        log.debug(
            "DataProcessManagementService:create_data_process - Create and store a new DataProcess with the resource registry"
        )
        data_process_def_obj = self.read_data_process_definition(
            data_process_definition_id)

        data_process_name = "process_" + data_process_def_obj.name \
                             + time.ctime()
        self.data_process = IonObject(RT.DataProcess, name=data_process_name)
        data_process_id, version = self.clients.resource_registry.create(
            self.data_process)
        log.debug(
            "DataProcessManagementService:create_data_process - Create and store a new DataProcess with the resource registry  data_process_id: %s"
            + str(data_process_id))

        # Register the data process instance as a data producer with DataAcquisitionMgmtSvc
        #TODO: should this be outside this method? Called by orchestration?
        data_producer_id = self.clients.data_acquisition_management.register_process(
            data_process_id)
        log.debug(
            "DataProcessManagementService:create_data_process register process with DataAcquisitionMgmtSvc: data_producer_id: %s   (L4-CI-SA-RQ-181)",
            str(data_producer_id))

        self.output_stream_dict = {}
        #TODO: should this be outside this method? Called by orchestration?
        if out_data_products is None:
            raise BadRequest(
                "Data Process must have output product(s) specified %s",
                str(data_process_definition_id))
        for name, out_data_product_id in out_data_products.iteritems():

            # check that the product is not already associated with a producer
            producer_ids, _ = self.clients.resource_registry.find_objects(
                out_data_product_id, PRED.hasDataProducer, RT.DataProducer,
                True)
            if producer_ids:
                raise BadRequest(
                    "Data Product should not already be associated to a DataProducer %s hasDataProducer %s",
                    str(data_process_id), str(producer_ids[0]))

            #Assign each output Data Product to this producer resource
            out_data_product_obj = self.clients.resource_registry.read(
                out_data_product_id)
            if not out_data_product_obj:
                raise NotFound("Output Data Product %s does not exist" %
                               out_data_product_id)
            # Associate with DataProcess: register as an output product for this process
            log.debug(
                "DataProcessManagementService:create_data_process link data process %s and output out data product: %s    (L4-CI-SA-RQ-260)",
                str(data_process_id), str(out_data_product_id))
            self.clients.data_acquisition_management.assign_data_product(
                data_process_id, out_data_product_id, create_stream=False)

            # Retrieve the id of the OUTPUT stream from the out Data Product
            stream_ids, _ = self.clients.resource_registry.find_objects(
                out_data_product_id, PRED.hasStream, RT.Stream, True)

            log.debug(
                "DataProcessManagementService:create_data_process retrieve out data prod streams: %s",
                str(stream_ids))
            if not stream_ids:
                raise NotFound("No Stream created for output Data Product " +
                               str(out_data_product_id))
            if len(stream_ids) != 1:
                raise BadRequest(
                    "Data Product should only have ONE stream at this time" +
                    str(out_data_product_id))
            self.output_stream_dict[name] = stream_ids[0]
            log.debug(
                "DataProcessManagementService:create_data_process -Register the data process instance as a data producer with DataAcquisitionMgmtSvc, then retrieve the id of the OUTPUT stream  out_stream_id: "
                + str(self.output_stream_dict[name]))

        # Associate with dataProcess
        self.clients.resource_registry.create_association(
            data_process_id, PRED.hasProcessDefinition,
            data_process_definition_id)

        #check if data process has lookup tables attached
        self._find_lookup_tables(data_process_definition_id, configuration)

        #Todo: currently this is handled explicitly after creating the data product, that code then calls DMAS:assign_data_product
        log.debug(
            "DataProcessManagementService:create_data_process associate data process workflows with source data products %s hasInputProducts  %s   (L4-CI-SA-RQ-260)",
            str(data_process_id), str(in_data_product_ids))
        for in_data_product_id in in_data_product_ids:
            self.clients.resource_registry.create_association(
                data_process_id, PRED.hasInputProduct, in_data_product_id)

            #check if in data product is attached to an instrument, check instrumentDevice and InstrumentModel for lookup table attachments
            instdevice_ids, _ = self.clients.resource_registry.find_subjects(
                RT.InstrumentDevice, PRED.hasOutputProduct, in_data_product_id,
                True)
            for instdevice_id in instdevice_ids:
                log.debug(
                    "DataProcessManagementService:create_data_process instrument device_id assoc to the input data product of this data process: %s   (L4-CI-SA-RQ-231)",
                    str(instdevice_id))
                self._find_lookup_tables(instdevice_id, configuration)
                instmodel_ids, _ = self.clients.resource_registry.find_objects(
                    instdevice_id, PRED.hasModel, RT.InstrumentModel, True)
                for instmodel_id in instmodel_ids:
                    log.debug(
                        "DataProcessManagementService:create_data_process instmodel_id assoc to the instDevice: %s",
                        str(instmodel_id))
                    self._find_lookup_tables(instmodel_id, configuration)

        #-------------------------------
        # Create subscription from in_data_product, which should already be associated with a stream via the Data Producer
        #-------------------------------

#        # first - get the data producer associated with this IN data product
#        log.debug("DataProcessManagementService:create_data_process - get the data producer associated with this IN data product")
#        producer_ids, _ = self.clients.resource_registry.find_objects(in_data_product_id, PRED.hasDataProducer, RT.DataProducer, True)
#        if not producer_ids:
#            raise NotFound("No Data Producer created for this Data Product " + str(in_data_product_id))
#        if len(producer_ids) != 1:
#            raise BadRequest("Data Product should only have ONE Data Producers at this time" + str(in_data_product_id))
#        in_product_producer = producer_ids[0]
#        log.debug("DataProcessManagementService:create_data_process - get the data producer associated with this IN data product  in_product_producer: " +  str(in_product_producer))

# second - get the streams associated with this IN data products
        self.in_stream_ids = []
        for in_data_product_id in in_data_product_ids:
            log.debug(
                "DataProcessManagementService:create_data_process - get the stream associated with this IN data product"
            )
            stream_ids, _ = self.clients.resource_registry.find_objects(
                in_data_product_id, PRED.hasStream, RT.Stream, True)
            if not stream_ids:
                raise NotFound("No Stream created for this IN Data Product " +
                               str(in_data_product_id))
            if len(stream_ids) != 1:
                raise BadRequest(
                    "IN Data Product should only have ONE stream at this time"
                    + str(in_data_product_id))
            log.debug(
                "DataProcessManagementService:create_data_process - get the stream associated with this IN data product:  %s  in_stream_id: %s ",
                str(in_data_product_id), str(stream_ids[0]))
            self.in_stream_ids.append(stream_ids[0])

        # Finally - create a subscription to the input stream
        log.debug(
            "DataProcessManagementService:create_data_process - Finally - create a subscription to the input stream"
        )
        in_data_product_obj = self.clients.data_product_management.read_data_product(
            in_data_product_id)
        query = StreamQuery(stream_ids=self.in_stream_ids)
        #self.input_subscription_id = self.clients.pubsub_management.create_subscription(query=query, exchange_name=in_data_product_obj.name)
        self.input_subscription_id = self.clients.pubsub_management.create_subscription(
            query=query, exchange_name=data_process_name)
        log.debug(
            "DataProcessManagementService:create_data_process - Finally - create a subscription to the input stream   input_subscription_id"
            + str(self.input_subscription_id))

        # add the subscription id to the resource for clean up later
        data_process_obj = self.clients.resource_registry.read(data_process_id)
        data_process_obj.input_subscription_id = self.input_subscription_id
        self.clients.resource_registry.update(data_process_obj)

        procdef_ids, _ = self.clients.resource_registry.find_objects(
            data_process_definition_id,
            PRED.hasProcessDefinition,
            RT.ProcessDefinition,
            id_only=True)
        if not procdef_ids:
            raise BadRequest(
                "Cannot find associated ProcessDefinition for DataProcessDefinition id=%s"
                % data_process_definition_id)
        process_definition_id = procdef_ids[0]

        # Launch the transform process
        log.debug(
            "DataProcessManagementService:create_data_process - Launch the first transform process: "
        )
        log.debug(
            "DataProcessManagementService:create_data_process - input_subscription_id: "
            + str(self.input_subscription_id))
        log.debug(
            "DataProcessManagementService:create_data_process - out_stream_id: "
            + str(self.output_stream_dict))
        log.debug(
            "DataProcessManagementService:create_data_process - process_definition_id: "
            + str(process_definition_id))
        log.debug(
            "DataProcessManagementService:create_data_process - data_process_id: "
            + str(data_process_id))

        transform_id = self.clients.transform_management.create_transform(
            name=data_process_id,
            description=data_process_id,
            in_subscription_id=self.input_subscription_id,
            out_streams=self.output_stream_dict,
            process_definition_id=process_definition_id,
            configuration=configuration)

        log.debug(
            "DataProcessManagementService:create_data_process - transform_id: "
            + str(transform_id))

        self.clients.resource_registry.create_association(
            data_process_id, PRED.hasTransform, transform_id)
        log.debug(
            "DataProcessManagementService:create_data_process - Launch the first transform process   transform_id"
            + str(transform_id))

        # TODO: Flesh details of transform mgmt svc schedule method
        #        self.clients.transform_management_service.schedule_transform(transform_id)

        return data_process_id

    def _find_lookup_tables(self, resource_id="", configuration=None):
        #check if resource has lookup tables attached
        attachment_objs, _ = self.clients.resource_registry.find_objects(
            resource_id, PRED.hasAttachment, RT.Attachment, False)
        for attachment_obj in attachment_objs:
            log.debug(
                "DataProcessManagementService:_find_lookup_tables  attachment %s",
                str(attachment_obj))
            words = set(attachment_obj.keywords)
            if 'DataProcessInput' in words:
                configuration[attachment_obj.name] = attachment_obj.content
                log.debug(
                    "DataProcessManagementService:_find_lookup_tables lookup table found in attachment %s",
                    attachment_obj.name)
            else:
                log.debug(
                    "DataProcessManagementService:_find_lookup_tables NO lookup table in attachment %s",
                    attachment_obj.name)

    def update_data_process(self, ):
        #todo: What are valid ways to update a data process?.

        return

    def read_data_process(self, data_process_id=""):
        # Read DataProcess object with _id matching  id
        log.debug("Reading DataProcess object id: %s" % data_process_id)
        data_proc_obj = self.clients.resource_registry.read(data_process_id)
        if not data_proc_obj:
            raise NotFound("DataProcess %s does not exist" % data_process_id)
        return data_proc_obj

    def delete_data_process(self, data_process_id=""):
        # Delete the specified DataProcessDefinition object
        data_process_obj = self.clients.resource_registry.read(data_process_id)
        if data_process_obj is None:
            raise NotFound("Data Process %s does not exist" % data_process_id)

        # Deactivates and deletes the input subscription
        # todo: create did not activate the subscription, should Transform deactivate?
        try:
            self.clients.pubsub_management.deactivate_subscription(
                data_process_obj.input_subscription_id)
            log.debug(
                "DataProcessManagementService:delete_data_process  delete subscription"
            )
            self.clients.pubsub_management.delete_subscription(
                data_process_obj.input_subscription_id)
        except BadRequest, e:
            #May not have activated the subscription so just skip - had to add this to get AS integration tests to pass - probably should be fixed
            pass

        self.clients.data_acquisition_management.unregister_process(
            data_process_id)

        # Delete the output stream, but not the output product
        out_products, _ = self.clients.resource_registry.find_objects(
            data_process_id, PRED.hasOutputProduct, RT.DataProduct, True)
        if len(out_products) < 1:
            raise NotFound(
                'The the Data Process %s output product cannot be located.' %
                str(data_process_id))

#        outprod_associations = self.clients.resource_registry.find_associations(data_process_id, PRED.hasOutputProduct)
#        for outprod_association in outprod_associations:
#            log.debug("DataProcessManagementService:delete_data_process  delete outprod assoc")
#            self.clients.resource_registry.delete_association(outprod_association)

        for out_product in out_products:
            out_streams, _ = self.clients.resource_registry.find_objects(
                out_product, PRED.hasStream, RT.Stream, True)
            for out_stream in out_streams:

                outprod_associations = self.clients.resource_registry.find_associations(
                    data_process_id, PRED.hasOutputProduct, out_product)
                log.debug(
                    "DataProcessManagementService:delete_data_process  delete outprod assoc"
                )
                self.clients.resource_registry.delete_association(
                    outprod_associations[0])

                # delete the stream def assoc to the stream
                streamdef_list = self.clients.resource_registry.find_objects(
                    subject=out_stream,
                    predicate=PRED.hasStreamDefinition,
                    id_only=True)

                # delete the associations link first
                streamdef_assocs = self.clients.resource_registry.find_associations(
                    out_stream, PRED.hasStreamDefinition)
                for streamdef_assoc in streamdef_assocs:
                    log.debug(
                        "DataProcessManagementService:delete_data_process  delete streamdef assocs"
                    )
                    self.clients.resource_registry.delete_association(
                        streamdef_assoc)

#                for streamdef in streamdef_list:
#                    self.clients.resource_registry.delete_association(streamdef)

# delete the connector first
                stream_associations = self.clients.resource_registry.find_associations(
                    out_product, PRED.hasStream)
                for stream_association in stream_associations:
                    log.debug(
                        "DataProcessManagementService:delete_data_process  delete stream assocs"
                    )
                    self.clients.resource_registry.delete_association(
                        stream_association)

                log.debug(
                    "DataProcessManagementService:delete_data_process  delete outstreams"
                )
                self.clients.pubsub_management.delete_stream(out_stream)

        # Delete the input products link
        inprod_associations = self.clients.resource_registry.find_associations(
            data_process_id, PRED.hasInputProduct)
        if len(inprod_associations) < 1:
            raise NotFound(
                'The the Data Process %s input product link cannot be located.'
                % str(data_process_id))
        for inprod_association in inprod_associations:
            log.debug(
                "DataProcessManagementService:delete_data_process  delete inprod assocs"
            )
            self.clients.resource_registry.delete_association(
                inprod_association)

        # Delete the transform
        transforms, _ = self.clients.resource_registry.find_objects(
            data_process_id, PRED.hasTransform, RT.Transform, True)
        if len(transforms) < 1:
            raise NotFound(
                'There is no Transform linked to this Data Process %s' %
                str(data_process_id))

        # delete the transform associations link first
        transform_assocs = self.clients.resource_registry.find_associations(
            data_process_id, PRED.hasTransform)
        for transform_assoc in transform_assocs:
            log.debug(
                "DataProcessManagementService:delete_data_process  delete transform assocs"
            )
            self.clients.resource_registry.delete_association(transform_assoc)

        for transform in transforms:
            log.debug(
                "DataProcessManagementService:delete_data_process  delete transform"
            )
            self.clients.transform_management.delete_transform(transform)

        # Delete the assoc with Data Process Definition
        data_process_defs = self.clients.resource_registry.find_associations(
            data_process_id, PRED.hasProcessDefinition, None)
        if len(data_process_defs) < 1:
            raise NotFound(
                'The the Data Process %s is not linked to a Data Process Definition.'
                % str(data_process_id))
        for data_process_def in data_process_defs:
            log.debug(
                "DataProcessManagementService:delete_data_process  data_process_def transform"
            )
            self.clients.resource_registry.delete_association(data_process_def)

#        other_assocs = self.clients.resource_registry.find_associations(subject=data_process_id)
#        for other_assoc in other_assocs:
#            log.debug("DataProcessManagementService:delete_data_process  delete other assoc")
#            self.clients.resource_registry.delete_association(other_assoc)

# Delete the data process
        log.debug(
            "DataProcessManagementService:delete_data_process the data_process"
        )
        self.clients.resource_registry.delete(data_process_id)
        return
Example #43
0
 def send(self, data):
     # send data from parent to tcp client
     log.debug("TcpServer.send(): data = " + str(data))
     if self.server_ready_to_send:
         self._write(data)
class PolicyManagementService(BasePolicyManagementService):

    def __init__(self, *args, **kwargs):
        BasePolicyManagementService.__init__(self,*args,**kwargs)

        self.event_pub = None  # For unit tests


    def on_start(self):
        self.event_pub = EventPublisher()

        self.policy_event_subscriber = ProcessEventSubscriber(event_type="ResourceModifiedEvent", origin_type="Policy", callback=self._policy_event_callback, process=self)
        self._process.add_endpoint(self.policy_event_subscriber)

    """Provides the interface to define and manage policy and a repository to store and retrieve policy
    and templates for policy definitions, aka attribute authority.

    @see https://confluence.oceanobservatories.org/display/syseng/CIAD+COI+OV+Policy+Management+Service
    """

    def create_resource_access_policy(self, resource_id='', policy_name='', description='', policy_rule=''):
        """Helper operation for creating an access policy for a specific resource. The id string returned
        is the internal id by which Policy will be identified in the data store.

        @param resource_id    str
        @param policy_name    str
        @param description    str
        @param policy_rule    str
        @retval policy_id    str
        @throws BadRequest    If any of the paramaters are not set.
        """
        if not resource_id:
            raise BadRequest("The resource_id parameter is missing")

        if not policy_name:
            raise BadRequest("The policy_name parameter is missing")

        if not description:
            raise BadRequest("The description parameter is missing")

        if not policy_rule:
            raise BadRequest("The policy_rule parameter is missing")


        resource_policy_obj = IonObject(OT.ResourceAccessPolicy, policy_rule=policy_rule, resource_id=resource_id)

        policy_obj = IonObject(RT.Policy, name=policy_name, description=description, policy_type=resource_policy_obj)

        policy_id = self.create_policy(policy_obj)

        self._add_resource_policy(resource_id, policy_id, publish_event=False)

        return policy_id

    def create_service_access_policy(self, service_name='', policy_name='', description='', policy_rule=''):
        """Helper operation for creating an access policy for a specific service. The id string returned
        is the internal id by which Policy will be identified in the data store.

        @param service_name    str
        @param policy_name    str
        @param description    str
        @param policy_rule    str
        @retval policy_id    str
        @throws BadRequest    If any of the paramaters are not set.
        """
        if not service_name:
            raise BadRequest("The service_name parameter is missing")

        if not policy_name:
            raise BadRequest("The policy_name parameter is missing")

        if not description:
            raise BadRequest("The description parameter is missing")

        if not policy_rule:
            raise BadRequest("The policy_rule parameter is missing")


        service_policy_obj = IonObject(OT.ServiceAccessPolicy, policy_rule=policy_rule, service_name=service_name)

        policy_obj = IonObject(RT.Policy, name=policy_name, description=description, policy_type=service_policy_obj)

        return self.create_policy(policy_obj)

    def create_common_service_access_policy(self, policy_name='', description='', policy_rule=''):
        """Helper operation for creating a service access policy common to all services. The id string returned
        is the internal id by which Policy will be identified in the data store.

        @param policy_name    str
        @param description    str
        @param policy_rule    str
        @retval policy_id    str
        @throws BadRequest    If any of the paramaters are not set.
        """

        if not policy_name:
            raise BadRequest("The policy_name parameter is missing")

        if not description:
            raise BadRequest("The description parameter is missing")

        if not policy_rule:
            raise BadRequest("The policy_rule parameter is missing")


        service_policy_obj = IonObject(OT.CommonServiceAccessPolicy, policy_rule=policy_rule)

        policy_obj = IonObject(RT.Policy, name=policy_name, description=description, policy_type=service_policy_obj)

        return self.create_policy(policy_obj)


    def add_process_operation_precondition_policy(self, process_name='', op='', policy_content=''):
        """Helper operation for adding a precondition policy for a specific process operation; could be a service or agent.
        The id string returned is the internal id by which Policy will be identified in the data store. The precondition
        method must return a tuple (boolean, string).

        @param process_name    str
        @param op    str
        @param policy_content    str
        @retval policy_id    str
        @throws BadRequest    If any of the parameters are not set.
        """
        if not process_name:
            raise BadRequest("The process_name parameter is missing")

        if not op:
            raise BadRequest("The op parameter is missing")

        if not policy_content:
            raise BadRequest("The policy_content parameter is missing")

        policy_name = process_name + "_" + op + "_Precondition_Policies"

        policies,_ = self.clients.resource_registry.find_resources(restype=RT.Policy, name=policy_name)
        if policies:
            #Update existing policy by adding to list
            if len(policies) > 1:
                raise Inconsistent('There should only be one Policy object per process_name operation')

            if policies[0].policy_type.op != op or  policies[0].policy_type.type_ != OT.ProcessOperationPreconditionPolicy:
                raise Inconsistent('There Policy object %s does not match the requested process operation %s: %s' % ( policies[0].name, process_name, op ))

            policies[0].policy_type.preconditions.append(policy_content)

            self.update_policy(policies[0])

            return policies[0]._id

        else:
            #Create a new policy object

            op_policy_obj = IonObject(OT.ProcessOperationPreconditionPolicy,  process_name=process_name, op=op)
            op_policy_obj.preconditions.append(policy_content)

            policy_obj = IonObject(RT.Policy, name=policy_name, policy_type=op_policy_obj, description='List of operation precondition policies for ' + process_name)

            return self.create_policy(policy_obj)



    def create_policy(self, policy=None):
        """Persists the provided Policy object The id string returned
        is the internal id by which Policy will be identified in the data store.

        @param policy    Policy
        @retval policy_id    str
        @throws BadRequest    if object passed has _id or _rev attribute
        """

        if not policy:
            raise BadRequest("The policy parameter is missing")

        if not is_basic_identifier(policy.name):
            raise BadRequest("The policy name '%s' can only contain alphanumeric and underscore characters" % policy.name)

        try:
            #If there is a policy_rule field then try to add the policy name and decription to the rule text
            if hasattr(policy.policy_type, 'policy_rule'):
                policy.policy_type.policy_rule = policy.policy_type.policy_rule % (policy.name, policy.description)

        except Exception, e:
            raise Inconsistent("Missing the elements in the policy rule to set the description: " + e.message)

        policy_id, version = self.clients.resource_registry.create(policy)

        log.debug('Policy created: ' + policy.name)

        return policy_id
Example #45
0
    def _control_flow(self):
        """
        Main process thread of execution method.

        This method is run inside a greenlet and exists for each ION process. Listeners
        attached to the process, either RPC Servers or Subscribers, synchronize their calls
        by placing future calls into the queue by calling _routing_call.  This is all done
        automatically for you by the Container's Process Manager.

        This method blocks until there are calls to be made in the synchronized queue, and
        then calls from within this greenlet.  Any exception raised is caught and re-raised
        in the greenlet that originally scheduled the call.  If successful, the AsyncResult
        created at scheduling time is set with the result of the call.
        """
        if self.name:
            svc_name = "unnamed-service"
            if self.service is not None and hasattr(self.service, 'name'):
                svc_name = self.service.name
            threading.current_thread().name = "%s-%s-ctrl" % (svc_name,
                                                              self.name)

        self._ready_control.set()

        for calltuple in self._ctrl_queue:
            calling_gl, ar, call, callargs, callkwargs, context = calltuple
            log.debug("control_flow making call: %s %s %s (has context: %s)",
                      call, callargs, callkwargs, context is not None)

            res = None
            start_proc_time = int(get_ion_ts())

            # check context for expiration
            if context is not None and 'reply-by' in context:
                if start_proc_time >= int(context['reply-by']):
                    log.info(
                        "control_flow: attempting to process message already exceeding reply-by, ignore"
                    )

                    # raise a timeout in the calling thread to allow endpoints to continue processing
                    e = IonTimeout(
                        "Reply-by time has already occurred (reply-by: %s, op start time: %s)"
                        % (context['reply-by'], start_proc_time))
                    calling_gl.kill(exception=e, block=False)

                    continue

            # also check ar if it is set, if it is, that means it is cancelled
            if ar.ready():
                log.info(
                    "control_flow: attempting to process message that has been cancelled, ignore"
                )
                continue

            try:
                with self.service.push_context(context):
                    with self.service.container.context.push_context(context):
                        self._ctrl_current = ar
                        res = call(*callargs, **callkwargs)
            except OperationInterruptedException:
                # endpoint layer takes care of response as it's the one that caused this
                log.debug("Operation interrupted")
                pass
            except Exception as e:
                # raise the exception in the calling greenlet, and don't
                # wait for it to die - it's likely not going to do so.

                # try decorating the args of the exception with the true traceback
                # this should be reported by ThreadManager._child_failed
                exc = PyonThreadTraceback(
                    "IonProcessThread _control_flow caught an exception (call: %s, *args %s, **kwargs %s, context %s)\nTrue traceback captured by IonProcessThread' _control_flow:\n\n%s"
                    % (call, callargs, callkwargs, context,
                       traceback.format_exc()))
                e.args = e.args + (exc, )

                # HACK HACK HACK
                # we know that we only handle TypeError and IonException derived things, so only forward those if appropriate
                if isinstance(e, (TypeError, IonException)):
                    calling_gl.kill(exception=e, block=False)
                else:
                    # otherwise, swallow/record/report and hopefully we can continue on our way
                    self._errors.append(
                        (call, callargs, callkwargs, context, e, exc))

                    log.warn(exc)
                    log.warn("Attempting to continue...")

                    # have to raise something friendlier on the client side
                    calling_gl.kill(exception=ContainerError(str(exc)),
                                    block=False)
            finally:
                proc_time = int(get_ion_ts()) - start_proc_time
                self._proc_time += proc_time

                self._ctrl_current = None

            ar.set(res)
Example #46
0
 def _handler(self):
     "The actual handler to which the client is connected.  Must be implemented in any server that inherits from this class"
     log.debug("TcpServer._handler(): not implemented")
     raise NotImplementedException('TcpServer._handler() not implemented.')        
Example #47
0
 def start(self):
     log.debug("AppManager starting ...")
Example #48
0
 def stop(self):
     log.debug("SFlowManager.stop")
     if self._gl_counter:
         self._gl_counter.kill()
Example #49
0
 def __init__(self, *args, **kwargs):
     log.debug('GovernanceDispatcher.__init__()')
Example #50
0
 def stop(self):
     log.debug("AppManager stopping ...")
     # Stop apps in reverse order of startup
     for appdef in reversed(self.apps):
         self.stop_app(appdef)
     log.debug("AppManager stopped, OK.")
Example #51
0
def start(container, starttype, app_definition, config):
    log.debug("Hello app started")
    return (None, None)
Example #52
0
            except Exception, ex:
                log.exception("Appl %s start from processapp failed" %
                              appdef.name)
        else:
            # Case 2: Appdef contains full app start params
            modpath = appdef.mod
            try:
                mod = named_any(modpath)
                appdef._mod_loaded = mod

                # Start the app
                supid, state = mod.start(self.container, START_PERMANENT,
                                         appdef, config)
                appdef._supid = supid
                appdef._state = state

                log.debug("App '%s' started. Root sup-id=%s" %
                          (appdef.name, supid))

                self.apps.append(appdef)
            except Exception, ex:
                log.exception("Appl %s start from appdef failed" % appdef.name)

    def stop_app(self, appdef):
        log.debug("App '%s' stopping" % appdef.name)
        try:
            if '_mod_loaded' in appdef:
                appdef._mod_loaded.stop(self.container, appdef._state)
        except Exception, ex:
            log.exception("Application %s stop failed" % appdef.name)
Example #53
0
 def on_quit(self, *args, **kwargs):
     log.debug("Hello service quit")
     self.container.governance_controller.unregister_process_operation_precondition(
         self, 'noop', self.deny_noop)
Example #54
0
def stop(container, state):
    log.debug("Hello app stopped")
Example #55
0
 def on_init(self, *args, **kwargs):
     log.debug("Hello service init. Self.id=%s" % self.id)
     self.container.governance_controller.register_process_operation_precondition(
         self, 'noop', self.deny_noop)
Example #56
0
 def hello(self, text=''):
     log.debug("In hello_service.hello. Text=%s" % text)
     return "BACK:%s" % text
 def _stop_process(self, data_process):
     log.debug("stopping data process '%s'" % data_process.process_id)
     pid = data_process.process_id
     self.clients.process_dispatcher.cancel_process(pid)
Example #58
0
 def on_start(self, *args, **kwargs):
     log.debug("Hello service start")
    def create_data_product_resource_full(self):

        geospatial_bounds = {
            "geospatial_latitude_limit_north": 1.0,
            "geospatial_latitude_limit_south": 1.0,
            "geospatial_longitude_limit_east": 1.0,
            "geospatial_longitude_limit_west": 1.0,
            "geospatial_vertical_min": 1.0,
            "geospatial_vertical_max": 1.0
        }

        #create a paramter dictionary the a stream definition for this data product
        DICTIONARY_NAME = 'ctd_parsed_param_dict'
        response = self.test_app.get(
            '/ion-service/resource_registry/find_resources?name=' +
            convert_unicode(DICTIONARY_NAME) +
            '&id_only=True&user_id=123abc456')
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        param_dictionary_id = convert_unicode(response_data[0])
        test = str(param_dictionary_id[0])
        log.debug(
            'create_data_product_resource_full  param_dictionary_id:  %s',
            param_dictionary_id)
        log.debug('create_data_product_resource_full  test:  %s', test)

        response = self.test_app.get(
            '/ion-service/pubsub_management/create_stream_definition?name=CTDData&parameter_dictionary_id='
            + convert_unicode(param_dictionary_id[0]))
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        log.debug('create_data_product_resource_full   response_data:  %s',
                  response_data)
        stream_definition_id = convert_unicode(response_data)
        log.debug(
            'create_data_product_resource_full  stream_definition_id:  %s',
            stream_definition_id)

        data_product_create_request = {
            "serviceRequest": {
                "serviceName": "data_product_management",
                "serviceOp": "create_data_product",
                "params": {
                    "data_product": {
                        "type_": "DataProduct",
                        "lcstate": "DRAFT",
                        "description": DATA_PRODUCT_DESCRIPTION,
                        "name": DATA_PRODUCT_NAME,
                        'geospatial_bounds': geospatial_bounds,
                        'temporal_domain': TEMPORAL_DOMAIN
                    },
                    "stream_definition_id": stream_definition_id
                }
            }
        }

        response = self.test_app.post(
            '/ion-service/data_product_management/create_data_product',
            {'payload': simplejson.dumps(data_product_create_request)})
        self.check_response_headers(response)
        self.assertIn(GATEWAY_RESPONSE, response.json['data'])
        response_data = response.json['data'][GATEWAY_RESPONSE]
        log.debug(
            'create_data_product_resource_full  create_data_product response_data:  %s',
            response_data)
        #self.assertEqual(len(response_data), 2 )
        data_product_id = convert_unicode(response_data)
        return data_product_id
Example #60
0
 def incoming(self, invocation):
     log.debug("EncodeInterceptor.incoming: %s", invocation)
     log.debug("Pre-transform: %s", invocation.message)
     invocation.message = msgpack.unpackb(invocation.message, object_hook=decode_ion, use_list=1)
     log.debug("Post-transform: %s", invocation.message)
     return invocation