示例#1
0
def am_initialize(annroot, userhome, userconfig, options):
    """
    Initialize Annalist server data, database, etc.

    annroot     is the root directory for theannalist software installation.
    userhome    is the home directory for the host system user issuing the initialize command.
    userconfig  is the directory used for user-specific configuration files.
    options     contains options parsed from the command line.

    returns     0 if all is well, or a non-zero status code.
                This value is intended to be used as an exit status code
                for the calling program.
    """
    settings = am_get_settings(annroot, userhome, options)
    if not settings:
        print("Settings not found (%s)"%(options.configuration), file=sys.stderr)
        return am_errors.AM_NOSETTINGS
    if len(options.args) != 0:
        print("Unexpected arguments for initialize: (%s)"%(" ".join(options.args)), file=sys.stderr)
        return am_errors.AM_UNEXPECTEDARGS
    # Get config base directory from settings, and make sure it exists
    with SuppressLogging(logging.INFO):
        sitesettings = importlib.import_module(settings.modulename)
    providersdir = os.path.join(sitesettings.CONFIG_BASE, "providers")
    databasedir  = os.path.dirname(sitesettings.DATABASES['default']['NAME'])
    ensure_dir(providersdir)
    ensure_dir(databasedir)
    # Initialze the database
    status = am_errors.AM_SUCCESS
    subprocess_command = "django-admin migrate --pythonpath=%s --settings=%s"%(annroot, settings.modulename)
    log.debug("am_initialize subprocess: %s"%subprocess_command)
    # OLD: status = os.system(subprocess_command)
    status = subprocess.call(subprocess_command.split())
    log.debug("am_initialize subprocess status: %s"%status)
    return status
示例#2
0
 def _save(self):
     """
     Save current entity to Annalist storage
     """
     # @@TODO: think about capturing provenance metadata too.
     if not self._entityref:
         raise ValueError("Entity._save without defined entity reference")
     if not self._values:
         raise ValueError("Entity._save without defined entity values")
     (body_dir, body_file) = self._dir_path()
     log.debug("EntityRoot._save: dir %s, file %s"%(body_dir, body_file))
     fullpath = os.path.join(settings.BASE_DATA_DIR, "annalist_site", body_file)
     # Next is partial protection against code errors
     if not fullpath.startswith(os.path.join(settings.BASE_DATA_DIR, "annalist_site")):
         raise ValueError("Attempt to create entity file outside Annalist site tree")
     # Create directory (if needed) and save data
     util.ensure_dir(body_dir)
     values = self._values.copy()
     values['@id']   = self._entityref
     values['@type'] = self._get_types(values.get('@type', None))
     # @TODO: is this next needed?  Put logic in set_values?
     if self._entityid:
         values[ANNAL.CURIE.id] = self._entityid
     with open(fullpath, "wt") as entity_io:
         json.dump(values, entity_io, indent=2, separators=(',', ': '))
     self._entityuseurl  = self._entityurl
     return
示例#3
0
def am_initialize(annroot, userhome, userconfig, options):
    """
    Initialize Annalist server data, database, etc.

    annroot     is the root directory for the annalist software installation.
    userhome    is the home directory for the host system user issuing the initialize command.
    userconfig  is the directory used for user-specific configuration files.
    options     contains options parsed from the command line.

    returns     0 if all is well, or a non-zero status code.
                This value is intended to be used as an exit status code
                for the calling program.
    """
    settings_obj = am_get_settings(annroot, userhome, options)
    if not settings_obj:
        print("Settings not found (%s)"%(options.configuration), file=sys.stderr)
        return am_errors.AM_NOSETTINGS
    if len(options.args) != 0:
        print("Unexpected arguments for initialize: (%s)"%(" ".join(options.args)), file=sys.stderr)
        return am_errors.AM_UNEXPECTEDARGS
    # Get config base directory from settings, and make sure it exists
    with SuppressLogging(logging.INFO):
        sitesettings = importlib.import_module(settings_obj.modulename)

    # For unknown reason, the database path in DATABASES gets zapped, 
    # so code changed to use separately saved DATABASE_PATH.
    providersdir = os.path.join(sitesettings.CONFIG_BASE, "providers")
    databasedir  = os.path.dirname(sitesettings.DATABASE_PATH)
    ensure_dir(providersdir)
    ensure_dir(databasedir)
    # Initialze the database
    status = am_errors.AM_SUCCESS
    subprocess_command = (
        "django-admin migrate --pythonpath=%s --settings=%s"%
        (annroot, settings_obj.modulename)
        )
    log.debug("am_initialize subprocess: %s"%subprocess_command)
    # status = subprocess.call(
    #     subprocess_command.split(), 
    #     #stdout=sys.stdout, stderr=sys.stderr
    #     )
    # Allow stdout and stderr to be captured for testing
    p = subprocess.Popen(
        subprocess_command.split(), 
        stdout=subprocess.PIPE, stderr=subprocess.PIPE
        )
    out, err = p.communicate(None)
    status = p.returncode
    sys.stdout.write(bytes_to_str(out))
    sys.stderr.write(bytes_to_str(err))
    log.debug("am_initialize subprocess status: %s"%status)
    return status
