Beispiel #1
0
def migrate():
    """Migrate DB schema changes"""
    from spc import migrate
    dal = migrate.dal(uri=config.uri, migrate=True)

    # add default groups
    dal.db.groups.update_or_insert(name="admin")
    dal.db.groups.update_or_insert(name="default")

    # need to run:
    # alter table datasource add column label text;

    # need to get this working in the future
    # default = 1
    # update all group ids to be 1 for now
    # dal.db.jobs(dal.db.jobs.id > 0).update_record(gid=default)
    # dal.db.apps(dal.db.apps.id > 0).update_record(gid=default)
    # dal.db.users(dal.db.users.id > 0).update_record(gid=default)

    dal.db.commit()
Beispiel #2
0
def initdb():
    """Initializes database file"""
    from spc import config, migrate

    # create db directory if it doesn't exist
    if not os.path.exists(config.dbdir):
        os.makedirs(config.dbdir)

    # somehow the following doesn't work properly
    # make a backup copy of db file if it exists
    #if os.path.isfile(db):
    #    print "ERROR: a database file already exists, please rename it and rerun"
    #    sys.exit()
    #    shutil.copyfile(db, db+".bak")

    # get rid of old .table files
    for f in os.listdir(config.dbdir):
        if re.search("\.table", f):
            print "removing file:", f
            os.remove(os.path.join(config.dbdir, f))
    # delete previous .db file should back first (future)
    dbpath = os.path.join(config.dbdir, config.db)
    if os.path.isfile(dbpath): os.remove(dbpath)
    # create db
    dal = migrate.dal(uri=config.uri, migrate=True)

    # add default groups
    dal.db.groups.insert(name="admin")
    dal.db.groups.insert(name="genetics")

    # add admin and guest user
    hashpw = hashlib.sha256("admin").hexdigest()
    dal.db.users.insert(user="******", passwd=hashpw, gid=0)
    hashpw = hashlib.sha256("guest").hexdigest()
    dal.db.users.insert(user="******", passwd=hashpw, gid=1)

    # add default app
    dal.db.apps.insert(name="dna",description="Compute reverse complement," +\
                       "GC content, and codon analysis of given DNA string.",
                       category="bioinformatics",
                       language="python",
                       input_format="ini",
                       command="<rel_apps_path>/dna/dna")
    dal.db.plots.insert(id=1, appid=1, ptype="flot-cat", title="Dinucleotides")
    dal.db.plots.insert(id=2, appid=1, ptype="flot-cat", title="Nucleotides")
    dal.db.plots.insert(id=3, appid=1, ptype="flot-cat", title="Codons")
    dal.db.datasource.insert(filename="din.out",
                             cols="1:2",
                             pltid=1,
                             data_def='{label: "Dinucleotides"}')
    dal.db.datasource.insert(filename="nucs.out",
                             cols="1:2",
                             pltid=2,
                             data_def='{label: "Nucleotides"}')
    dal.db.datasource.insert(filename="codons.out",
                             cols="1:2",
                             pltid=3,
                             data_def='{label: "Codons"}')

    # activate the default app for admin and guest
    dal.db.app_user.insert(appid=1, uid=1)
    dal.db.app_user.insert(appid=1, uid=2)

    #dal.db.disciplines.insert(name="Chemistry")
    #dal.db.disciplines.insert(name="Linguistics")
    #dal.db.disciplines.insert(name="Finance")
    #dal.db.disciplines.insert(name="Biology")
    #dal.db.disciplines.insert(name="Physics")
    #dal.db.disciplines.insert(name="Fluid Dynamics")
    #dal.db.disciplines.insert(name="Geodynamics")
    #dal.db.disciplines.insert(name="Molecular Dynamics")
    #dal.db.disciplines.insert(name="Weather Prediction")
    # write changes to db
    dal.db.commit()
