예제 #1
0
    def start(self):
        """
        Translate self.get_query() into the corresponding SQL command.
        The PostgreSQL's get_sql method is overloaded in order to redirect
        handle queries related to pseudo tables (traceroute, bgp, ...) and craft a
        customized query.
        """
        query = self.get_query()
        table_name = query.get_from()

        if table_name in self.METHOD_MAP.keys():
            if self.METHOD_MAP[table_name]:
                # See manifold/gateways/tdmi/methods/*
                params = None
                instance = self.METHOD_MAP[table_name](query, db = self)
                sql = instance.get_sql()
                rows = self.selectall(sql, params)

                # Does this object tweak the python dictionnary returned by selectall?
                if instance.need_repack and instance.repack:
                    if instance.need_repack(query):
                        rows = [instance.repack(query, row) for row in rows]
            else:
                # Dummy object, like hops (hops is declared in tdmi.h) but
                # do not corresponds to any 
                rows = list()

            map(self.send, Records(rows))
            self.send(LastRecord())
        else:
            # Update FROM clause according to postgresql aliases
            self.query.object = self.get_pgsql_name(table_name)
            return super(TDMIGateway, self).start()
예제 #2
0
    def _on_right_done(self):
        # Send records in left_results that have not been joined...
        for left_record_list in self.left_map.values():
            for left_record in left_record_list:
                self.send(left_record)

        # ... and terminates
        self.send(LastRecord())
예제 #3
0
 def callback_error(self, error):
     """
     (Internal usage) See ManifoldGateway::receive_impl.
     Args:
         packet: A QUERY Packet.
         error: The corresponding error message.
     """
     Log.error("Error during Manifold call: %r" % error)
     self.send(LastRecord())
예제 #4
0
 def start(self):
     """
     Propagates a START message through the FromTable Node.
     """
     for record in self.records:
         if not isinstance(record, Record):
             record = {self.key: record}
         self.send(record)
     self.send(LastRecord())
예제 #5
0
 def set_records(self, records):
     if not isinstance(records, list):
         records = [records]
     self._pending_records = list()
     self._records = records
     self._updated = time.time()
     for operator in self._operators:
         for record in records:
             operator.child_callback(record)
         operator.child_callback(LastRecord())
예제 #6
0
    def start(self):
        """
        Fetch records stored in the postgresql database according to self.query
        """

        # Results of the query (TODO)
        rows = []

        # Sending rows to parent processing node in the AST
        map(self.send, Records(rows))
        self.send(LastRecord())
예제 #7
0
    def start(self):

        # Will receive a start when executed == when the source is ready to receive records
        # That's when we make the difference between different modes (cached, buffered, multicast)

        # TMP CACHE DEBUG
        #import pdb
        #pdb.set_trace()
        if self._cache_entry.has_query_in_progress():
            print "query in progress"
            if self._cache_entry.has_pending_records():
                print "has pending records"
                # Let's first return all pending records, then wait for
                # set_records to receive further records
                print "pending records = ", self._cache_entry._pending_records
                for record in self._cache_entry._pending_records:
                    record.set_annotation('cache', 'buffered multicast')
                    self.send(record)

            else:
                # Query did not started, just return new incoming records
                # Nothing to do, let's wait for set_records
                pass

            # Inform the cache entry we are interested in its records
            self._cache_entry.add_operator(self)

        else:
            # If we reached here, we _have_ records in cache
            # otherwise, we would have a cache entry and no query in progress,
            # and no query ever done == INCONSISTENT
            for record in self._cache_entry.get_records():
                record.set_annotation('cache', 'cache')
                self.send(record)
            record = LastRecord()
            record.set_annotation('cache', 'cache')
            self.send(record)
예제 #8
0
 def start(self):
     assert self.query, "Cannot start gateway with no query associated"
     _map_action = {
         'get': self.local_query_get,
         'update': self.local_query_update,
         'create': self.local_query_create,
         'delete': self.local_query_delete
     }
     table = _map_action[self.query.action](self.query)
     # XXX For local namespace queries, we need to keep a dict
     if table:
         for t in table:
             #MANDO|            row = row2dict(t) if self.format == 'dict' else t.get_object()
             row = row2record(t) if self.format == 'record' else t
             self.send(row)
     self.send(LastRecord())