示例#4
0
 def _save(self, post_update_flags=None):
     """
     Save current entity to Annalist storage
     """
     # @@TODO: think about capturing provenance metadata too.
     if not self._entityref:
         raise ValueError("Entity._save without defined entity reference")
     if not self._contextref:
         raise ValueError("Entity._save without defined context reference")
     if not self._values:
         raise ValueError("Entity._save without defined entity values")
     (body_dir, body_file) = self._dir_path()
     # log.debug("EntityRoot._save: dir %s, file %s"%(body_dir, body_file))
     fullpath = os.path.join(settings.BASE_DATA_DIR, "annalist_site",
                             body_file)
     # Next is partial protection against code errors
     if not fullpath.startswith(
             os.path.join(settings.BASE_DATA_DIR, "annalist_site")):
         log.error("EntityRoot._save: Failing to create entity at %s" %
                   (fullpath, ))
         log.info("EntityRoot._save: dir %s, file %s" %
                  (body_dir, body_file))
         log.info("EntityRoot._save: settings.BASE_DATA_DIR %s" %
                  (settings.BASE_DATA_DIR, ))
         raise ValueError(
             "Attempt to create entity file outside Annalist site tree (%s)"
             % fullpath)
     # Create directory (if needed) and save data
     util.ensure_dir(body_dir)
     values = self._values.copy()
     values['@id'] = self._entityref
     values['@type'] = self._get_types(values.get('@type', None))
     values['@context'] = ([
         {
             '@base': self._baseref
         }, self._contextref
         # layout.COLL_CONTEXT_FILE
         # layout.ENTITY_CONTEXT_PATH + "/" + layout.COLL_CONTEXT_FILE
     ])
     # @TODO: is this next needed?  Put logic in set_values?
     if self._entityid:
         values[ANNAL.CURIE.id] = self._entityid
     values.pop(ANNAL.CURIE.url, None)
     with open(fullpath, "wt") as entity_io:
         json.dump(values,
                   entity_io,
                   indent=2,
                   separators=(',', ': '),
                   sort_keys=True)
     self._post_update_processing(values, post_update_flags)
     return
示例#5
0
 def _save(self, post_update_flags=None):
     """
     Save current entity to Annalist storage
     """
     # @@TODO: think about capturing provenance metadata too.
     if not self._entityref:
         msg = "Entity._save without defined entity reference"
         log.error(msg)
         raise ValueError(msg)
     if not self._contextbase:
         msg = "Entity._save without defined context base"
         log.error(msg)
         raise ValueError(msg)
     if not self._contextref:
         msg = "Entity._save without defined context reference"
         log.error(msg)
         raise ValueError(msg)
     if not self._values:
         msg = "Entity._save without defined entity values"
         log.error(msg)
         raise ValueError(msg)
     (body_dir, body_file) = self._dir_path()
     # log.debug("EntityRoot._save: dir %s, file %s"%(body_dir, body_file))
     fullpath = os.path.join(settings.BASE_DATA_DIR, "annalist_site",
                             body_file)
     # Next is partial protection against code errors
     if not fullpath.startswith(
             os.path.join(settings.BASE_DATA_DIR, "annalist_site")):
         log.error("EntityRoot._save: Failing to create entity at %s" %
                   (fullpath, ))
         log.info("EntityRoot._save: dir %s, file %s" %
                  (body_dir, body_file))
         log.info("EntityRoot._save: settings.BASE_DATA_DIR %s" %
                  (settings.BASE_DATA_DIR, ))
         msg = (
             "Attempt to create entity file outside Annalist site tree (%s)"
             % fullpath)
         log.error(msg)
         raise ValueError(msg)
     # Create directory (if needed) and save data
     util.ensure_dir(body_dir)
     values = self.get_save_values()
     with open(fullpath, "wt") as entity_io:
         json.dump(values,
                   entity_io,
                   indent=2,
                   separators=(',', ': '),
                   sort_keys=True)
     self._post_update_processing(values, post_update_flags)
     return
