예제 #1
0
    def do_register(rt, name, fqdn):
        global n
        global s

        log.info("Registering Ferry Node")

        n = rt.nodes.where({"name": name})
        try:
            n = next(n)
        except StopIteration:
            n = Node()
            n.name = name
            rt.insert(n, commit=True)
            rt.flush()

        s = rt.services.where({"runningOn": n})
        try:
            s = next(s)
        except (StopIteration, AttributeError):
            s = DLNFerry()
            s.runningOn = n
            s.serviceType = "datalogistics:wdln:base"
            s.name = name
            s.accessPoint = "ibp://{}:6714".format(fqdn)
            s.unis_url = "http://{}:{}".format(fqdn, LOCAL_UNIS_PORT)
            s.status = "READY"
            s.ttl = 600  # 10m
            rt.insert(s, commit=True)
            rt.flush()
예제 #2
0
def main():
    parser = argparse.ArgumentParser(description="DLN Base Station Agent")
    parser.add_argument('-H',
                        '--host',
                        type=str,
                        default=UNIS_URL,
                        help='UNIS instance for registration and metadata')
    parser.add_argument('-n',
                        '--name',
                        type=str,
                        default=None,
                        help='Set base node name (ignore system hostname)')
    parser.add_argument('-v',
                        '--verbose',
                        action='store_true',
                        help='Produce verbose output from the script')
    parser.add_argument('-q',
                        '--quiet',
                        action='store_true',
                        help='Quiet mode, no logging output')

    args = parser.parse_args()

    # configure logging level
    level = logging.DEBUG if args.verbose else logging.INFO
    level = logging.CRITICAL if args.quiet else level
    log.setLevel(level)

    name = socket.gethostname()
    fqdn = socket.getfqdn()
    log.info("Base Station \"{}\" reporting for duty".format(name))
    if args.name:
        name = args.name
        log.info("Setting base name to \"{}\"".format(name))

    # use fqdn to determine local endpoints
    LOCAL_DEPOT = {"ibp://{}:6714".format(fqdn): {"enabled": True}}

    # allow an alternative UNIS instance (non-ferry) in local mode
    if (args.host != UNIS_URL):
        LOCAL_UNIS = args.host
    else:
        LOCAL_UNIS = "http://{}:{}".format(fqdn, LOCAL_UNIS_PORT)

    # get our initial UNIS-RT and libdlt sessions
    rt = init_runtime(LOCAL_UNIS)

    # Start the registration loop
    # returns handles to the node and service objects
    register(rt, name, fqdn)

    # start base-ferry sync
    BaseFerrySync(rt, name)

    run_base(rt)
예제 #3
0
    def query(self):
        if not self.sock:
            if self.gps_box:
                min_x, min_y, max_x, max_y = self.gps_box.bounds
                pt = Point([
                    random.uniform(min_x, max_x),
                    random.uniform(min_y, max_y)
                ])
                log.info('Location identified as %f,%f' % (pt.x, pt.y))
                return (pt.x, pt.y)
            return (GPS_DEFAULT[0], GPS_DEFAULT[1])

        lack_lat = True
        lack_long = True
        lack_alt = True

        for new_data in self.sock:
            latitude = 'n/a'
            longitude = 'n/a'
            altitude = 'n/a'

            if new_data:
                self.stream.unpack(new_data)
                self.read_count = self.read_count + 1

                latitude = self.stream.TPV['lat']
                longitude = self.stream.TPV['lon']
                altitude = self.stream.TPV['alt']

            if lack_lat and latitude != 'n/a' and type(latitude) == float:
                latitude = float(latitude)
                lack_lat = False

            if lack_long and longitude != 'n/a' and type(longitude) == float:
                longitude = float(longitude)
                lack_long = False

            if lack_alt and altitude != 'n/a' and type(altitude) == float:
                altitude = float(altitude)
                lack_alt = False

            if not lack_lat and not lack_long:  # optional: and not lack_alt
                log.info('Location identified as %f,%f' %
                         (latitude, longitude))
                return (latitude, longitude)

            if self.read_count > GPS_DEV_READ_LEN:
                break

            # only return default if socket is dead
            # otherwise location will jump if GPS signal is lost
            return (None, None)
        return (None, None)
예제 #4
0
    def on_any_event(self, event):
        if event.is_directory:
            return None

        if event.event_type == 'moved':
            if not os.path.basename(event.src_path).startswith("."):
                return

            fname = os.path.basename(event.src_path)
            dname = os.path.dirname(event.src_path)
            npath = os.path.join(dname, fname[1:])
            dpath = os.path.join(DOWNLOAD_DIR, fname[1:])
            if os.path.getsize(npath) > 0:
                log.info("Handling new file upload: %s" % npath)
                self._do_upload(npath)
                os.rename(npath, dpath)
예제 #5
0
def run_remote(sess, rt):
    i = 0
    while True:
        with slock:
            (i % 5) or log.info("[{}]Waiting for some remote action...".format(
                s.status))
            if s.status == "UPDATE":
                dl_list = s.new_exnodes
                log.info("Caught UPDATE status with {} new exnodes".format(
                    len(dl_list)))
                local_download(sess, dl_list)
                time.sleep(1)
                s.status = "READY"
                rt.flush()
        i += 1
        time.sleep(1)