예제 #9
0
    def start(self):
        """
        Fetch records stored in the postgresql database according to self.query
        """
        sql = PostgreSQLGateway.to_sql(self.query)
        Log.tmp(sql)
        if self.query.get_action() in [ACTION_GET, ACTION_CREATE]:
            rows = self.selectall(sql)
        else:
            count = self.do(sql)
            if self.query.get_select():
                select_query = self.query.copy()
                select_query.action = ACTION_GET
                if self.query.get_action() == ACTION_DELETE:
                    select_query.filter_by(None)
                select_sql = PostgreSQLGateway.to_sql(select_query)
                rows = self.selectall(select_sql)
            else:
                rows = list()

        map(self.send, Records(rows))
        self.send(LastRecord())
예제 #10
0
    def start(self):
        assert self.query, "Query should have been associated before start"

        table = self.query.object

        dialect, field_names, field_types = self.get_dialect_and_field_info(
            table)
        key = self.get_key(table)

        filename = self.config[table]['filename']

        with open(filename, 'rb') as csvfile:
            reader = csv.reader(csvfile, dialect=dialect)
            try:
                if self.has_headers[table]:
                    values = reader.next()
                for row in reader:
                    row = self.convert(row, field_names, field_types)
                    if not row: continue
                    self.send(row)
                self.send(LastRecord())
            except csv.Error as e:
                sys.exit('file %s, line %d: %s' %
                         (filename, reader.line_num, e))
예제 #11
0
 def exception_cb(self, error):
     print 'Error during Manifold call: ', error
     self.callback(LastRecord())
예제 #12
0
 def start(self):
     results = getattr(self, "get_%s" % self.query.object)()
     map(self.send, Records(results))
     self.send(LastRecord())
예제 #13
0
    def start(self):
        query = self.query
        table_name = query.get_from()

        # Need to transform manifold fields into query fields, and then back in
        # callback_records

        ## Insert a RENAME Node above this FROM Node if necessary.
        #instance = self.get_object(query.get_from())
        #aliases  = instance.get_aliases()
        #if aliases:
        #    Log.warning("I don't think this properly recables everything")
        #    try:
        #        Rename(self, aliases)
        #    except Exception, e:
        #        print "EEE:", e

        filters = MyPLCGateway.manifold_to_myplc_filter(query.get_where())
        fields = query.get_select()
        fields = list(fields)

        if query.get_from() in MAP_METHOD:
            method = MAP_METHOD[query.get_from()]
        else:
            # XXX Only admin user has an account on ple-myplc platform
            # XXX Check if the user has the right to do it before the admin_execute_query
            # XXX Slice or Authority Credentials !!!
            if query.action == 'get' and query.get_from() == 'initscript':
                method = "GetSliceInitscriptCode"
                fields = False
                slicename = self.get_slicename(filters)
                if not slicename:
                    self.send(LastRecord())
                    return

                filters = slicename

            if query.action == 'update' and query.get_from() == 'initscript':
                # UpdateSlice (auth, slice_id_or_name, slice_fields)
                method = "UpdateSlice"

                slicename = self.get_slicename(filters)
                if not slicename:
                    self.send(LastRecord())
                    return

                filters = slicename
                params = query.get_params()
                print params
                fields = {'initscript_code': params['initscript_code']}
                # initscript_code ???

            # Either in request RSpec or using UpdateSlice method
            # <node ...>
            # <sliver_type name="plab-vnode">
            #     <planetlab:initscript name="gpolab_sirius"/>
            # </sliver_type>
            # </node>

            if query.action == 'delete' and query.get_from() == 'initscript':
                #method = "DeleteSliceTag"
                # GetSliceTags (auth, slice_tag_filter, return_fields)

                # slicename from slice_hrn
                slicename = self.get_slicename(filters)
                if not slicename:
                    self.send(LastRecord())
                    return

                # slice_tag_id for initscript_code tag
                filters = {'name': slicename}
                fields = ['slice_tag_id', 'tagname']
                plc_api = xmlrpclib.ServerProxy(API_URL, allow_none=True)

                result = plc_api.GetSliceTags(self._get_auth(), filters,
                                              fields)
                # XXX How to get the result from callRemote and use it in the rest of the code?
                for r in result:
                    if r['tagname'] == 'initscript_code':
                        method = 'DeleteSliceTag'
                        fields = False
                        filters = r['slice_tag_id']

        if fields:
            d = self._proxy.callRemote(method, self._get_auth(), filters,
                                       fields)
        else:
            d = self._proxy.callRemote(method, self._get_auth(), filters)

        d.addCallback(self.callback_records)
        d.addErrback(self.callback_error)