示例#6
0
 def _save(self, post_update_flags=None):
     """
     Save current entity to Annalist storage
     """
     # @@TODO: think about capturing provenance metadata too.
     if not self._entityref:
         raise ValueError("Entity._save without defined entity reference")
     if not self._contextref:
         raise ValueError("Entity._save without defined context reference")
     if not self._values:
         raise ValueError("Entity._save without defined entity values")
     (body_dir, body_file) = self._dir_path()
     # log.debug("EntityRoot._save: dir %s, file %s"%(body_dir, body_file))
     fullpath = os.path.join(settings.BASE_DATA_DIR, "annalist_site", body_file)
     # Next is partial protection against code errors
     if not fullpath.startswith(os.path.join(settings.BASE_DATA_DIR, "annalist_site")):
         log.error("EntityRoot._save: Failing to create entity at %s"%(fullpath,))
         log.info("EntityRoot._save: dir %s, file %s"%(body_dir, body_file))
         log.info("EntityRoot._save: settings.BASE_DATA_DIR %s"%(settings.BASE_DATA_DIR,))
         raise ValueError(
             "Attempt to create entity file outside Annalist site tree (%s)"%
             fullpath
             )
     # Create directory (if needed) and save data
     util.ensure_dir(body_dir)
     values = self._values.copy()
     values['@id']      = self._entityref
     values['@type']    = self._get_types(values.get('@type', None))
     values['@context'] = (
         [ { '@base': self._baseref }
         , self._contextref
         # layout.COLL_CONTEXT_FILE
         # layout.ENTITY_CONTEXT_PATH + "/" + layout.COLL_CONTEXT_FILE
         ])
     # @TODO: is this next needed?  Put logic in set_values?
     if self._entityid:
         values[ANNAL.CURIE.id] = self._entityid
     values.pop(ANNAL.CURIE.url, None)
     with open(fullpath, "wt") as entity_io:
         json.dump(values, entity_io, indent=2, separators=(',', ': '), sort_keys=True)
     self._post_update_processing(values, post_update_flags)
     return
示例#7
0
 def _save(self, post_update_flags=None):
     """
     Save current entity to Annalist storage
     """
     # @@TODO: think about capturing provenance metadata too.
     if not self._entityref:
         msg = "Entity._save without defined entity reference"
         log.error(msg)
         raise ValueError(msg)
     if not self._contextbase:
         msg = "Entity._save without defined context base"
         log.error(msg)
         raise ValueError(msg)
     if not self._contextref:
         msg = "Entity._save without defined context reference"
         log.error(msg)
         raise ValueError(msg)
     if not self._values:
         msg = "Entity._save without defined entity values"
         log.error(msg)
         raise ValueError(msg)
     (body_dir, body_file) = self._dir_path()
     # log.debug("EntityRoot._save: dir %s, file %s"%(body_dir, body_file))
     fullpath = os.path.join(settings.BASE_SITE_DIR, body_file)
     # Next is partial protection against code errors
     if not fullpath.startswith(settings.BASE_SITE_DIR):
         log.error("EntityRoot._save: Failing to create entity at %s"%(fullpath,))
         log.info("EntityRoot._save: dir %s, file %s"%(body_dir, body_file))
         log.info("EntityRoot._save: settings.BASE_DATA_DIR %s"%(settings.BASE_DATA_DIR,))
         msg = (
             "Attempt to create entity file outside Annalist site tree (%s)"%
             fullpath
             )
         log.error(msg)
         raise ValueError(msg)
     # Create directory (if needed) and save data
     util.ensure_dir(body_dir)
     values = self.get_save_values()
     with open(fullpath, "wt") as entity_io:
         json.dump(values, entity_io, indent=2, separators=(',', ': '), sort_keys=True)
     self._post_update_processing(values, post_update_flags)
     return
