Beispiel #1
0
    def init():
        dckr = docker.Client()
        cfg = read_config()
        cloud_cfg = cfg['cloud_host']
        cloud_cfg['backup_bucket'] = "juliabox_userbackup"

        LoggerMixin.setup_logger(level=cfg['root_log_level'])
        LoggerMixin.DEFAULT_LEVEL = cfg['jbox_log_level']

        CloudHost.configure(
            has_s3=True,  #cloud_cfg['s3'],
            has_dynamodb=cloud_cfg['dynamodb'],
            has_cloudwatch=cloud_cfg['cloudwatch'],
            has_autoscale=cloud_cfg['autoscale'],
            has_route53=cloud_cfg['route53'],
            has_ebs=cloud_cfg['ebs'],
            has_ses=cloud_cfg['ses'],
            scale_up_at_load=cloud_cfg['scale_up_at_load'],
            scale_up_policy=cloud_cfg['scale_up_policy'],
            autoscale_group=cloud_cfg['autoscale_group'],
            route53_domain=cloud_cfg['route53_domain'],
            region=cloud_cfg['region'],
            install_id=cloud_cfg['install_id'])

        VolMgr.configure(dckr, cfg)
Beispiel #2
0
 def pull_backup(user_email):
     sessname = unique_sessname(user_email)
     S3Disk.log_info("pulling %s.tar.gz from %s", sessname,
                     JBoxVol.BACKUP_BUCKET)
     CloudHost.pull_file_from_s3(JBoxVol.BACKUP_BUCKET,
                                 sessname + ".tar.gz",
                                 metadata_only=False)
Beispiel #3
0
    def auto_activate():
        try:
            num_mails_24h, rate = CloudHost.get_email_rates()
            rate_per_second = min(JBoxd.MAX_ACTIVATIONS_PER_SEC, rate)
            num_mails = min(JBoxd.MAX_AUTO_ACTIVATIONS_PER_RUN, num_mails_24h)

            JBoxd.log_info(
                "Will activate max %d users at %d per second. AWS limits: %d mails at %d per second",
                num_mails, rate_per_second, num_mails_24h, rate)
            user_ids = JBoxUserV2.get_pending_activations(num_mails)
            JBoxd.log_info("Got %d user_ids to be activated", len(user_ids))

            for user_id in user_ids:
                JBoxd.log_info("Activating %s", user_id)

                # send email by SES
                CloudHost.send_email(user_id, JBoxd.ACTIVATION_SENDER,
                                     JBoxd.ACTIVATION_SUBJECT,
                                     JBoxd.ACTIVATION_BODY)

                # set user as activated
                user = JBoxUserV2(user_id)
                user.set_activation_state(JBoxUserV2.ACTIVATION_CODE_AUTO,
                                          JBoxUserV2.ACTIVATION_GRANTED)
                user.save()

                rate_per_second -= 1
                if rate_per_second <= 0:
                    time.sleep(1)
                    rate_per_second = min(JBoxd.MAX_ACTIVATIONS_PER_SEC, rate)
        finally:
            JBoxd.finish_thread()
Beispiel #4
0
    def __init__(self):
        dckr = docker.Client()
        cfg = read_config()
        cloud_cfg = cfg['cloud_host']
        user_activation_cfg = cfg['user_activation']

        LoggerMixin.setup_logger(level=cfg['root_log_level'])
        LoggerMixin.DEFAULT_LEVEL = cfg['jbox_log_level']

        db.configure_db(cfg)

        CloudHost.configure(has_s3=cloud_cfg['s3'],
                            has_dynamodb=cloud_cfg['dynamodb'],
                            has_cloudwatch=cloud_cfg['cloudwatch'],
                            has_autoscale=cloud_cfg['autoscale'],
                            has_route53=cloud_cfg['route53'],
                            has_ebs=cloud_cfg['ebs'],
                            has_ses=cloud_cfg['ses'],
                            scale_up_at_load=cloud_cfg['scale_up_at_load'],
                            scale_up_policy=cloud_cfg['scale_up_policy'],
                            autoscale_group=cloud_cfg['autoscale_group'],
                            route53_domain=cloud_cfg['route53_domain'],
                            region=cloud_cfg['region'],
                            install_id=cloud_cfg['install_id'])
        VolMgr.configure(dckr, cfg)
        JBoxContainer.configure(dckr, cfg['docker_image'], cfg['mem_limit'], cfg['cpu_limit'],
                                cfg['numlocalmax'], cfg['async_job_port'], async_mode=JBoxAsyncJob.MODE_SUB)
        self.log_debug("Backup daemon listening on port: " + str(cfg['async_job_port']))
        self.queue = JBoxContainer.ASYNC_JOB

        JBoxd.MAX_ACTIVATIONS_PER_SEC = user_activation_cfg['max_activations_per_sec']
        JBoxd.MAX_AUTO_ACTIVATIONS_PER_RUN = user_activation_cfg['max_activations_per_run']
        JBoxd.ACTIVATION_SUBJECT = user_activation_cfg['mail_subject']
        JBoxd.ACTIVATION_BODY = user_activation_cfg['mail_body']
        JBoxd.ACTIVATION_SENDER = user_activation_cfg['sender']
Beispiel #5
0
    def handle_if_instance_info(self, is_allowed):
        stats = self.get_argument('instance_info', None)
        if stats is None:
            return False

        if not is_allowed:
            AdminHandler.log_error("Show instance info not allowed for user")
            response = {'code': -1, 'data': 'You do not have permissions to view these stats'}
        else:
            try:
                if stats == 'load':
                    stats = {}
                    # get cluster loads
                    average_load = CloudHost.get_cluster_average_stats('Load')
                    if None != average_load:
                        stats['Average Load'] = average_load;

                    machine_loads = CloudHost.get_cluster_stats('Load')
                    if None != machine_loads:
                        for n, v in machine_loads.iteritems():
                            stats['Instance ' + n] = v

                response = {'code': 0, 'data': stats} if stats is not None else {'code': 1, 'data': {}}
            except:
                AdminHandler.log_error("exception while getting stats")
                response = {'code': -1, 'data': 'error getting stats'}

        self.write(response)
        return True
Beispiel #6
0
    def auto_activate():
        try:
            num_mails_24h, rate = CloudHost.get_email_rates()
            rate_per_second = min(JBoxd.MAX_ACTIVATIONS_PER_SEC, rate)
            num_mails = min(JBoxd.MAX_AUTO_ACTIVATIONS_PER_RUN, num_mails_24h)

            JBoxd.log_info("Will activate max %d users at %d per second. AWS limits: %d mails at %d per second",
                           num_mails, rate_per_second,
                           num_mails_24h, rate)
            user_ids = JBoxUserV2.get_pending_activations(num_mails)
            JBoxd.log_info("Got %d user_ids to be activated", len(user_ids))

            for user_id in user_ids:
                JBoxd.log_info("Activating %s", user_id)

                # send email by SES
                CloudHost.send_email(user_id, JBoxd.ACTIVATION_SENDER, JBoxd.ACTIVATION_SUBJECT, JBoxd.ACTIVATION_BODY)

                # set user as activated
                user = JBoxUserV2(user_id)
                user.set_activation_state(JBoxUserV2.ACTIVATION_CODE_AUTO, JBoxUserV2.ACTIVATION_GRANTED)
                user.save()

                rate_per_second -= 1
                if rate_per_second <= 0:
                    time.sleep(1)
                    rate_per_second = min(JBoxd.MAX_ACTIVATIONS_PER_SEC, rate)
        finally:
            JBoxd.finish_thread()