예제 #6
0
def local_download(sess, exnodes):
    for f in exnodes:
        if not len(f.extents):
            continue
        fpath = os.path.join(DOWNLOAD_DIR, f.name)
        if os.path.exists(fpath) and os.path.getsize(fpath) == f.size:
            log.debug("File exists: {}, skipping!".format(f.name))
            continue
        log.info("Downloading: {} ({} bytes)".format(f.name, f.size))
        try:
            result = sess.download(f.selfRef, fpath)
            res, diff, dsize = result.exnode, result.time, result.t_size
        except Exception as e:
            log.error("Could not download file: {}".format(e))
            continue
        if dsize != res.size:
            log.warn("WARNING: {}: transferred {} of {} bytes \
            (check depot file)".format(res.name, dsize, res.size))
        else:
            log.info("{0} ({1} {2:.2f} MB/s) {3}".format(
                res.name, res.size, res.size / 1e6 / diff, res.selfRef))
예제 #7
0
    def __init__(self):
        self.sock = gps3.GPSDSocket()
        self.stream = gps3.DataStream()

        # GPS3 throws no exceptions and returns no status,
        # so we have to capture stdout and do string matching, sigh
        f = io.StringIO()
        with redirect_stderr(f):
            self.sock.connect()
        if "Connection refused" in f.getvalue():
            log.warn(
                "Could not connect to GPSD socket, continuing with GPS_BOX")
            self.sock = None
        else:
            log.info("Connected to GPSD socket")
            self.sock.watch()

        # we will use the GPS_BOX setting to determine if
        # queries will return locations within a specified range
        if len(GPS_BOX) == 4:
            self.gps_box = box(GPS_BOX[0], GPS_BOX[1], GPS_BOX[2], GPS_BOX[3])
            log.info("Created GPS box")
        else:
            log.warn("Invalid GPS_BOX size, using GPS_DEFAULT")
예제 #8
0
def run_base(rt):
    i = 0
    while True:
        (i % 5) or log.info("Waiting for something to do...")
        i += 1
        time.sleep(1)
예제 #9
0
 def update_ibp_server(self, istr):
     cmdstr = "sudo sed -i 's/^interfaces=.*$/interfaces=" + istr + "/g' " + self.cfg
     subprocess.run(shlex.split(cmdstr))
     cmdstr = "sudo /etc/init.d/ibp-server restart"
     subprocess.run(shlex.split(cmdstr), stdout=subprocess.DEVNULL)
     log.info("Detected interface change, restarted ibp-server")
예제 #10
0
def main():
    global DOWNLOAD_DIR
    global sess

    parser = argparse.ArgumentParser(description="DLN Mobile Ferry Agent")
    parser.add_argument('-H',
                        '--host',
                        type=str,
                        default=UNIS_URL,
                        help='UNIS instance for registration and metadata')
    parser.add_argument('-n',
                        '--name',
                        type=str,
                        default=None,
                        help='Set ferry node name (ignore system hostname)')
    parser.add_argument('-d',
                        '--download',
                        type=str,
                        default=DOWNLOAD_DIR,
                        help='Set local download directory')
    parser.add_argument('-u',
                        '--upload',
                        type=str,
                        default=UPLOAD_DIR,
                        help='Set local upload directory')
    parser.add_argument('-l',
                        '--local',
                        action='store_true',
                        help='Run using only local UNIS instance (on-ferry)')
    parser.add_argument(
        '-i',
        '--ibp',
        action='store_true',
        help='Update IBP config to reflect interface changes on system')
    parser.add_argument('-v',
                        '--verbose',
                        action='store_true',
                        help='Produce verbose output from the script')
    parser.add_argument('-q',
                        '--quiet',
                        action='store_true',
                        help='Quiet mode, no logging output')

    args = parser.parse_args()

    # configure logging level
    level = logging.DEBUG if args.verbose else logging.INFO
    level = logging.CRITICAL if args.quiet else level
    log.setLevel(level)

    name = socket.gethostname()
    fqdn = socket.getfqdn()
    log.info("Ferry \"{}\" reporting for duty".format(name))
    if args.name:
        name = args.name
        log.info("Setting ferry name to \"{}\"".format(name))

    DOWNLOAD_DIR = args.download
    try:
        os.makedirs(DOWNLOAD_DIR)
    except FileExistsError:
        pass
    except OSError as exp:
        raise exp

    # use fqdn to determine local endpoints
    LOCAL_DEPOT = {"ibp://{}:6714".format(fqdn): {"enabled": True}}

    # allow an alternative UNIS instance (non-ferry) in local mode
    if (args.local and args.host != UNIS_URL):
        LOCAL_UNIS = args.host
    else:
        LOCAL_UNIS = "http://{}:{}".format(fqdn, LOCAL_UNIS_PORT)

    # get our initial UNIS-RT and libdlt sessions
    rt = init_runtime(args.host, LOCAL_UNIS, args.local)
    sess = libdlt.Session(rt, bs="5m", depots=LOCAL_DEPOT, threads=1)

    # Start the registration loop
    register(rt, name, fqdn)

    # Start the iface watcher for IBP config
    if args.ibp:
        IBPWatcher()

    # Start the upload dir watcher
    #UploadWatcher(s, LOCAL_UNIS)

    # Start uploader thread
    run_uploader(args.upload)

    # run our main loop
    if args.local:
        run_local(sess, rt)
    else:
        run_remote(sess, rt)
예제 #11
0
def run_local(sess, rt):
    i = 0
    while True:
        (i % 5) or log.info("Waiting for some local action...")
        i += 1
        time.sleep(1)