示例#8
0
    def _metaobj(self, localpath, localname, mode):
        #@@TODO: abstract logic to work with non-file storage
        #        Used by 'collection', 'site'
        """
        Returns a file object for accessing a metadata resource associated with 
        the current entity.

        localpath   is the local directory path (relative to the current entity's data)
                    where the metadata resource will be accessed.
        localname   is the local name used to identify the file/resource among all those
                    associated with the current entity.
        mode        is a string defining how the resource is opened (using the same values
                    as the built-in `open` function).
        """
        (body_dir, body_file) = self._dir_path()  # Same as `_save`
        local_dir = os.path.join(body_dir, localpath)
        util.ensure_dir(local_dir)
        filename = os.path.join(local_dir, localname)
        # log.debug("entityroot._metaobj: self._entitydir %s"%(self._entitydir,))
        # log.debug("entityroot._metaobj: body_dir %s, body_file %s"%(body_dir, body_file))
        # log.debug("entityroot._metaobj: filename %s"%(filename,))
        return open(filename, mode)
示例#9
0
    def _metaobj(self, localpath, localname, mode):
        #@@TODO: abstract logic to work with non-file storage
        #        Used by 'collection', 'site'
        """
        Returns a file object for accessing a metadata resource associated with 
        the current entity.

        localpath   is the local directory path (relative to the current entity's data)
                    where the metadata resource will be accessed.
        localname   is the local name used to identify the file/resource among all those
                    associated with the current entity.
        mode        is a string defining how the resource is opened (using the same values
                    as the built-in `open` function).
        """
        (body_dir, body_file) = self._dir_path()  # Same as `_save`
        local_dir = os.path.join(body_dir, localpath)
        util.ensure_dir(local_dir)
        filename = os.path.join(local_dir, localname)
        # log.debug("entityroot._metaobj: self._entitydir %s"%(self._entitydir,))
        # log.debug("entityroot._metaobj: body_dir %s, body_file %s"%(body_dir, body_file))
        # log.debug("entityroot._metaobj: filename %s"%(filename,))
        return open(filename, mode)
示例#10
0
def am_createsite(annroot, userhome, options):
    """
    Create Annalist empty site data.

    annroot     is the root directory for the Annalist software installation.
    userhome    is the home directory for the host system user issuing the command.
    options     contains options parsed from the command line.

    returns     0 if all is well, or a non-zero status code.
                This value is intended to be used as an exit status code
                for the calling program.
    """
    status       = am_errors.AM_SUCCESS
    sitesettings = am_get_site_settings(annroot, userhome, options) 
    if not sitesettings:
        print("Settings not found (%s)"%(options.configuration), file=sys.stderr)
        return am_errors.AM_NOSETTINGS
    if len(options.args) > 0:
        print(
            "Unexpected arguments for %s: (%s)"%
            (options.command, " ".join(options.args)), 
            file=sys.stderr
            )
        return am_errors.AM_UNEXPECTEDARGS
    site_layout = layout.Layout(sitesettings.BASE_DATA_DIR, sitesettings.SITE_DIR_NAME)
    sitebasedir = site_layout.SITE_PATH
    #@@@@@ sitebaseurl = "/annalist/"     # @@TODO: figure more robust way to define this
    sitebaseurl = sitesettings.STATIC_URL
    # --- If old site exists and --force option given, remove it
    if os.path.exists(os.path.join(sitebasedir, site_layout.SITEDATA_DIR)):
        if options.force:
            print("Removing old Annalist site at %s"%(sitebasedir))
            log.info("rmtree: %s"%(sitebasedir))
            removetree(sitebasedir)
        else:
            print(
                "Old data already exists at %s (use '--force' or '-f' to overwrite)."%
                (sitebasedir), file=sys.stderr
                )
            print(
                "NOTE: using '--force' or '-f' "+
                "removes old site user permissions and namespace data "+
                "and requires re-initialization of Django database with local usernames; "+
                "consider using 'annalist-manager updatesite'."
                )
            return am_errors.AM_EXISTS
    # --- Initialize empty site data in target directory
    print("Initializing Annalist site in %s"%(sitebasedir))
    site = Site.create_site_metadata(
        sitebaseurl, sitebasedir,
        label="Annalist site (%s configuration)"%options.configuration, 
        description="Annalist %s site metadata and site-wide values."%options.configuration
        )
    sitedata = site.site_data_collection()
    Site.create_site_readme(site)
    site_data_src = os.path.join(annroot, "annalist/data/sitedata")     # @@TODO: more robust definition
    site_data_tgt, site_data_file = sitedata._dir_path()
    print("Copy Annalist site data")
    print("from %s"%site_data_src)
    for sdir in layout.COLL_DIRS:
        print("- %s -> %s"%(sdir, site_data_tgt))
        Site.replace_site_data_dir(sitedata, sdir, site_data_src)
    # @@TODO: filename logic copied from EntityRoot and Collection - create separate method for getting this
    (sitedata_dir, sitedata_file) = sitedata._dir_path()
    context_dir  = os.path.join(sitedata_dir, layout.META_COLL_BASE_REF)
    context_file = os.path.join(context_dir, layout.COLL_CONTEXT_FILE)
    #@@
    print("Generating %s"%(context_file))
    sitedata.generate_coll_jsonld_context()
    # --- Copy provider data to site config provider directory
    provider_dir_src = os.path.join(annroot, "annalist/data/identity_providers")
    provider_dir_tgt = os.path.join(sitesettings.CONFIG_BASE, "providers")
    print("Copy identity provider data:")
    print("- from: %s"%(provider_dir_src,))
    print("-   to: %s"%(provider_dir_tgt,))
    ensure_dir(provider_dir_tgt)
    updatetree(provider_dir_src, provider_dir_tgt)
    # --- Copy sample system configuration files to config directory
    config_dir_src = os.path.join(annroot, "annalist/data/config_examples")
    config_dir_tgt = os.path.join(sitesettings.CONFIG_BASE, "config")
    print("Copy system configuration sample files:")
    print("- from: %s"%(config_dir_src,))
    print("-   to: %s"%(config_dir_tgt,))
    ensure_dir(config_dir_tgt)
    updatetree(config_dir_src, config_dir_tgt)
    # --- Created
    print("Now run 'annalist-manager initialize' to create site admin database")
    return status