Beispiel #7
0
 def release(self, backup=False):
     if not JBoxEBSVol.HAS_EBS:
         raise Exception("EBS disks not enabled")
     disk_id = self.disk_path.split('/')[-1]
     CloudHost.unmount_device(disk_id, JBoxEBSVol.FS_LOC)
     if backup:
         self._backup()
     vol_id = CloudHost.get_volume_id_from_device(disk_id)
     CloudHost.detach_volume(vol_id, delete=True)
Beispiel #8
0
 def release(self, backup=False):
     if not JBoxEBSVol.HAS_EBS:
         raise Exception("EBS disks not enabled")
     disk_id = self.disk_path.split('/')[-1]
     CloudHost.unmount_device(disk_id, JBoxEBSVol.FS_LOC)
     if backup:
         self._backup()
     vol_id = CloudHost.get_volume_id_from_device(disk_id)
     CloudHost.detach_volume(vol_id, delete=True)
Beispiel #9
0
 def test():
     CloudHost.send_email('*****@*****.**', '*****@*****.**', "test SES",
                          """hello world
                          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
                          ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation
                          ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
                          reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
                          Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
                          anim id est laborum.""")
Beispiel #10
0
 def _backup(self, clear_volume=False):
     sess_props = JBoxSessionProps(self.sessname)
     desc = sess_props.get_user_id() + " JuliaBox Backup"
     disk_id = self.disk_path.split('/')[-1]
     snap_id = CloudHost.snapshot_volume(dev_id=disk_id, tag=self.sessname, description=desc)
     old_snap_id = sess_props.get_snapshot_id()
     sess_props.set_snapshot_id(snap_id)
     sess_props.save()
     if old_snap_id is not None:
         CloudHost.delete_snapshot(old_snap_id)
Beispiel #11
0
 def test():
     CloudHost.send_email(
         '*****@*****.**', '*****@*****.**', "test SES",
         """hello world
                          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
                          ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation
                          ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
                          reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
                          Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
                          anim id est laborum.""")
Beispiel #12
0
 def _backup(self, clear_volume=False):
     sess_props = JBoxSessionProps(self.sessname)
     desc = sess_props.get_user_id() + " JuliaBox Backup"
     disk_id = self.disk_path.split('/')[-1]
     snap_id = CloudHost.snapshot_volume(dev_id=disk_id,
                                         tag=self.sessname,
                                         description=desc)
     old_snap_id = sess_props.get_snapshot_id()
     sess_props.set_snapshot_id(snap_id)
     sess_props.save()
     if old_snap_id is not None:
         CloudHost.delete_snapshot(old_snap_id)
Beispiel #13
0
    def __init__(self):
        dckr = docker.Client()
        cfg = JBox.cfg = read_config()
        cloud_cfg = cfg['cloud_host']

        LoggerMixin.setup_logger(level=cfg['root_log_level'])
        LoggerMixin.DEFAULT_LEVEL = cfg['jbox_log_level']

        JBoxHandler.configure(cfg)
        db.configure_db(cfg)

        CloudHost.configure(has_s3=cloud_cfg['s3'],
                            has_dynamodb=cloud_cfg['dynamodb'],
                            has_cloudwatch=cloud_cfg['cloudwatch'],
                            has_autoscale=cloud_cfg['autoscale'],
                            has_route53=cloud_cfg['route53'],
                            has_ebs=cloud_cfg['ebs'],
                            has_ses=cloud_cfg['ses'],
                            scale_up_at_load=cloud_cfg['scale_up_at_load'],
                            scale_up_policy=cloud_cfg['scale_up_policy'],
                            autoscale_group=cloud_cfg['autoscale_group'],
                            route53_domain=cloud_cfg['route53_domain'],
                            region=cloud_cfg['region'],
                            install_id=cloud_cfg['install_id'])

        VolMgr.configure(dckr, cfg)
        JBoxAsyncJob.configure(cfg)
        JBoxContainer.configure(dckr, cfg['docker_image'], cfg['mem_limit'],
                                cfg['cpu_limit'], cfg['numlocalmax'],
                                cfg['async_job_ports'])

        self.application = tornado.web.Application([
            (r"/", MainHandler), (r"/hostlaunchipnb/", AuthHandler),
            (r"/hostadmin/", AdminHandler), (r"/ping/", PingHandler),
            (r"/cors/", CorsHandler)
        ])
        cookie_secret = ''.join(
            random.choice(string.ascii_uppercase + string.digits)
            for x in xrange(32))
        self.application.settings["cookie_secret"] = cookie_secret
        self.application.settings["google_oauth"] = cfg["google_oauth"]
        self.application.listen(cfg["port"])

        self.ioloop = tornado.ioloop.IOLoop.instance()

        # run container maintainence every 5 minutes
        run_interval = 5 * 60 * 1000
        self.log_info("Container maintenance every " +
                      str(run_interval / (60 * 1000)) + " minutes")
        self.ct = tornado.ioloop.PeriodicCallback(JBox.do_housekeeping,
                                                  run_interval, self.ioloop)
Beispiel #14
0
    def __init__(self):
        dckr = docker.Client()
        cfg = JBox.cfg = read_config()
        cloud_cfg = cfg['cloud_host']

        LoggerMixin.setup_logger(level=cfg['root_log_level'])
        LoggerMixin.DEFAULT_LEVEL = cfg['jbox_log_level']

        JBoxHandler.configure(cfg)
        db.configure_db(cfg)

        CloudHost.configure(has_s3=cloud_cfg['s3'],
                            has_dynamodb=cloud_cfg['dynamodb'],
                            has_cloudwatch=cloud_cfg['cloudwatch'],
                            has_autoscale=cloud_cfg['autoscale'],
                            has_route53=cloud_cfg['route53'],
                            has_ebs=cloud_cfg['ebs'],
                            has_ses=cloud_cfg['ses'],
                            scale_up_at_load=cloud_cfg['scale_up_at_load'],
                            scale_up_policy=cloud_cfg['scale_up_policy'],
                            autoscale_group=cloud_cfg['autoscale_group'],
                            route53_domain=cloud_cfg['route53_domain'],
                            region=cloud_cfg['region'],
                            install_id=cloud_cfg['install_id'])

        VolMgr.configure(dckr, cfg)
        JBoxAsyncJob.configure(cfg)
        JBoxContainer.configure(dckr, cfg['docker_image'], cfg['mem_limit'], cfg['cpu_limit'],
                                cfg['numlocalmax'], cfg['async_job_ports'])

        self.application = tornado.web.Application([
            (r"/", MainHandler),
            (r"/hostlaunchipnb/", AuthHandler),
            (r"/hostadmin/", AdminHandler),
            (r"/ping/", PingHandler),
            (r"/cors/", CorsHandler),
            (r"/hw/", HomeworkHandler)
        ])
        cookie_secret = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in xrange(32))
        self.application.settings["cookie_secret"] = cookie_secret
        self.application.settings["google_oauth"] = cfg["google_oauth"]
        self.application.listen(cfg["port"])

        self.ioloop = tornado.ioloop.IOLoop.instance()

        # run container maintainence every 5 minutes
        run_interval = 5 * 60 * 1000
        self.log_info("Container maintenance every " + str(run_interval / (60 * 1000)) + " minutes")
        self.ct = tornado.ioloop.PeriodicCallback(JBox.do_housekeeping, run_interval, self.ioloop)