예제 #14
0
    def all_done(self):
        """
        \brief Called when all children of the current subquery are done: we
         process results stored in the parent.
        """
        try:
            for parent_record in self.parent_output:
                # Dispatching child results
                for i, child in enumerate(self.children):
                    relation = self.relations[i]
                    predicate = relation.get_predicate()

                    key, op, value = predicate.get_tuple()

                    if op == eq:
                        # 1..N
                        # Example: parent has slice_hrn, resource has a reference to slice
                        #            PARENT       CHILD
                        # Predicate: (slice_hrn,) == slice

                        # Collect in parent all child such as they have a pointer to the parent
                        record = Record.get_value(parent_record, key)
                        if not record:
                            record = []
                        if not isinstance(record,
                                          (list, tuple, set, frozenset)):
                            record = [record]
                        if relation.get_type() in [
                                Relation.types.LINK_1N,
                                Relation.types.LINK_1N_BACKWARDS
                        ]:
                            # we have a list of elements
                            # element = id or dict    : cle simple
                            #         = tuple or dict : cle multiple
                            ids = [
                                SubQuery.get_element_key(r, value)
                                for r in record
                            ]
                        else:
                            ids = [SubQuery.get_element_key(record, value)]
                        if len(ids) == 1:
                            id, = ids
                            filter = Filter().filter_by(
                                Predicate(value, eq, id))
                        else:
                            filter = Filter().filter_by(
                                Predicate(value, included, ids))
                        #if isinstance(key, StringTypes):
                        #    # simple key
                        #    ids = [o[key]] if key in o else []
                        #    #print "IDS=", ids
                        #    #if ids and isinstance(ids[0], dict):
                        #    #    ids = map(lambda x: x[value], ids)
                        #    # XXX we might have equality instead of IN in case of a single ID
                        #    print "VALUE", value, "INCLUDED ids=", ids
                        #    filter = Filter().filter_by(Predicate(value, included, ids))
                        #else:
                        #    # Composite key, o[value] is a dictionary
                        #    for field in value:
                        #        filter = filter.filter_by(Predicate(field, included, o[value][field])) # o[value] might be multiple

                        parent_record[relation.get_relation_name()] = []
                        for child_record in self.child_results[i]:
                            if filter.match(child_record):
                                parent_record[relation.get_relation_name(
                                )].append(child_record)

                    elif op == contains:
                        # 1..N
                        # Example: parent 'slice' has a list of 'user' keys == user_hrn
                        #            PARENT        CHILD
                        # Predicate: user contains (user_hrn, )

                        # first, replace records by dictionaries. This only works for non-composite keys
                        if parent_record[child.query.object]:
                            record = parent_record[child.query.object][0]
                            if not isinstance(record, dict):
                                parent_record[child.query.object] = [{
                                    value:
                                    record
                                } for record in parent_record[
                                    child.query.object]]

                        if isinstance(value, StringTypes):
                            for record in parent_record[child.query.object]:
                                # Find the corresponding record in child_results and update the one in the parent with it
                                for k, v in record.items():
                                    filter = Filter().filter_by(
                                        Predicate(value, eq, record[value]))
                                    for r in self.child_results[i]:
                                        if filter.match(r):
                                            record.update(r)
                        else:
                            for record in parent_record[child.query.object]:
                                # Find the corresponding record in child_results and update the one in the parent with it
                                for k, v in record.items():
                                    filter = Filter()
                                    for field in value:
                                        filter = filter.filter_by(
                                            Predicate(field, eq,
                                                      record[field]))
                                    for r in self.child_results[i]:
                                        if filter.match(r):
                                            record.update(r)

                    else:
                        raise Exception, "No link between parent and child queries"

                self.send(parent_record)
            self.send(LastRecord())
        except Exception, e:
            print "EEE", e
            traceback.print_exc()