Beispiel #3
0
def main():
    if (sys.argv[1] == "init"):
        create_config_file()
        print "creating database."
        initdb()
    elif (sys.argv[1] == "migrate"):
        print "migrating database schema changes"
        migrate()
    elif (sys.argv[1] == "run"):
        import config
        if config.server == 'uwsgi':
            os.system('/usr/local/bin/uwsgi etc/uwsgi.ini')
        else:
            import spc.main
            spc.main.main()
    elif (sys.argv[1] == "runworker"):
        import spc.worker
        spc.worker.main()
    elif (sys.argv[1] == "runsslworker"):
        import spc.worker_ssl
        spc.worker_ssl.main()
    elif (sys.argv[1] == "search"):
        print notyet
    elif (sys.argv[1] == "test"):
        import spc.test
        spc.test.main()
    elif (sys.argv[1] == "uninstall"):
        import app_reader_writer as apprw
        install_usage = "usage: spc uninstall appname"
        if len(sys.argv) == 3:
            import migrate, config

            app = sys.argv[2]
            a = apprw.App(app)
            # connect to db
            dal = migrate.dal(uri=config.uri)
            result = dal.db(dal.db.apps.name == app).select()
            if result:
                appid = dal.db(dal.db.apps.name == app).select().first()["id"]
                if a.delete(appid, True):
                    print "SUCCESS: uninstalled app", app, "with appid:", appid
            else:
                print "ERROR: app does not exist"
                sys.exit()
        else:
            print install_usage

    elif (sys.argv[1] == "import"):
        if len(sys.argv) <= 2:
            print "usage: spc import zipcase.zip (file.zip downloaded from another SPC instance)"
            sys.exit()
        else:
            save_path = sys.argv[2]

        filename, file_extension = os.path.splitext(save_path)

        if file_extension == ".zip":

            print "importing zip file:", save_path

            # unzip file
            fh = open(save_path, 'rb')
            z = zipfile.ZipFile(fh)
            z.extractall()
            # depending on how file was zipped, the extracted directory
            # may be different than the zip filename, so update the app_dir_name
            # to the extracted filename
            app_dir_name = z.namelist()[0]
            fh.close()

            # get the username, appname, and case id out of the file structure
            _, user, app, cid, _ = z.namelist()[0].split(os.sep, 4)

            # delete zip file
            user_input = ''
            if 'SPC_REMOVE_ZIP' in os.environ:
                user_input = os.environ['SPC_REMOVE_ZIP']
            else:
                user_input = raw_input('Remove zip file? [Yn] ') or 'y'
            if user_input.lower() == 'y':
                os.unlink(save_path)
                print save_path, " removed"
            else:
                print save_path, " not removed"

        else:
            print "importing directory:", save_path
            _, user, app, cid = save_path.split(os.sep)

        import_job_db(user, app, cid)

        print "imported case. user:"******"app:", app, "cid:", cid

    elif (sys.argv[1] == "install"):
        import app_reader_writer as apprw
        #import platform
        #platform.system()  # Darwin, Linux, Windows, or Java
        #platform.machine() # i386, x86_64
        install_usage = "usage: spc install /path/to/file.zip\n    or spc install http://url/to/file.zip"

        if len(sys.argv) == 3:
            import migrate, config

            if re.search(r'http[s]://.*$', sys.argv[2]):
                dlfile(sys.argv[2])  # download zip file
                # if url is http://website.com/path/to/file.zip
                # following line extracts out just "file.zip" which should
                # now be in the current directory
                save_path = os.path.basename(sys.argv[2].split('//')[1])
            else:
                save_path = sys.argv[2]

            app_dir_name = os.path.basename(save_path).split('.')[0]
            if os.path.isfile(app_dir_name):
                print 'ERROR: app directory exists already. Please remove first.'
                sys.exit()
            # don't overwrite another directory if it exists
            # instead rename old redirectory with timestamp
            if os.path.isfile(app_dir_name):
                timestr = time.strftime("%Y%m%d-%H%M%S")
                shutil.move(app_dir_name, app_dir_name + "." + timestr)

            # unzip file
            fh = open(save_path, 'rb')
            z = zipfile.ZipFile(fh)
            z.extractall()
            # depending on how file was zipped, the extracted directory
            # may be different than the zip filename, so update the app_dir_name
            # to the extracted filename
            app_dir_name = z.namelist()[0]
            fh.close()

            # delete downloaded zip file
            if re.search(r'http[s]://.*$', sys.argv[2]):
                os.unlink(save_path)

            # delete __MACOSX dir if exists
            if os.path.exists("__MACOSX"):
                shutil.rmtree("__MACOSX")

            # read the json app config file and insert info into db
            path = app_dir_name + os.sep + "spc.json"
            with open(path, 'r') as f:
                data = f.read()
            parsed = json.loads(data)

            # get name of app from json data
            app = parsed['name']
            app_path = apprw.apps_dir + os.sep + app

            # move directory to apps folder
            shutil.move(app_dir_name, app_path)

            # connect to db
            dal = migrate.dal(uri=config.uri)

            # check if app already exists before preceding
            result = dal.db(
                dal.db.apps.name == parsed['name']).select().first()
            if result:
                print "\n*** ERROR: app already exists in database ***"
                shutil.rmtree(app_path)
                sys.exit()

            # copy tpl file to views/apps folder
            src = apprw.apps_dir + os.sep + app + os.sep + app + '.tpl'
            dst = 'views' + os.sep + 'apps'
            shutil.copy(src, dst)

            # turn on executable bit
            path = os.path.join(apprw.apps_dir, app, app)
            if os.path.exists(path): os.chmod(path, 0700)

            # add app to database
            appid = dal.db.apps.insert(name=app,
                                       description=parsed['description'],
                                       category=parsed['category'],
                                       language=parsed['language'],
                                       input_format=parsed['input_format'],
                                       command=parsed['command'],
                                       assets=', '.join(parsed['assets']),
                                       preprocess=parsed['preprocess'],
                                       postprocess=parsed['postprocess'])

            # copy static assets to static/apps/appname directory
            stat_apps_dir = os.path.join('static', 'apps')
            if not os.path.exists(stat_apps_dir):
                os.makedirs(stat_apps_dir)

            stat_app_dir = os.path.join(stat_apps_dir, app)
            if not os.path.exists(stat_app_dir):
                os.makedirs(stat_app_dir)

            dst = 'static' + os.sep + 'apps' + os.sep + app
            if 'assets' in parsed.keys():
                for asset in parsed['assets']:
                    src = os.path.join(apprw.apps_dir, app, asset)
                    shutil.copy(src, dst)

            # add plots and datasources to db
            if 'plots' in parsed.keys():
                for key in parsed['plots']:
                    if key['ptype'] == 'flot-3d':
                        # For flot-3d we need different fields than other plot types
                        # so as a hack we json encode everything and save it in
                        # the filename field
                        pltid = dal.db.plots.insert(appid=appid,
                                                    ptype=key['ptype'],
                                                    title=key['title'],
                                                    options=json.dumps(
                                                        key['options']))
                    else:
                        pltid = dal.db.plots.insert(appid=appid,
                                                    ptype=key['ptype'],
                                                    title=key['title'],
                                                    options=key['options'])

                        for ds in key['datasource']:
                            dal.db.datasource.insert(
                                pltid=pltid,
                                filename=ds['filename'],
                                cols=ds['cols'],
                                line_range=ds['line_range'],
                                data_def=ds['data_def'])

            # commit to db
            dal.db.commit()
            print "SUCCESS: installed app", app
            print "Note: If SPC is running, you will need to restart"
        else:
            print install_usage

    elif (sys.argv[1] == "list"):
        from spc import config
        list_usage = "usage: spc list [available|installed]"
        if (len(sys.argv) == 3):
            if (sys.argv[2] == "installed"):
                from spc import migrate
                dal = migrate.dal(uri=config.uri)
                result = dal.db().select(dal.db.apps.ALL)
                for r in result:
                    print r.name
            elif (sys.argv[2] == "available"):
                try:
                    response = urllib2.urlopen(url)
                    html = response.read()
                    root = ET.fromstring(html)
                    for child in root.findall(
                            "{http://s3.amazonaws.com/doc/2006-03-01/}Contents"
                    ):
                        for c in child.findall(
                                "{http://s3.amazonaws.com/doc/2006-03-01/}Key"
                        ):
                            (app, ext) = c.text.split(".")
                            print app
                except:
                    print "ERROR: problem accessing network"
                    sys.exit()
            else:
                print list_usage
        else:
            print list_usage

    elif (sys.argv[1] == "update"):
        import migrate, config, app_reader_writer as apprw

        usage = "usage: spc update appname [command|plots]"

        if len(sys.argv) > 2:
            app = sys.argv[2]
        else:
            print usage
            sys.exit()

        app_path = apprw.apps_dir + os.sep + app
        dal = migrate.dal(uri=config.uri, migrate=True)

        # check if directory exists
        if not os.path.isdir(app_path):
            print 'ERROR: app directory does not exist'
            print usage
            sys.exit()

        file_path = os.path.join(app_path, "spc.json")

        if not os.path.isfile(os.path.join(app_path, "spc.json")):
            print 'ERROR: spc.json file does not exist in ' + app_path
            sys.exit()

        # read the json app config file and insert info into db
        with open(file_path, 'r') as f:
            data = f.read()
        parsed = json.loads(data)

        # check if this is the correct spc.json for the app specified
        if not app == parsed['name']:
            print 'ERROR: app name specified in spc.json file different than command line'
            sys.exit()
        else:
            appid = dal.db.apps(name=app).id

        if len(sys.argv) == 4:

            if sys.argv[3] == "command":
                dal = migrate.dal(uri=config.uri, migrate=True)
                dal.db.apps(name=sys.argv[2]).update_record(
                    command=parsed['command'])
                dal.db.commit()
                print "updated", app, "command to:", parsed['command']

            elif sys.argv[3] == "plots":

                np = nd = 0
                # update plots and datasources
                if 'plots' in parsed.keys():

                    for key in parsed['plots']:
                        sys.stdout.write('P')
                        # following is not working but it should be the proper way to implement
                        nrecords = dal.db.plots.update_or_insert(
                            dal.db.plots.title == key['title'],
                            appid=appid,
                            ptype=key['ptype'],
                            title=key['title'],
                            options=key['options'])

                        if nrecords is not None:
                            print '\nINFO: inserting plot definition', key[
                                'title']
                            np += 1

                        pltid = dal.db.plots(title=key['title']).id

                        for ds in key['datasource']:
                            sys.stdout.write('.')
                            nrecords = dal.db.datasource.update_or_insert(
                                dal.db.datasource.label == ds['label'],
                                label=ds['label'],
                                pltid=pltid,
                                filename=ds['filename'],
                                cols=ds['cols'],
                                line_range=ds['line_range'],
                                data_def=ds['data_def'])
                            if nrecords is not None:
                                print '\nINFO: inserting datasource for plt', pltid
                                nd += 1

                # commit changes to db
                dal.db.commit()
                print
                if np > 0: print "SUCCESS: inserted", np, "plot defs"
                if nd > 0: print "SUCCESS: inserted defs for app", app
                print
                print "NOTE: some plot records may have been updated but currently web2py DAL does not notify about that"
            else:
                print "ERROR: option not supported"
                sys.exit()
        else:
            print usage
            sys.exit()

    elif sys.argv[1] == "requirements":
        os.system('virtualenv venv')
        os.system('./venv/bin/pip install -r requirements.txt')
    else:
        print "ERROR: option not supported"
        sys.exit()