Beispiel #15
0
    def __init__(self, ports, mode):
        self._mode = mode
        self._ctx = zmq.Context()

        ppmode = zmq.PUSH if (mode == JBoxAsyncJob.MODE_PUB) else zmq.PULL
        self._push_pull_sock = self._ctx.socket(ppmode)

        rrmode = zmq.REQ if (mode == JBoxAsyncJob.MODE_PUB) else zmq.REP

        local_ip = CloudHost.instance_local_ip()
        JBoxAsyncJob.log_debug("local hostname [%s]", local_ip)

        ppbindaddr = 'tcp://%s:%d' % (local_ip, ports[0],)
        ppconnaddr = 'tcp://%s:%d' % (local_ip, ports[0],)
        rraddr = 'tcp://%s:%d' % (local_ip, ports[1],)
        self._rrport = ports[1]
        self._poller = zmq.Poller()

        if mode == JBoxAsyncJob.MODE_PUB:
            self._push_pull_sock.bind(ppbindaddr)
        else:
            self._push_pull_sock.connect(ppconnaddr)
            self._poller.register(self._push_pull_sock, zmq.POLLIN)
            self._req_rep_sock = self._ctx.socket(rrmode)
            self._req_rep_sock.bind(rraddr)
Beispiel #16
0
    def push_backup(user_email, disk_path):
        sessname = unique_sessname(user_email)
        S3Disk.log_info("pushing %s.tar.gz from %s to %s", sessname, disk_path,
                        JBoxVol.BACKUP_BUCKET)

        bkup_file = os.path.join('/tmp', sessname + ".tar.gz")
        bkup_tar = tarfile.open(bkup_file, 'w:gz')

        def set_perms(tinfo):
            tinfo.uid = 1000
            tinfo.gid = 1000
            tinfo.uname = 'ubuntu'
            tinfo.gname = 'ubuntu'
            return tinfo

        for f in os.listdir(disk_path):
            if f.startswith('.') and (f in ['.julia', '.juliabox']):
                continue
            full_path = os.path.join(disk_path, f)
            bkup_tar.add(full_path, os.path.join('juser', f), filter=set_perms)
        bkup_tar.close()
        os.chmod(bkup_file, 0666)

        # Upload to S3 if so configured. Delete from local if successful.
        bkup_file_mtime = datetime.datetime.fromtimestamp(os.path.getmtime(bkup_file), pytz.utc) + \
            datetime.timedelta(seconds=JBoxVol.LOCAL_TZ_OFFSET)
        if JBoxVol.BACKUP_BUCKET is not None:
            if CloudHost.push_file_to_s3(
                    JBoxVol.BACKUP_BUCKET,
                    bkup_file,
                    metadata={'backup_time':
                              bkup_file_mtime.isoformat()}) is not None:
                os.remove(bkup_file)
                S3Disk.log_info("Moved backup to S3 " + sessname)
Beispiel #17
0
    def sendrecv(self, cmd, data, dest=None, port=None):
        if (dest is None) or (dest == 'localhost'):
            dest = '127.0.0.1'
        else:
            dest = CloudHost.instance_local_ip(dest)
        if port is None:
            port = self._rrport
        rraddr = 'tcp://%s:%d' % (dest, port)

        JBoxAsyncJob.log_debug("sendrecv to %s. connecting...", rraddr)
        sock = self._ctx.socket(zmq.REQ)
        sock.setsockopt(zmq.LINGER, 5 * 1000)
        sock.connect(rraddr)

        poller = zmq.Poller()
        poller.register(sock, zmq.POLLOUT)

        if poller.poll(10 * 1000):
            sock.send_json(self._make_msg(cmd, data))
        else:
            sock.close()
            raise IOError("could not connect to %s", rraddr)

        poller.modify(sock, zmq.POLLIN)
        if poller.poll(10 * 1000):
            msg = sock.recv_json()
        else:
            sock.close()
            raise IOError("did not receive anything from %s", rraddr)

        JBoxAsyncJob.log_debug("sendrecv to %s. received.", rraddr)
        sock.close()
        return msg
Beispiel #18
0
    def sendrecv(self, cmd, data, dest=None, port=None):
        if (dest is None) or (dest == 'localhost'):
            dest = '127.0.0.1'
        else:
            dest = CloudHost.instance_local_ip(dest)
        if port is None:
            port = self._rrport
        rraddr = 'tcp://%s:%d' % (dest, port)

        JBoxAsyncJob.log_debug("sendrecv to %s. connecting...", rraddr)
        sock = self._ctx.socket(zmq.REQ)
        sock.setsockopt(zmq.LINGER, 5*1000)
        sock.connect(rraddr)

        poller = zmq.Poller()
        poller.register(sock, zmq.POLLOUT)

        if poller.poll(10*1000):
            sock.send_json(self._make_msg(cmd, data))
        else:
            sock.close()
            raise IOError("could not connect to %s", rraddr)

        poller.modify(sock, zmq.POLLIN)
        if poller.poll(10*1000):
            msg = sock.recv_json()
        else:
            sock.close()
            raise IOError("did not receive anything from %s", rraddr)

        JBoxAsyncJob.log_debug("sendrecv to %s. received.", rraddr)
        sock.close()
        return msg
Beispiel #19
0
    def _backup(self, clear_volume=False):
        JBoxVol.log_info("Backing up " + self.sessname + " at " + str(JBoxVol.BACKUP_LOC))

        bkup_file = os.path.join(JBoxVol.BACKUP_LOC, self.sessname + ".tar.gz")
        bkup_tar = tarfile.open(bkup_file, 'w:gz')

        for f in os.listdir(self.disk_path):
            if f.startswith('.') and (f in ['.julia', '.ipython']):
                continue
            full_path = os.path.join(self.disk_path, f)
            bkup_tar.add(full_path, os.path.join('juser', f))
        bkup_tar.close()
        os.chmod(bkup_file, 0666)

        if clear_volume:
            ensure_delete(self.disk_path)

        # Upload to S3 if so configured. Delete from local if successful.
        bkup_file_mtime = datetime.datetime.fromtimestamp(os.path.getmtime(bkup_file), pytz.utc) + \
            datetime.timedelta(seconds=JBoxVol.LOCAL_TZ_OFFSET)
        if JBoxVol.BACKUP_BUCKET is not None:
            if CloudHost.push_file_to_s3(JBoxVol.BACKUP_BUCKET, bkup_file,
                                           metadata={'backup_time': bkup_file_mtime.isoformat()}) is not None:
                os.remove(bkup_file)
                JBoxVol.log_info("Moved backup to S3 " + self.sessname)
Beispiel #20
0
    def calc_stat(user_email):
        VolMgr.STATS['num_users'] += 1
        sessname = unique_sessname(user_email)

        k = CloudHost.pull_file_from_s3(JBoxVol.BACKUP_BUCKET, sessname + ".tar.gz", metadata_only=True)
        if k is not None:
            VolMgr.STATS['loopback']['sizes'].append(k.size)
Beispiel #21
0
    def push_backup(user_email, disk_path):
        sessname = unique_sessname(user_email)
        S3Disk.log_info("pushing %s.tar.gz from %s to %s", sessname, disk_path, JBoxVol.BACKUP_BUCKET)

        bkup_file = os.path.join('/tmp', sessname + ".tar.gz")
        bkup_tar = tarfile.open(bkup_file, 'w:gz')

        def set_perms(tinfo):
            tinfo.uid = 1000
            tinfo.gid = 1000
            tinfo.uname = 'ubuntu'
            tinfo.gname = 'ubuntu'
            return tinfo

        for f in os.listdir(disk_path):
            if f.startswith('.') and (f in ['.julia', '.juliabox']):
                continue
            full_path = os.path.join(disk_path, f)
            bkup_tar.add(full_path, os.path.join('juser', f), filter=set_perms)
        bkup_tar.close()
        os.chmod(bkup_file, 0666)

        # Upload to S3 if so configured. Delete from local if successful.
        bkup_file_mtime = datetime.datetime.fromtimestamp(os.path.getmtime(bkup_file), pytz.utc) + \
            datetime.timedelta(seconds=JBoxVol.LOCAL_TZ_OFFSET)
        if JBoxVol.BACKUP_BUCKET is not None:
            if CloudHost.push_file_to_s3(JBoxVol.BACKUP_BUCKET, bkup_file,
                                         metadata={'backup_time': bkup_file_mtime.isoformat()}) is not None:
                os.remove(bkup_file)
                S3Disk.log_info("Moved backup to S3 " + sessname)