示例#11
0
def am_updatesite(annroot, userhome, options):
    """
    Update site data, leaving user data alone

    annroot     is the root directory for the Annalist software installation.
    userhome    is the home directory for the host system user issuing the command.
    options     contains options parsed from the command line.

    returns     0 if all is well, or a non-zero status code.
                This value is intended to be used as an exit status code
                for the calling program.
    """
    status       = am_errors.AM_SUCCESS
    sitesettings = am_get_site_settings(annroot, userhome, options) 
    if not sitesettings:
        print("Settings not found (%s)"%(options.configuration), file=sys.stderr)
        return am_errors.AM_NOSETTINGS
    if len(options.args) > 0:
        print(
            "Unexpected arguments for %s: (%s)"%
            (options.command, " ".join(options.args)), 
            file=sys.stderr
            )
        return am_errors.AM_UNEXPECTEDARGS
    site_layout   = layout.Layout(sitesettings.BASE_DATA_DIR, sitesettings.SITE_DIR_NAME)
    sitebasedir   = site_layout.SITE_PATH
    sitebaseurl   = "/annalist/"                # @@TODO: figure more robust way to define this
    site          = Site(sitebaseurl, site_layout.SITE_PATH)
    sitedata      = site.site_data_collection(test_exists=False)
    if sitedata is None:
        print("Initializing Annalist site metadata in %s (migrating to new layout)"%(sitebasedir))
        site = Site.create_site_metadata(
            sitebaseurl, sitebasedir,
            label="Annalist site (%s configuration)"%options.configuration, 
            description="Annalist %s site metadata and site-wide values."%options.configuration
            )
        sitedata      = site.site_data_collection()
    site_data_src = os.path.join(annroot, "annalist/data/sitedata")  # @@TODO: more robust definition
    site_data_tgt, site_data_file = sitedata._dir_path()
    # --- Migrate old site data to new site directory
    #    _annalist_site/
    site_data_old1      = os.path.join(sitebasedir, site_layout.SITEDATA_OLD_DIR1)
    old_site_metadata   = os.path.join(site_data_old1, site_layout.SITE_META_FILE)
    old_site_database   = os.path.join(site_data_old1, site_layout.SITE_DATABASE_FILE)
    old_users1          = os.path.join(site_data_old1, layout.USER_DIR_PREV)
    old_vocabs1         = os.path.join(site_data_old1, layout.VOCAB_DIR_PREV)
    if os.path.isfile(old_site_metadata):
        print("Move old site metadata: %s -> %s"%(old_site_metadata, sitebasedir))
        new_site_metadata   = os.path.join(sitebasedir, site_layout.SITE_META_FILE)
        os.rename(old_site_metadata, new_site_metadata)
    if os.path.isfile(old_site_database):
        print("Move old site database: %s -> %s"%(old_site_database, sitebasedir))
        new_site_database   = os.path.join(sitebasedir, site_layout.SITE_DATABASE_FILE)
        os.rename(old_site_database, new_site_database)
    if os.path.isdir(old_users1) or os.path.isdir(old_vocabs1):
        print("Copy Annalist old user and/or vocab data from %s"%site_data_old1)
        migrate_old_data(site_data_old1, layout.USER_DIR_PREV,  site_data_tgt, layout.USER_DIR )
        migrate_old_data(site_data_old1, layout.VOCAB_DIR_PREV, site_data_tgt, layout.VOCAB_DIR)
    #    c/_annalist_site/_annalist_collection/ - using new dir names
    site_data_old2 = os.path.join(sitebasedir, site_layout.SITEDATA_OLD_DIR2)
    old_users2     = os.path.join(site_data_old2, layout.USER_DIR)
    old_vocabs2    = os.path.join(site_data_old2, layout.VOCAB_DIR)
    if os.path.isdir(old_users2) or os.path.isdir(old_vocabs2):
        print("Copy Annalist old user and/or vocab data from %s"%site_data_old2)
        migrate_old_data(site_data_old2, layout.USER_DIR_PREV,  site_data_tgt, layout.USER_DIR )
        migrate_old_data(site_data_old2, layout.VOCAB_DIR_PREV, site_data_tgt, layout.VOCAB_DIR)
    # --- Archive old site data so it's not visible next time
    if os.path.isdir(site_data_old1):  
        archive_old_data(site_data_old1, "")
    if os.path.isdir(site_data_old2):
        archive_old_data(site_data_old2, "")
    # --- Copy latest site data to target directory
    print("Copy Annalist site data")
    print("from %s"%site_data_src)
    for sdir in layout.DATA_DIRS:
        print("- %s -> %s"%(sdir, site_data_tgt))
        Site.replace_site_data_dir(sitedata, sdir, site_data_src)
    for sdir in (layout.USER_DIR, layout.VOCAB_DIR):
        print("- %s +> %s"%(sdir, site_data_tgt))
        Site.update_site_data_dir(sitedata, sdir, site_data_src)
    for sdir in (layout.INFO_DIR,):
        print("- %s ~> %s"%(sdir, site_data_tgt))
        Site.expand_site_data_dir(sitedata, sdir, site_data_src)
    for sdir in layout.COLL_DIRS_PREV:
        remove_old_data(site_data_tgt, sdir)
    print("Generating context for site data")
    sitedata.generate_coll_jsonld_context()
    # --- Copy provider data to site config provider directory
    provider_dir_src = os.path.join(annroot, "annalist/data/identity_providers")
    provider_dir_tgt = os.path.join(sitesettings.CONFIG_BASE, "providers")
    print("Copy identity provider data:")
    print("- from: %s"%(provider_dir_src,))
    print("-   to: %s"%(provider_dir_tgt,))
    ensure_dir(provider_dir_tgt)
    updatetree(provider_dir_src, provider_dir_tgt)
    # --- Copy sample system configuration files to config directory
    config_dir_src = os.path.join(annroot, "annalist/data/config_examples")
    config_dir_tgt = os.path.join(sitesettings.CONFIG_BASE, "config")
    print("Copy system configuration sample files:")
    print("- from: %s"%(config_dir_src,))
    print("-   to: %s"%(config_dir_tgt,))
    ensure_dir(config_dir_tgt)
    updatetree(config_dir_src, provider_dir_tgt)
    return status
