Exemple #1
0
 def find_logged_in_instance(user_id):
     sessname = unique_sessname(user_id)
     try:
         sess_props = JBoxSessionProps(Compute.get_install_id(), sessname)
         return sess_props.get_instance_id()
     except JBoxDBItemNotFound:
         return None
 def do_cluster_housekeeping():
     JBoxEBSHousekeep.log_debug("starting cluster housekeeping")
     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(Compute.get_install_id(), unique_sessname(user_id))
         incomplete_snapshots = []
         modified = False
         for snap_id in disk_info.get_snapshot_ids():
             if not EBSVol.is_snapshot_complete(snap_id):
                 incomplete_snapshots.append(snap_id)
                 continue
             JBoxEBSHousekeep.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:
                 EBSVol.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()
                 JBoxEBSHousekeep.log_debug("volume %s for user %s unused for too long", vol_id, user_id)
                 disk_info.delete()
                 EBSVol.detach_volume(vol_id, delete=True)
         else:
             JBoxEBSHousekeep.log_debug("ongoing snapshots of user %s: %r", user_id, incomplete_snapshots)
     JBoxEBSHousekeep.log_debug("finished cluster housekeeping")
Exemple #3
0
 def pull_backup(user_email):
     sessname = unique_sessname(user_email)
     JBoxDisk.log_info("pulling %s.tar.gz from %s", sessname,
                       JBoxVol.BACKUP_BUCKET)
     JBoxDisk.PLUGIN.pull(JBoxVol.BACKUP_BUCKET,
                          sessname + ".tar.gz",
                          metadata_only=False)
Exemple #4
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 JBoxS3.push(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)
Exemple #5
0
 def do_cluster_housekeeping():
     JBoxEBSHousekeep.log_debug("starting cluster housekeeping")
     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 EBSVol.is_snapshot_complete(snap_id):
                 incomplete_snapshots.append(snap_id)
                 continue
             JBoxEBSHousekeep.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:
                 EBSVol.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()
                 JBoxEBSHousekeep.log_debug("volume %s for user %s unused for too long", vol_id, user_id)
                 disk_info.delete()
                 EBSVol.detach_volume(vol_id, delete=True)
         else:
             JBoxEBSHousekeep.log_debug("ongoing snapshots of user %s: %r", user_id, incomplete_snapshots)
     JBoxEBSHousekeep.log_debug("finished cluster housekeeping")
Exemple #6
0
    def __init__(self, disk_path, user_email=None, user_name=None, sessname=None, old_sessname=None):
        self.disk_path = disk_path
        self.user_email = user_email

        if user_name is not None:
            self.user_name = user_name
        elif user_email is not None:
            self.user_name = get_user_name(user_email)
        else:
            self.user_name = None

        if sessname is not None:
            self.sessname = sessname
        elif user_email is not None:
            self.sessname = unique_sessname(user_email)
        else:
            self.sessname = None

        if old_sessname is not None:
            self.old_sessname = old_sessname
        elif user_email is not None:
            self.old_sessname = esc_sessname(user_email)
        else:
            self.old_sessname = None

        self._dbg_str = str(self.sessname) + "(" + self.disk_path + ")"
Exemple #7
0
    def try_launch_container(cls, user_id, max_hop=False):
        sessname = unique_sessname(user_id)
        cont = SessContainer.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 = Compute.get_instance_stats(Compute.get_instance_id(),
                                                   'Load')
            if self_load < 100:
                SessContainer.invalidate_container(sessname)
                JBoxAsyncJob.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 Compute.should_accept_session(is_leader)):
            if cont is not None:
                SessContainer.invalidate_container(cont.get_name())
                JBoxAsyncJob.async_backup_and_cleanup(cont.dockid)
            return False

        SessContainer.invalidate_container(sessname)
        JBoxAsyncJob.async_launch_by_name(sessname, user_id, True)
        return True
Exemple #8
0
    def __init__(self,
                 disk_path,
                 user_email=None,
                 user_name=None,
                 sessname=None,
                 old_sessname=None):
        self.disk_path = disk_path
        self.user_email = user_email

        if user_name is not None:
            self.user_name = user_name
        elif user_email is not None:
            self.user_name = get_user_name(user_email)
        else:
            self.user_name = None

        if sessname is not None:
            self.sessname = sessname
        elif user_email is not None:
            self.sessname = unique_sessname(user_email)
        else:
            self.sessname = None

        if old_sessname is not None:
            self.old_sessname = old_sessname
        elif user_email is not None:
            self.old_sessname = esc_sessname(user_email)
        else:
            self.old_sessname = None

        self._dbg_str = str(self.sessname) + "(" + self.disk_path + ")"