Beispiel #22
0
    def __init__(self, ports, mode):
        self._mode = mode
        self._ctx = zmq.Context()

        ppmode = zmq.PUSH if (mode == JBoxAsyncJob.MODE_PUB) else zmq.PULL
        self._push_pull_sock = self._ctx.socket(ppmode)

        rrmode = zmq.REQ if (mode == JBoxAsyncJob.MODE_PUB) else zmq.REP

        local_ip = CloudHost.instance_local_ip()
        JBoxAsyncJob.log_debug("local hostname [%s]", local_ip)

        ppbindaddr = 'tcp://%s:%d' % (
            local_ip,
            ports[0],
        )
        ppconnaddr = 'tcp://%s:%d' % (
            local_ip,
            ports[0],
        )
        rraddr = 'tcp://%s:%d' % (
            local_ip,
            ports[1],
        )
        self._rrport = ports[1]
        self._poller = zmq.Poller()

        if mode == JBoxAsyncJob.MODE_PUB:
            self._push_pull_sock.bind(ppbindaddr)
        else:
            self._push_pull_sock.connect(ppconnaddr)
            self._poller.register(self._push_pull_sock, zmq.POLLIN)
            self._req_rep_sock = self._ctx.socket(rrmode)
            self._req_rep_sock.bind(rraddr)
Beispiel #23
0
    def _backup(self, clear_volume=False):
        JBoxVol.log_info("Backing up " + self.sessname + " at " +
                         str(JBoxVol.BACKUP_LOC))

        bkup_file = os.path.join(JBoxVol.BACKUP_LOC, self.sessname + ".tar.gz")
        bkup_tar = tarfile.open(bkup_file, 'w:gz')

        for f in os.listdir(self.disk_path):
            if f.startswith('.') and (f in ['.julia', '.juliabox']):
                continue
            full_path = os.path.join(self.disk_path, f)
            bkup_tar.add(full_path, os.path.join('juser', f))
        bkup_tar.close()
        os.chmod(bkup_file, 0666)

        if clear_volume:
            ensure_delete(self.disk_path)

        # Upload to S3 if so configured. Delete from local if successful.
        bkup_file_mtime = datetime.datetime.fromtimestamp(os.path.getmtime(bkup_file), pytz.utc) + \
            datetime.timedelta(seconds=JBoxVol.LOCAL_TZ_OFFSET)
        if JBoxVol.BACKUP_BUCKET is not None:
            if CloudHost.push_file_to_s3(
                    JBoxVol.BACKUP_BUCKET,
                    bkup_file,
                    metadata={'backup_time':
                              bkup_file_mtime.isoformat()}) is not None:
                os.remove(bkup_file)
                JBoxVol.log_info("Moved backup to S3 " + self.sessname)
Beispiel #24
0
def is_proposed_cluster_leader():
    if not CloudHost.ENABLED['cloudwatch']:
        return False

    cluster = CloudHost.INSTALL_ID
    leader = JBoxDynConfig.get_cluster_leader(cluster)
    return leader == CloudHost.instance_id()
Beispiel #25
0
    def get(self):
        args = self.get_argument('m', default=None)

        if args is not None:
            args = json.loads(
                decrypt(base64.b64decode(args), self.config(key='sesskey')))

        if args is not None:
            self.log_debug("setting cookies")
            for cname in [
                    'sessname', 'hostshell', 'hostupload', 'hostipnb', 'sign',
                    'juliabox'
            ]:
                self.set_cookie(cname, args[cname])
            self.set_status(status_code=204)
            self.finish()
        else:
            args = dict()
            for cname in [
                    'sessname', 'hostshell', 'hostupload', 'hostipnb', 'sign',
                    'juliabox'
            ]:
                args[cname] = self.get_cookie(cname)
            args = tornado.escape.url_escape(
                base64.b64encode(
                    encrypt(json.dumps(args), self.config(key='sesskey'))))
            url = "//" + CloudHost.notebook_websocket_hostname(
            ) + "/cors/?m=" + args
            self.log_debug("redirecting to " + url)
            self.redirect(url)
Beispiel #26
0
    def get_disk_for_user(user_email):
        JBoxEBSVol.log_debug("creating EBS volume for %s", user_email)
        if not JBoxEBSVol.HAS_EBS:
            raise Exception("EBS disks not enabled")

        disk_id = JBoxEBSVol._reserve_disk_id()
        if disk_id is None:
            raise Exception("No free disk available")

        sess_id = unique_sessname(user_email)
        sess_props = JBoxSessionProps(sess_id, create=True, user_id=user_email)
        if sess_props.is_new:
            sess_props.save()
        snap_id = sess_props.get_snapshot_id()
        if snap_id is None:
            snap_id = JBoxEBSVol.DISK_TEMPLATE_SNAPSHOT

        JBoxEBSVol.log_debug("will use snapshot id %s for %s", snap_id, user_email)

        _dev_path, mnt_path = CloudHost.create_new_volume(snap_id, disk_id, JBoxEBSVol.FS_LOC, tag=user_email)
        ebsvol = JBoxEBSVol(mnt_path, user_email=user_email)

        if snap_id == JBoxEBSVol.DISK_TEMPLATE_SNAPSHOT:
            JBoxEBSVol.log_debug("creating home folder on blank volume for %s", user_email)
            ebsvol.restore_user_home()
            ebsvol.restore()
        #else:
        #    snap_age_days = CloudHost.get_snapshot_age(snap_id).total_seconds()/(60*60*24)
        #    if snap_age_days > 7:
        #        ebsvol.restore_user_home()
        JBoxEBSVol.log_debug("setting up instance configuration on disk for %s", user_email)
        ebsvol.setup_instance_config()

        return ebsvol
Beispiel #27
0
def is_proposed_cluster_leader():
    if not CloudHost.ENABLED['cloudwatch']:
        return False

    cluster = CloudHost.INSTALL_ID
    leader = JBoxDynConfig.get_cluster_leader(cluster)
    return leader == CloudHost.instance_id()
Beispiel #28
0
    def is_ready_to_terminate():
        if not JBox.cfg['cloud_host']['scale_down']:
            return False

        num_containers = JBoxContainer.num_active(
        ) + JBoxContainer.num_stopped()
        return (num_containers == 0) and CloudHost.can_terminate(
            is_proposed_cluster_leader())
Beispiel #29
0
    def calc_stat(user_email):
        VolMgr.STATS['num_users'] += 1
        sessname = unique_sessname(user_email)

        k = CloudHost.pull_file_from_s3(JBoxVol.BACKUP_BUCKET,
                                        sessname + ".tar.gz",
                                        metadata_only=True)
        if k is not None:
            VolMgr.STATS['loopback']['sizes'].append(k.size)