示例#12
0
def am_createsite(annroot, userhome, options):
    """
    Create Annalist empty site data.

    annroot     is the root directory for the Annalist software installation.
    userhome    is the home directory for the host system user issuing the command.
    options     contains options parsed from the command line.

    returns     0 if all is well, or a non-zero status code.
                This value is intended to be used as an exit status code
                for the calling program.
    """
    status = am_errors.AM_SUCCESS
    sitesettings = am_get_site_settings(annroot, userhome, options)
    if not sitesettings:
        print("Settings not found (%s)" % (options.configuration),
              file=sys.stderr)
        return am_errors.AM_NOSETTINGS
    if len(options.args) > 0:
        print("Unexpected arguments for %s: (%s)" %
              (options.command, " ".join(options.args)),
              file=sys.stderr)
        return am_errors.AM_UNEXPECTEDARGS
    site_layout = layout.Layout(sitesettings.BASE_DATA_DIR)
    sitebasedir = site_layout.SITE_PATH
    sitebaseurl = "/annalist/"  # @@TODO: figure more robust way to define this
    # --- If old site exists and --force option given, remove it
    if os.path.exists(os.path.join(sitebasedir, site_layout.SITEDATA_DIR)):
        if options.force:
            print("Removing old Annalist site at %s" % (sitebasedir))
            log.info("rmtree: %s" % (sitebasedir))
            removetree(sitebasedir)
        else:
            print(
                "Old data already exists at %s (use '--force' or '-f' to overwrite)."
                % (sitebasedir),
                file=sys.stderr)
            print(
                "NOTE: using '--force' or '-f' " +
                "removes old site user permissions and namespace data " +
                "and requires re-initialization of Django database with local usernames; "
                + "consider using 'annalist-manager updatesite'.")
            return am_errors.AM_EXISTS
    # --- Initialize empty site data in target directory
    print("Initializing Annalist site in %s" % (sitebasedir))
    site = Site.create_site_metadata(
        sitebaseurl,
        sitebasedir,
        label="Annalist site (%s configuration)" % options.configuration,
        description="Annalist %s site metadata and site-wide values." %
        options.configuration)
    sitedata = site.site_data_collection()
    Site.create_site_readme(site)
    site_data_src = os.path.join(
        annroot, "annalist/data/sitedata")  # @@TODO: more robust definition
    site_data_tgt, site_data_file = sitedata._dir_path()
    print("Copy Annalist site data")
    print("from %s" % site_data_src)
    for sdir in layout.COLL_DIRS:
        print("- %s -> %s" % (sdir, site_data_tgt))
        Site.replace_site_data_dir(sitedata, sdir, site_data_src)
    # @@TODO: filename logic copied from EntityRoot and Collection - create separate method for getting this
    (sitedata_dir, sitedata_file) = sitedata._dir_path()
    context_dir = os.path.join(sitedata_dir, layout.META_COLL_BASE_REF)
    context_file = os.path.join(context_dir, layout.COLL_CONTEXT_FILE)
    #@@
    print("Generating %s" % (context_file))
    sitedata.generate_coll_jsonld_context()
    # --- Copy provider data to site config provider directory
    provider_dir_src = os.path.join(annroot,
                                    "annalist/data/identity_providers")
    provider_dir_tgt = os.path.join(sitesettings.CONFIG_BASE, "providers")
    print("Copy identity provider data:")
    print("- from: %s" % (provider_dir_src, ))
    print("-   to: %s" % (provider_dir_tgt, ))
    ensure_dir(provider_dir_tgt)
    updatetree(provider_dir_src, provider_dir_tgt)
    # --- Created
    print(
        "Now run 'annalist-manager initialize' to create site admin database")
    return status