Exemple #9
0
    def push_backup(user_email, disk_path):
        sessname = unique_sessname(user_email)
        JBoxDisk.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 cloud storage 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 JBoxDisk.PLUGIN.push(JBoxVol.BACKUP_BUCKET, bkup_file,
                                    metadata={'backup_time': bkup_file_mtime.isoformat()}) is not None:
                os.remove(bkup_file)
                JBoxDisk.log_info("Moved backup to cloud " + sessname)
Exemple #10
0
    def restore(self):
        sessname = unique_sessname(self.user_email)
        old_sessname = esc_sessname(self.user_email)
        src = os.path.join(JBoxVol.BACKUP_LOC, sessname + ".tar.gz")

        pull_from_bucketstore = JBoxVol.pull_from_bucketstore
        mig_hndl = JBPluginCloud.jbox_get_plugin(JBPluginCloud.JBP_MIGRATE)
        if mig_hndl and mig_hndl.should_migrate(self.user_email):
            pull_from_bucketstore = mig_hndl.pull_from_bucketstore

        k = pull_from_bucketstore(src)  # download from S3 if exists
        if not os.path.exists(src):
            if old_sessname is not None:
                src = os.path.join(JBoxVol.BACKUP_LOC, old_sessname + ".tar.gz")
                k = pull_from_bucketstore(src)  # download from S3 if exists

        if not os.path.exists(src):
            return

        JBoxVol.log_info("Filtering out restore info from backup " + src + " to " + self.disk_path)

        src_tar = tarfile.open(src, 'r:gz')
        try:
            perms = {}
            for info in src_tar.getmembers():
                if not info.name.startswith('juser/'):
                    continue
                extract_name = info.name[6:]
                if (info.type == tarfile.LNKTYPE or info.type == tarfile.SYMTYPE) and \
                        info.linkname.startswith('juser/'):
                    info.linkname = info.linkname[6:]
                if info.name.startswith('juser/.'):
                    if JBoxVol._is_path_user_home_essential(extract_name):
                        continue
                info.name = extract_name
                if len(info.name) == 0:
                    continue
                src_tar.extract(info, self.disk_path)
                extracted_path = os.path.join(self.disk_path, extract_name)
                if os.path.isdir(extracted_path) and not os.access(extracted_path, os.W_OK):
                    st = os.stat(extracted_path)
                    perms[extracted_path] = st
                    os.chmod(extracted_path, st.st_mode | stat.S_IWRITE)
            if len(perms) > 0:
                JBoxVol.log_debug("resetting permissions on %d folders", len(perms))
                for extracted_path, perm in perms.iteritems():
                    os.chmod(extracted_path, perm)
            JBoxVol.log_info("Restored backup at " + self.disk_path)
        except IOError as ioe:
            if ioe.errno == errno.ENOSPC:
                # continue login on ENOSPC to allow user to delete files
                JBoxVol.log_exception("No space left to restore backup for %s", sessname)
            else:
                raise
        finally:
            src_tar.close()
        # delete local copy of backup if we have it on bucketstore
        if k is not None:
            os.remove(src)
Exemple #11
0
    def get_disk_for_user(user_email):
        JBoxDefaultConfigVol.log_debug("creating configs disk for %s", user_email)
        if JBoxDefaultConfigVol.FS_LOC is None:
            JBoxDefaultConfigVol.configure()

        disk_path = os.path.join(JBoxDefaultConfigVol.FS_LOC, unique_sessname(user_email))
        cfgvol = JBoxDefaultConfigVol(disk_path, user_email=user_email)
        cfgvol._unpack_config()
        return cfgvol
Exemple #12
0
    def calc_stat(user_email):
        VolMgr.STATS['num_users'] += 1
        sessname = unique_sessname(user_email)

        plugin = JBPluginCloud.jbox_get_plugin(JBPluginCloud.JBP_BUCKETSTORE)
        if plugin is not None:
            k = plugin.pull(JBoxVol.BACKUP_BUCKET, sessname + ".tar.gz", metadata_only=True)
            if k is not None:
                VolMgr.STATS['loopback']['sizes'].append(k.size)