Beispiel #30
0
    def __init__(self):
        dckr = docker.Client()
        cfg = read_config()
        cloud_cfg = cfg['cloud_host']
        user_activation_cfg = cfg['user_activation']

        LoggerMixin.setup_logger(level=cfg['root_log_level'])
        LoggerMixin.DEFAULT_LEVEL = cfg['jbox_log_level']

        db.configure_db(cfg)

        CloudHost.configure(has_s3=cloud_cfg['s3'],
                            has_dynamodb=cloud_cfg['dynamodb'],
                            has_cloudwatch=cloud_cfg['cloudwatch'],
                            has_autoscale=cloud_cfg['autoscale'],
                            has_route53=cloud_cfg['route53'],
                            has_ebs=cloud_cfg['ebs'],
                            has_ses=cloud_cfg['ses'],
                            scale_up_at_load=cloud_cfg['scale_up_at_load'],
                            scale_up_policy=cloud_cfg['scale_up_policy'],
                            autoscale_group=cloud_cfg['autoscale_group'],
                            route53_domain=cloud_cfg['route53_domain'],
                            region=cloud_cfg['region'],
                            install_id=cloud_cfg['install_id'])
        VolMgr.configure(dckr, cfg)
        JBoxAsyncJob.configure(cfg)
        JBoxContainer.configure(dckr,
                                cfg['docker_image'],
                                cfg['mem_limit'],
                                cfg['cpu_limit'],
                                cfg['numlocalmax'],
                                cfg['async_job_ports'],
                                async_mode=JBoxAsyncJob.MODE_SUB)
        self.log_debug("Backup daemon listening on ports: %s",
                       repr(cfg['async_job_ports']))
        JBoxd.QUEUE = JBoxContainer.ASYNC_JOB

        JBoxd.MAX_ACTIVATIONS_PER_SEC = user_activation_cfg[
            'max_activations_per_sec']
        JBoxd.MAX_AUTO_ACTIVATIONS_PER_RUN = user_activation_cfg[
            'max_activations_per_run']
        JBoxd.ACTIVATION_SUBJECT = user_activation_cfg['mail_subject']
        JBoxd.ACTIVATION_BODY = user_activation_cfg['mail_body']
        JBoxd.ACTIVATION_SENDER = user_activation_cfg['sender']
Beispiel #31
0
 def setup_instance_config(self, profiles=('julia', 'jboxjulia')):
     for profile in profiles:
         profile_path = '.ipython/profile_' + profile
         profile_path = os.path.join(self.disk_path, profile_path)
         if not os.path.exists(profile_path):
             continue
         nbconfig = os.path.join(profile_path, 'ipython_notebook_config.py')
         wsock_cfg = "c.NotebookApp.websocket_url = '" + JBoxVol.NOTEBOOK_WEBSOCK_PROTO + \
                     CloudHost.notebook_websocket_hostname() + "'\n"
         JBoxVol.replace_in_file(nbconfig, "c.NotebookApp.websocket_url", wsock_cfg)
Beispiel #32
0
 def setup_instance_config(self, profiles=('julia', 'jboxjulia')):
     for profile in profiles:
         profile_path = '.ipython/profile_' + profile
         profile_path = os.path.join(self.disk_path, profile_path)
         if not os.path.exists(profile_path):
             continue
         nbconfig = os.path.join(profile_path, 'ipython_notebook_config.py')
         wsock_cfg = "c.NotebookApp.websocket_url = '" + JBoxVol.NOTEBOOK_WEBSOCK_PROTO + \
                     CloudHost.notebook_websocket_hostname() + "'\n"
         JBoxVol.replace_in_file(nbconfig, "c.NotebookApp.websocket_url", wsock_cfg)
Beispiel #33
0
    def handle_if_instance_info(self, is_allowed):
        stats = self.get_argument('instance_info', None)
        if stats is None:
            return False

        if not is_allowed:
            AdminHandler.log_error("Show instance info not allowed for user")
            response = {'code': -1, 'data': 'You do not have permissions to view these stats'}
        else:
            try:
                if stats == 'load':
                    result = {}
                    # get cluster loads
                    average_load = CloudHost.get_cluster_average_stats('Load')
                    if None != average_load:
                        result['Average Load'] = average_load;

                    machine_loads = CloudHost.get_cluster_stats('Load')
                    if None != machine_loads:
                        for n, v in machine_loads.iteritems():
                            result['Instance ' + n] = v
                elif stats == 'sessions':
                    result = {}
                    if CloudHost.ENABLED['autoscale']:
                        instances = CloudHost.get_autoscaled_instances()
                    else:
                        instances = ['localhost']

                    for idx in range(0, len(instances)):
                        inst = instances[idx]
                        result[inst] = JBoxContainer.sync_session_status(inst)['data']
                else:
                    raise Exception("unknown command %s" % (stats,))

                response = {'code': 0, 'data': result}
            except:
                AdminHandler.log_error("exception while getting stats")
                AdminHandler._get_logger().exception("exception while getting stats")
                response = {'code': -1, 'data': 'error getting stats'}

        self.write(response)
        return True
Beispiel #34
0
 def run(self):
     if CloudHost.ENABLED['route53']:
         try:
             CloudHost.deregister_instance_dns()
             CloudHost.log_warn("Prior dns registration was found for the instance")
         except:
             CloudHost.log_debug("No prior dns registration found for the instance")
         CloudHost.register_instance_dns()
     JBoxContainer.publish_container_stats()
     JBox.do_update_user_home_image()
     JBoxContainer.async_refresh_disks()
     self.ct.start()
     self.ioloop.start()
Beispiel #35
0
    def release(self, backup=False):
        if not JBoxEBSVol.HAS_EBS:
            raise Exception("EBS disks not enabled")
        disk_id = self.disk_path.split('/')[-1]
        CloudHost.unmount_device(disk_id, JBoxEBSVol.FS_LOC)
        if backup:
            snap_id = self._backup()
        else:
            snap_id = None
        vol_id = CloudHost.get_volume_id_from_device(disk_id)
        CloudHost.detach_volume(vol_id, delete=False)

        sess_props = JBoxSessionProps(self.sessname)
        existing_disk = JBoxDiskState(cluster_id=CloudHost.INSTALL_ID, region_id=CloudHost.REGION,
                                      user_id=sess_props.get_user_id())
        if snap_id is not None:
            existing_disk.add_snapshot_id(snap_id)
        existing_disk.set_detach_time()
        existing_disk.set_state(JBoxDiskState.STATE_DETACHED)
        existing_disk.save()
Beispiel #36
0
    def try_launch_container(cls, user_id, max_hop=False):
        sessname = unique_sessname(user_id)
        cont = JBoxContainer.get_by_name(sessname)
        cls.log_debug("have existing container for %s: %r", sessname, None != cont)
        if cont is not None:
            cls.log_debug("container running: %r", cont.is_running())

        if max_hop:
            self_load = CloudHost.get_instance_stats(CloudHost.instance_id(), 'Load')
            if self_load < 100:
                JBoxContainer.async_launch_by_name(sessname, user_id, True)
                return True

        is_leader = is_proposed_cluster_leader()
        if ((cont is None) or (not cont.is_running())) and (not CloudHost.should_accept_session(is_leader)):
            if cont is not None:
                cont.async_backup_and_cleanup()
            return False

        JBoxContainer.async_launch_by_name(sessname, user_id, True)
        return True