示例#13
0
def am_updatesite(annroot, userhome, options):
    """
    Update site data, leaving user data alone

    annroot     is the root directory for the Annalist software installation.
    userhome    is the home directory for the host system user issuing the command.
    options     contains options parsed from the command line.

    returns     0 if all is well, or a non-zero status code.
                This value is intended to be used as an exit status code
                for the calling program.
    """
    status = am_errors.AM_SUCCESS
    sitesettings = am_get_site_settings(annroot, userhome, options)
    if not sitesettings:
        print("Settings not found (%s)" % (options.configuration),
              file=sys.stderr)
        return am_errors.AM_NOSETTINGS
    if len(options.args) > 0:
        print("Unexpected arguments for %s: (%s)" %
              (options.command, " ".join(options.args)),
              file=sys.stderr)
        return am_errors.AM_UNEXPECTEDARGS
    site_layout = layout.Layout(sitesettings.BASE_DATA_DIR)
    sitebasedir = site_layout.SITE_PATH
    sitebaseurl = "/annalist/"  # @@TODO: figure more robust way to define this
    site = Site(sitebaseurl, site_layout.SITE_PATH)
    sitedata = site.site_data_collection(test_exists=False)
    if sitedata is None:
        print(
            "Initializing Annalist site metadata in %s (migrating to new layout)"
            % (sitebasedir))
        site = Site.create_site_metadata(
            sitebaseurl,
            sitebasedir,
            label="Annalist site (%s configuration)" % options.configuration,
            description="Annalist %s site metadata and site-wide values." %
            options.configuration)
        sitedata = site.site_data_collection()
    site_data_src = os.path.join(
        annroot, "annalist/data/sitedata")  # @@TODO: more robust definition
    site_data_tgt, site_data_file = sitedata._dir_path()
    # --- Migrate old site data to new site directory
    #    _annalist_site/
    site_data_old1 = os.path.join(sitebasedir, site_layout.SITEDATA_OLD_DIR1)
    old_site_metadata = os.path.join(site_data_old1,
                                     site_layout.SITE_META_FILE)
    old_site_database = os.path.join(site_data_old1,
                                     site_layout.SITE_DATABASE_FILE)
    old_users1 = os.path.join(site_data_old1, layout.USER_DIR_PREV)
    old_vocabs1 = os.path.join(site_data_old1, layout.VOCAB_DIR_PREV)
    if os.path.isfile(old_site_metadata):
        print("Move old site metadata: %s -> %s" %
              (old_site_metadata, sitebasedir))
        new_site_metadata = os.path.join(sitebasedir,
                                         site_layout.SITE_META_FILE)
        os.rename(old_site_metadata, new_site_metadata)
    if os.path.isfile(old_site_database):
        print("Move old site database: %s -> %s" %
              (old_site_database, sitebasedir))
        new_site_database = os.path.join(sitebasedir,
                                         site_layout.SITE_DATABASE_FILE)
        os.rename(old_site_database, new_site_database)
    if os.path.isdir(old_users1) or os.path.isdir(old_vocabs1):
        print("Copy Annalist old user and/or vocab data from %s" %
              site_data_old1)
        migrate_old_data(site_data_old1, layout.USER_DIR_PREV, site_data_tgt,
                         layout.USER_DIR)
        migrate_old_data(site_data_old1, layout.VOCAB_DIR_PREV, site_data_tgt,
                         layout.VOCAB_DIR)
    #    c/_annalist_site/_annalist_collection/ - using new dir names
    site_data_old2 = os.path.join(sitebasedir, site_layout.SITEDATA_OLD_DIR2)
    old_users2 = os.path.join(site_data_old2, layout.USER_DIR)
    old_vocabs2 = os.path.join(site_data_old2, layout.VOCAB_DIR)
    if os.path.isdir(old_users2) or os.path.isdir(old_vocabs2):
        print("Copy Annalist old user and/or vocab data from %s" %
              site_data_old2)
        migrate_old_data(site_data_old2, layout.USER_DIR_PREV, site_data_tgt,
                         layout.USER_DIR)
        migrate_old_data(site_data_old2, layout.VOCAB_DIR_PREV, site_data_tgt,
                         layout.VOCAB_DIR)
    # --- Archive old site data so it's not visible next time
    if os.path.isdir(site_data_old1):
        archive_old_data(site_data_old1, "")
    if os.path.isdir(site_data_old2):
        archive_old_data(site_data_old2, "")
    # --- Copy latest site data to target directory
    print("Copy Annalist site data")
    print("from %s" % site_data_src)
    for sdir in layout.DATA_DIRS:
        print("- %s -> %s" % (sdir, site_data_tgt))
        Site.replace_site_data_dir(sitedata, sdir, site_data_src)
    for sdir in (layout.USER_DIR, layout.VOCAB_DIR):
        print("- %s +> %s" % (sdir, site_data_tgt))
        Site.update_site_data_dir(sitedata, sdir, site_data_src)
    for sdir in layout.COLL_DIRS_PREV:
        remove_old_data(site_data_tgt, sdir)
    print("Generating context for site data")
    sitedata.generate_coll_jsonld_context()
    # --- Copy provider data to site config provider directory
    provider_dir_tgt = os.path.join(sitesettings.CONFIG_BASE, "providers")
    provider_dir_src = os.path.join(annroot,
                                    "annalist/data/identity_providers")
    print("Copy identity provider data:")
    print("- from: %s" % (provider_dir_src, ))
    print("-   to: %s" % (provider_dir_tgt, ))
    ensure_dir(provider_dir_tgt)
    updatetree(provider_dir_src, provider_dir_tgt)
    return status