Exemple #13
0
    def calc_stat(user_email):
        VolMgr.STATS["num_users"] += 1
        sessname = unique_sessname(user_email)

        plugin = JBPluginCloud.jbox_get_plugin(JBPluginCloud.JBP_BUCKETSTORE)
        if plugin is not None:
            k = plugin.pull(JBoxVol.BACKUP_BUCKET, sessname + ".tar.gz", metadata_only=True)
            if k is not None:
                VolMgr.STATS["loopback"]["sizes"].append(k.size)
Exemple #14
0
    def get_disk_for_user(user_email):
        JBoxPolsarDiskVol.log_debug("Mounting polsar disk for %s", user_email)

        disk_id = unique_sessname(user_email)
        disk_path = JBoxPolsarDiskVol.FS_LOC
        if not os.path.exists(disk_path):
            os.mkdir(disk_path)

        polsarvol = JBoxPolsarDiskVol(disk_path, user_email=user_email)
        return polsarvol
Exemple #15
0
 def get_disk_from_container(cid):
     container_name = JBoxVol.get_cname(cid)
     sessname = container_name[1:]
     for dev, vol in JBoxEBSVol.get_mapped_volumes().iteritems():
         vol = EBSVol.get_volume(vol.volume_id)
         if 'Name' in vol.tags:
             name = vol.tags['Name']
             if unique_sessname(name) == sessname:
                 return JBoxEBSVol(dev, sessname=sessname)
     return None
Exemple #16
0
 def get_disk_from_container(cid):
     container_name = JBoxVol.get_cname(cid)
     sessname = container_name[1:]
     for dev, vol in JBoxEBSVol.get_mapped_volumes().iteritems():
         vol = EBSVol.get_volume(vol.volume_id)
         if 'Name' in vol.tags:
             name = vol.tags['Name']
             if unique_sessname(name) == sessname:
                 return JBoxEBSVol(dev, sessname=sessname)
     return None
Exemple #17
0
    def get_disk_for_user(user_email):
        JBoxDefaultConfigVol.log_debug("creating configs disk for %s",
                                       user_email)
        if JBoxDefaultConfigVol.FS_LOC is None:
            JBoxDefaultConfigVol.configure()

        disk_path = os.path.join(JBoxDefaultConfigVol.FS_LOC,
                                 unique_sessname(user_email))
        cfgvol = JBoxDefaultConfigVol(disk_path, user_email=user_email)
        cfgvol._unpack_config()
        return cfgvol
Exemple #18
0
    def restore(self):
        sessname = unique_sessname(self.user_email)
        old_sessname = esc_sessname(self.user_email)
        src = os.path.join(JBoxVol.BACKUP_LOC, sessname + ".tar.gz")
        k = JBoxVol.pull_from_bucketstore(src)  # download from S3 if exists
        if not os.path.exists(src):
            if old_sessname is not None:
                src = os.path.join(JBoxVol.BACKUP_LOC,
                                   old_sessname + ".tar.gz")
                k = JBoxVol.pull_from_bucketstore(
                    src)  # download from S3 if exists

        if not os.path.exists(src):
            return

        JBoxVol.log_info("Filtering out restore info from backup " + src +
                         " to " + self.disk_path)

        src_tar = tarfile.open(src, 'r:gz')
        try:
            perms = {}
            for info in src_tar.getmembers():
                if not info.name.startswith('juser/'):
                    continue
                extract_name = info.name[6:]
                if (info.type == tarfile.LNKTYPE or info.type == tarfile.SYMTYPE) and \
                        info.linkname.startswith('juser/'):
                    info.linkname = info.linkname[6:]
                if info.name.startswith('juser/.'):
                    if JBoxVol._is_path_user_home_essential(extract_name):
                        continue
                info.name = extract_name
                if len(info.name) == 0:
                    continue
                src_tar.extract(info, self.disk_path)
                extracted_path = os.path.join(self.disk_path, extract_name)
                if os.path.isdir(extracted_path) and not os.access(
                        extracted_path, os.W_OK):
                    st = os.stat(extracted_path)
                    perms[extracted_path] = st
                    os.chmod(extracted_path, st.st_mode | stat.S_IWRITE)
            if len(perms) > 0:
                JBoxVol.log_debug("resetting permissions on %d folders",
                                  len(perms))
                for extracted_path, perm in perms.iteritems():
                    os.chmod(extracted_path, perm)
            JBoxVol.log_info("Restored backup at " + self.disk_path)
        except IOError, ioe:
            if ioe.errno == errno.ENOSPC:
                # continue login on ENOSPC to allow user to delete files
                JBoxVol.log_exception("No space left to restore backup for %s",
                                      sessname)
            else:
                raise