Beispiel #37
0
def is_cluster_leader():
    if not CloudHost.ENABLED['cloudwatch']:
        return False

    cluster = CloudHost.INSTALL_ID
    instances = CloudHost.get_autoscaled_instances()
    leader = JBoxDynConfig.get_cluster_leader(cluster)
    ami_recentness = CloudHost.get_ami_recentness()
    JBoxDB.log_debug("cluster: %s. instances: %s. leader: %s. ami_recentness: %d",
                     cluster, repr(instances), repr(leader), ami_recentness)

    # if none set, or set instance is dead elect self as leader, but wait till next cycle to prevent conflicts
    if (leader is None) or (leader not in instances) and (ami_recentness >= 0):
        JBoxDB.log_info("setting self (%s) as cluster leader", CloudHost.instance_id())
        JBoxDynConfig.set_cluster_leader(cluster, CloudHost.instance_id())
        return False

    is_leader = (leader == CloudHost.instance_id())

    # if running an older ami, step down from cluster leader
    if (ami_recentness < 0) and is_leader:
        JBoxDB.log_info("unmarking self (%s) as cluster leader", CloudHost.instance_id())
        JBoxDynConfig.unset_cluster_leader(cluster)
        return False

    return is_leader
Beispiel #38
0
    def monitor_registrations():
        max_rate = JBoxDynConfig.get_registration_hourly_rate(
            CloudHost.INSTALL_ID)
        rate = JBoxUserV2.count_created(1)
        reg_allowed = JBoxDynConfig.get_allow_registration(
            CloudHost.INSTALL_ID)
        CloudHost.log_debug(
            "registration allowed: %r, rate: %d, max allowed: %d", reg_allowed,
            rate, max_rate)

        if (reg_allowed and
            (rate > max_rate * 1.1)) or ((not reg_allowed) and
                                         (rate < max_rate * 0.9)):
            reg_allowed = not reg_allowed
            CloudHost.log_info("Changing registration allowed to %r",
                               reg_allowed)
            JBoxDynConfig.set_allow_registration(CloudHost.INSTALL_ID,
                                                 reg_allowed)

        if reg_allowed:
            num_pending_activations = JBoxUserV2.count_pending_activations()
            if num_pending_activations > 0:
                CloudHost.log_info(
                    "scheduling activations for %d pending activations",
                    num_pending_activations)
                JBoxContainer.async_schedule_activations()
Beispiel #39
0
 def run(self):
     try:
         CloudHost.deregister_instance_dns()
         CloudHost.log_warn(
             "Prior dns registration was found for the instance")
     except:
         CloudHost.log_debug(
             "No prior dns registration found for the instance")
     CloudHost.register_instance_dns()
     JBoxContainer.publish_container_stats()
     JBox.do_update_user_home_image()
     JBoxContainer.async_refresh_disks()
     self.ct.start()
     self.ioloop.start()
Beispiel #40
0
def is_cluster_leader():
    if not CloudHost.ENABLED['cloudwatch']:
        return False

    cluster = CloudHost.INSTALL_ID
    instances = CloudHost.get_autoscaled_instances()
    leader = JBoxDynConfig.get_cluster_leader(cluster)
    ami_recentness = CloudHost.get_ami_recentness()
    JBoxDB.log_debug(
        "cluster: %s. instances: %s. leader: %s. ami_recentness: %d", cluster,
        repr(instances), repr(leader), ami_recentness)

    # if none set, or set instance is dead elect self as leader, but wait till next cycle to prevent conflicts
    if (leader is None) or (leader not in instances) and (ami_recentness >= 0):
        JBoxDB.log_info("setting self (%s) as cluster leader",
                        CloudHost.instance_id())
        JBoxDynConfig.set_cluster_leader(cluster, CloudHost.instance_id())
        return False

    is_leader = (leader == CloudHost.instance_id())

    # if running an older ami, step down from cluster leader
    if (ami_recentness < 0) and is_leader:
        JBoxDB.log_info("unmarking self (%s) as cluster leader",
                        CloudHost.instance_id())
        JBoxDynConfig.unset_cluster_leader(cluster)
        return False

    return is_leader
Beispiel #41
0
    def do_housekeeping():
        JBox.do_update_user_home_image()

        server_delete_timeout = JBox.cfg['expire']
        JBoxContainer.maintain(max_timeout=server_delete_timeout, inactive_timeout=JBox.cfg['inactivity_timeout'],
                               protected_names=JBox.cfg['protected_docknames'])
        if JBox.cfg['cloud_host']['scale_down'] and (JBoxContainer.num_active() == 0) and \
                (JBoxContainer.num_stopped() == 0) and CloudHost.should_terminate():
            JBox.log_info("terminating to scale down")
            try:
                CloudHost.deregister_instance_dns()
            except:
                CloudHost.log_error("Error deregistering instance dns")
            CloudHost.terminate_instance()
        elif is_cluster_leader():
            CloudHost.log_info("I am the cluster leader")
            JBox.monitor_registrations()
            if not JBoxDynConfig.is_stat_collected_within(CloudHost.INSTALL_ID, 7):
                JBoxContainer.async_collect_stats()
Beispiel #42
0
    def handle_if_instance_info(self, is_allowed):
        stats = self.get_argument('instance_info', None)
        if stats is None:
            return False

        if not is_allowed:
            AdminHandler.log_error("Show instance info not allowed for user")
            response = {
                'code': -1,
                'data': 'You do not have permissions to view these stats'
            }
        else:
            try:
                if stats == 'load':
                    stats = {}
                    # get cluster loads
                    average_load = CloudHost.get_cluster_average_stats('Load')
                    if None != average_load:
                        stats['Average Load'] = average_load

                    machine_loads = CloudHost.get_cluster_stats('Load')
                    if None != machine_loads:
                        for n, v in machine_loads.iteritems():
                            stats['Instance ' + n] = v

                response = {
                    'code': 0,
                    'data': stats
                } if stats is not None else {
                    'code': 1,
                    'data': {}
                }
            except:
                AdminHandler.log_error("exception while getting stats")
                response = {'code': -1, 'data': 'error getting stats'}

        self.write(response)
        return True
Beispiel #43
0
def process_commands(argv):
    with open(argv[2]) as f:
        uplcourse = eval(f.read())

    cfg = read_config()
    cloud_cfg = cfg['cloud_host']

    LoggerMixin.setup_logger(level=cfg['root_log_level'])
    LoggerMixin.DEFAULT_LEVEL = cfg['jbox_log_level']

    db.configure_db(cfg)

    CloudHost.configure(has_s3=cloud_cfg['s3'],
                        has_dynamodb=cloud_cfg['dynamodb'],
                        has_cloudwatch=cloud_cfg['cloudwatch'],
                        has_autoscale=cloud_cfg['autoscale'],
                        has_route53=cloud_cfg['route53'],
                        has_ebs=cloud_cfg['ebs'],
                        has_ses=cloud_cfg['ses'],
                        scale_up_at_load=cloud_cfg['scale_up_at_load'],
                        scale_up_policy=cloud_cfg['scale_up_policy'],
                        autoscale_group=cloud_cfg['autoscale_group'],
                        route53_domain=cloud_cfg['route53_domain'],
                        region=cloud_cfg['region'],
                        install_id=cloud_cfg['install_id'])

    cmd = argv[1]
    if cmd == "upload":
        HomeworkHandler.upload_course(None, uplcourse)
    elif cmd == "report":
        as_csv = (argv[3] == "csv") if len(argv) > 3 else False
        get_report(uplcourse, as_csv)
    elif cmd == "answers":
        get_answers(uplcourse)
    else:
        print("Unknown option %s" % (cmd, ))

    print("DONE!")