예제 #15
0
    def run_children(self):
        """
        Run children queries (subqueries) assuming the parent query (main query)
        has successfully ended.
        """
        if not self.parent_output:
            # No parent record, this is useless to run children queries.
            self.send(LastRecord())
            return

        #print "=" * 80
        #print self.parent_output
        #print "=" * 80

        if not self.children:
            # The top operator has build a SubQuery node without child queries,
            # so this SubQuery operator is useless and should be replaced by
            # its main query.
            Log.warning(
                "SubQuery::run_children: no child node. The query plan could be improved"
            )
            self.send(LastRecord())
            return

        # Inspect the first parent record to deduce which fields have already
        # been fetched
        first_record = self.parent_output[0]
        parent_fields = set(first_record.keys())

        # Optimize child queries according to the fields already retrieved thanks
        # to the parent query.
        useless_children = set()
        for i, child in enumerate(self.children[:]):
            # Test whether the current child provides relevant fields (e.g.
            # fields not already fetched in the parent record). If so, reduce
            # the set of queried field in order to only retrieve relevant fields.
            child_fields = child.get_query().get_select()
            relation = self.relations[i]
            relation_name = relation.get_relation_name()
            already_fetched_fields = set()
            if relation_name in parent_fields:
                if relation.get_type() in [
                        Relation.types.LINK_1N,
                        Relation.types.LINK_1N_BACKWARDS
                ]:
                    if relation_name in first_record and first_record[
                            relation_name] and len(
                                first_record[relation_name]) > 0:
                        if isinstance(first_record[relation_name][0], Record):
                            already_fetched_fields = set(
                                first_record[relation_name][0].keys())
                        else:
                            # If we do not have a dict, we have only keys, so it's like we had no field of importance...
                            already_fetched_fields = set()
                    else:
                        already_fetched_fields = set()
                else:
                    if relation_name in first_record and first_record[
                            relation_name] and len(
                                first_record[relation_name]) > 0:
                        already_fetched_fields = set(
                            first_record[relation_name].keys())
                    else:
                        already_fetched_fields = set()

            # XXX routerv2: we need to keep key used for subquery
            key_field = relation.get_predicate().get_value()

            relevant_fields = child_fields - already_fetched_fields

            if not relevant_fields:
                tmp = list()
                for pr in self.parent_output:
                    tmp.extend(pr[relation_name])
                self.child_results[i] = tmp  # Records

                useless_children.add(i)
                continue
            else:
                relevant_fields |= frozenset([key_field])  # necessary ?
                if child_fields != relevant_fields:
                    # XXX This seems to remove the key used for joining
                    self.children[i] = child.optimize_projection(
                        relevant_fields)

        # If every children are useless, this means that we already have full records
        # thanks to the parent query, so we simply forward those records.
        if len(self.children) == len(useless_children):
            map(self.send, self.parent_output)
            self.send(LastRecord())
            return

        # Loop through children and inject the appropriate parent results
        for i, child in enumerate(self.children):
            if i in useless_children: continue

            # We have two cases:
            # (1) either the parent query has subquery fields (a list of child
            #     ids + eventually some additional information)
            # (2) either the child has a backreference to the parent
            #     ... eventually a partial reference in case of a 1..N relationship
            #
            # In all cases, we will collect all identifiers to proceed to a
            # single child query for efficiency purposes, unless it's not
            # possible (?).
            #
            # We have several parent records stored in self.parent_output
            #
            # /!\ Can we have a mix of (1) and (2) ? For now, let's suppose NO.
            #  *  We could expect key information to be stored in the DBGraph

            # The operation to be performed is understood only be looking at the predicate
            relation = self.relations[i]
            predicate = relation.get_predicate()

            key, op, value = predicate.get_tuple()
            if op == eq:
                # 1..N
                # Example: parent has slice_hrn, resource has a reference to slice
                if relation.get_type() == Relation.types.LINK_1N_BACKWARDS:
                    parent_ids = [record[key] for record in self.parent_output]
                    if len(parent_ids) == 1:
                        parent_id, = parent_ids
                        filter_pred = Predicate(value, eq, parent_id)
                    else:
                        filter_pred = Predicate(value, included, parent_ids)
                else:
                    parent_ids = []
                    for parent_record in self.parent_output:
                        record = Record.get_value(parent_record, key)
                        if not record:
                            record = []
                        # XXX Nothing to do for the case where the list of keys in the parent is empty
                        if relation.get_type() in [
                                Relation.types.LINK_1N,
                                Relation.types.LINK_1N_BACKWARDS
                        ]:
                            # we have a list of elements
                            # element = id or dict    : cle simple
                            #         = tuple or dict : cle multiple
                            parent_ids.extend([
                                self.get_element_key(r, value) for r in record
                            ])
                        else:
                            parent_ids.append(
                                self.get_element_key(record, value))

                    #if isinstance(key, tuple):
                    #    parent_ids = [x for record in self.parent_output if key in record for x in record[key]]
                    #else:
                    #    ##### record[key] = text, dict, or list of (text, dict)
                    #    parent_ids = [record[key] for record in self.parent_output if key in record]
                    #
                    #if parent_ids and isinstance(parent_ids[0], dict):
                    #    parent_ids = map(lambda x: x[value], parent_ids)

                    if len(parent_ids) == 1:
                        parent_id, = parent_ids
                        filter_pred = Predicate(value, eq, parent_id)
                    else:
                        filter_pred = Predicate(value, included, parent_ids)

                # Injecting predicate
                old_child_callback = child.get_callback()
                self.children[i] = child.optimize_selection(
                    Filter().filter_by(filter_pred))
                self.children[i].set_callback(old_child_callback)

            elif op == contains:
                # 1..N
                # Example: parent 'slice' has a list of 'user' keys == user_hrn
                for slice in self.parent_output:
                    if not child.get_query().object in slice: continue
                    users = slice[key]
                    # users est soit une liste d'id, soit une liste de records
                    user_data = []
                    for user in users:
                        if isinstance(user, dict):
                            user_data.append(user)
                        else:
                            # have have a key
                            # XXX Take multiple keys into account
                            user_data.append({value: user})
                    # Let's inject user_data in the right child
                    child.inject(user_data, value, None)

            else:
                raise Exception, "No link between parent and child queries"

        #print "*** before run children ***"
        #self.dump()

        # We make another loop since the children might have been modified in
        # the previous one.
        for i, child in enumerate(self.children):
            if i in useless_children: continue
            self.status.started(i)
        for i, child in enumerate(self.children):
            if i in useless_children: continue
            child.start()