Exemple #19
0
    def get_disk_for_user(user_email):
        JBoxEBSVol.log_debug("creating EBS volume for %s", user_email)

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

        try:
            existing_disk = JBoxDiskState(cluster_id=CompEC2.INSTALL_ID,
                                          region_id=CompEC2.REGION,
                                          user_id=user_email)
        except Exception as ex:
            JBoxEBSVol.log_debug("No existing disk for %s. Exception %r",
                                 user_email, ex)
            existing_disk = None

        if existing_disk is None:
            sess_id = unique_sessname(user_email)
            sess_props = JBoxSessionProps(Compute.get_install_id(),
                                          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, vol_id = EBSVol.create_new_volume(
                snap_id,
                disk_id,
                tag=user_email,
                disk_sz_gb=JBoxEBSVol.DISK_LIMIT)
            existing_disk = JBoxDiskState(cluster_id=CompEC2.INSTALL_ID,
                                          region_id=CompEC2.REGION,
                                          user_id=user_email,
                                          volume_id=vol_id,
                                          attach_time=None,
                                          create=True)
        else:
            dev_path = EBSVol.attach_volume(existing_disk.get_volume_id(),
                                            disk_id)

        existing_disk.set_state(JBoxDiskState.STATE_ATTACHING)
        existing_disk.save()

        return JBoxEBSVol(dev_path, user_email=user_email)
Exemple #20
0
    def find_logged_in_instance(user_id):
        container_id = "/" + unique_sessname(user_id)
        instances = Compute.get_all_instances()

        for inst in instances:
            try:
                sessions = JBoxAsyncJob.sync_session_status(inst)['data']
                if len(sessions) > 0:
                    if container_id in sessions:
                        return inst
            except:
                JBoxHandler.log_error("Error receiving sessions list from %r", inst)
                pass
        return None
Exemple #21
0
    def find_logged_in_instance(user_id):
        container_id = "/" + unique_sessname(user_id)
        instances = Compute.get_all_instances()

        for inst in instances:
            try:
                sessions = JBoxAsyncJob.sync_session_status(inst)['data']
                if len(sessions) > 0:
                    if container_id in sessions:
                        return inst
            except:
                JBoxHandler.log_error("Error receiving sessions list from %r",
                                      inst)
                pass
        return None
Exemple #22
0
    def get_disk_for_user(user_email):
        JBoxHostDiskVol.log_debug("creating host disk for %s", user_email)

        disk_id = unique_sessname(user_email)
        disk_path = os.path.join(JBoxHostDiskVol.FS_LOC, disk_id)
        if not os.path.exists(disk_path):
            os.mkdir(disk_path)
        hostvol = JBoxHostDiskVol(disk_path, user_email=user_email)
        hostvol.refresh_disk(mark_refreshed=False)

        if JBoxVol.BACKUP_LOC is not None:
            JBoxHostDiskVol.log_debug("restoring data for %s", user_email)
            hostvol.restore()

        return hostvol
Exemple #23
0
    def get_disk_for_user(user_email):
        JBoxHostDiskVol.log_debug("creating host disk for %s", user_email)

        disk_id = unique_sessname(user_email)
        disk_path = os.path.join(JBoxHostDiskVol.FS_LOC, disk_id)
        if not os.path.exists(disk_path):
            os.mkdir(disk_path)
        hostvol = JBoxHostDiskVol(disk_path, user_email=user_email)
        hostvol.refresh_disk(mark_refreshed=False)

        if JBoxVol.BACKUP_LOC is not None:
            JBoxHostDiskVol.log_debug("restoring data for %s", user_email)
            hostvol.restore()

        return hostvol
Exemple #24
0
    def do_monitor_loading_ajax(self, user_id):
        sessname = unique_sessname(user_id)
        self.log_debug("AJAX monitoring loading of session [%s] user[%s]...", sessname, user_id)
        cont = SessContainer.get_by_name(sessname)
        if (cont is None) or (not cont.is_running()):
            loading_step = int(self.get_loading_state(), 0)
            if loading_step > 90:
                self.log_error("Could not start instance. Session [%s] for user [%s] didn't load.", sessname, user_id)
                self.write({'code': -1})
                return

            loading_step += 1
            self.set_loading_state(loading_step)
            self.write({'code': 0})
        else:
            self.write({'code': 1})
Exemple #25
0
    def do_monitor_loading_ajax(self, user_id):
        sessname = unique_sessname(user_id)
        self.log_debug("AJAX monitoring loading of session [%s] user[%s]...", sessname, user_id)
        cont = SessContainer.get_by_name(sessname)
        if (cont is None) or (not cont.is_running()):
            loading_step = int(self.get_loading_state(), 0)
            if loading_step > 60:
                self.log_error("Could not start instance. Session [%s] for user [%s] didn't load.", sessname, user_id)
                self.write({'code': -1})
                return

            loading_step += 1
            self.set_loading_state(loading_step)
            self.write({'code': 0})
        else:
            self.write({'code': 1})
Exemple #26
0
 def do_node_housekeeping():
     JBoxEBSHousekeep.log_debug("starting node housekeeping")
     for device, vol in JBoxEBSVol.get_mapped_volumes().iteritems():
         deviceid = os.path.basename(device)
         vol_id = vol.volume_id
         vol = EBSVol.get_volume(vol_id)
         user_id = vol.tags["Name"] if "Name" in vol.tags else None
         if user_id is None:
             continue
         sessname = unique_sessname(user_id)
         cont = SessContainer.get_by_name(sessname)
         if cont is not None:
             continue
         JBoxEBSHousekeep.log_debug("Found orphaned volume %s for %s, %s", vol_id, user_id, sessname)
         ebsvol = JBoxEBSVol(deviceid, sessname=sessname)
         ebsvol.release(backup=True)
     JBoxEBSHousekeep.log_debug("finished node housekeeping")
Exemple #27
0
    def do_monitor_loading(self, user_id):
        sessname = unique_sessname(user_id)
        self.log_debug("Monitoring loading of session [%s] user[%s]...",
                       sessname, user_id)
        cont = SessContainer.get_by_name(sessname)
        if (cont is None) or (not cont.is_running()):
            loading_step = int(self.get_loading_state(), 0)
            if loading_step > 30:
                self.log_error(
                    "Could not start instance. Session [%s] for user [%s] didn't load.",
                    sessname, user_id)
                self.clear_container()
                self.rendertpl(
                    "index.tpl",
                    cfg=JBoxCfg.nv,
                    state=self.state(
                        error=
                        'Could not start your instance! Please try again.',
                        pending_activation=False,
                        user_id=user_id))
                return
            else:
                loading_step += 1

            self.set_loading_state(loading_step)
            self.rendertpl("loading.tpl",
                           user_id=user_id,
                           cfg=JBoxCfg.nv,
                           js_includes=JBPluginHandler.PLUGIN_JAVASCRIPTS)
        else:
            (shellport, uplport, ipnbport) = cont.get_host_ports()

            self.set_container_ports({
                JBoxHandler.COOKIE_PORT_SHELL: shellport,
                JBoxHandler.COOKIE_PORT_UPL: uplport,
                JBoxHandler.COOKIE_PORT_IPNB: ipnbport
            })
            self.clear_loading()

            self.rendertpl("ipnbsess.tpl",
                           sessname=sessname,
                           cfg=JBoxCfg.nv,
                           user_id=user_id,
                           plugin_features=json.dumps(
                               self.application.settings["plugin_features"]),
                           js_includes=JBPluginHandler.PLUGIN_JAVASCRIPTS)
Exemple #28
0
 def do_node_housekeeping():
     JBoxEBSHousekeep.log_debug("starting node housekeeping")
     for device, vol in JBoxEBSVol.get_mapped_volumes().iteritems():
         deviceid = os.path.basename(device)
         vol_id = vol.volume_id
         vol = EBSVol.get_volume(vol_id)
         user_id = vol.tags['Name'] if 'Name' in vol.tags else None
         if user_id is None:
             continue
         sessname = unique_sessname(user_id)
         cont = SessContainer.get_by_name(sessname)
         if cont is not None:
             continue
         JBoxEBSHousekeep.log_debug("Found orphaned volume %s for %s, %s", vol_id, user_id, sessname)
         ebsvol = JBoxEBSVol(deviceid, sessname=sessname)
         ebsvol.release(backup=True)
     JBoxEBSHousekeep.log_debug("finished node housekeeping")
Exemple #29
0
    def __init__(self, user_email, gname=None):
        UserCluster.configure_dynamic()
        self.user_email = user_email

        if gname is None:
            self.gname = UserCluster.NAME_PFX + unique_sessname(user_email)
        else:
            self.gname = gname

        if user_email is not None:
            self._dbg_str = ("UserCluster(%s - %s)" % (user_email, self.gname))
        else:
            self._dbg_str = ("UserCluster(%s)" % (self.gname,))

        self.placement_group = None
        self.autoscale_group = None
        self.launch_config = None
        self.instances = []
        self.public_ips = []
        self.public_hosts = []
        self.private_ips = []
        self.private_hosts = []
Exemple #30
0
    def get_disk_for_user(user_email):
        JBoxEBSVol.log_debug("creating EBS volume for %s", user_email)

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

        try:
            existing_disk = JBoxDiskState(cluster_id=CompEC2.INSTALL_ID, region_id=CompEC2.REGION,
                                          user_id=user_email)
        except Exception as ex:
            JBoxEBSVol.log_debug("No existing disk for %s. Exception %r", user_email, ex)
            existing_disk = None

        if existing_disk is None:
            sess_id = unique_sessname(user_email)
            sess_props = JBoxSessionProps(Compute.get_install_id(), 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, vol_id = EBSVol.create_new_volume(snap_id, disk_id, tag=user_email,
                                                        disk_sz_gb=JBoxEBSVol.DISK_LIMIT)
            existing_disk = JBoxDiskState(cluster_id=CompEC2.INSTALL_ID, region_id=CompEC2.REGION,
                                          user_id=user_email,
                                          volume_id=vol_id,
                                          attach_time=None,
                                          create=True)
        else:
            dev_path = EBSVol.attach_volume(existing_disk.get_volume_id(), disk_id)

        existing_disk.set_state(JBoxDiskState.STATE_ATTACHING)
        existing_disk.save()

        return JBoxEBSVol(dev_path, user_email=user_email)
Exemple #31
0
    def set_container_initialized(self, instance_id, user_id):
        """ Marks a container as being allocated to a user session.
        Sets a cookie named COOKIE_SESS (jb_sess). Cookie contains:
        - Container id (session name / docker container name).
        - Container location (instance id).
        - Creation time stamp.
        - Signature for validity check.
        It also clears any stale port mapping cookies, and sets the loading state to 1.
        :param instance_id: The instance where container is allocated, to redirect future requests to.
        :param user_id: The user id for which container is allocated.
        :return: None
        """
        self.set_redirect_instance_id(instance_id)
        t = datetime.datetime.now(pytz.utc).isoformat()
        cid = unique_sessname(user_id)
        sign = signstr(cid + instance_id + t, JBoxCfg.get('sesskey'))

        sess_cookie = {'c': cid, 't': t, 'i': instance_id, 'x': sign}
        self._set_container_cookies({
            JBoxCookies.COOKIE_SESS: base64.b64encode(json.dumps(sess_cookie))
        })
        self._clear_container_ports()
        self.set_loading_state(1)
Exemple #32
0
    def do_monitor_loading(self, user_id):
        sessname = unique_sessname(user_id)
        self.log_debug("Monitoring loading of session [%s] user[%s]...", sessname, user_id)
        cont = SessContainer.get_by_name(sessname)
        if (cont is None) or (not cont.is_running()):
            loading_step = int(self.get_loading_state(), 0)
            if loading_step > 30:
                self.log_error("Could not start instance. Session [%s] for user [%s] didn't load.", sessname, user_id)
                self.clear_container()
                self.rendertpl("index.tpl", cfg=JBoxCfg.nv,
                               state=self.state(
                                   error='Could not start your instance! Please try again.',
                                   pending_activation=False,
                                   user_id=user_id))
                return
            else:
                loading_step += 1

            self.set_loading_state(loading_step)
            self.rendertpl("loading.tpl",
                           user_id=user_id,
                           cfg=JBoxCfg.nv,
                           js_includes=JBPluginHandler.PLUGIN_JAVASCRIPTS)
        else:
            (shellport, uplport, ipnbport) = cont.get_host_ports()

            self.set_container_ports({
                JBoxHandler.COOKIE_PORT_SHELL: shellport,
                JBoxHandler.COOKIE_PORT_UPL: uplport,
                JBoxHandler.COOKIE_PORT_IPNB: ipnbport
            })
            self.clear_loading()

            self.rendertpl("ipnbsess.tpl",  sessname=sessname, cfg=JBoxCfg.nv, user_id=user_id,
                           plugin_features=json.dumps(self.application.settings["plugin_features"]),
                           js_includes=JBPluginHandler.PLUGIN_JAVASCRIPTS)
Exemple #33
0
    def set_container_initialized(self, instance_id, user_id):
        """ Marks a container as being allocated to a user session.
        Sets a cookie named COOKIE_SESS (jb_sess). Cookie contains:
        - Container id (session name / docker container name).
        - Container location (instance id).
        - Creation time stamp.
        - Signature for validity check.
        It also clears any stale port mapping cookies, and sets the loading state to 1.
        :param instance_id: The instance where container is allocated, to redirect future requests to.
        :param user_id: The user id for which container is allocated.
        :return: None
        """
        self.set_redirect_instance_id(instance_id)
        t = datetime.datetime.now(pytz.utc).isoformat()
        cid = unique_sessname(user_id)
        sign = signstr(cid + instance_id + t, JBoxCfg.get('sesskey'))

        sess_cookie = {'c': cid, 't': t, 'i': instance_id, 'x': sign}
        self._set_container_cookies({
            JBoxCookies.COOKIE_SESS:
            base64.b64encode(json.dumps(sess_cookie))
        })
        self._clear_container_ports()
        self.set_loading_state(1)
Exemple #34
0
    def try_launch_container(cls, user_id, max_hop=False):
        sessname = unique_sessname(user_id)
        cont = SessContainer.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 = Compute.get_instance_stats(Compute.get_instance_id(), 'Load')
            if self_load < 100:
                SessContainer.invalidate_container(sessname)
                JBoxAsyncJob.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 Compute.should_accept_session(is_leader)):
            if cont is not None:
                SessContainer.invalidate_container(cont.get_name())
                JBoxAsyncJob.async_backup_and_cleanup(cont.dockid)
            return False

        SessContainer.invalidate_container(sessname)
        JBoxAsyncJob.async_launch_by_name(sessname, user_id, True)
        return True
Exemple #35
0
 def pull_backup(user_email):
     sessname = unique_sessname(user_email)
     JBoxDisk.log_info("pulling %s.tar.gz from %s", sessname, JBoxVol.BACKUP_BUCKET)
     JBoxDisk.PLUGIN.pull(JBoxVol.BACKUP_BUCKET, sessname + ".tar.gz", metadata_only=False)
Exemple #36
0
class JBoxEBSVol(JBoxVol):
    provides = [JBoxVol.JBP_DATA_EBS, JBoxVol.JBP_DATA]

    DEVICES = []
    MAX_DISKS = 0
    DISK_LIMIT = None
    DISK_USE_STATUS = {}
    DISK_RESERVE_TIME = {}
    DISK_TEMPLATE_SNAPSHOT = None
    LOCK = None

    @staticmethod
    def configure():
        num_disks_max = JBoxCfg.get('numdisksmax')
        JBoxEBSVol.DISK_LIMIT = 10
        JBoxEBSVol.MAX_DISKS = num_disks_max
        JBoxEBSVol.DISK_TEMPLATE_SNAPSHOT = JBoxCfg.get(
            'cloud_host.ebs_template')

        JBoxEBSVol.DEVICES = JBoxEBSVol._guess_configured_devices(
            'xvd', num_disks_max)
        JBoxEBSVol.log_debug(
            "Assuming %d EBS volumes configured in range xvdba..xvdcz",
            len(JBoxEBSVol.DEVICES))

        JBoxEBSVol.LOCK = threading.Lock()
        JBoxEBSVol.refresh_disk_use_status()

    @classmethod
    def get_disk_allocated_size(cls):
        return JBoxEBSVol.DISK_LIMIT * 1000000000

    @staticmethod
    def _guess_configured_devices(devidpfx, num_disks):
        devices = []
        for pfx1 in 'bc':
            for pfx2 in ascii_lowercase:
                devices.append(devidpfx + pfx1 + pfx2)
                if len(devices) == num_disks:
                    return devices
        return devices

    @staticmethod
    def refresh_disk_use_status(container_id_list=None):
        JBoxEBSVol.log_debug("Refrshing EBS disk use status")
        JBoxEBSVol.LOCK.acquire()
        try:
            nfree = 0
            for idx in range(0, JBoxEBSVol.MAX_DISKS):
                dev = JBoxEBSVol.DEVICES[idx]
                if JBoxEBSVol._is_reserved(dev):
                    JBoxEBSVol.DISK_USE_STATUS[dev] = True
                else:
                    JBoxEBSVol.DISK_USE_STATUS[dev] = False
                    nfree += 1

            for device, volume in JBoxEBSVol.get_mapped_volumes().iteritems():
                JBoxEBSVol.DISK_USE_STATUS[os.path.basename(device)] = True
                nfree -= 1
            JBoxEBSVol.log_info("EBS Disk free: " + str(nfree) + "/" +
                                str(JBoxEBSVol.MAX_DISKS))
        except:
            JBoxEBSVol.log_exception("Exception refrshing EBS disk use status")
        finally:
            JBoxEBSVol.LOCK.release()

    @staticmethod
    def get_mapped_volumes():
        allmaps = EBSVol.get_mapped_volumes()
        JBoxEBSVol.log_debug("Devices mapped: %r", allmaps)
        return dict((d, v) for d, v in allmaps.iteritems()
                    if os.path.basename(d) in JBoxEBSVol.DEVICES)

    @staticmethod
    def _get_unused_disk_id():
        for idx in range(0, JBoxEBSVol.MAX_DISKS):
            dev = JBoxEBSVol.DEVICES[idx]
            if not JBoxEBSVol.DISK_USE_STATUS[dev]:
                return dev
        return None

    @staticmethod
    def _is_reserved(idx):
        if (idx in JBoxEBSVol.DISK_RESERVE_TIME) and (
                JBoxEBSVol.DISK_RESERVE_TIME[idx] < time.time()):
            del JBoxEBSVol.DISK_RESERVE_TIME[idx]
        return idx in JBoxEBSVol.DISK_RESERVE_TIME

    @staticmethod
    def _mark_disk_used(idx, used=True, for_secs=0):
        JBoxEBSVol.DISK_USE_STATUS[idx] = used
        if used and (for_secs > 0):
            JBoxEBSVol.DISK_RESERVE_TIME[idx] = time.time() + for_secs
        else:
            if idx in JBoxEBSVol.DISK_RESERVE_TIME:
                del JBoxEBSVol.DISK_RESERVE_TIME[idx]

    @staticmethod
    def _reserve_disk_id():
        JBoxEBSVol.LOCK.acquire()
        try:
            disk_id = JBoxEBSVol._get_unused_disk_id()
            JBoxEBSVol._mark_disk_used(disk_id, for_secs=120)
            return disk_id
        finally:
            JBoxEBSVol.LOCK.release()

    @staticmethod
    def is_mount_path(fs_path):
        # EBS volumes are not mounted on host
        return False

    @staticmethod
    def disk_ids_used_pct():
        pct = (sum(JBoxEBSVol.DISK_USE_STATUS.values()) * 100) / len(
            JBoxEBSVol.DISK_USE_STATUS)
        return min(100, max(0, pct))

    @staticmethod
    def get_disk_for_user(user_email):
        JBoxEBSVol.log_debug("creating EBS volume for %s", user_email)

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

        try:
            existing_disk = JBoxDiskState(cluster_id=CompEC2.INSTALL_ID,
                                          region_id=CompEC2.REGION,
                                          user_id=user_email)
        except Exception, ex:
            JBoxEBSVol.log_debug("No existing disk for %s. Exception %r",
                                 user_email, ex)
            existing_disk = None

        if existing_disk is None:
            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, vol_id = EBSVol.create_new_volume(
                snap_id,
                disk_id,
                tag=user_email,
                disk_sz_gb=JBoxEBSVol.DISK_LIMIT)
            existing_disk = JBoxDiskState(cluster_id=CompEC2.INSTALL_ID,
                                          region_id=CompEC2.REGION,
                                          user_id=user_email,
                                          volume_id=vol_id,
                                          attach_time=None,
                                          create=True)
        else:
            dev_path = EBSVol.attach_volume(existing_disk.get_volume_id(),
                                            disk_id)

        existing_disk.set_state(JBoxDiskState.STATE_ATTACHING)
        existing_disk.save()

        return JBoxEBSVol(dev_path, user_email=user_email)
Exemple #37
0
 def rename_and_delete(user_email):
     sessname = unique_sessname(user_email)
     renamed_sessname = sessname + '_old'
     JBoxDisk.PLUGIN.move(sessname + ".tar.gz", renamed_sessname + ".tar.gz", JBoxVol.BACKUP_BUCKET)
Exemple #38
0
 def rename_and_delete(user_email):
     sessname = unique_sessname(user_email)
     renamed_sessname = sessname + '_old'
     JBoxS3.move(sessname + ".tar.gz", renamed_sessname + ".tar.gz", JBoxVol.BACKUP_BUCKET)
Exemple #39
0
 def delete(user_email):
     sessname = unique_sessname(user_email)
     JBoxS3.delete(JBoxVol.BACKUP_BUCKET, sessname + ".tar.gz")
Exemple #40
0
 def delete(user_email):
     sessname = unique_sessname(user_email)
     JBoxDisk.PLUGIN.delete(JBoxVol.BACKUP_BUCKET, sessname + ".tar.gz")