Beispiel #44
0
def process_commands(argv):
    with open(argv[2]) as f:
        uplcourse = eval(f.read())

    cfg = read_config()
    cloud_cfg = cfg['cloud_host']

    LoggerMixin.setup_logger(level=cfg['root_log_level'])
    LoggerMixin.DEFAULT_LEVEL = cfg['jbox_log_level']

    db.configure_db(cfg)

    CloudHost.configure(has_s3=cloud_cfg['s3'],
                        has_dynamodb=cloud_cfg['dynamodb'],
                        has_cloudwatch=cloud_cfg['cloudwatch'],
                        has_autoscale=cloud_cfg['autoscale'],
                        has_route53=cloud_cfg['route53'],
                        has_ebs=cloud_cfg['ebs'],
                        has_ses=cloud_cfg['ses'],
                        scale_up_at_load=cloud_cfg['scale_up_at_load'],
                        scale_up_policy=cloud_cfg['scale_up_policy'],
                        autoscale_group=cloud_cfg['autoscale_group'],
                        route53_domain=cloud_cfg['route53_domain'],
                        region=cloud_cfg['region'],
                        install_id=cloud_cfg['install_id'])

    cmd = argv[1]
    if cmd == "upload":
        HomeworkHandler.upload_course(None, uplcourse)
    elif cmd == "report":
        as_csv = (argv[3] == "csv") if len(argv) > 3 else False
        get_report(uplcourse, as_csv)
    elif cmd == "answers":
        get_answers(uplcourse)
    else:
        print("Unknown option %s" % (cmd,))

    print("DONE!")
Beispiel #45
0
    def try_launch_container(cls, user_id):
        sessname = unique_sessname(user_id)
        cont = JBoxContainer.get_by_name(sessname)
        cls.log_debug("have existing container for %s: %r", sessname, None != cont)
        if cont is not None:
            cls.log_debug("container running: %r", cont.is_running())

        if ((cont is None) or (not cont.is_running())) and (not CloudHost.should_accept_session()):
            if cont is not None:
                cont.async_backup_and_cleanup()
            return False

        JBoxContainer.async_launch_by_name(sessname, user_id, True)
        return True
Beispiel #46
0
    def init():
        dckr = docker.Client()
        cfg = read_config()
        cloud_cfg = cfg['cloud_host']
        cloud_cfg['backup_bucket'] = "juliabox_userbackup"

        LoggerMixin.setup_logger(level=cfg['root_log_level'])
        LoggerMixin.DEFAULT_LEVEL = cfg['jbox_log_level']

        CloudHost.configure(has_s3=True, #cloud_cfg['s3'],
                        has_dynamodb=cloud_cfg['dynamodb'],
                        has_cloudwatch=cloud_cfg['cloudwatch'],
                        has_autoscale=cloud_cfg['autoscale'],
                        has_route53=cloud_cfg['route53'],
                        has_ebs=cloud_cfg['ebs'],
                        has_ses=cloud_cfg['ses'],
                        scale_up_at_load=cloud_cfg['scale_up_at_load'],
                        scale_up_policy=cloud_cfg['scale_up_policy'],
                        autoscale_group=cloud_cfg['autoscale_group'],
                        route53_domain=cloud_cfg['route53_domain'],
                        region=cloud_cfg['region'],
                        install_id=cloud_cfg['install_id'])

        VolMgr.configure(dckr, cfg)
Beispiel #47
0
    def try_launch_container(cls, user_id, max_hop=False):
        sessname = unique_sessname(user_id)
        cont = JBoxContainer.get_by_name(sessname)
        cls.log_debug("have existing container for %s: %r", sessname,
                      None != cont)
        if cont is not None:
            cls.log_debug("container running: %r", cont.is_running())

        if max_hop:
            self_load = CloudHost.get_instance_stats(CloudHost.instance_id(),
                                                     'Load')
            if self_load < 100:
                JBoxContainer.async_launch_by_name(sessname, user_id, True)
                return True

        is_leader = is_proposed_cluster_leader()
        if ((cont is None) or (not cont.is_running())) and (
                not CloudHost.should_accept_session(is_leader)):
            if cont is not None:
                cont.async_backup_and_cleanup()
            return False

        JBoxContainer.async_launch_by_name(sessname, user_id, True)
        return True
Beispiel #48
0
 def update_disk_states():
     detached_disks = JBoxDiskState.get_detached_disks()
     time_now = datetime.datetime.now(pytz.utc)
     for disk_key in detached_disks:
         disk_info = JBoxDiskState(disk_key=disk_key)
         user_id = disk_info.get_user_id()
         sess_props = JBoxSessionProps(unique_sessname(user_id))
         incomplete_snapshots = []
         modified = False
         for snap_id in disk_info.get_snapshot_ids():
             if not CloudHost.is_snapshot_complete(snap_id):
                 incomplete_snapshots.append(snap_id)
                 continue
             JBoxd.log_debug("updating latest snapshot of user %s to %s",
                             user_id, snap_id)
             old_snap_id = sess_props.get_snapshot_id()
             sess_props.set_snapshot_id(snap_id)
             modified = True
             if old_snap_id is not None:
                 CloudHost.delete_snapshot(old_snap_id)
         if modified:
             sess_props.save()
             disk_info.set_snapshot_ids(incomplete_snapshots)
             disk_info.save()
         if len(incomplete_snapshots) == 0:
             if (time_now - disk_info.get_detach_time()
                 ).total_seconds() > 24 * 60 * 60:
                 vol_id = disk_info.get_volume_id()
                 JBoxd.log_debug(
                     "volume %s for user %s unused for too long", vol_id,
                     user_id)
                 disk_info.delete()
                 CloudHost.detach_volume(vol_id, delete=True)
         else:
             JBoxd.log_debug("ongoing snapshots of user %s: %r", user_id,
                             incomplete_snapshots)
Beispiel #49
0
    def update_user_home_image(fetch=True):
        img_dir, curr_img = os.path.split(JBoxVol.USER_HOME_IMG)
        bucket, new_img = JBoxDynConfig.get_user_home_image(CloudHost.INSTALL_ID)
        new_img_path = os.path.join(img_dir, new_img)

        if fetch and (not os.path.exists(new_img_path)):
            VolMgr.log_debug("fetching new image to %s", new_img_path)
            k = CloudHost.pull_file_from_s3(bucket, new_img_path)
            if k is not None:
                VolMgr.log_debug("fetched new user home image")

        if os.path.exists(new_img_path):
            VolMgr.log_debug("set new image to %s", new_img_path)
            JBoxVol.USER_HOME_IMG = new_img_path
            return True
        return False
Beispiel #50
0
 def run(self):
     try:
         CloudHost.deregister_instance_dns()
     except:
         CloudHost.log_info("No prior dns registration found for the instance")
     CloudHost.register_instance_dns()
     JBoxContainer.publish_container_stats()
     JBox.do_update_user_home_image()
     JBoxContainer.async_refresh_disks()
     self.ct.start()
     self.ioloop.start()
Beispiel #51
0
    def update_user_home_image(fetch=True):
        img_dir, curr_img = os.path.split(JBoxVol.USER_HOME_IMG)
        bucket, new_img = JBoxDynConfig.get_user_home_image(
            CloudHost.INSTALL_ID)
        new_img_path = os.path.join(img_dir, new_img)

        if fetch and (not os.path.exists(new_img_path)):
            VolMgr.log_debug("fetching new image to %s", new_img_path)
            k = CloudHost.pull_file_from_s3(bucket, new_img_path)
            if k is not None:
                VolMgr.log_debug("fetched new user home image")

        if os.path.exists(new_img_path):
            VolMgr.log_debug("set new image to %s", new_img_path)
            JBoxVol.USER_HOME_IMG = new_img_path
            return True
        return False