예제 #16
0
파일: union.py 프로젝트: onelab-eu/manifold
 def all_done(self):
     for record in self.key_map.values():
         self.send(record)
     self.send(LastRecord())
예제 #17
0
class MyPLCGateway(Gateway):

    __gateway_name__ = "myplc"

    #---------------------------------------------------------------------------
    # Constructor
    #---------------------------------------------------------------------------

    def __init__(self, router, platform, query, config, user_config, user):
        super(MyPLCGateway, self).__init__(router, platform, query, config,
                                           user_config, user)

        # The default xmlrpc.Proxy does not work, we need to use ReactorThread()...
        # XXX Share this code among manifold
        from twisted.web import xmlrpc

        class Proxy(xmlrpc.Proxy):
            ''' See: http://twistedmatrix.com/projects/web/documentation/howto/xmlrpc.html
                this is eacly like the xmlrpc.Proxy included in twisted but you can
                give it a SSLContext object insted of just accepting the defaults..
            '''
            def setSSLClientContext(self, SSLClientContext):
                self.SSLClientContext = SSLClientContext

            def callRemote(self, method, *args):
                def cancel(d):
                    factory.deferred = None
                    connector.disconnect()

                factory = self.queryFactory(self.path, self.host, method,
                                            self.user, self.password,
                                            self.allowNone, args, cancel,
                                            self.useDateTime)
                #factory = xmlrpc._QueryFactory(
                #    self.path, self.host, method, self.user,
                #    self.password, self.allowNone, args)

                if self.secure:
                    try:
                        self.SSLClientContext
                    except NameError:
                        print "Must Set a SSL Context"
                        print "use self.setSSLClientContext() first"
                        # Its very bad to connect to ssl without some kind of
                        # verfication of who your talking to
                        # Using the default sslcontext without verification
                        # Can lead to man in the middle attacks
                    ReactorThread().connectSSL(self.host,
                                               self.port or 443,
                                               factory,
                                               self.SSLClientContext,
                                               timeout=self.connectTimeout)

                else:
                    ReactorThread().connectTCP(self.host,
                                               self.port or 80,
                                               factory,
                                               timeout=self.connectTimeout)
                return factory.deferred

        self._proxy = Proxy(API_URL.encode('latin-1'), allowNone=True)

        # XXX We should provide a default SSL Context...
        from twisted.internet import ssl
        self._proxy.setSSLClientContext(ssl.ClientContextFactory())

#         ReactorThread().start_reactor()
#
#     def terminate(self):
#         ReactorThread().stop_reactor()

#---------------------------------------------------------------------------
# Internal methods
#---------------------------------------------------------------------------

    @returns(StringTypes)
    def __str__(self):
        """
        Returns:
            The '%s' representation of this gateway.
        """
        return "<MyPLCGateway %s>" % (API_URL,
                                      )  #(self._platform_config['url'])

    #---------------------------------------------------------------------------
    # Methods
    #---------------------------------------------------------------------------

    # XXX        nodes = srv.GetNodes(AUTH, {}, ['hostname', 'site_id'])

    def callback_getResult(self, rows):
        self.send(rows)

    def callback_records(self, rows):
        """
        (Internal usage) See ManifoldGateway::receive_impl.
        Args:
            packet: A QUERY Packet.
            rows: The corresponding list of dict or Record instances.
        """
        if rows is not None:
            try:
                iterator = iter(rows)
            except TypeError, te:
                print "rows = ", rows
                rows = [{'initscript_code': rows}]

            if isinstance(rows, basestring):
                rows = [{'initscript_code': rows}]

            for row in rows:
                print row
                self.send(Record(row))

        self.send(LastRecord())
예제 #18
0
 def success_cb(self, table):
     print "Manifold SUCCESS", len(table)
     for record in table:
         self.callback(Record(record))
     self.callback(LastRecord())