Beispiel #52
0
    def setup_instance_config(self):
        nbconfig = os.path.join(self.disk_path, '.ipython/profile_julia/ipython_notebook_config.py')
        nbconfig_temp = os.path.join(self.disk_path, '.ipython/profile_julia/ipython_notebook_config.py.temp')

        if os.path.exists(nbconfig_temp):
            os.remove(nbconfig_temp)
        os.rename(nbconfig, nbconfig_temp)

        wsock_cfg = "c.NotebookApp.websocket_url = 'wss://" + CloudHost.notebook_websocket_hostname() + "'\n"

        replaced = False
        with open(nbconfig_temp) as fin, open(nbconfig, 'w') as fout:
            for line in fin:
                if line.startswith("c.NotebookApp.websocket_url"):
                    line = wsock_cfg
                    replaced = True
                fout.write(line)
            if not replaced:
                fout.write(wsock_cfg)
Beispiel #53
0
    def get_disk_for_user(user_email):
        JBoxEBSVol.log_debug("creating EBS volume for %s", user_email)
        if not JBoxEBSVol.HAS_EBS:
            raise Exception("EBS disks not enabled")

        disk_id = JBoxEBSVol._reserve_disk_id()
        if disk_id is None:
            raise Exception("No free disk available")

        sess_id = unique_sessname(user_email)
        sess_props = JBoxSessionProps(sess_id, create=True, user_id=user_email)
        if sess_props.is_new:
            sess_props.save()
        snap_id = sess_props.get_snapshot_id()
        if snap_id is None:
            snap_id = JBoxEBSVol.DISK_TEMPLATE_SNAPSHOT

        JBoxEBSVol.log_debug("will use snapshot id %s for %s", snap_id,
                             user_email)

        _dev_path, mnt_path = CloudHost.create_new_volume(snap_id,
                                                          disk_id,
                                                          JBoxEBSVol.FS_LOC,
                                                          tag=user_email)
        ebsvol = JBoxEBSVol(mnt_path, user_email=user_email)

        if snap_id == JBoxEBSVol.DISK_TEMPLATE_SNAPSHOT:
            JBoxEBSVol.log_debug("creating home folder on blank volume for %s",
                                 user_email)
            ebsvol.restore_user_home(True)
            ebsvol.restore()
        else:
            JBoxEBSVol.log_debug(
                "updating home folder on existing volume for %s", user_email)
            ebsvol.restore_user_home(False)
        #    snap_age_days = CloudHost.get_snapshot_age(snap_id).total_seconds()/(60*60*24)
        #    if snap_age_days > 7:
        #        ebsvol.restore_user_home()
        JBoxEBSVol.log_debug(
            "setting up instance configuration on disk for %s", user_email)
        ebsvol.setup_instance_config()

        return ebsvol
Beispiel #54
0
    def get(self):
        args = self.get_argument('m', default=None)

        if args is not None:
            args = json.loads(decrypt(base64.b64decode(args), self.config(key='sesskey')))

        if args is not None:
            self.log_debug("setting cookies")
            for cname in ['sessname', 'hostshell', 'hostupload', 'hostipnb', 'sign', 'juliabox']:
                self.set_cookie(cname, args[cname])
            self.set_status(status_code=204)
            self.finish()
        else:
            args = dict()
            for cname in ['sessname', 'hostshell', 'hostupload', 'hostipnb', 'sign', 'juliabox']:
                args[cname] = self.get_cookie(cname)
            args = tornado.escape.url_escape(base64.b64encode(encrypt(json.dumps(args), self.config(key='sesskey'))))
            url = "//" + CloudHost.notebook_websocket_hostname() + "/cors/?m=" + args
            self.log_debug("redirecting to " + url)
            self.redirect(url)
Beispiel #55
0
    def do_housekeeping():
        terminating = False
        server_delete_timeout = JBox.cfg['expire']
        JBoxContainer.maintain(max_timeout=server_delete_timeout, inactive_timeout=JBox.cfg['inactivity_timeout'],
                               protected_names=JBox.cfg['protected_docknames'])
        if is_cluster_leader():
            CloudHost.log_info("I am the cluster leader")
            JBox.monitor_registrations()
            if not JBoxDynConfig.is_stat_collected_within(CloudHost.INSTALL_ID, 1):
                JBoxContainer.async_collect_stats()
            JBoxContainer.async_update_disk_state()
        elif JBox.is_ready_to_terminate():
            terminating = True
            JBox.log_warn("terminating to scale down")
            try:
                CloudHost.deregister_instance_dns()
            except:
                CloudHost.log_error("Error deregistering instance dns")
            CloudHost.terminate_instance()

        if not terminating:
            JBox.do_update_user_home_image()
Beispiel #56
0
    def do_housekeeping():
        terminating = False
        server_delete_timeout = JBox.cfg['expire']
        JBoxContainer.maintain(max_timeout=server_delete_timeout,
                               inactive_timeout=JBox.cfg['inactivity_timeout'],
                               protected_names=JBox.cfg['protected_docknames'])
        if is_cluster_leader():
            CloudHost.log_info("I am the cluster leader")
            JBox.monitor_registrations()
            if not JBoxDynConfig.is_stat_collected_within(
                    CloudHost.INSTALL_ID, 7):
                JBoxContainer.async_collect_stats()
        elif JBox.is_ready_to_terminate():
            terminating = True
            JBox.log_info("terminating to scale down")
            try:
                CloudHost.deregister_instance_dns()
            except:
                CloudHost.log_error("Error deregistering instance dns")
            CloudHost.terminate_instance()

        if not terminating:
            JBox.do_update_user_home_image()
Beispiel #57
0
    def monitor_registrations():
        max_rate = JBoxDynConfig.get_registration_hourly_rate(CloudHost.INSTALL_ID)
        rate = JBoxUserV2.count_created(1)
        reg_allowed = JBoxDynConfig.get_allow_registration(CloudHost.INSTALL_ID)
        CloudHost.log_debug("registration allowed: %r, rate: %d, max allowed: %d", reg_allowed, rate, max_rate)

        if (reg_allowed and (rate > max_rate*1.1)) or ((not reg_allowed) and (rate < max_rate*0.9)):
            reg_allowed = not reg_allowed
            CloudHost.log_warn("Changing registration allowed to %r", reg_allowed)
            JBoxDynConfig.set_allow_registration(CloudHost.INSTALL_ID, reg_allowed)

        if reg_allowed:
            num_pending_activations = JBoxUserV2.count_pending_activations()
            if num_pending_activations > 0:
                CloudHost.log_info("scheduling activations for %d pending activations", num_pending_activations)
                JBoxContainer.async_schedule_activations()
Beispiel #58
0
    def setup_instance_config(self):
        nbconfig = os.path.join(
            self.disk_path,
            '.ipython/profile_julia/ipython_notebook_config.py')
        nbconfig_temp = os.path.join(
            self.disk_path,
            '.ipython/profile_julia/ipython_notebook_config.py.temp')

        if os.path.exists(nbconfig_temp):
            os.remove(nbconfig_temp)
        os.rename(nbconfig, nbconfig_temp)

        wsock_cfg = "c.NotebookApp.websocket_url = '" + JBoxVol.NOTEBOOK_WEBSOCK_PROTO + \
                    CloudHost.notebook_websocket_hostname() + "'\n"

        replaced = False
        with open(nbconfig_temp) as fin, open(nbconfig, 'w') as fout:
            for line in fin:
                if line.startswith("c.NotebookApp.websocket_url"):
                    line = wsock_cfg
                    replaced = True
                fout.write(line)
            if not replaced:
                fout.write(wsock_cfg)
Beispiel #59
0
 def pull_backup(user_email):
     sessname = unique_sessname(user_email)
     S3Disk.log_info("pulling %s.tar.gz from %s", sessname, JBoxVol.BACKUP_BUCKET)
     CloudHost.pull_file_from_s3(JBoxVol.BACKUP_BUCKET, sessname + ".tar.gz", metadata_only=False)