<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.archivematica.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jdunham</id>
	<title>Archivematica - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.archivematica.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jdunham"/>
	<link rel="alternate" type="text/html" href="https://wiki.archivematica.org/Special:Contributions/Jdunham"/>
	<updated>2026-04-29T23:21:33Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.4</generator>
	<entry>
		<id>https://wiki.archivematica.org/index.php?title=MCPClient&amp;diff=12483</id>
		<title>MCPClient</title>
		<link rel="alternate" type="text/html" href="https://wiki.archivematica.org/index.php?title=MCPClient&amp;diff=12483"/>
		<updated>2018-05-11T17:16:37Z</updated>

		<summary type="html">&lt;p&gt;Jdunham: /* Config File */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Main Page]] &amp;gt; [[Development]] &amp;gt; [[:Category:Development documentation|Development documentation]] &amp;gt; MCPClient&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;status&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
Design&lt;br /&gt;
&amp;lt;div class=&amp;quot;description&amp;quot;&amp;gt;This page proposes a new feature and reviews design options&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
Development&lt;br /&gt;
&amp;lt;div class=&amp;quot;description&amp;quot;&amp;gt;This page describes a feature that's in development&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;active&amp;quot;&amp;gt;&lt;br /&gt;
Documentation&lt;br /&gt;
&amp;lt;div class=&amp;quot;description&amp;quot;&amp;gt;This page documents an implemented feature&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Archivematica has one or more MCPClient instances to perform the actual work.  They are gearman worker implementations that inform the gearman server what tasks they can perform, and wait for the server to assign them a task. When a client starts, it connects to the specified gearman server and provides a list of modules they support. When the [[MCPServer]] informs the gearman server of a Task that the client supports and the gearman server assigns the job to the client, the client will process the Job, and return the results to the gearman server, which in turn will return them to the MCPServer.&lt;br /&gt;
&lt;br /&gt;
== Client scripts ==&lt;br /&gt;
Client scripts do the actual work in Archivematica. They are anything that can be run on the command line, from builtins like mv and cp, to custom-written scripts.&lt;br /&gt;
&lt;br /&gt;
New scripts are defined in &amp;lt;code&amp;gt;[https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/archivematicaClientModules src/MCPClient/lib/archivematicaClientModules]&amp;lt;/code&amp;gt;, which is what is registered with Gearman on MCPClient startup.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement note: archivematicaClientModules lists both 'supportedCommandSpecial' and 'supportedCommands'. This distinction may have once been based on scripts that relied on external services, but serves no purpose now and should be removed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The name is what the [[MCPServer#StandardTasksConfigs | StandardTasksConfig]] table will refer to them as, and the value is the script that will be run. Some are defined as shell builtins (eg copy_v0.0 is cp). Most are paths to a script in the clientScripts directory, using the &amp;lt;code&amp;gt;%clientScriptsDirectory%&amp;lt;/code&amp;gt; replacement variable.  The name of the client script is usually the same as the name in archivematicaClientModules, but for very old scripts may have ‘archivematica’ at the beginning (eg createMETS_v2.0 = archivematicaCreateMETS2.py) or be named more pythonically (eg parseExternalMETS = parse_external_mets.py).  Entries are added alphabetically.&lt;br /&gt;
&lt;br /&gt;
The version (eg copy_v0.0) was originally intended to be used to version the scripts as they changed, and be able to track those changes, but that did not happen.  Newer scripts may not have the version defined.&lt;br /&gt;
&lt;br /&gt;
The list of client scripts is sorted roughly in order of appearance during processing&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== moveTransfer_v0.0 ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Move a Transfer &amp;amp; update database&lt;br /&gt;
* '''Script''': [https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/archivematicaMoveTransfer.py archivematicaMoveTransfer.py]&lt;br /&gt;
* '''Used in''': Transfer&lt;br /&gt;
* '''Task type''': [[MCPServer/TaskTypes#Run once  | once]]&lt;br /&gt;
* '''Event?''': No&lt;br /&gt;
* '''FPR?''': No&lt;br /&gt;
&lt;br /&gt;
Moves the whole Transfer and updates the database with the new location relative to the shared directory.&lt;br /&gt;
&lt;br /&gt;
=== assignFileUUIDs_v0.0 ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Starts tracking files new to Archivematica&lt;br /&gt;
* '''Script''': [https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/archivematicaAssignFileUUID.py archivematicaAssignFileUUID.py]&lt;br /&gt;
* '''Used in''': Transfer, Ingest&lt;br /&gt;
* '''Task type''': [[MCPServer/TaskTypes#Run for each file | per file]]&lt;br /&gt;
* '''Event?''': ingestion/reingestion, possibly registration&lt;br /&gt;
* '''FPR?''': No&lt;br /&gt;
&lt;br /&gt;
This creates an entry in the Files table with the file's UUID, current &amp;amp; original paths and file group.  It also creates an 'ingestion' Event and an 'registration' Event if an accession ID was specified.  Updating the file group (eg original, preservation, submission documentation) can be disabled with &amp;lt;code&amp;gt;--disable-update-filegrpuse&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In ingest, is used on manually normalized files which may have been newly added, metadata and submission documentation.&lt;br /&gt;
&lt;br /&gt;
On reingest, it parses the METS file instead of generating the file UUID, path &amp;amp; group.  The Event type is 'reingestion'.&lt;br /&gt;
&lt;br /&gt;
=== updateSizeAndChecksum_v0.0 ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Set file's size &amp;amp; checksum&lt;br /&gt;
* '''Script''': [https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/archivematicaUpdateSizeAndChecksum.py archivematicaUpdateSizeAndChecksum.py]&lt;br /&gt;
* '''Used in''': Transfer, Ingest&lt;br /&gt;
* '''Task type''': [[MCPServer/TaskTypes#Run for each file | per file]]&lt;br /&gt;
* '''Event?''': message digest calculation&lt;br /&gt;
* '''FPR?''': No&lt;br /&gt;
&lt;br /&gt;
Updates the entry in the Files table with a size and checksum. IT also generates a 'message digest calculation' Event.&lt;br /&gt;
&lt;br /&gt;
On reingest, it parses the METS file instead of generating the checksums &amp;amp; sizes. It also re-adds Derivation &amp;amp; Format links.&lt;br /&gt;
&lt;br /&gt;
Note this script will fail if there was a problem with [[#assignFileUUIDs_v0.0]].&lt;br /&gt;
&lt;br /&gt;
=== createMETS_v0.0 ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Generate the transfer METS file&lt;br /&gt;
* '''Script''': [https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/archivematicaCreateMETS.py archivematicaCreateMETS.py]&lt;br /&gt;
* '''Used in''': Transfer&lt;br /&gt;
* '''Task type''': [[MCPServer/TaskTypes#Run once | once]]&lt;br /&gt;
* '''Event?''': No&lt;br /&gt;
* '''FPR?''': No&lt;br /&gt;
&lt;br /&gt;
Creates the Transfer METS file. This will contain all the information generated on the transfer during processing, and is especially useful for backlogged transfers.&lt;br /&gt;
&lt;br /&gt;
Not to be confused with [[#createMETS_v2.0]] for the AIP METS.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement note: The Transfer METS file &amp;amp; related backlog functionality needs to be expanded. See [[Transfer_backlog_requirements#Proposed_improvements]] for details.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== createEvent_v0.0 ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Create an Event outside of other scripts&lt;br /&gt;
* '''Script''': [https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/createEvent.py createEvent.py]&lt;br /&gt;
* '''Used in''': Transfer&lt;br /&gt;
* '''Task type''': [[MCPServer/TaskTypes#Run for each file | per file]]&lt;br /&gt;
* '''Event?''': as parameter: quarantine, unquarantine, placement in backlog, removal from backlog&lt;br /&gt;
* '''FPR?''': No&lt;br /&gt;
&lt;br /&gt;
Used to generate events for when a file is placed in or removed from quarantine or backlog.  These do not have scripts associated with them, so the event creation is handled here.&lt;br /&gt;
&lt;br /&gt;
=== archivematicaClamscan_v0.0 ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Check for viruses in incoming files&lt;br /&gt;
* '''Script''': [https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/archivematicaClamscan.py archivematicaClamscan.py]&lt;br /&gt;
* '''Used in''': Transfer, Ingest&lt;br /&gt;
* '''Task type''': [[MCPServer/TaskTypes#Run for each file | per file]]&lt;br /&gt;
* '''Event?''': virus check&lt;br /&gt;
* '''FPR?''': No&lt;br /&gt;
&lt;br /&gt;
Runs clamscan on the file and generates a 'virus scan' event. If a scan has been run, it is not run again on the same file.&lt;br /&gt;
&lt;br /&gt;
This is run on incoming files, files after extraction, metadata files and submission documentation.  It is not run on normalized files.&lt;br /&gt;
&lt;br /&gt;
=== sanitizeObjectNames_v0.0 ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Strip problematic characters from filenames&lt;br /&gt;
* '''Script''': [https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/sanitizeObjectNames.py sanitizeObjectNames.py]&lt;br /&gt;
* '''Used in''': Transfer, Ingest&lt;br /&gt;
* '''Task type''': [[MCPServer/TaskTypes#Run once | once]]&lt;br /&gt;
* '''Event?''': name cleanup&lt;br /&gt;
* '''FPR?''': No&lt;br /&gt;
* '''Tests''': [https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/tests/test_sanitize.py test_sanitize.py]&lt;br /&gt;
&lt;br /&gt;
Sanitize object names by replacing anything that isn't an ASCII letter, number, hyphen, underscore, period or parenthesis.  This runs on both files and directories, though only files have Events generated. An Event is generated for a file even if only a parent directory is sanitized.&lt;br /&gt;
&lt;br /&gt;
This used code from [https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/sanitizeNames.py sanitizeNames.py]&lt;br /&gt;
&lt;br /&gt;
=== identifyFileFormat_v0.0 ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Identify a file's format&lt;br /&gt;
* '''Script''': [https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/identifyFileFormat.py identifyFileFormat.py]&lt;br /&gt;
* '''Used in''': Transfer, Ingest&lt;br /&gt;
* '''Task type''': [[MCPServer/TaskTypes#Run for each file | per file]]&lt;br /&gt;
* '''Event?''': format identification&lt;br /&gt;
* '''FPR?''': IDCommand &amp;amp; IDRule&lt;br /&gt;
&lt;br /&gt;
One of the most important scripts in Archivematica. Since the file format is used to determine many later actions (extraction, characterization, normalization etc), if this fails many important command later will also fail.  This is the only script that uses the FPR that doesn't use the file format as a key for looking up what command to run. Instead, an IDCommand is selected and the output is matched to an IDRule to find the FormatVersion.&lt;br /&gt;
&lt;br /&gt;
There is a short circuit handling of PRONOM ID (PUID) outputs. Since many FormatVersions have PUIDs, and both FIDO &amp;amp; Siegfried output PUIDs, this script looks for a FormatVersion with a given PUID. This reduces the number of IDRules that have to be created.&lt;br /&gt;
&lt;br /&gt;
This also populates the legacy but still required FilesIDs table.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: Only one identification tool can be run at a time currently. It would be better to allow a cascading of tools. E.g. if a file is identified as a video to subsequently run a tool specialized in identifying different types of video. Similarly, if the default tool failed, we could run a backup tool for a second opinion.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== extractContents_v0.0 ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Extract files from packages&lt;br /&gt;
* '''Script''': [https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/extractContents.py extractContents.py]&lt;br /&gt;
* '''Used in''': Transfer&lt;br /&gt;
* '''Task type''': [[MCPServer/TaskTypes#Run once | once]]&lt;br /&gt;
* '''Event?''': unpacking, registration, deletion, message digest calculation&lt;br /&gt;
* '''FPR?''': extract&lt;br /&gt;
&lt;br /&gt;
Extracts files from a package (e.g. zip, tar, 7z etc) and optionally deletes the package.  Generates Events for the new files.&lt;br /&gt;
&lt;br /&gt;
=== characterizeFile_v0.0 ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Collects characterization information on a file&lt;br /&gt;
* '''Script''': [https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/characterizeFile.py characterizeFile.py]&lt;br /&gt;
* '''Used in''': Transfer, Ingest&lt;br /&gt;
* '''Task type''': [[MCPServer/TaskTypes#Run for each file | per file]]&lt;br /&gt;
* '''Event?''': No&lt;br /&gt;
* '''FPR?''': characterization, default_characterization&lt;br /&gt;
&lt;br /&gt;
Collects characterization commands for the provided file, then either&lt;br /&gt;
# Inserts the tool's XML output into the database, or&lt;br /&gt;
# Prints the tool's stdout, for tools which do not output XML&lt;br /&gt;
&lt;br /&gt;
If a tool has no defined characterization commands, then the default will be run instead (currently FITS).  Can run multiple characterization commands and log the output of all of them.&lt;br /&gt;
&lt;br /&gt;
=== validateFile_v1.0 ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Validate a file&lt;br /&gt;
* '''Script''': [https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/validateFile.py validateFile.py]&lt;br /&gt;
* '''Used in''': Transfer&lt;br /&gt;
* '''Task type''': [[MCPServer/TaskTypes#Run for each file | per file]]&lt;br /&gt;
* '''Event?''': validation&lt;br /&gt;
* '''FPR?''': validation, default_validation&lt;br /&gt;
&lt;br /&gt;
Validates files are correct, where correctness is defined by the file format.&lt;br /&gt;
&lt;br /&gt;
=== examineContents_v0.0  ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Run bulk extractor for a detailed analysis of contents&lt;br /&gt;
* '''Script''': [https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/examineContents.py examineContents.py]&lt;br /&gt;
* '''Used in''': Transfer&lt;br /&gt;
* '''Task type''': [[MCPServer/TaskTypes#Run for each file | per file]]&lt;br /&gt;
* '''Event?''': No&lt;br /&gt;
* '''FPR?''': No&lt;br /&gt;
&lt;br /&gt;
Runs bulk extractor and stores the outputs in the logs directory.&lt;br /&gt;
&lt;br /&gt;
=== elasticSearchIndex_v0.0 ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Index the Transfer METS into ElasticSearch when sending files to backlog&lt;br /&gt;
* '''Script''': [https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/elasticSearchIndexProcessTransfer.py  elasticSearchIndexProcessTransfer.py]&lt;br /&gt;
* '''Used in''': Transfer&lt;br /&gt;
* '''Task type''': [[MCPServer/TaskTypes#Run once | once]]&lt;br /&gt;
* '''Event?''': No&lt;br /&gt;
* '''FPR?''': No&lt;br /&gt;
&lt;br /&gt;
The data in ElasticSearch is used by the Backlog tab, SIP Arrangement and the Appraisal tab when dealing with files from backlog. Note that this is not run if the transfer is not sent to backlog (since AM 1.5).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement note: The client config 'disableElasticsearchIndexing' can disable indexing, but this should be removed, since searching for files in backlog is required functionality.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== moveSIP_v0.0 ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Move a SIP &amp;amp; update database&lt;br /&gt;
* '''Script''': [https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/archivematicaMoveSIP.py archivematicaMoveSIP.py]&lt;br /&gt;
* '''Used in''': Ingest&lt;br /&gt;
* '''Task type''': [[MCPServer/TaskTypes#Run once | once]]&lt;br /&gt;
* '''Event?''': No&lt;br /&gt;
* '''FPR?''': No&lt;br /&gt;
&lt;br /&gt;
Moves the whole SIP and updates the database with the new location relative to the shared directory.&lt;br /&gt;
&lt;br /&gt;
=== normalize_v1.0 ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Generate a preservation or access derivative&lt;br /&gt;
* '''Script''': [https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/normalize.py normalize.py]&lt;br /&gt;
* '''Used in''': Ingest&lt;br /&gt;
* '''Task type''': [[MCPServer/TaskTypes#Run for each file | per file]]&lt;br /&gt;
* '''Event?''': normalization&lt;br /&gt;
* '''FPR?''': Rules: access, preservation, thumbnail, default_access, default_thumbnail.  Commands: normalization, verification&lt;br /&gt;
&lt;br /&gt;
One of the most important scripts in Archivematica. This generates the preservation and access derivatives, as well as thumbnails.  If manual normalization happens, this instead finds the manually normalized files and links them as derivatives.&lt;br /&gt;
&lt;br /&gt;
The same script is used for generating preservation, access or thumbnail derivatives, controlled by the parameter passed in. In general, normalization is only performed on original files, but may be done on service files.  This reads the FPR for the specific command, and may fall back to a default access or thumbnail command.&lt;br /&gt;
&lt;br /&gt;
The output is used to generate the normalization report about normalization attempted and success/failure rates.&lt;br /&gt;
&lt;br /&gt;
For historical reasons, much of the functionality is also implemented in [https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/transcoder.py transcoder.py].  It runs an event detail &amp;amp; verification command associated with the normalization command.&lt;br /&gt;
&lt;br /&gt;
On reingest, a 'deletion' Event is created for replaced derivatives.&lt;br /&gt;
&lt;br /&gt;
=== transcribeFile_v0.0 ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Generate OCR of files.&lt;br /&gt;
* '''Script''': [https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/archivematicaTranscribeFile.py archivematicaTranscribeFile.py]&lt;br /&gt;
* '''Used in''': Ingest&lt;br /&gt;
* '''Task type''': [[MCPServer/TaskTypes#Run for each file | per file]]&lt;br /&gt;
* '''Event?''': transcription&lt;br /&gt;
* '''FPR?''': transcription&lt;br /&gt;
&lt;br /&gt;
Optionally generates an OCR file for original files based on FPR entries for transcription.  If the original file has no transcription rules, runs on the derivative.  The new file is a derivation of the original, has a group of 'text/ocr' and is updated with a UUID, checksum, size etc.&lt;br /&gt;
&lt;br /&gt;
=== createMETS_v2.0 ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Generate the AIP METS file&lt;br /&gt;
* '''Script''': [https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/archivematicaCreateMETS2.py archivematicaCreateMETS2.py]&lt;br /&gt;
* '''Used in''': SIP&lt;br /&gt;
* '''Task type''': [[MCPServer/TaskTypes#Run once  | once]]&lt;br /&gt;
* '''Event?''': No&lt;br /&gt;
* '''FPR?''': No&lt;br /&gt;
* '''Tests''': &lt;br /&gt;
** [https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/tests/test_create_aip_mets.py test_create_aip_mets.py]&lt;br /&gt;
** [https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/tests/test_reingest_mets.py test_reingest_mets.py]&lt;br /&gt;
&lt;br /&gt;
Perhaps the most important script in Archivematica: it creates the AIP METS which contains all the archival metadata generated by previous client scripts.&lt;br /&gt;
&lt;br /&gt;
This script imports from several other files for additional functionality: &lt;br /&gt;
[https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/archivematicaCreateMETSMetadataCSV.py archivematicaCreateMETSMetadataCSV]&lt;br /&gt;
[https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/archivematicaCreateMETSRights.py archivematicaCreateMETSRights]&lt;br /&gt;
[https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/archivematicaCreateMETSRightsDspaceMDRef.py archivematicaCreateMETSRightsDspaceMDRef]&lt;br /&gt;
[https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/archivematicaCreateMETSTrim.py archivematicaCreateMETSTrim]&lt;br /&gt;
&lt;br /&gt;
On reingest, it short-circuits and runs [https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/archivematicaCreateMETSReingest.py archivematicaCreateMETSReingest] to update the METS file instead.&lt;br /&gt;
&lt;br /&gt;
Not to be confused with [[#createMETS_v0.0]] for the transfer METS.&lt;br /&gt;
&lt;br /&gt;
=== storeAIP_v0.0 ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Send the completed AIP to the storage service&lt;br /&gt;
* '''Script''': [https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/storeAIP.py storeAIP.py]&lt;br /&gt;
* '''Used in''': SIP&lt;br /&gt;
* '''Task type''': [[MCPServer/TaskTypes#Run once  | once]]&lt;br /&gt;
* '''Event?''': No&lt;br /&gt;
* '''FPR?''': No&lt;br /&gt;
&lt;br /&gt;
Sends the currently processing AIP to the storage service.  The Location is selected from the list of AIP Storage Locations associated with the Pipeline in previous tasks.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===  ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': &lt;br /&gt;
* '''Script''': [https://github.com/artefactual/archivematica/blob/qa/1.x/src/MCPClient/lib/clientScripts/]&lt;br /&gt;
* '''Used in''':&lt;br /&gt;
* '''Task type''': &lt;br /&gt;
* '''Event?''': &lt;br /&gt;
* '''FPR?''': &lt;br /&gt;
* '''Tests''':&lt;br /&gt;
&lt;br /&gt;
== Config File ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Several config settings are read from &amp;lt;code&amp;gt;/etc/archivematica/MCPClient/clientConfig.conf&amp;lt;/code&amp;gt; on startup.&lt;br /&gt;
&lt;br /&gt;
Variables in the MCPClient section:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
! Variable !! Description !! Default value&lt;br /&gt;
|-&lt;br /&gt;
| MCPArchivematicaServer || URL of the MCP gearman server. Must match the [[MCPServer#Config File | server config file]]. || localhost:4730&lt;br /&gt;
|-&lt;br /&gt;
| sharedDirectoryMounted || Directory structure owned by Archivematica and shared between the MCPServer &amp;amp; MCPClient. Must match the [[MCPServer#Config File | server config file]]. || /var/archivematica/sharedDirectory/&lt;br /&gt;
|-&lt;br /&gt;
| archivematicaClientModules || Path to the list of jobs to register with Gearman || /usr/lib/archivematica/MCPClient/archivematicaClientModules&lt;br /&gt;
|-&lt;br /&gt;
| clientScriptsDirectory || Path to the directory where client scripts are installed. Used when parsing archivematicaClientModules || /usr/lib/archivematica/MCPClient/clientScripts/&lt;br /&gt;
|- style=&amp;quot;background: #ffeecc;&amp;quot;&lt;br /&gt;
| LoadSupportedCommandsSpecial || Whether or not to register the SupportedCommandsSpecial section of archivematicaClientModules. This should be removed. || True&lt;br /&gt;
|-&lt;br /&gt;
| numberOfTasks || Number of MCPClient workers to created. 0 detects the number of cores and uses that. || 0&lt;br /&gt;
|-&lt;br /&gt;
| elasticsearchServer || URL of the ElasticSearch server. || localhost:9200&lt;br /&gt;
|- style=&amp;quot;background: #ffeecc;&amp;quot;&lt;br /&gt;
| disableElasticsearchIndexing || If true, do not index AIPs or Transfers in backlog. This should be removed, since ElasticSearch indexing is required || False&lt;br /&gt;
|-&lt;br /&gt;
| temp_dir || Path to the temporary usage directory. Should be in the shared directory || /var/archivematica/sharedDirectory/tmp&lt;br /&gt;
|- style=&amp;quot;background: #ffeecc;&amp;quot;&lt;br /&gt;
| kioskMode || Dashboard setting that disables editing users. This should be removed, or at least moved to dashboard settings || False&lt;br /&gt;
|-&lt;br /&gt;
| removableFiles || List of filenames that are not archivally significant and can be removed. || Thumbs.db, Icon, Icon\r, .DS_Store&lt;br /&gt;
|-&lt;br /&gt;
| django_settings_module || Name of the Django settings module, so the client scripts can access the database via the Django ORM. || settings.common&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Category:Development documentation]]&lt;/div&gt;</summary>
		<author><name>Jdunham</name></author>
	</entry>
	<entry>
		<id>https://wiki.archivematica.org/index.php?title=Storage_Service_API&amp;diff=12269</id>
		<title>Storage Service API</title>
		<link rel="alternate" type="text/html" href="https://wiki.archivematica.org/index.php?title=Storage_Service_API&amp;diff=12269"/>
		<updated>2018-02-27T23:45:38Z</updated>

		<summary type="html">&lt;p&gt;Jdunham: /* Delete package request */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Main Page]] &amp;gt; [[Development]] &amp;gt; Storage Service API&lt;br /&gt;
&lt;br /&gt;
The [[Storage Service]] API provides programmatic access to moving files around in storage areas that the Storage Service has access to.&lt;br /&gt;
&lt;br /&gt;
The API is written using [http://django-tastypie.readthedocs.io/en/latest/ TastyPie].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: TastyPie is less well supported than [http://www.django-rest-framework.org/ Django REST Framework], both in terms of docs &amp;amp; community. We should look at replacing TastyPie with DRF.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Endpoints require authentication with a username and API key.  This can be submitted as GET parameters (eg &amp;lt;code&amp;gt;?username=test&amp;amp;api_key=e6282adabed84e39ffe451f8bf6ff1a67c1fc9f2&amp;lt;/code&amp;gt;) or as a header (eg &amp;lt;code&amp;gt;Authorization: ApiKey test:e6282adabed84e39ffe451f8bf6ff1a67c1fc9f2&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== A note about browsing ==&lt;br /&gt;
&lt;br /&gt;
A detailed schema can be found for each of the resources by adding &amp;quot;schema&amp;quot; to the get all URL.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 $ curl -X GET -H&amp;quot;Authorization: ApiKey test:95141fc645ed97a95893f1f865d24687f89a27ad&amp;quot; 'http://localhost:8000/api/v2/location/schema/?format=json&lt;br /&gt;
 {&lt;br /&gt;
    &amp;quot;allowed_detail_http_methods&amp;quot;: [&lt;br /&gt;
        &amp;quot;get&amp;quot;,&lt;br /&gt;
        &amp;quot;post&amp;quot;&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;allowed_list_http_methods&amp;quot;: [&lt;br /&gt;
        &amp;quot;get&amp;quot;&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;default_format&amp;quot;: &amp;quot;application/json&amp;quot;,&lt;br /&gt;
    &amp;quot;default_limit&amp;quot;: 20,&lt;br /&gt;
    &amp;quot;fields&amp;quot;: {&lt;br /&gt;
        &amp;quot;description&amp;quot;: {&lt;br /&gt;
            &amp;quot;blank&amp;quot;: false,&lt;br /&gt;
            &amp;quot;default&amp;quot;: &amp;quot;No default provided.&amp;quot;,&lt;br /&gt;
            &amp;quot;help_text&amp;quot;: &amp;quot;Unicode string data. Ex: \&amp;quot;Hello World\&amp;quot;&amp;quot;,&lt;br /&gt;
            &amp;quot;nullable&amp;quot;: false,&lt;br /&gt;
            &amp;quot;primary_key&amp;quot;: false,&lt;br /&gt;
            &amp;quot;readonly&amp;quot;: true,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;,&lt;br /&gt;
            &amp;quot;unique&amp;quot;: false,&lt;br /&gt;
            &amp;quot;verbose_name&amp;quot;: &amp;quot;description&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;enabled&amp;quot;: {&lt;br /&gt;
            &amp;quot;blank&amp;quot;: true,&lt;br /&gt;
            &amp;quot;default&amp;quot;: true,&lt;br /&gt;
            &amp;quot;help_text&amp;quot;: &amp;quot;True if space can be accessed.&amp;quot;,&lt;br /&gt;
            &amp;quot;nullable&amp;quot;: false,&lt;br /&gt;
            &amp;quot;primary_key&amp;quot;: false,&lt;br /&gt;
            &amp;quot;readonly&amp;quot;: false,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;boolean&amp;quot;,&lt;br /&gt;
            &amp;quot;unique&amp;quot;: false,&lt;br /&gt;
            &amp;quot;verbose_name&amp;quot;: &amp;quot;Enabled&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;path&amp;quot;: {&lt;br /&gt;
            &amp;quot;blank&amp;quot;: false,&lt;br /&gt;
            &amp;quot;default&amp;quot;: &amp;quot;No default provided.&amp;quot;,&lt;br /&gt;
            &amp;quot;help_text&amp;quot;: &amp;quot;Unicode string data. Ex: \&amp;quot;Hello World\&amp;quot;&amp;quot;,&lt;br /&gt;
            &amp;quot;nullable&amp;quot;: false,&lt;br /&gt;
            &amp;quot;primary_key&amp;quot;: false,&lt;br /&gt;
            &amp;quot;readonly&amp;quot;: true,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;,&lt;br /&gt;
            &amp;quot;unique&amp;quot;: false,&lt;br /&gt;
            &amp;quot;verbose_name&amp;quot;: &amp;quot;path&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;pipeline&amp;quot;: {&lt;br /&gt;
            &amp;quot;blank&amp;quot;: false,&lt;br /&gt;
            &amp;quot;default&amp;quot;: &amp;quot;No default provided.&amp;quot;,&lt;br /&gt;
            &amp;quot;help_text&amp;quot;: &amp;quot;Many related resources. Can be either a list of URIs or list of individually nested resource data.&amp;quot;,&lt;br /&gt;
            &amp;quot;nullable&amp;quot;: false,&lt;br /&gt;
            &amp;quot;primary_key&amp;quot;: false,&lt;br /&gt;
            &amp;quot;readonly&amp;quot;: false,&lt;br /&gt;
            &amp;quot;related_schema&amp;quot;: &amp;quot;/api/v2/pipeline/schema/&amp;quot;,&lt;br /&gt;
            &amp;quot;related_type&amp;quot;: &amp;quot;to_many&amp;quot;,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;related&amp;quot;,&lt;br /&gt;
            &amp;quot;unique&amp;quot;: false,&lt;br /&gt;
            &amp;quot;verbose_name&amp;quot;: &amp;quot;pipeline&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;purpose&amp;quot;: {&lt;br /&gt;
            &amp;quot;blank&amp;quot;: false,&lt;br /&gt;
            &amp;quot;default&amp;quot;: &amp;quot;No default provided.&amp;quot;,&lt;br /&gt;
            &amp;quot;help_text&amp;quot;: &amp;quot;Purpose of the space.  Eg. AIP storage, Transfer source&amp;quot;,&lt;br /&gt;
            &amp;quot;nullable&amp;quot;: false,&lt;br /&gt;
            &amp;quot;primary_key&amp;quot;: false,&lt;br /&gt;
            &amp;quot;readonly&amp;quot;: false,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;,&lt;br /&gt;
            &amp;quot;unique&amp;quot;: false,&lt;br /&gt;
            &amp;quot;verbose_name&amp;quot;: &amp;quot;Purpose&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;quota&amp;quot;: {&lt;br /&gt;
            &amp;quot;blank&amp;quot;: false,&lt;br /&gt;
            &amp;quot;default&amp;quot;: null,&lt;br /&gt;
            &amp;quot;help_text&amp;quot;: &amp;quot;Size, in bytes (optional)&amp;quot;,&lt;br /&gt;
            &amp;quot;nullable&amp;quot;: true,&lt;br /&gt;
            &amp;quot;primary_key&amp;quot;: false,&lt;br /&gt;
            &amp;quot;readonly&amp;quot;: false,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;,&lt;br /&gt;
            &amp;quot;unique&amp;quot;: false,&lt;br /&gt;
            &amp;quot;verbose_name&amp;quot;: &amp;quot;Quota&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;relative_path&amp;quot;: {&lt;br /&gt;
            &amp;quot;blank&amp;quot;: false,&lt;br /&gt;
            &amp;quot;default&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
            &amp;quot;help_text&amp;quot;: &amp;quot;Path to location, relative to the storage space's path.&amp;quot;,&lt;br /&gt;
            &amp;quot;nullable&amp;quot;: false,&lt;br /&gt;
            &amp;quot;primary_key&amp;quot;: false,&lt;br /&gt;
            &amp;quot;readonly&amp;quot;: false,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;,&lt;br /&gt;
            &amp;quot;unique&amp;quot;: false,&lt;br /&gt;
            &amp;quot;verbose_name&amp;quot;: &amp;quot;Relative Path&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;resource_uri&amp;quot;: {&lt;br /&gt;
            &amp;quot;blank&amp;quot;: false,&lt;br /&gt;
            &amp;quot;default&amp;quot;: &amp;quot;No default provided.&amp;quot;,&lt;br /&gt;
            &amp;quot;help_text&amp;quot;: &amp;quot;Unicode string data. Ex: \&amp;quot;Hello World\&amp;quot;&amp;quot;,&lt;br /&gt;
            &amp;quot;nullable&amp;quot;: false,&lt;br /&gt;
            &amp;quot;primary_key&amp;quot;: false,&lt;br /&gt;
            &amp;quot;readonly&amp;quot;: true,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;,&lt;br /&gt;
            &amp;quot;unique&amp;quot;: false,&lt;br /&gt;
            &amp;quot;verbose_name&amp;quot;: &amp;quot;resource uri&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;space&amp;quot;: {&lt;br /&gt;
            &amp;quot;blank&amp;quot;: false,&lt;br /&gt;
            &amp;quot;default&amp;quot;: &amp;quot;No default provided.&amp;quot;,&lt;br /&gt;
            &amp;quot;help_text&amp;quot;: &amp;quot;A single related resource. Can be either a URI or set of nested resource data.&amp;quot;,&lt;br /&gt;
            &amp;quot;nullable&amp;quot;: false,&lt;br /&gt;
            &amp;quot;primary_key&amp;quot;: false,&lt;br /&gt;
            &amp;quot;readonly&amp;quot;: false,&lt;br /&gt;
            &amp;quot;related_schema&amp;quot;: &amp;quot;/api/v2/space/schema/&amp;quot;,&lt;br /&gt;
            &amp;quot;related_type&amp;quot;: &amp;quot;to_one&amp;quot;,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;related&amp;quot;,&lt;br /&gt;
            &amp;quot;unique&amp;quot;: false,&lt;br /&gt;
            &amp;quot;verbose_name&amp;quot;: &amp;quot;space&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;used&amp;quot;: {&lt;br /&gt;
            &amp;quot;blank&amp;quot;: false,&lt;br /&gt;
            &amp;quot;default&amp;quot;: 0,&lt;br /&gt;
            &amp;quot;help_text&amp;quot;: &amp;quot;Amount used, in bytes.&amp;quot;,&lt;br /&gt;
            &amp;quot;nullable&amp;quot;: false,&lt;br /&gt;
            &amp;quot;primary_key&amp;quot;: false,&lt;br /&gt;
            &amp;quot;readonly&amp;quot;: false,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;,&lt;br /&gt;
            &amp;quot;unique&amp;quot;: false,&lt;br /&gt;
            &amp;quot;verbose_name&amp;quot;: &amp;quot;Used&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;uuid&amp;quot;: {&lt;br /&gt;
            &amp;quot;blank&amp;quot;: true,&lt;br /&gt;
            &amp;quot;default&amp;quot;: &amp;quot;&amp;quot;,&lt;br /&gt;
            &amp;quot;help_text&amp;quot;: &amp;quot;Unique identifier&amp;quot;,&lt;br /&gt;
            &amp;quot;nullable&amp;quot;: false,&lt;br /&gt;
            &amp;quot;primary_key&amp;quot;: false,&lt;br /&gt;
            &amp;quot;readonly&amp;quot;: false,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;,&lt;br /&gt;
            &amp;quot;unique&amp;quot;: true,&lt;br /&gt;
            &amp;quot;verbose_name&amp;quot;: &amp;quot;uuid&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;filtering&amp;quot;: {&lt;br /&gt;
        &amp;quot;pipeline&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;purpose&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;quota&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;relative_path&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;space&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;used&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;uuid&amp;quot;: 1&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
This schema, among other things, describes the fields in the resource (including the schema URI of related resource fields) and the fields that allow filtering. Valid filtering values are: Django ORM filters (e.g. startswith, exact, lte, etc.) or 1 or 2. If a filtering field is set to 2 it can be filtered over the related resource fields. For example, the locations could be filtered by their pipeline UUID setting it in a request parameter formatted with two underscore chars: &amp;lt;code&amp;gt;/api/v2/location/?pipeline__uuid=&amp;lt;uuid&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more info on how to interact with the API see:&lt;br /&gt;
&lt;br /&gt;
http://django-tastypie.readthedocs.io/en/v0.13.1/interacting.html&lt;br /&gt;
&lt;br /&gt;
== Pipeline ==&lt;br /&gt;
&lt;br /&gt;
=== Get all pipelines ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/pipeline/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
* '''Parameters''': Query string parameters&lt;br /&gt;
** &amp;lt;code&amp;gt;description&amp;lt;/code&amp;gt;: Description of the pipeline&lt;br /&gt;
** &amp;lt;code&amp;gt;uuid&amp;lt;/code&amp;gt;: UUID of the pipeline&lt;br /&gt;
* '''Response''': JSON&lt;br /&gt;
** &amp;lt;code&amp;gt;meta&amp;lt;/code&amp;gt;: Metadata on the response: number of hits, pagination information&lt;br /&gt;
** &amp;lt;code&amp;gt;objects&amp;lt;/code&amp;gt;: List of pipelines. See [[#Get pipeline details]] for format&lt;br /&gt;
&lt;br /&gt;
Returns information about all the pipelines in the system.  Can be [http://django-tastypie.readthedocs.io/en/latest/resources.html#basic-filtering filtered] by the description or uuid. Disabled pipelines are not returned.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 $ curl -X GET -H&amp;quot;Authorization: ApiKey test:95141fc645ed97a95893f1f865d24687f89a27ad&amp;quot; 'http://localhost:8000/api/v2/pipeline/?description__startswith=Archivematica' | python -m json.tool&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;meta&amp;quot;: {&lt;br /&gt;
         &amp;quot;limit&amp;quot;: 20,&lt;br /&gt;
         &amp;quot;next&amp;quot;: null,&lt;br /&gt;
         &amp;quot;offset&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;previous&amp;quot;: null,&lt;br /&gt;
         &amp;quot;total_count&amp;quot;: 1&lt;br /&gt;
     },&lt;br /&gt;
     &amp;quot;objects&amp;quot;: [&lt;br /&gt;
         {&lt;br /&gt;
             &amp;quot;description&amp;quot;: &amp;quot;Archivematica on alouette&amp;quot;,&lt;br /&gt;
             &amp;quot;remote_name&amp;quot;: &amp;quot;127.0.0.1&amp;quot;,&lt;br /&gt;
             &amp;quot;resource_uri&amp;quot;: &amp;quot;/api/v2/pipeline/dd354557-9e6e-4918-9fe3-a65b00ecb1af/&amp;quot;,&lt;br /&gt;
             &amp;quot;uuid&amp;quot;: &amp;quot;dd354557-9e6e-4918-9fe3-a65b00ecb1af&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
     ]&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== Create new pipeline ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/pipeline/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': POST&lt;br /&gt;
* '''Parameters''': JSON body&lt;br /&gt;
** Should contain fields for a new pipeline: &amp;lt;code&amp;gt;uuid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;description&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;api_key&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;api_username&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;create_default_locations&amp;lt;/code&amp;gt;: If True, will associated default [[Storage Service#Locations | Locations]] with the newly created pipeline&lt;br /&gt;
** &amp;lt;code&amp;gt;shared_path&amp;lt;/code&amp;gt;: If default locations are created, create the [[Storage Service#Currently Processing | processing]] location at this path in the local filesystem&lt;br /&gt;
** &amp;lt;code&amp;gt;remote_name&amp;lt;/code&amp;gt;: IP or hostname of the pipeline. If not provided and  &amp;lt;code&amp;gt;create_default_locations&amp;lt;/code&amp;gt; is set, will try to populate from the IP of the request.&lt;br /&gt;
* '''Response''': JSON with data for the pipeline&lt;br /&gt;
&lt;br /&gt;
If the 'Pipelines disabled on creation' setting is set, the pipeline will be disabled by default, and will not respond to queries.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 $ curl -X POST -H&amp;quot;Authorization: ApiKey test:95141fc645ed97a95893f1f865d24687f89a27ad&amp;quot; -H&amp;quot;Content-Type: application/json&amp;quot; -d'{&amp;quot;uuid&amp;quot;: &amp;quot;99354557-9e6e-4918-9fe3-a65b00ecb199&amp;quot;, &amp;quot;description&amp;quot;: &amp;quot;Test pipeline&amp;quot;, &amp;quot;create_default_locations&amp;quot;: true, &amp;quot;api_username&amp;quot;: &amp;quot;demo&amp;quot;, &amp;quot;api_key&amp;quot;: &amp;quot;03ecb307f5b8012f4771d245d534830378a87259&amp;quot;}' 'http://192.168.1.42:8000/api/v2/pipeline/'&lt;br /&gt;
 {&lt;br /&gt;
    &amp;quot;create_default_locations&amp;quot;: true,&lt;br /&gt;
    &amp;quot;description&amp;quot;: &amp;quot;Test pipeline&amp;quot;,&lt;br /&gt;
    &amp;quot;remote_name&amp;quot;: &amp;quot;192.168.1.42&amp;quot;,&lt;br /&gt;
    &amp;quot;resource_uri&amp;quot;: &amp;quot;/api/v2/pipeline/99354557-9e6e-4918-9fe3-a65b00ecb199/&amp;quot;,&lt;br /&gt;
    &amp;quot;uuid&amp;quot;: &amp;quot;99354557-9e6e-4918-9fe3-a65b00ecb199&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== Get pipeline details ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/pipeline/&amp;lt;UUID&amp;gt;/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
* '''Parameters''': None&lt;br /&gt;
* '''Response''': JSON&lt;br /&gt;
** &amp;lt;code&amp;gt;description&amp;lt;/code&amp;gt;: Pipeline description&lt;br /&gt;
** &amp;lt;code&amp;gt;remote_name&amp;lt;/code&amp;gt;: IP or hostname of the pipeline. For use in API calls&lt;br /&gt;
** &amp;lt;code&amp;gt;resource_uri&amp;lt;/code&amp;gt;: URI for this pipeline in the API&lt;br /&gt;
** &amp;lt;code&amp;gt;uuid&amp;lt;/code&amp;gt;: UUID of the pipeline&lt;br /&gt;
&lt;br /&gt;
== Space ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: Is there no way to create Spaces in the API?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Get all spaces ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/space/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
* '''Parameters''': Query string parameters&lt;br /&gt;
** &amp;lt;code&amp;gt;access_protocol&amp;lt;/code&amp;gt;: Protocol that the [[Storage Service#Space | Space]] uses. Must be searched based on the database code.&lt;br /&gt;
** &amp;lt;code&amp;gt;path&amp;lt;/code&amp;gt;: Space's path&lt;br /&gt;
** &amp;lt;code&amp;gt;size&amp;lt;/code&amp;gt;: Maximum size in bytes. Can use greater than (size__gt=1024), less than (size__lt=1024), and other Django [https://docs.djangoproject.com/en/1.8/ref/models/querysets/#field-lookups field lookups].&lt;br /&gt;
** &amp;lt;code&amp;gt;used&amp;lt;/code&amp;gt;: Bytes stored in this space. Can use greater than (size__gt=1024), less than (size__lt=1024), and other Django [https://docs.djangoproject.com/en/1.8/ref/models/querysets/#field-lookups field lookups].&lt;br /&gt;
** &amp;lt;code&amp;gt;uuid&amp;lt;/code&amp;gt;: UUID of the Space&lt;br /&gt;
* '''Response''': JSON&lt;br /&gt;
** &amp;lt;code&amp;gt;meta&amp;lt;/code&amp;gt;: Metadata on the response: number of hits, pagination information&lt;br /&gt;
** &amp;lt;code&amp;gt;objects&amp;lt;/code&amp;gt;: List of spaces. See [[#Get space details]] for format&lt;br /&gt;
&lt;br /&gt;
Returns information about all the spaces in the system.  Can be [http://django-tastypie.readthedocs.io/en/latest/resources.html#basic-filtering filtered] by several fields: access protocol, path, size, amount used, UUID and verified status. Disabled spaces are not returned.&lt;br /&gt;
&lt;br /&gt;
=== Get space details ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/space/&amp;lt;UUID&amp;gt;/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
* '''Parameters''': None&lt;br /&gt;
* '''Response''': JSON&lt;br /&gt;
** &amp;lt;code&amp;gt;access_protocol&amp;lt;/code&amp;gt;: Database code for the access protocol&lt;br /&gt;
** &amp;lt;code&amp;gt;last_verified&amp;lt;/code&amp;gt;: Date of last verification. This is a stub feature&lt;br /&gt;
** &amp;lt;code&amp;gt;path&amp;lt;/code&amp;gt;: Space's path&lt;br /&gt;
** &amp;lt;code&amp;gt;resource_uri&amp;lt;/code&amp;gt;: URI to the resource in the API&lt;br /&gt;
** &amp;lt;code&amp;gt;size&amp;lt;/code&amp;gt;: Maximum size of the space in bytes.&lt;br /&gt;
** &amp;lt;code&amp;gt;used&amp;lt;/code&amp;gt;: Bytes stored in this space. &lt;br /&gt;
** &amp;lt;code&amp;gt;uuid&amp;lt;/code&amp;gt;: UUID of the space&lt;br /&gt;
** &amp;lt;code&amp;gt;verified&amp;lt;/code&amp;gt;: If the space is verified. This is a stub feature&lt;br /&gt;
** Other space-specific fields&lt;br /&gt;
&lt;br /&gt;
=== Browse space path ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/space/&amp;lt;UUID&amp;gt;/browse/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
* '''Parameters''': Query string parameters&lt;br /&gt;
** &amp;lt;code&amp;gt;path&amp;lt;/code&amp;gt;: Path inside the Space to look&lt;br /&gt;
* '''Response''': JSON&lt;br /&gt;
** &amp;lt;code&amp;gt;entries&amp;lt;/code&amp;gt;: List of entries at path, files or directories&lt;br /&gt;
** &amp;lt;code&amp;gt;directories&amp;lt;/code&amp;gt;: List of directories in path. Subset of `entries`.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffffcc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Version 1: Returns paths as strings&lt;br /&gt;
Version 2: Returns all paths base64 encoded&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Location ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: Is there no way to create Locations in the API?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Get all locations ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/location/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
&lt;br /&gt;
=== Get location details ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/location/&amp;lt;UUID&amp;gt;/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
&lt;br /&gt;
=== Move files to this location ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/location/&amp;lt;UUID&amp;gt;/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': POST&lt;br /&gt;
* '''Parameters''': JSON body&lt;br /&gt;
** &amp;lt;code&amp;gt;origin_location&amp;lt;/code&amp;gt;: URI of the Location the files should be moved from&lt;br /&gt;
** &amp;lt;code&amp;gt;pipeline&amp;lt;/code&amp;gt;: URI of the [[Storage Service#Pipeline | pipeline]]. Both Locations must be associated with this pipeline.&lt;br /&gt;
** &amp;lt;code&amp;gt;files&amp;lt;/code&amp;gt;: List of dicts containing &amp;lt;code&amp;gt;source&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;destination&amp;lt;/code&amp;gt;.  The source and destination are paths relative to their Location of the files to be moved.&lt;br /&gt;
&lt;br /&gt;
Intended for use with creating Transfers, SIPs, etc and other cases where files need to be moved but not tracked by the storage service.&lt;br /&gt;
&lt;br /&gt;
=== Browse location path ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/location/&amp;lt;UUID&amp;gt;/browse/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
* '''Parameters''': Query string parameters&lt;br /&gt;
** &amp;lt;code&amp;gt;path&amp;lt;/code&amp;gt;: Path inside the Location to look&lt;br /&gt;
* '''Response''': JSON&lt;br /&gt;
** &amp;lt;code&amp;gt;entries&amp;lt;/code&amp;gt;: List of entries in `path`, files or directories&lt;br /&gt;
** &amp;lt;code&amp;gt;directories&amp;lt;/code&amp;gt;: List of directories in `path`. Subset of `entries`.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffffcc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Version 1: Returns paths as strings&lt;br /&gt;
Version 2: Returns all paths base64 encoded&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== SWORD collection ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/location/&amp;lt;UUID&amp;gt;/sword/collection/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET, POST&lt;br /&gt;
&lt;br /&gt;
See [[Sword API]] for details&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Package ==&lt;br /&gt;
&lt;br /&gt;
=== Get all packages ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
&lt;br /&gt;
=== Create new package ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': POST&lt;br /&gt;
* '''Parameters''': JSON. Fields for a new package:&lt;br /&gt;
** &amp;lt;code&amp;gt;uuid&amp;lt;/code&amp;gt;: UUID of the new package&lt;br /&gt;
** &amp;lt;code&amp;gt;origin_location&amp;lt;/code&amp;gt;: URI of the Location where the package is currently&lt;br /&gt;
** &amp;lt;code&amp;gt;origin_path&amp;lt;/code&amp;gt;: Path to the package, relative to the origin_location&lt;br /&gt;
** &amp;lt;code&amp;gt;current_location&amp;lt;/code&amp;gt;: URI of the Location where the package should be stored&lt;br /&gt;
** &amp;lt;code&amp;gt;current_path&amp;lt;/code&amp;gt;: Path where the package should be stored, relative to the current_location&lt;br /&gt;
** &amp;lt;code&amp;gt;package_type&amp;lt;/code&amp;gt;: Type of package this is. One of: &amp;lt;code&amp;gt;AIP&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;AIC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DIP&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SIP&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;file&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;deposit&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;size&amp;lt;/code&amp;gt;: Size of the package&lt;br /&gt;
** &amp;lt;code&amp;gt;origin_pipeline&amp;lt;/code&amp;gt;: URI of the pipeline the package is from&lt;br /&gt;
** &amp;lt;code&amp;gt;related_package_uuid&amp;lt;/code&amp;gt;: UUID of a package that is related to this one. E.g. UUID of a DIP when storing an AIP&lt;br /&gt;
&lt;br /&gt;
Creates a database entry tracking the package (AIP, transfer, etc).  If the package is an AIP, DIP or AIC and the current_location is an AIP or DIP storage location it also moves the files from the source to destination location.  If the package is a Transfer and the current_location is transfer backlog, it is also moved.&lt;br /&gt;
&lt;br /&gt;
This is handled through the modified &amp;lt;code&amp;gt;obj_create&amp;lt;/code&amp;gt; function, which calls &amp;lt;code&amp;gt;Package.store_aip&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Package.backlog_transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Get package details ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
&lt;br /&gt;
=== Update package contents ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': PUT&lt;br /&gt;
* '''Parameters''': JSON body&lt;br /&gt;
** &amp;lt;code&amp;gt;reingest&amp;lt;/code&amp;gt;: Flag to mark that this is reingest. Reduces chance to accidentally modify an AIP.&lt;br /&gt;
** &amp;lt;code&amp;gt;uuid&amp;lt;/code&amp;gt;: UUID of the existing package&lt;br /&gt;
** &amp;lt;code&amp;gt;origin_location&amp;lt;/code&amp;gt;: URI of the Location where the package is currently&lt;br /&gt;
** &amp;lt;code&amp;gt;origin_path&amp;lt;/code&amp;gt;: Path to the package, relative to the origin_location&lt;br /&gt;
** &amp;lt;code&amp;gt;current_location&amp;lt;/code&amp;gt;: URI of the Location where the package should be stored&lt;br /&gt;
** &amp;lt;code&amp;gt;current_path&amp;lt;/code&amp;gt;: Path where the package should be stored, relative to the current_location&lt;br /&gt;
** &amp;lt;code&amp;gt;package_type&amp;lt;/code&amp;gt;: Type of package this is. One of: &amp;lt;code&amp;gt;AIP&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;AIC&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;size&amp;lt;/code&amp;gt;: Size of the package&lt;br /&gt;
** &amp;lt;code&amp;gt;origin_pipeline&amp;lt;/code&amp;gt;: URI of the pipeline the package is from.  This must be the same pipeline reingest was started on (tracked through &amp;lt;code&amp;gt;Package.misc_attributes.reingest_pipeline&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Updates the contents of a package during reingest.  If the package is an AIP or AIC, currently stored in an AIP storage location, and the 'reingest' parameter is set, it will call &amp;lt;code&amp;gt;Package.finish_reingest&amp;lt;/code&amp;gt; and merge the new AIP with the existing one.&lt;br /&gt;
&lt;br /&gt;
This is implemented using a modified &amp;lt;code&amp;gt;obj_update&amp;lt;/code&amp;gt; which calls &amp;lt;code&amp;gt;obj_update_hook&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Update package metadata ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': PATCH&lt;br /&gt;
* '''Parameters''': JSON body&lt;br /&gt;
** &amp;lt;code&amp;gt;reingest&amp;lt;/code&amp;gt;: Pipeline UUID or None.&lt;br /&gt;
&lt;br /&gt;
Used to update metadata stored in the database for the package.  Currently, this is used to update the reingest status.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: Currently, this always sets Package.misc_attributes.reingest to None, regardless of what value was actually passed in.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This is implemented using a modified &amp;lt;code&amp;gt;obj_update&amp;lt;/code&amp;gt; which calls &amp;lt;code&amp;gt;obj_update_hook&amp;lt;/code&amp;gt;.  &amp;lt;code&amp;gt;update_in_place&amp;lt;/code&amp;gt; also helps.&lt;br /&gt;
&lt;br /&gt;
=== Delete package request ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/delete_aip/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': POST&lt;br /&gt;
* '''Parameters''': JSON body&lt;br /&gt;
** &amp;lt;code&amp;gt;event_reason&amp;lt;/code&amp;gt;: Reason for deleting the AIP&lt;br /&gt;
** &amp;lt;code&amp;gt;pipeline&amp;lt;/code&amp;gt;: UUID of the pipeline the delete request is from&lt;br /&gt;
** &amp;lt;code&amp;gt;user_id&amp;lt;/code&amp;gt;: User ID requesting the deletion. This is the ID of the user on the pipeline, and must be an integer greater than 0.&lt;br /&gt;
** &amp;lt;code&amp;gt;user_email&amp;lt;/code&amp;gt;:  Email of the user requesting the deletion.&lt;br /&gt;
&lt;br /&gt;
=== Recover AIP request ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/recover_aip/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': POST&lt;br /&gt;
* '''Parameters''': JSON body&lt;br /&gt;
** &amp;lt;code&amp;gt;event_reason&amp;lt;/code&amp;gt;: Reason for recovering the AIP&lt;br /&gt;
** &amp;lt;code&amp;gt;pipeline&amp;lt;/code&amp;gt;: URI of the pipeline the recovery request is from&lt;br /&gt;
** &amp;lt;code&amp;gt;user_id&amp;lt;/code&amp;gt;: User ID requesting the recovery. This is the ID of the user on the pipeline, and must be an integer greater than 0.&lt;br /&gt;
** &amp;lt;code&amp;gt;user_email&amp;lt;/code&amp;gt;:  Email of the user requesting the recovery.&lt;br /&gt;
&lt;br /&gt;
=== Download single file ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/extract_file/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET, HEAD&lt;br /&gt;
* '''Parameters''': Query string parameters&lt;br /&gt;
** &amp;lt;code&amp;gt;relative_path_to_file&amp;lt;/code&amp;gt;: Path to the file to download, relative to the package path.&lt;br /&gt;
* '''Response''': Stream of the requested file&lt;br /&gt;
&lt;br /&gt;
Returns a single file from the Package.  If the package is compressed, it downloads the whole AIP and extracts it.&lt;br /&gt;
&lt;br /&gt;
This responds to HEAD because AtoM uses HEAD to check for the existence of a file. &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: HEAD and GET should not perform the same functions. HEAD should be updated to not return the file, and to only check for existence.  Currently, the storage service has no way to check if a file exists except by downloading and extracting this AIP&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If the package is in [[Storage Service#Arkivum | Arkivum]], the package may not actually be available.  This endpoint checks if the package is locally available. If it is, it is returned as normal. If not, it returns &amp;lt;code&amp;gt;202&amp;lt;/code&amp;gt; and emails the administrator about the attempted access.&lt;br /&gt;
&lt;br /&gt;
=== Download package ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/download/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/download/&amp;lt;chunk number&amp;gt;/&amp;lt;/code&amp;gt; (for [[Storage Service#LOCKSS-o-matic | LOCKSS]] harvesting)&lt;br /&gt;
* '''Verb''': GET, HEAD&lt;br /&gt;
* '''Parameters''': None&lt;br /&gt;
* '''Response''': Stream of the package&lt;br /&gt;
&lt;br /&gt;
Returns the entire package as a single file.  If the AIP is uncompressed, create one file by using `tar`.&lt;br /&gt;
&lt;br /&gt;
If the download URL has a chunk number, it will attempt to serve the LOCKSS chunk specified for that package. If the package is not in LOCKSS, it will return the the whole package.&lt;br /&gt;
&lt;br /&gt;
This responds to HEAD because AtoM uses HEAD to check for the existence of a file. &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: HEAD and GET should not perform the same functions. HEAD should be updated to not return the file, and to only check for existence.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If the package is in [[Storage Service#Arkivum | Arkivum]], the package may not actually be available.  This endpoint checks if the package is locally available. If it is, it is returned as normal. If not, it returns &amp;lt;code&amp;gt;202&amp;lt;/code&amp;gt; and emails the administrator about the attempted access.&lt;br /&gt;
&lt;br /&gt;
=== Get pointer file ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/pointer_file/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
* '''Parameters''': None&lt;br /&gt;
* '''Response''': Stream of the pointer file.&lt;br /&gt;
&lt;br /&gt;
=== Check fixity ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/check_fixity/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
* '''Parameters''': Query string parameters&lt;br /&gt;
** &amp;lt;code&amp;gt;force_local&amp;lt;/code&amp;gt;: If true, download and run fixity on the AIP locally, instead of using the Space-provided fixity if available.&lt;br /&gt;
* '''Response''': JSON&lt;br /&gt;
** &amp;lt;code&amp;gt;success&amp;lt;/code&amp;gt;: True if the verification succeeded, False if the verification failed, None if the scan could not start&lt;br /&gt;
** &amp;lt;code&amp;gt;message&amp;lt;/code&amp;gt;: Human-readable string explaining the report; it will be empty for successful scans.&lt;br /&gt;
** &amp;lt;code&amp;gt;failures&amp;lt;/code&amp;gt;: List of 0 or more errors&lt;br /&gt;
** &amp;lt;code&amp;gt;timestamp&amp;lt;/code&amp;gt;: ISO-formated string with the datetime of the last fixity check. If the check was performed by an external system, this will be provided by that system. If not provided,or on error, it will be None.&lt;br /&gt;
&lt;br /&gt;
=== AIP storage callback request ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/send_callback/post_store/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
&lt;br /&gt;
Request to call any Callbacks configured to run post-storage for this AIP.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: This only works on locally available AIPs (AIPs stored in Spaces that are available via a UNIX filesystem layer).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Get file information for package ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/contents/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
* '''Response''': JSON&lt;br /&gt;
** &amp;lt;code&amp;gt;success&amp;lt;/code&amp;gt;: True&lt;br /&gt;
** &amp;lt;code&amp;gt;package&amp;lt;/code&amp;gt;: UUID of the package&lt;br /&gt;
** &amp;lt;code&amp;gt;files&amp;lt;/code&amp;gt;: List of dictionaries with file information. Each dictionary has:&lt;br /&gt;
*** &amp;lt;code&amp;gt;source_id&amp;lt;/code&amp;gt;: UUID of the file to index&lt;br /&gt;
*** &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;: Relative path of the file inside the package&lt;br /&gt;
*** &amp;lt;code&amp;gt;source_package&amp;lt;/code&amp;gt;: UUID of the SIP this file is from&lt;br /&gt;
*** &amp;lt;code&amp;gt;checksum&amp;lt;/code&amp;gt;: Checksum of the file, or an empty string&lt;br /&gt;
*** &amp;lt;code&amp;gt;accessionid&amp;lt;/code&amp;gt;: Accession number, or an empty string&lt;br /&gt;
*** &amp;lt;code&amp;gt;origin&amp;lt;/code&amp;gt;: UUID of the Archivematica dashboard this is from&lt;br /&gt;
&lt;br /&gt;
Returns metadata about every file within the package.&lt;br /&gt;
&lt;br /&gt;
=== Update file information for package ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/contents/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': PUT&lt;br /&gt;
* '''Parameters''': JSON list of dictionaries with information on the files to be added. Each dict must have the following attributes:&lt;br /&gt;
** &amp;lt;code&amp;gt;relative_path&amp;lt;/code&amp;gt;: Relative path of the file inside the package&lt;br /&gt;
** &amp;lt;code&amp;gt;fileuuid&amp;lt;/code&amp;gt;: UUID of the file to index&lt;br /&gt;
** &amp;lt;code&amp;gt;accessionid&amp;lt;/code&amp;gt;: Accession number, or an empty string&lt;br /&gt;
** &amp;lt;code&amp;gt;sipuuid&amp;lt;/code&amp;gt;: UUID of the SIP this file is from&lt;br /&gt;
** &amp;lt;code&amp;gt;origin&amp;lt;/code&amp;gt;: UUID of the Archivematica dashboard this is from&lt;br /&gt;
&lt;br /&gt;
Adds a set of files to a package.&lt;br /&gt;
&lt;br /&gt;
=== Delete file information for package ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/contents/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': DELETE&lt;br /&gt;
&lt;br /&gt;
Removes all file records associated with this package.&lt;br /&gt;
&lt;br /&gt;
=== Query file information on packages ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/metadata/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET, POST&lt;br /&gt;
* '''Parameters''': Query string parameters.  Must have at least one, but not all are required&lt;br /&gt;
** &amp;lt;code&amp;gt;relative_path&amp;lt;/code&amp;gt;: Relative path of the file inside the package&lt;br /&gt;
** &amp;lt;code&amp;gt;fileuuid&amp;lt;/code&amp;gt;: UUID of the file&lt;br /&gt;
** &amp;lt;code&amp;gt;accessionid&amp;lt;/code&amp;gt;: Accession number&lt;br /&gt;
** &amp;lt;code&amp;gt;sipuuid&amp;lt;/code&amp;gt;: UUID of the SIP this file is from&lt;br /&gt;
* '''Response''': JSON. List of dicts with file information about the files that match the query.&lt;br /&gt;
** &amp;lt;code&amp;gt;accessionid&amp;lt;/code&amp;gt;: Accession number, or an empty string&lt;br /&gt;
** &amp;lt;code&amp;gt;file_extension&amp;lt;/code&amp;gt;: File extension&lt;br /&gt;
** &amp;lt;code&amp;gt;filename&amp;lt;/code&amp;gt;: Name of the file, sans path.&lt;br /&gt;
** &amp;lt;code&amp;gt;relative_path&amp;lt;/code&amp;gt;: Relative path of the file inside the package&lt;br /&gt;
** &amp;lt;code&amp;gt;fileuuid&amp;lt;/code&amp;gt;: UUID of the file to index&lt;br /&gt;
** &amp;lt;code&amp;gt;sipuuid&amp;lt;/code&amp;gt;: UUID of the SIP this file is from&lt;br /&gt;
** &amp;lt;code&amp;gt;origin&amp;lt;/code&amp;gt;: UUID of the Archivematica dashboard this is from&lt;br /&gt;
&lt;br /&gt;
=== Reingest AIP ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/reingest/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': POST&lt;br /&gt;
* '''Parameters''': JSON body&lt;br /&gt;
** &amp;lt;code&amp;gt;pipeline&amp;lt;/code&amp;gt;: UUID of the pipeline to reingest on&lt;br /&gt;
** &amp;lt;code&amp;gt;reingest_type&amp;lt;/code&amp;gt;: Type of reingest to start. One of &amp;lt;code&amp;gt;METADATA_ONLY&amp;lt;/code&amp;gt; (metadata-only reingest), &amp;lt;code&amp;gt;OBJECTS&amp;lt;/code&amp;gt; (partial reingest), &amp;lt;code&amp;gt;FULL&amp;lt;/code&amp;gt; (full reingest)&lt;br /&gt;
** &amp;lt;code&amp;gt;processing_config&amp;lt;/code&amp;gt;: Optional. Name of the processing configuration to use on full reingest&lt;br /&gt;
&lt;br /&gt;
=== SWORD endpoints ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/sword/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/sword/media/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/sword/state/&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[Sword API]] for details.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Development documentation]]&lt;/div&gt;</summary>
		<author><name>Jdunham</name></author>
	</entry>
	<entry>
		<id>https://wiki.archivematica.org/index.php?title=Dashboard&amp;diff=12268</id>
		<title>Dashboard</title>
		<link rel="alternate" type="text/html" href="https://wiki.archivematica.org/index.php?title=Dashboard&amp;diff=12268"/>
		<updated>2018-02-22T18:37:38Z</updated>

		<summary type="html">&lt;p&gt;Jdunham: /* Sections */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Main Page]] &amp;gt; [[Development]] &amp;gt; [[:Category:Development documentation|Development documentation]] &amp;gt; Dashboard&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;status&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
Design&lt;br /&gt;
&amp;lt;div class=&amp;quot;description&amp;quot;&amp;gt;This page proposes a new feature and reviews design options&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
Development&lt;br /&gt;
&amp;lt;div class=&amp;quot;description&amp;quot;&amp;gt;This page describes a feature that's in development&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;active&amp;quot;&amp;gt;&lt;br /&gt;
Documentation&lt;br /&gt;
&amp;lt;div class=&amp;quot;description&amp;quot;&amp;gt;This page documents an implemented feature&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The dashboard manages a pipeline’s behaviour. It provides a view into the status of units, allows workflow decisions to be made, handles configuration, allows arrangement &amp;amp; description, and customization of the [[Format policy registry requirements | FPR]].  Code for the dashboard is found in &amp;lt;code&amp;gt;src/dashboard/src/&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Previously the dashboard also handled starting transfers from disk &amp;amp; storing files, but much of that functionality has been moved to the storage service. &lt;br /&gt;
&lt;br /&gt;
== Sections ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;components/access&amp;lt;/code&amp;gt;: Internal API to talk to access systems (ArchivesSpace, Archivist’s Toolkit). Primarily supports the appraisal tab, and uses [[https://github.com/artefactual-labs/agentarchives agentarchives]]&lt;br /&gt;
* &amp;lt;code&amp;gt;components/accounts&amp;lt;/code&amp;gt;: Views related to account management (create, edit, delete, list)&lt;br /&gt;
* &amp;lt;code&amp;gt;components/administration&amp;lt;/code&amp;gt;: Views &amp;amp; models related to the Administration tab.  Contains the processing config form, DIP upload settings, etc&lt;br /&gt;
* &amp;lt;code&amp;gt;components/api&amp;lt;/code&amp;gt;: [[ Archivematica_API | External API]] endpoints.&lt;br /&gt;
* &amp;lt;code&amp;gt;components/appraisal&amp;lt;/code&amp;gt;: Appraisal tab view.&lt;br /&gt;
* &amp;lt;code&amp;gt;components/archival_storage&amp;lt;/code&amp;gt;: Views related to the Archival Storage tab.  Contains ElasticSearch queries, creating AICs, deleting AIPs and starting reingest.&lt;br /&gt;
* &amp;lt;code&amp;gt;components/backlog&amp;lt;/code&amp;gt;: Views related to the Backlog tab. Contains ElasticSearch queries, deleting &amp;amp; downloading backlogged transfers.&lt;br /&gt;
* &amp;lt;code&amp;gt;components/file&amp;lt;/code&amp;gt;: Internal API to get file information from ElasticSearch &amp;amp; Storage Service. Primarily supports the appraisal tab.&lt;br /&gt;
* &amp;lt;code&amp;gt;components/filesystem_ajax&amp;lt;/code&amp;gt;: Internal API to support SIP Arrangement and moving files to and from the pipeline. Much of its previous functionality has been superseded by the storage service&lt;br /&gt;
* &amp;lt;code&amp;gt;components/ingest&amp;lt;/code&amp;gt;: Views and internal API related to the Ingest tab.&lt;br /&gt;
* &amp;lt;code&amp;gt;components/mcp&amp;lt;/code&amp;gt;: Internal API for status updates from [[MCPServer]]&lt;br /&gt;
* &amp;lt;code&amp;gt;components/rights&amp;lt;/code&amp;gt;: Views and forms for editing unit rights.&lt;br /&gt;
* &amp;lt;code&amp;gt;components/transfer&amp;lt;/code&amp;gt;: Views and internal API related to the Transfer tab.&lt;br /&gt;
* &amp;lt;code&amp;gt;components/unit&amp;lt;/code&amp;gt;: Views and internal API common between Transfers and SIPs&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: This is newer than &amp;lt;code&amp;gt;components/transfer&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;components/ingest&amp;lt;/code&amp;gt;. Functionality that is the same between the two should be moved here as appropriate&lt;br /&gt;
|}&lt;br /&gt;
* &amp;lt;code&amp;gt;external&amp;lt;/code&amp;gt;: External dependencies, often git submodules. '''Note: as of Archivematica 1.7, there is no external/ directory here. The base64-helpers subdirectory is now required by the transfer-browser and appraisal-tab and is downloaded during the NPM build phase.'''&lt;br /&gt;
* &amp;lt;code&amp;gt;fpr&amp;lt;/code&amp;gt;: Views related to the Preservation Planning tab. This in the FPR-admin submodule from externals, and contains all [[Format policy registry requirements | FPR]] modification views. '''Note: as of Archivematica 1.7, there is no fpr/ directory here. The archivematica-fpr-admin module is now a dependency of the dashboard; see dashboard/src/requirements/base.txt.'''&lt;br /&gt;
* &amp;lt;code&amp;gt;installer&amp;lt;/code&amp;gt;: Views related to installation and setting up Archivematica&lt;br /&gt;
* &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt;: Models, views and internal APIs related to core dashboard functionality. Contains all model definitions &amp;amp; migrations, as well as app-wide configuration. Also includes Task &amp;amp; Job display, and views related to the Access tab.&lt;br /&gt;
* &amp;lt;code&amp;gt;media&amp;lt;/code&amp;gt;: All CSS, JS &amp;amp; images for the dashboard&lt;br /&gt;
* &amp;lt;code&amp;gt;middleware&amp;lt;/code&amp;gt;: Django middleware definitions.&lt;br /&gt;
* &amp;lt;code&amp;gt;requirements&amp;lt;/code&amp;gt;: Python requirements files&lt;br /&gt;
* &amp;lt;code&amp;gt;settings&amp;lt;/code&amp;gt;: Django settings modules for development or production configuration&lt;br /&gt;
* &amp;lt;code&amp;gt;templates&amp;lt;/code&amp;gt;: All templates for the dashboard. Structure broadly mirrors that of the components directory.&lt;br /&gt;
&lt;br /&gt;
== Old documentation ==&lt;br /&gt;
&lt;br /&gt;
===Technical Requirements===&lt;br /&gt;
The Dashboard is a web-based tool that is developed using Python-based [http://djangoproject.com Django] MVC framework.&lt;br /&gt;
&lt;br /&gt;
===Functional Requirements===&lt;br /&gt;
&lt;br /&gt;
*provide a web-based, multi-user interface that will report on the status of system events and make it simpler to control and trigger specific micro-services.&lt;br /&gt;
*provide a user-friendly interface to add/edit metadata&lt;br /&gt;
*coordinate the read and write operations of the AIP to file storage and the syncing of metadata updates between the AIPs and the access system.&lt;br /&gt;
*process Consumer AIP requests&lt;br /&gt;
*provide statistical information about Archivematica operation&lt;br /&gt;
*provide preservation planning information&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===User interface===&lt;br /&gt;
&lt;br /&gt;
Release 0.7-alpha (Feb 18, 2011)&lt;br /&gt;
&lt;br /&gt;
[[File:Dashboard-0.7.png|680px]]&lt;br /&gt;
&lt;br /&gt;
Django interface found in Archivematica 0.6.2 (dev tree, 29 Nov 2010)&lt;br /&gt;
&lt;br /&gt;
[[File:Archivematica-dashboard-0.6.2-dev-29Nov.png|480px]]&lt;br /&gt;
&lt;br /&gt;
Early mockup (March 2010)&lt;br /&gt;
&lt;br /&gt;
[[File:ArchivematicaDashboardScreencap05Mar2010.png|480px]]&lt;br /&gt;
&lt;br /&gt;
===Real-time interaction===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;background-color: #fffccc; border: 1px solid #ddd; padding: 8px;&amp;quot;&amp;gt;&lt;br /&gt;
Our preliminary design will be based in '''periodic refresh''', trying to minimize the risks of more sophisticated solutions before [http://archivematica.org/wiki/index.php?title=Development_roadmap#Release_0.7-alpha Release 0.7-alpha] is launched. In future releases, we will do more research on this topic trying to achieve the best user experience while we keep an eye on performance.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The Ajax web application model came to made the Web UI experience dynamic and asynchronous, as a replacement of the classic page-by-page web application model (see [http://www.adaptivepath.com/images/publications/essays/ajax-fig2.png graph]). However, Ajax applications don't offer a duplex communication where both client and server can send messages at any time. A new model of web applications frequently called [http://infrequently.org/2006/03/comet-low-latency-data-for-the-browser/ Comet] appeared providing bi-directional communications using persistent long-lasting HTTP connections between the server and the client (see [http://infrequently.org/wp-content/Comet.png graph]). Comet is similar to Ajax in that it's asynchronous, but '''applications following the Comet model can communicate state changes on the server with almost negligible latency, which makes it suitable for monitoring or multi-user collaboration applications'''.&lt;br /&gt;
&lt;br /&gt;
There exists different methods of implementing a Comet streaming transport (browser transport), but all of them are based in existing browser features: iframe HTML element, XMLHttpRequest or script tags. Between these methods, I think that we have two candidates:&lt;br /&gt;
&lt;br /&gt;
* '''XMLHttpRequest long polling''': firstly, the browser creates an asynchronous XMLHttpRequest with a long time-out. When we receive a response, the server closes the connection and we launch another XHR request immediately afterward, waiting for a new event.&lt;br /&gt;
* '''Script tag long polling''': the browser creates script HTML elements dinamically and setting their source (&amp;quot;src&amp;quot; attribute) to the location of the server, which then send back JavaScript code. Each time the script requests is completed, the browser opens a new one, just like XHR long polling design does. This method bypass the [http://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy same-origin policy security mechanism] implemented in modern browsers.&lt;br /&gt;
&lt;br /&gt;
====Alternatives====&lt;br /&gt;
&lt;br /&gt;
There exists other alternatives that we should consider:&lt;br /&gt;
&lt;br /&gt;
* '''WebSockets''': this technology is part of HTML5 and provides full-duplex communications channels over a single TCP socket between the browser and the server. The [http://dev.w3.org/html5/websockets/ WebSocket API] is being standardized by the W3C and the [http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol WebSocket protocol] is being standardized by the IETF ([https://datatracker.ietf.org/wg/hybi/charter/ HyBi working group]). Chrome 4, Safari 5, Firefox 4 (not yet in FF3) and Opera 11 support WebSockets. However, the last two ones have disabled this protocol by default. HTML5 Labs at Microsoft interoperability group recently launched a [http://blogs.msdn.com/b/interoperability/archive/2010/12/21/introducing-the-websockets-prototype.aspx prototype] compatible with IE8 and IE9 based in Silverlight. WebSockets is a promissing technology but unfortunately in the development phase yet.&lt;br /&gt;
** There are some solutions which provide an API that looks like WebSocket API, and fallback to other techniques if WebSocket is not available. A good example is Socket.IO, which supports different transports: WebSocket, Adobe® Flash® Socket, Ajax long polling, etc... however, the server module was designed for Node.JS. Several implementations have been started for other languages / frameworks that are compatible with the Socket.IO client.&lt;br /&gt;
** Other products like CometD, Lightstreamer and others provide a higher-level API using pubsub (see mod_pubsub) or some other messaging protocol, and use WebSocket or whatever other transport is available that is the fastest and safest option.&lt;br /&gt;
* '''Server-Sent Events''': another [http://dev.w3.org/html5/eventsource/ draft API] included in HTML5 designed for scenarios where data does not need to be sent from the client, just need updates from the server (server push only). This technology, only supported by some browsers like Chrome or Opera, could be considered as a formal and efficient alternative to Comet, but based in the same method: HTTP long-held requests. The big difference with WebSockets is, therefore, that it does not to implement a new protocol (it is based in HTTP) and it is not really full-duplex, although it could be simulated with parallel XHR requests.&lt;br /&gt;
* '''Periodic refresh''' (simple polling): to keep users informated about changes occurring on the server we can make the browser generates requests periodically, at fixed intervals, to gain new information: for example, one call every five seconds. This is a valid approximation where the server push data if data latency is not a critical for users. A callback function would be responsible for updating the DOM according to the server's latest report and the browser script can do some monitoring and dynamically adjust the period of refreshes to minimize the workload (e.g.: to cease it when the system detects the user is no longer active, see this [http://ajaxpatterns.org/Heartbeat article]).&lt;br /&gt;
** [https://github.com/brettstimmerman/lace Lace]: Old open source chat based in simple polling (periodic refresh).&lt;br /&gt;
&lt;br /&gt;
====Server design and scalability====&lt;br /&gt;
&lt;br /&gt;
When a web application creates bi-directional connections between the browser and the server, new server software is often required in order to scale well. Take into account that traditional web-based solutions would break down very quickly due to memory consumption and the excess overhead of framework for each HTTP (and possibly long-held) request made.&lt;br /&gt;
&lt;br /&gt;
More research on this must be done if we decide to take advantage of Comet or WebSockets technologies. These are some initial notes:&lt;br /&gt;
&lt;br /&gt;
* [http://httpd.apache.org/docs/2.2/mod/event.html Apache MPM event]: this experimental module included in Apache 2.2 has the potential to bring Twisted-esque funcionality within the Apache pipeline. It can save significant overhead in creating TCP connections, however, Apache traditionally keeps an entire child process/thread waiting for data from the client, which brings its own disadvantages. To solve this problem, this MPM uses a dedicated thread to handle both the listening sockets, and all sockets that are in a Keep Alive state.&lt;br /&gt;
* [http://www.tornadoweb.org/ Tornado]: an open source version of the scalable, non-blocking web server and tools that power FriendFeed. It is ideal for real-time web services. It is not just a web server, it could be considered a real-time web framework. [http://lincolnloop.com/blog/2009/sep/15/using-django-inside-tornado-web-server/ It can serves] Django applications.&lt;br /&gt;
* Twisted, eventlet, gevent, Tornado, Node.JS, greenlet, celery&lt;br /&gt;
&lt;br /&gt;
Some recipes:&lt;br /&gt;
&lt;br /&gt;
* [http://www.clemesha.org/blog/realtime-web-apps-python-django-orbited-twisted Django + Orbited + Twisted]: and an example, a realtime webapp: [https://github.com/clemesha/hotdot Hotdot].&lt;br /&gt;
* [http://media.eflorenzano.com/dropbox/UsingDjangoInNonStandardWays.pdf Using Django in Non-Standard Ways]&lt;br /&gt;
* [http://prg10001.blogspot.com/2009/09/simpler-long-polling-with-django-and.html Simple long polling with Django and gevent]&lt;br /&gt;
* [http://ajaxian.com/archives/django-and-comet Django and Comet using Orbited]&lt;br /&gt;
* [http://blog.gevent.org/2010/02/27/why-gevent/ Comparing gevent to eventlet]&lt;br /&gt;
* [http://stackoverflow.com/questions/1824418/a-clean-lightweight-alternative-to-pythons-twisted A clean, lightweight alternative to Python's twisted?]&lt;br /&gt;
* [http://stackoverflow.com/questions/4363899/making-moves-w-websockets-and-python-django-twisted Making moves w/ websockets and python/django(/twisted?)]&lt;br /&gt;
* [http://www.saltycrane.com/blog/2010/05/quick-notes-trying-twisted-websocket-branch-example/ Quick notes on trying the Twisted websocket branch example]&lt;br /&gt;
&lt;br /&gt;
===Debug mode===&lt;br /&gt;
&lt;br /&gt;
By default, the dashboard runs in &amp;quot;production&amp;quot; mode. To diagnose application errors it is usually useful to run in debug mode. Debug mode will display error messages. If you want to enable it, please follow these instructions:&lt;br /&gt;
&lt;br /&gt;
# Go to [http://code.google.com/p/archivematica/source/browse/trunk#trunk%2Fsrc%2Fdashboard dashboard sources directory]&lt;br /&gt;
# Open settings.py file with your preferred text editor&lt;br /&gt;
# Find the following line &amp;lt;pre&amp;gt;Debug = False&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Update the False flag to True &amp;lt;pre&amp;gt;Debug = True&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Save the file&lt;br /&gt;
# Restart Apache &amp;lt;pre&amp;gt;sudo /etc/init.d/apache2 restart&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Development documentation]]&lt;/div&gt;</summary>
		<author><name>Jdunham</name></author>
	</entry>
	<entry>
		<id>https://wiki.archivematica.org/index.php?title=Storage_Service_API&amp;diff=11691</id>
		<title>Storage Service API</title>
		<link rel="alternate" type="text/html" href="https://wiki.archivematica.org/index.php?title=Storage_Service_API&amp;diff=11691"/>
		<updated>2017-03-21T20:34:14Z</updated>

		<summary type="html">&lt;p&gt;Jdunham: /* Create new pipeline */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Main Page]] &amp;gt; [[Development]] &amp;gt; Storage Service API&lt;br /&gt;
&lt;br /&gt;
The [[Storage Service]] API provides programmatic access to moving files around in storage areas that the Storage Service has access to.&lt;br /&gt;
&lt;br /&gt;
The API is written using [http://django-tastypie.readthedocs.io/en/latest/ TastyPie].&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: TastyPie is less well supported than [http://www.django-rest-framework.org/ Django REST Framework], both in terms of docs &amp;amp; community. We should look at replacing TastyPie with DRF.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Endpoints require authentication with a username and API key.  This can be submitted as GET parameters (eg &amp;lt;code&amp;gt;?username=test&amp;amp;api_key=e6282adabed84e39ffe451f8bf6ff1a67c1fc9f2&amp;lt;/code&amp;gt;) or as a header (eg &amp;lt;code&amp;gt;Authorization: ApiKey test:e6282adabed84e39ffe451f8bf6ff1a67c1fc9f2&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== Pipeline ==&lt;br /&gt;
&lt;br /&gt;
=== Get all pipelines ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/pipeline/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
* '''Parameters''': Query string parameters&lt;br /&gt;
** &amp;lt;code&amp;gt;description&amp;lt;/code&amp;gt;: Description of the pipeline&lt;br /&gt;
** &amp;lt;code&amp;gt;uuid&amp;lt;/code&amp;gt;: UUID of the pipeline&lt;br /&gt;
* '''Response''': JSON&lt;br /&gt;
** &amp;lt;code&amp;gt;meta&amp;lt;/code&amp;gt;: Metadata on the response: number of hits, pagination information&lt;br /&gt;
** &amp;lt;code&amp;gt;objects&amp;lt;/code&amp;gt;: List of pipelines. See [[#Get pipeline details]] for format&lt;br /&gt;
&lt;br /&gt;
Returns information about all the pipelines in the system.  Can be [http://django-tastypie.readthedocs.io/en/latest/resources.html#basic-filtering filtered] by the description or uuid. Disabled pipelines are not returned.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 $ curl -X GET -H&amp;quot;Authorization: ApiKey test:95141fc645ed97a95893f1f865d24687f89a27ad&amp;quot; 'http://localhost:8000/api/v2/pipeline/?description__startswith=Archivematica' | python -m json.tool&lt;br /&gt;
 {&lt;br /&gt;
     &amp;quot;meta&amp;quot;: {&lt;br /&gt;
         &amp;quot;limit&amp;quot;: 20,&lt;br /&gt;
         &amp;quot;next&amp;quot;: null,&lt;br /&gt;
         &amp;quot;offset&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;previous&amp;quot;: null,&lt;br /&gt;
         &amp;quot;total_count&amp;quot;: 1&lt;br /&gt;
     },&lt;br /&gt;
     &amp;quot;objects&amp;quot;: [&lt;br /&gt;
         {&lt;br /&gt;
             &amp;quot;description&amp;quot;: &amp;quot;Archivematica on alouette&amp;quot;,&lt;br /&gt;
             &amp;quot;remote_name&amp;quot;: &amp;quot;127.0.0.1&amp;quot;,&lt;br /&gt;
             &amp;quot;resource_uri&amp;quot;: &amp;quot;/api/v2/pipeline/dd354557-9e6e-4918-9fe3-a65b00ecb1af/&amp;quot;,&lt;br /&gt;
             &amp;quot;uuid&amp;quot;: &amp;quot;dd354557-9e6e-4918-9fe3-a65b00ecb1af&amp;quot;&lt;br /&gt;
         }&lt;br /&gt;
     ]&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== Create new pipeline ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/pipeline/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': POST&lt;br /&gt;
* '''Parameters''': JSON body&lt;br /&gt;
** Should contain fields for a new pipeline: &amp;lt;code&amp;gt;uuid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;description&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;api_key&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;api_username&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;create_default_locations&amp;lt;/code&amp;gt;: If True, will associated default [[Storage Service#Locations | Locations]] with the newly created pipeline&lt;br /&gt;
** &amp;lt;code&amp;gt;shared_path&amp;lt;/code&amp;gt;: If default locations are created, create the [[Storage Service#Currently Processing | processing]] location at this path in the local filesystem&lt;br /&gt;
** &amp;lt;code&amp;gt;remote_name&amp;lt;/code&amp;gt;: IP or hostname of the pipeline. If not provided and  &amp;lt;code&amp;gt;create_default_locations&amp;lt;/code&amp;gt; is set, will try to populate from the IP of the request.&lt;br /&gt;
* '''Response''': JSON with data for the pipeline&lt;br /&gt;
&lt;br /&gt;
If the 'Pipelines disabled on creation' setting is set, the pipeline will be disabled by default, and will not respond to queries.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 $ curl -X POST -H&amp;quot;Authorization: ApiKey test:95141fc645ed97a95893f1f865d24687f89a27ad&amp;quot; -H&amp;quot;Content-Type: application/json&amp;quot; -d'{&amp;quot;uuid&amp;quot;: &amp;quot;99354557-9e6e-4918-9fe3-a65b00ecb199&amp;quot;, &amp;quot;description&amp;quot;: &amp;quot;Test pipeline&amp;quot;, &amp;quot;create_default_locations&amp;quot;: true, &amp;quot;api_username&amp;quot;: &amp;quot;demo&amp;quot;, &amp;quot;api_key&amp;quot;: &amp;quot;03ecb307f5b8012f4771d245d534830378a87259&amp;quot;}' 'http://192.168.1.42:8000/api/v2/pipeline/'&lt;br /&gt;
 {&lt;br /&gt;
    &amp;quot;create_default_locations&amp;quot;: true,&lt;br /&gt;
    &amp;quot;description&amp;quot;: &amp;quot;Test pipeline&amp;quot;,&lt;br /&gt;
    &amp;quot;remote_name&amp;quot;: &amp;quot;192.168.1.42&amp;quot;,&lt;br /&gt;
    &amp;quot;resource_uri&amp;quot;: &amp;quot;/api/v2/pipeline/99354557-9e6e-4918-9fe3-a65b00ecb199/&amp;quot;,&lt;br /&gt;
    &amp;quot;uuid&amp;quot;: &amp;quot;99354557-9e6e-4918-9fe3-a65b00ecb199&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== Get pipeline details ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/pipeline/&amp;lt;UUID&amp;gt;/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
* '''Parameters''': None&lt;br /&gt;
* '''Response''': JSON&lt;br /&gt;
** &amp;lt;code&amp;gt;description&amp;lt;/code&amp;gt;: Pipeline description&lt;br /&gt;
** &amp;lt;code&amp;gt;remote_name&amp;lt;/code&amp;gt;: IP or hostname of the pipeline. For use in API calls&lt;br /&gt;
** &amp;lt;code&amp;gt;resource_uri&amp;lt;/code&amp;gt;: URI for this pipeline in the API&lt;br /&gt;
** &amp;lt;code&amp;gt;uuid&amp;lt;/code&amp;gt;: UUID of the pipeline&lt;br /&gt;
&lt;br /&gt;
== Space ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: Is there no way to create Spaces in the API?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Get all spaces ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/space/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
* '''Parameters''': Query string parameters&lt;br /&gt;
** &amp;lt;code&amp;gt;access_protocol&amp;lt;/code&amp;gt;: Protocol that the [[Storage Service#Space | Space]] uses. Must be searched based on the database code.&lt;br /&gt;
** &amp;lt;code&amp;gt;path&amp;lt;/code&amp;gt;: Space's path&lt;br /&gt;
** &amp;lt;code&amp;gt;size&amp;lt;/code&amp;gt;: Maximum size in bytes. Can use greater than (size__gt=1024), less than (size__lt=1024), and other Django [https://docs.djangoproject.com/en/1.8/ref/models/querysets/#field-lookups field lookups].&lt;br /&gt;
** &amp;lt;code&amp;gt;used&amp;lt;/code&amp;gt;: Bytes stored in this space. Can use greater than (size__gt=1024), less than (size__lt=1024), and other Django [https://docs.djangoproject.com/en/1.8/ref/models/querysets/#field-lookups field lookups].&lt;br /&gt;
** &amp;lt;code&amp;gt;uuid&amp;lt;/code&amp;gt;: UUID of the Space&lt;br /&gt;
* '''Response''': JSON&lt;br /&gt;
** &amp;lt;code&amp;gt;meta&amp;lt;/code&amp;gt;: Metadata on the response: number of hits, pagination information&lt;br /&gt;
** &amp;lt;code&amp;gt;objects&amp;lt;/code&amp;gt;: List of spaces. See [[#Get space details]] for format&lt;br /&gt;
&lt;br /&gt;
Returns information about all the spaces in the system.  Can be [http://django-tastypie.readthedocs.io/en/latest/resources.html#basic-filtering filtered] by several fields: access protocol, path, size, amount used, UUID and verified status. Disabled spaces are not returned.&lt;br /&gt;
&lt;br /&gt;
=== Get space details ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/space/&amp;lt;UUID&amp;gt;/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
* '''Parameters''': None&lt;br /&gt;
* '''Response''': JSON&lt;br /&gt;
** &amp;lt;code&amp;gt;access_protocol&amp;lt;/code&amp;gt;: Database code for the access protocol&lt;br /&gt;
** &amp;lt;code&amp;gt;last_verified&amp;lt;/code&amp;gt;: Date of last verification. This is a stub feature&lt;br /&gt;
** &amp;lt;code&amp;gt;path&amp;lt;/code&amp;gt;: Space's path&lt;br /&gt;
** &amp;lt;code&amp;gt;resource_uri&amp;lt;/code&amp;gt;: URI to the resource in the API&lt;br /&gt;
** &amp;lt;code&amp;gt;size&amp;lt;/code&amp;gt;: Maximum size of the space in bytes.&lt;br /&gt;
** &amp;lt;code&amp;gt;used&amp;lt;/code&amp;gt;: Bytes stored in this space. &lt;br /&gt;
** &amp;lt;code&amp;gt;uuid&amp;lt;/code&amp;gt;: UUID of the space&lt;br /&gt;
** &amp;lt;code&amp;gt;verified&amp;lt;/code&amp;gt;: If the space is verified. This is a stub feature&lt;br /&gt;
** Other space-specific fields&lt;br /&gt;
&lt;br /&gt;
=== Browse space path ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/space/&amp;lt;UUID&amp;gt;/browse/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
* '''Parameters''': Query string parameters&lt;br /&gt;
** &amp;lt;code&amp;gt;path&amp;lt;/code&amp;gt;: Path inside the Space to look&lt;br /&gt;
* '''Response''': JSON&lt;br /&gt;
** &amp;lt;code&amp;gt;entries&amp;lt;/code&amp;gt;: List of entries at path, files or directories&lt;br /&gt;
** &amp;lt;code&amp;gt;directories&amp;lt;/code&amp;gt;: List of directories in path. Subset of `entries`.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffffcc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Version 1: Returns paths as strings&lt;br /&gt;
Version 2: Returns all paths base64 encoded&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Location ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: Is there no way to create Locations in the API?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Get all locations ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/location/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
&lt;br /&gt;
=== Get location details ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/location/&amp;lt;UUID&amp;gt;/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
&lt;br /&gt;
=== Move files to this location ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/location/&amp;lt;UUID&amp;gt;/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': POST&lt;br /&gt;
* '''Parameters''': JSON body&lt;br /&gt;
** &amp;lt;code&amp;gt;origin_location&amp;lt;/code&amp;gt;: URI of the Location the files should be moved from&lt;br /&gt;
** &amp;lt;code&amp;gt;pipeline&amp;lt;/code&amp;gt;: URI of the [[Storage Service#Pipeline | pipeline]]. Both Locations must be associated with this pipeline.&lt;br /&gt;
** &amp;lt;code&amp;gt;files&amp;lt;/code&amp;gt;: List of dicts containing &amp;lt;code&amp;gt;source&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;destination&amp;lt;/code&amp;gt;.  The source and destination are paths relative to their Location of the files to be moved.&lt;br /&gt;
&lt;br /&gt;
Intended for use with creating Transfers, SIPs, etc and other cases where files need to be moved but not tracked by the storage service.&lt;br /&gt;
&lt;br /&gt;
=== Browse location path ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/location/&amp;lt;UUID&amp;gt;/browse/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
* '''Parameters''': Query string parameters&lt;br /&gt;
** &amp;lt;code&amp;gt;path&amp;lt;/code&amp;gt;: Path inside the Location to look&lt;br /&gt;
* '''Response''': JSON&lt;br /&gt;
** &amp;lt;code&amp;gt;entries&amp;lt;/code&amp;gt;: List of entries in `path`, files or directories&lt;br /&gt;
** &amp;lt;code&amp;gt;directories&amp;lt;/code&amp;gt;: List of directories in `path`. Subset of `entries`.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffffcc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Version 1: Returns paths as strings&lt;br /&gt;
Version 2: Returns all paths base64 encoded&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== SWORD collection ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/location/&amp;lt;UUID&amp;gt;/sword/collection/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET, POST&lt;br /&gt;
&lt;br /&gt;
See [[Sword API]] for details&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Package ==&lt;br /&gt;
&lt;br /&gt;
=== Get all packages ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
&lt;br /&gt;
=== Create new package ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': POST&lt;br /&gt;
* '''Parameters''': JSON. Fields for a new package:&lt;br /&gt;
** &amp;lt;code&amp;gt;uuid&amp;lt;/code&amp;gt;: UUID of the new package&lt;br /&gt;
** &amp;lt;code&amp;gt;origin_location&amp;lt;/code&amp;gt;: URI of the Location where the package is currently&lt;br /&gt;
** &amp;lt;code&amp;gt;origin_path&amp;lt;/code&amp;gt;: Path to the package, relative to the origin_location&lt;br /&gt;
** &amp;lt;code&amp;gt;current_location&amp;lt;/code&amp;gt;: URI of the Location where the package should be stored&lt;br /&gt;
** &amp;lt;code&amp;gt;current_path&amp;lt;/code&amp;gt;: Path where the package should be stored, relative to the current_location&lt;br /&gt;
** &amp;lt;code&amp;gt;package_type&amp;lt;/code&amp;gt;: Type of package this is. One of: &amp;lt;code&amp;gt;AIP&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;AIC&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DIP&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;transfer&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SIP&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;file&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;deposit&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;size&amp;lt;/code&amp;gt;: Size of the package&lt;br /&gt;
** &amp;lt;code&amp;gt;origin_pipeline&amp;lt;/code&amp;gt;: URI of the pipeline the package is from&lt;br /&gt;
** &amp;lt;code&amp;gt;related_package_uuid&amp;lt;/code&amp;gt;: UUID of a package that is related to this one. E.g. UUID of a DIP when storing an AIP&lt;br /&gt;
&lt;br /&gt;
Creates a database entry tracking the package (AIP, transfer, etc).  If the package is an AIP, DIP or AIC and the current_location is an AIP or DIP storage location it also moves the files from the source to destination location.  If the package is a Transfer and the current_location is transfer backlog, it is also moved.&lt;br /&gt;
&lt;br /&gt;
This is handled through the modified &amp;lt;code&amp;gt;obj_create&amp;lt;/code&amp;gt; function, which calls &amp;lt;code&amp;gt;Package.store_aip&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Package.backlog_transfer&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Get package details ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
&lt;br /&gt;
=== Update package contents ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': PUT&lt;br /&gt;
* '''Parameters''': JSON body&lt;br /&gt;
** &amp;lt;code&amp;gt;reingest&amp;lt;/code&amp;gt;: Flag to mark that this is reingest. Reduces chance to accidentally modify an AIP.&lt;br /&gt;
** &amp;lt;code&amp;gt;uuid&amp;lt;/code&amp;gt;: UUID of the existing package&lt;br /&gt;
** &amp;lt;code&amp;gt;origin_location&amp;lt;/code&amp;gt;: URI of the Location where the package is currently&lt;br /&gt;
** &amp;lt;code&amp;gt;origin_path&amp;lt;/code&amp;gt;: Path to the package, relative to the origin_location&lt;br /&gt;
** &amp;lt;code&amp;gt;current_location&amp;lt;/code&amp;gt;: URI of the Location where the package should be stored&lt;br /&gt;
** &amp;lt;code&amp;gt;current_path&amp;lt;/code&amp;gt;: Path where the package should be stored, relative to the current_location&lt;br /&gt;
** &amp;lt;code&amp;gt;package_type&amp;lt;/code&amp;gt;: Type of package this is. One of: &amp;lt;code&amp;gt;AIP&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;AIC&amp;lt;/code&amp;gt;&lt;br /&gt;
** &amp;lt;code&amp;gt;size&amp;lt;/code&amp;gt;: Size of the package&lt;br /&gt;
** &amp;lt;code&amp;gt;origin_pipeline&amp;lt;/code&amp;gt;: URI of the pipeline the package is from.  This must be the same pipeline reingest was started on (tracked through &amp;lt;code&amp;gt;Package.misc_attributes.reingest_pipeline&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Updates the contents of a package during reingest.  If the package is an AIP or AIC, currently stored in an AIP storage location, and the 'reingest' parameter is set, it will call &amp;lt;code&amp;gt;Package.finish_reingest&amp;lt;/code&amp;gt; and merge the new AIP with the existing one.&lt;br /&gt;
&lt;br /&gt;
This is implemented using a modified &amp;lt;code&amp;gt;obj_update&amp;lt;/code&amp;gt; which calls &amp;lt;code&amp;gt;obj_update_hook&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Update package metadata ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': PATCH&lt;br /&gt;
* '''Parameters''': JSON body&lt;br /&gt;
** &amp;lt;code&amp;gt;reingest&amp;lt;/code&amp;gt;: Pipeline UUID or None.&lt;br /&gt;
&lt;br /&gt;
Used to update metadata stored in the database for the package.  Currently, this is used to update the reingest status.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: Currently, this always sets Package.misc_attributes.reingest to None, regardless of what value was actually passed in.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This is implemented using a modified &amp;lt;code&amp;gt;obj_update&amp;lt;/code&amp;gt; which calls &amp;lt;code&amp;gt;obj_update_hook&amp;lt;/code&amp;gt;.  &amp;lt;code&amp;gt;update_in_place&amp;lt;/code&amp;gt; also helps.&lt;br /&gt;
&lt;br /&gt;
=== Delete package request ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/delete_aip/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': POST&lt;br /&gt;
* '''Parameters''': JSON body&lt;br /&gt;
** &amp;lt;code&amp;gt;event_reason&amp;lt;/code&amp;gt;: Reason for deleting the AIP&lt;br /&gt;
** &amp;lt;code&amp;gt;pipeline&amp;lt;/code&amp;gt;: URI of the pipeline the delete request is from&lt;br /&gt;
** &amp;lt;code&amp;gt;user_id&amp;lt;/code&amp;gt;: User ID requesting the deletion. This is the ID of the user on the pipeline, and must be an integer greater than 0.&lt;br /&gt;
** &amp;lt;code&amp;gt;user_email&amp;lt;/code&amp;gt;:  Email of the user requesting the deletion.&lt;br /&gt;
&lt;br /&gt;
=== Recover AIP request ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/recover_aip/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': POST&lt;br /&gt;
* '''Parameters''': JSON body&lt;br /&gt;
** &amp;lt;code&amp;gt;event_reason&amp;lt;/code&amp;gt;: Reason for recovering the AIP&lt;br /&gt;
** &amp;lt;code&amp;gt;pipeline&amp;lt;/code&amp;gt;: URI of the pipeline the recovery request is from&lt;br /&gt;
** &amp;lt;code&amp;gt;user_id&amp;lt;/code&amp;gt;: User ID requesting the recovery. This is the ID of the user on the pipeline, and must be an integer greater than 0.&lt;br /&gt;
** &amp;lt;code&amp;gt;user_email&amp;lt;/code&amp;gt;:  Email of the user requesting the recovery.&lt;br /&gt;
&lt;br /&gt;
=== Download single file ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/extract_file/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET, HEAD&lt;br /&gt;
* '''Parameters''': Query string parameters&lt;br /&gt;
** &amp;lt;code&amp;gt;relative_path_to_file&amp;lt;/code&amp;gt;: Path to the file to download, relative to the package path.&lt;br /&gt;
* '''Response''': Stream of the requested file&lt;br /&gt;
&lt;br /&gt;
Returns a single file from the Package.  If the package is compressed, it downloads the whole AIP and extracts it.&lt;br /&gt;
&lt;br /&gt;
This responds to HEAD because AtoM uses HEAD to check for the existence of a file. &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: HEAD and GET should not perform the same functions. HEAD should be updated to not return the file, and to only check for existence.  Currently, the storage service has no way to check if a file exists except by downloading and extracting this AIP&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If the package is in [[Storage Service#Arkivum | Arkivum]], the package may not actually be available.  This endpoint checks if the package is locally available. If it is, it is returned as normal. If not, it returns &amp;lt;code&amp;gt;202&amp;lt;/code&amp;gt; and emails the administrator about the attempted access.&lt;br /&gt;
&lt;br /&gt;
=== Download package ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/download/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/download/&amp;lt;chunk number&amp;gt;/&amp;lt;/code&amp;gt; (for [[Storage Service#LOCKSS-o-matic | LOCKSS]] harvesting)&lt;br /&gt;
* '''Verb''': GET, HEAD&lt;br /&gt;
* '''Parameters''': None&lt;br /&gt;
* '''Response''': Stream of the package&lt;br /&gt;
&lt;br /&gt;
Returns the entire package as a single file.  If the AIP is uncompressed, create one file by using `tar`.&lt;br /&gt;
&lt;br /&gt;
If the download URL has a chunk number, it will attempt to serve the LOCKSS chunk specified for that package. If the package is not in LOCKSS, it will return the the whole package.&lt;br /&gt;
&lt;br /&gt;
This responds to HEAD because AtoM uses HEAD to check for the existence of a file. &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: HEAD and GET should not perform the same functions. HEAD should be updated to not return the file, and to only check for existence.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If the package is in [[Storage Service#Arkivum | Arkivum]], the package may not actually be available.  This endpoint checks if the package is locally available. If it is, it is returned as normal. If not, it returns &amp;lt;code&amp;gt;202&amp;lt;/code&amp;gt; and emails the administrator about the attempted access.&lt;br /&gt;
&lt;br /&gt;
=== Get pointer file ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/pointer_file/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
* '''Parameters''': None&lt;br /&gt;
* '''Response''': Stream of the pointer file.&lt;br /&gt;
&lt;br /&gt;
=== Check fixity ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/check_fixity/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
* '''Parameters''': Query string parameters&lt;br /&gt;
** &amp;lt;code&amp;gt;force_local&amp;lt;/code&amp;gt;: If true, download and run fixity on the AIP locally, instead of using the Space-provided fixity if available.&lt;br /&gt;
* '''Response''': JSON&lt;br /&gt;
** &amp;lt;code&amp;gt;success&amp;lt;/code&amp;gt;: True if the verification succeeded, False if the verification failed, None if the scan could not start&lt;br /&gt;
** &amp;lt;code&amp;gt;message&amp;lt;/code&amp;gt;: Human-readable string explaining the report; it will be empty for successful scans.&lt;br /&gt;
** &amp;lt;code&amp;gt;failures&amp;lt;/code&amp;gt;: List of 0 or more errors&lt;br /&gt;
** &amp;lt;code&amp;gt;timestamp&amp;lt;/code&amp;gt;: ISO-formated string with the datetime of the last fixity check. If the check was performed by an external system, this will be provided by that system. If not provided,or on error, it will be None.&lt;br /&gt;
&lt;br /&gt;
=== AIP storage callback request ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/send_callback/post_store/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
&lt;br /&gt;
Request to call any Callbacks configured to run post-storage for this AIP.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: This only works on locally available AIPs (AIPs stored in Spaces that are available via a UNIX filesystem layer).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Get file information for package ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/contents/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET&lt;br /&gt;
* '''Response''': JSON&lt;br /&gt;
** &amp;lt;code&amp;gt;success&amp;lt;/code&amp;gt;: True&lt;br /&gt;
** &amp;lt;code&amp;gt;package&amp;lt;/code&amp;gt;: UUID of the package&lt;br /&gt;
** &amp;lt;code&amp;gt;files&amp;lt;/code&amp;gt;: List of dictionaries with file information. Each dictionary has:&lt;br /&gt;
*** &amp;lt;code&amp;gt;source_id&amp;lt;/code&amp;gt;: UUID of the file to index&lt;br /&gt;
*** &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;: Relative path of the file inside the package&lt;br /&gt;
*** &amp;lt;code&amp;gt;source_package&amp;lt;/code&amp;gt;: UUID of the SIP this file is from&lt;br /&gt;
*** &amp;lt;code&amp;gt;checksum&amp;lt;/code&amp;gt;: Checksum of the file, or an empty string&lt;br /&gt;
*** &amp;lt;code&amp;gt;accessionid&amp;lt;/code&amp;gt;: Accession number, or an empty string&lt;br /&gt;
*** &amp;lt;code&amp;gt;origin&amp;lt;/code&amp;gt;: UUID of the Archivematica dashboard this is from&lt;br /&gt;
&lt;br /&gt;
Returns metadata about every file within the package.&lt;br /&gt;
&lt;br /&gt;
=== Update file information for package ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/contents/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': PUT&lt;br /&gt;
* '''Parameters''': JSON list of dictionaries with information on the files to be added. Each dict must have the following attributes:&lt;br /&gt;
** &amp;lt;code&amp;gt;relative_path&amp;lt;/code&amp;gt;: Relative path of the file inside the package&lt;br /&gt;
** &amp;lt;code&amp;gt;fileuuid&amp;lt;/code&amp;gt;: UUID of the file to index&lt;br /&gt;
** &amp;lt;code&amp;gt;accessionid&amp;lt;/code&amp;gt;: Accession number, or an empty string&lt;br /&gt;
** &amp;lt;code&amp;gt;sipuuid&amp;lt;/code&amp;gt;: UUID of the SIP this file is from&lt;br /&gt;
** &amp;lt;code&amp;gt;origin&amp;lt;/code&amp;gt;: UUID of the Archivematica dashboard this is from&lt;br /&gt;
&lt;br /&gt;
Adds a set of files to a package.&lt;br /&gt;
&lt;br /&gt;
=== Delete file information for package ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/contents/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': DELETE&lt;br /&gt;
&lt;br /&gt;
Removes all file records associated with this package.&lt;br /&gt;
&lt;br /&gt;
=== Query file information on packages ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/metadata/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': GET, POST&lt;br /&gt;
* '''Parameters''': Query string parameters.  Must have at least one, but not all are required&lt;br /&gt;
** &amp;lt;code&amp;gt;relative_path&amp;lt;/code&amp;gt;: Relative path of the file inside the package&lt;br /&gt;
** &amp;lt;code&amp;gt;fileuuid&amp;lt;/code&amp;gt;: UUID of the file&lt;br /&gt;
** &amp;lt;code&amp;gt;accessionid&amp;lt;/code&amp;gt;: Accession number&lt;br /&gt;
** &amp;lt;code&amp;gt;sipuuid&amp;lt;/code&amp;gt;: UUID of the SIP this file is from&lt;br /&gt;
* '''Response''': JSON. List of dicts with file information about the files that match the query.&lt;br /&gt;
** &amp;lt;code&amp;gt;accessionid&amp;lt;/code&amp;gt;: Accession number, or an empty string&lt;br /&gt;
** &amp;lt;code&amp;gt;file_extension&amp;lt;/code&amp;gt;: File extension&lt;br /&gt;
** &amp;lt;code&amp;gt;filename&amp;lt;/code&amp;gt;: Name of the file, sans path.&lt;br /&gt;
** &amp;lt;code&amp;gt;relative_path&amp;lt;/code&amp;gt;: Relative path of the file inside the package&lt;br /&gt;
** &amp;lt;code&amp;gt;fileuuid&amp;lt;/code&amp;gt;: UUID of the file to index&lt;br /&gt;
** &amp;lt;code&amp;gt;sipuuid&amp;lt;/code&amp;gt;: UUID of the SIP this file is from&lt;br /&gt;
** &amp;lt;code&amp;gt;origin&amp;lt;/code&amp;gt;: UUID of the Archivematica dashboard this is from&lt;br /&gt;
&lt;br /&gt;
=== Reingest AIP ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/reingest/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''Verb''': POST&lt;br /&gt;
* '''Parameters''': JSON body&lt;br /&gt;
** &amp;lt;code&amp;gt;pipeline&amp;lt;/code&amp;gt;: UUID of the pipeline to reingest on&lt;br /&gt;
** &amp;lt;code&amp;gt;reingest_type&amp;lt;/code&amp;gt;: Type of reingest to start. One of &amp;lt;code&amp;gt;METADATA_ONLY&amp;lt;/code&amp;gt; (metadata-only reingest), &amp;lt;code&amp;gt;OBJECTS&amp;lt;/code&amp;gt; (partial reingest), &amp;lt;code&amp;gt;FULL&amp;lt;/code&amp;gt; (full reingest)&lt;br /&gt;
** &amp;lt;code&amp;gt;processing_config&amp;lt;/code&amp;gt;: Optional. Name of the processing configuration to use on full reingest&lt;br /&gt;
&lt;br /&gt;
=== SWORD endpoints ===&lt;br /&gt;
&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/sword/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/sword/media/&amp;lt;/code&amp;gt;&lt;br /&gt;
* '''URL''': &amp;lt;code&amp;gt;/api/v2/file/&amp;lt;UUID&amp;gt;/sword/state/&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[Sword API]] for details.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Development documentation]]&lt;/div&gt;</summary>
		<author><name>Jdunham</name></author>
	</entry>
	<entry>
		<id>https://wiki.archivematica.org/index.php?title=Storage_Service&amp;diff=11690</id>
		<title>Storage Service</title>
		<link rel="alternate" type="text/html" href="https://wiki.archivematica.org/index.php?title=Storage_Service&amp;diff=11690"/>
		<updated>2017-03-21T20:33:38Z</updated>

		<summary type="html">&lt;p&gt;Jdunham: /* AIP Recovery */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Main Page]] &amp;gt; [[Development]] &amp;gt; [[:Category:Development documentation|Development documentation]] &amp;gt; Storage Service&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;status&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
Design&lt;br /&gt;
&amp;lt;div class=&amp;quot;description&amp;quot;&amp;gt;This page proposes a new feature and reviews design options&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
Development&lt;br /&gt;
&amp;lt;div class=&amp;quot;description&amp;quot;&amp;gt;This page describes a feature that's in development&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;active&amp;quot;&amp;gt;&lt;br /&gt;
Documentation&lt;br /&gt;
&amp;lt;div class=&amp;quot;description&amp;quot;&amp;gt;This page documents an implemented feature&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The Archivematica Storage Service is a standalone web application that handles moving files to Archivematica for processing, from Archivematica into long term storage, and keeps track of their location for later retrieval.&lt;br /&gt;
&lt;br /&gt;
There are 2 main configuration levels in the Storage Service: Spaces and Locations.&lt;br /&gt;
* [[#Space | Space]]: '''where''' the files are stored. This is the protocol used to fetch and store the files in a storage system.  Examples: Local filesystem, Duracloud.  Spaces contain Locations.&lt;br /&gt;
* [[#Location | Location]]: '''why''' the files are there. This is what purpose Archivematica is using them for. Examples: Transfer Source, AIP Storage.  Locations are inside Spaces.&lt;br /&gt;
&lt;br /&gt;
[[Storage API | Initial design requirements]] and [[Storage Service API | API documentation]] also exist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Space ==&lt;br /&gt;
&lt;br /&gt;
A storage Space contains all the information necessary to connect to the physical storage. It is '''where''' the files are stored. Protocol-specific information, like an NFS export path and hostname, or the username of a system accessible only via SSH, is stored here. All locations must be contained in a space.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Because Spaces deal with many different protocols and transportation needs, there are many different types of them. Each different Space type defines its own Django model (class), which has an associated Space instance.&lt;br /&gt;
&lt;br /&gt;
For path-based spaces, the Space is the immediate parent of the Location folders. For example, if you had transfer source locations at &amp;lt;code&amp;gt;/home/artefactual/archivematica-sampledata-2013-10-10-09-17-20&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;/home/artefactual/maildir_transfers&amp;lt;/code&amp;gt;, the Space’s path could be &amp;lt;code&amp;gt;/home/artefactual/&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All protocols require a staging path. This is a temporary location on the Storage Service server that is used when moving files.  The storage service moves files by first copying them to the destination Space's staging directory, and then to the actual destination space. This reduces complexity, because each Space only needs to know how to get files between the locally-accessible staging directory &amp;amp; its own protocol, not between all other protocols.&lt;br /&gt;
&lt;br /&gt;
There are 4 core methods that a Space should implement&lt;br /&gt;
* &amp;lt;code&amp;gt;browse&amp;lt;/code&amp;gt;&lt;br /&gt;
** Allows seeing the files available or stored here.&lt;br /&gt;
* &amp;lt;code&amp;gt;move_to_storage_service&amp;lt;/code&amp;gt;&lt;br /&gt;
** Moves files from the remote storage to the staging path&lt;br /&gt;
* &amp;lt;code&amp;gt;move_from_storage_service&amp;lt;/code&amp;gt;&lt;br /&gt;
** Moves files from the staging path to the remote storage.&lt;br /&gt;
* &amp;lt;code&amp;gt;delete_path&amp;lt;/code&amp;gt;&lt;br /&gt;
** Deletes files at a path.&lt;br /&gt;
&lt;br /&gt;
Additionally, several other functions enable custom behaviour&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;post_move_to_storage_service&amp;lt;/code&amp;gt;&lt;br /&gt;
** Allows post-processing after fetching files. E.g. putting a split package back together&lt;br /&gt;
* &amp;lt;code&amp;gt;post_move_from_storage_service&amp;lt;/code&amp;gt;&lt;br /&gt;
** Allows post-processing after storing files. E.g. Notifying the storage system of the new files&lt;br /&gt;
* &amp;lt;code&amp;gt;update_package_status&amp;lt;/code&amp;gt;&lt;br /&gt;
** Allow the status of a package in this system to be checked and updated. E.g. ensure replication has completed&lt;br /&gt;
* &amp;lt;code&amp;gt;check_package_fixity&amp;lt;/code&amp;gt;&lt;br /&gt;
** Allow a space's fixity check to be called, instead of downloading and running bagit manually&lt;br /&gt;
&lt;br /&gt;
Spaces can also be configured with a maximum quota to allow in that space, and track how much data has been stored in them through the storage service. &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: Quota and storage tracking is a stub feature, and does not properly track how much has been stored, especially with uncompressed AIPs and deleting AIPs.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: Currently, the Spaces are distinct models with a OnetoOneField back to Space. This was done because of warnings against concrete inheritance in models [https://jacobian.org/writing/concrete-inheritance/] [http://stackoverflow.com/questions/23466577/should-i-avoid-multi-table-concrete-inheritance-in-django-by-any-means]. However, in the Storage Service we never want to access a child space without also accessing its parent, so that concern is probably not founded.  A better future design would use concrete multi-table inheritance for the different types of Spaces.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: When originally written, the only Spaces conceived of were path-based (local filesystem, NFS, etc), so the Space/Location information reflected that. However, most new Spaces are object based, or otherwise don’t use the Space.path &amp;amp; Location.relative_path, and shouldn’t use os.path.join to join the two.  A better future design would move all path-related features out of Space into LocalFilesystem etc and remove the implicit os.path.join with Location.relative_path&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Spaces are sorted alphabetically in the docs.&lt;br /&gt;
&lt;br /&gt;
=== Arkivum ===&lt;br /&gt;
&lt;br /&gt;
* '''Uses Space.path''': Yes&lt;br /&gt;
* '''Supported purposes''': [[#AIP Storage | AIP Storage]]&lt;br /&gt;
* '''Database code''': ARKIVUM&lt;br /&gt;
&lt;br /&gt;
This uses Arkivum's A-Stor.  A-Stor exposes a CIFS share, which is mounted on the Storage Service and treated like a local filesystem. After files are copied to the share, a release request is sent to A-Stor to start its internal processing (copying the files to multiple datapools).  While the mount is exposed as a CIFS share, it is only imitating the behaviour. The files may not exist, and the package info must be checked before accessing files to ensure they are actually present and avoid long waits.&lt;br /&gt;
&lt;br /&gt;
=== Dataverse ===&lt;br /&gt;
&lt;br /&gt;
* '''Uses Space.path''': No&lt;br /&gt;
* '''Supported purposes''': [[#Transfer Source | Transfer Source]]&lt;br /&gt;
* '''Database code''': DV&lt;br /&gt;
&lt;br /&gt;
Dataverse is a prototype Space that requires support in Archivematica that is [https://github.com/artefactual/archivematica/pull/347 not yet merged]. It uses the search interface to 'browse' datasets by querying with the provided path.  It uses the returned JSON to fetch all files associated with that dataset, and the returned JSON is stored as &amp;lt;code&amp;gt;dataset.json&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| When fetching datasets to start a transfer with, it assumes that the identifier is a digit, and the Location &amp;amp; Space paths contain no digits.  This is a likely source of bugs.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Duracloud ===&lt;br /&gt;
&lt;br /&gt;
* '''Uses Space.path''': No&lt;br /&gt;
* '''Supported purposes''': [[#Transfer Source | Transfer Source]], [[#Transfer Backlog | Transfer Backlog]], [[#AIP Storage | AIP Storage ]], [[#DIP Storage | DIP Storage]], [[#AIP Recovery | AIP Recovery]]&lt;br /&gt;
* '''Database code''': DC&lt;br /&gt;
&lt;br /&gt;
A Duracloud Space corresponds with a Space in Archivematica, so to support multiple Duracloud Spaces, multiple storage service spaces must be created. The Location path is used as a prefix to the path. Duracloud is used in hosted Archivematica.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: The Location path should track which Space in Duracloud to upload to, instead of Duracloud.duraspace.  This would also remove the unnecessary prefixes in paths when uploading.  Care would have to be taken to migrate existing Duracloud configurations correctly. An optional path prefix could be useful. This would benefit from having Space.path removed first (see above improvement notes). &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== DSpace ===&lt;br /&gt;
&lt;br /&gt;
* '''Uses Space.path''': No&lt;br /&gt;
* '''Supported purposes''': [[#AIP Storage | AIP Storage]]&lt;br /&gt;
* '''Database code''': DSPACE&lt;br /&gt;
&lt;br /&gt;
DSpace uses the SWORD2 API &amp;amp; DSpace REST API to upload the AIP.  Before uploading, the AIP is split into two packages: one containing the objects, and one containing everything else (metadata, logs, bagit structure).  It also uploads Dublin Core information to DSpace if available. For the Dublin Core upload to work, some configuration changes in DSpace are required.&lt;br /&gt;
&lt;br /&gt;
To make DSpace fit with the path-based structure of Spaces, the &amp;lt;code&amp;gt;Space.path&amp;lt;/code&amp;gt; is unused, and the service document URL is stored in the Service Document IRI field.  The &amp;lt;code&amp;gt;Location.relative_path&amp;lt;/code&amp;gt; is overloaded to represent the collection.&lt;br /&gt;
&lt;br /&gt;
* Example service document IRI: http://dspace.institution.org:8080/swordv2/servicedocument&lt;br /&gt;
* Example location relative path: http://dspace.institution.org:8080/swordv2/collection/123456789/2&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: DSpace does not support fetching files from DSpace, so downloading the AIP, fixity check, and AIP reingest do not work. This should be implemented.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== FEDORA via SWORD2 ===&lt;br /&gt;
&lt;br /&gt;
* '''Uses Space.path''': Yes&lt;br /&gt;
* '''Supported purposes''': [[#FEDORA Deposit|FEDORA Deposit]]&lt;br /&gt;
* '''Database code''': FEDORA&lt;br /&gt;
&lt;br /&gt;
This offers a SWORD2 server API to allow another system (developed for [https://wiki.duraspace.org/display/ISLANDORA/Archidora Archidora], but could be others) to deposit content into Archivematica and trigger a Transfer. This is contrasted with the other Spaces, which require Archivematica to initiate contact. Examples and documentation at [[Sword API]].&lt;br /&gt;
&lt;br /&gt;
=== Local Filesystem ===&lt;br /&gt;
&lt;br /&gt;
* '''Uses Space.path''': Yes&lt;br /&gt;
* '''Supported purposes''': [[#Transfer Source | Transfer Source]], [[#Currently Processing | Currently Processing]], [[#Transfer Backlog | Transfer Backlog]], [[#AIP Storage | AIP Storage ]], [[#DIP Storage | DIP Storage]], [[#AIP Recovery | AIP Recovery]], [[#Storage Service Internal | Storage Service Internal]]&lt;br /&gt;
* '''Database code''': FS&lt;br /&gt;
&lt;br /&gt;
Local Filesystem spaces handle storage that is available locally on the machine running the storage service. This can be a hard drive, or a mounted remote filesystem. This is the default configured space.&lt;br /&gt;
&lt;br /&gt;
=== LOCKSS-o-matic ===&lt;br /&gt;
&lt;br /&gt;
* '''Uses Space.path''': Yes&lt;br /&gt;
* '''Supported purposes''': [[#AIP Storage | AIP Storage]]&lt;br /&gt;
* '''Database code''': LOM&lt;br /&gt;
&lt;br /&gt;
This support storing AIPs in a LOCKSS network via LOCKSS-O-Matic, which uses SWORD to communicate between the Storage Service and a Private LOCKSS Network (PLN). The Space.path is used as a staging location when making files available for harvesting.&lt;br /&gt;
&lt;br /&gt;
=== NFS ===&lt;br /&gt;
&lt;br /&gt;
* '''Uses Space.path''': Yes&lt;br /&gt;
* '''Supported purposes''': [[#Transfer Source | Transfer Source]], [[#Currently Processing | Currently Processing]], [[#Transfer Backlog | Transfer Backlog]], [[#AIP Storage | AIP Storage ]], [[#DIP Storage | DIP Storage]], [[#AIP Recovery | AIP Recovery]], [[#Storage Service Internal | Storage Service Internal]]&lt;br /&gt;
* '''Database code''': NFS&lt;br /&gt;
&lt;br /&gt;
NFS is a stub space. It was intended to support auto mounting NFS shares, but is not significantly different from [[#Local Filesystem | Local Filesystem]]. Currently, NFS handling should be done outside of Archivematica.&lt;br /&gt;
&lt;br /&gt;
=== Pipeline Local Filesystem ===&lt;br /&gt;
&lt;br /&gt;
* '''Uses Space.path''': Yes&lt;br /&gt;
* '''Supported purposes''': [[#Transfer Source | Transfer Source]], [[#Currently Processing | Currently Processing]], [[#Transfer Backlog | Transfer Backlog]], [[#AIP Storage | AIP Storage ]], [[#DIP Storage | DIP Storage]], [[#AIP Recovery | AIP Recovery]]&lt;br /&gt;
* '''Database code''': PIPE_FS&lt;br /&gt;
&lt;br /&gt;
Pipeline Local Filesystems refer to the storage that is local to the Archivematica pipeline, but remote to the storage service. For this Space to work properly, passwordless SSH must be set up between the Storage Service host and the Archivematica host.  This is the easiest way to support having the Pipeline and Storage Service on different machines.&lt;br /&gt;
&lt;br /&gt;
=== Swift ===&lt;br /&gt;
&lt;br /&gt;
* '''Uses Space.path''': No&lt;br /&gt;
* '''Supported purposes''': [[#Transfer Source | Transfer Source]], [[#Transfer Backlog | Transfer Backlog]], [[#AIP Storage | AIP Storage ]], [[#DIP Storage | DIP Storage]]&lt;br /&gt;
* '''Database code''': SWIFT&lt;br /&gt;
&lt;br /&gt;
This stores in OpenStack's Swift using the [https://pypi.python.org/pypi/python-swiftclient swiftclient] library.&lt;br /&gt;
&lt;br /&gt;
== Locations ==&lt;br /&gt;
&lt;br /&gt;
A storage Location is contained in a Space, and knows its purpose in the Archivematica system.   This is '''why''' the files are there.  A Location allows Archivematica to query for only storage that has been marked for a particular purpose.&lt;br /&gt;
&lt;br /&gt;
Each Location should be associated with at least one pipeline.   A pipeline can have multiple instances of any location, except for Backlog and Currently Processing locations which should only be one of. If you want the same directory on disk to have multiple purposes, multiple Locations with different purposes can be created.&lt;br /&gt;
&lt;br /&gt;
Not all Spaces support all Location purposes. For example, several Spaces only allow AIP storage, because they are only suitable for long term storage and do not provide temporary storage (eg Transfer backlog) or easy access to files (eg Transfer source). When creating a new Location, only allowed purposes are selectable in the menu.&lt;br /&gt;
&lt;br /&gt;
Locations are sorted by order of appearance in processing in the docs.&lt;br /&gt;
&lt;br /&gt;
=== Transfer Source ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Input into Archivematica&lt;br /&gt;
* '''Required''': Yes&lt;br /&gt;
* '''Multiples allowed''': Yes&lt;br /&gt;
* '''Database code''': TS&lt;br /&gt;
&lt;br /&gt;
Trasfer source locations are where Transfers can be started from and where metadata files can be added to a unit from.  Transfer source locations display in Archivematica’s Transfer tab. Any folder in a transfer source can be selected to become a Transfer. The default value is &amp;lt;code&amp;gt;/home&amp;lt;/code&amp;gt; in a Local Filesystem.&lt;br /&gt;
&lt;br /&gt;
=== Currently Processing ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': For Archivematica's internal processing&lt;br /&gt;
* '''Required''': Yes&lt;br /&gt;
* '''Multiples allowed''': No&lt;br /&gt;
* '''Database code''': CP&lt;br /&gt;
&lt;br /&gt;
During processing, Archivematica uses the currently processing location associated with that pipeline. Exactly one currently processing location should be associated with a given pipeline. The default value is &amp;lt;code&amp;gt;/var/archivematica/sharedDirectory&amp;lt;/code&amp;gt; in a Local Filesystem. This is required for Archivematica to run.&lt;br /&gt;
&lt;br /&gt;
=== Transfer Backlog ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Store Transfers in backlog&lt;br /&gt;
* '''Required''': No (Yes if using Backlog)&lt;br /&gt;
* '''Multiples allowed''': No&lt;br /&gt;
* '''Database code''': BL&lt;br /&gt;
&lt;br /&gt;
Transfer backlog stores transfers until such a time that the user continues processing them. The default value is &amp;lt;code&amp;gt;/var/archivematica/sharedDirectory/www/AIPsStore/transferBacklog&amp;lt;/code&amp;gt; in a Local Filesystem. This is required to store and retrieve transfers in backlog.&lt;br /&gt;
&lt;br /&gt;
=== AIP Storage ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Store AIPs for long term storage&lt;br /&gt;
* '''Required''': Yes&lt;br /&gt;
* '''Multiples allowed''': Yes&lt;br /&gt;
* '''Database code''': AS&lt;br /&gt;
&lt;br /&gt;
AIP storage locations are where the completed AIPs are put for long-term storage. The default value is &amp;lt;code&amp;gt;/var/archivematica/sharedDirectory/www/AIPsStore&amp;lt;/code&amp;gt; in a Local Filesystem. This is required to store and retrieve AIPs.&lt;br /&gt;
&lt;br /&gt;
=== DIP Storage ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Store DIPs before uploading to access systems&lt;br /&gt;
* '''Required''': No&lt;br /&gt;
* '''Multiples allowed''': Yes&lt;br /&gt;
* '''Database code''': DS&lt;br /&gt;
&lt;br /&gt;
DIP storage is used for storing DIPs until such a time that they can be uploaded to an access system. The default value is &amp;lt;code&amp;gt;/var/archivematica/sharedDirectory/www/DIPsStore&amp;lt;/code&amp;gt; in a Local Filesystem. This is required to store and retrieve DIPs. This is not required to upload DIPs to access systems.&lt;br /&gt;
&lt;br /&gt;
=== AIP Recovery ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Recover a corrupted AIP&lt;br /&gt;
* '''Required''': No&lt;br /&gt;
* '''Multiples allowed''': No&lt;br /&gt;
* '''Database code''': AR&lt;br /&gt;
&lt;br /&gt;
AIP Recovery is where the AIP recovery feature looks for an AIP to recover. No more than one AIP recovery location should be associated with a given pipeline. The default value is &amp;lt;code&amp;gt;/var/archivematica/storage_service/recover&amp;lt;/code&amp;gt; in a Local Filesystem. This is only required if AIP recovery is used.&lt;br /&gt;
&lt;br /&gt;
Needs clarification: Is this for storing the corrupted AIP, or for storing a duplicate copy of the AIP from which it can be recovered, or for something else?&lt;br /&gt;
&lt;br /&gt;
=== Storage Service Internal ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Internal staging area for the Storage Service&lt;br /&gt;
* '''Required''': Yes&lt;br /&gt;
* '''Multiples allowed''': No&lt;br /&gt;
* '''Database code''': SS&lt;br /&gt;
* '''Associated with a pipeline''': No&lt;br /&gt;
&lt;br /&gt;
There should only be exactly one Storage Service Internal Processing location for each Storage Service installation. The default value is &amp;lt;code&amp;gt;/var/archivematica/storage_service&amp;lt;/code&amp;gt; in a Local Filesystem. This is required for the Storage Service to run, and must be locally available to the storage service. It should not be associated with any pipelines.&lt;br /&gt;
&lt;br /&gt;
=== FEDORA Deposit ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Store deposited transfers from Archidora before starting as a Transfer.&lt;br /&gt;
* '''Required''': No&lt;br /&gt;
* '''Multiples allowed''': Yes&lt;br /&gt;
* '''Database code''': SD&lt;br /&gt;
&lt;br /&gt;
FEDORA Deposit is used with the Archidora plugin to ingest material from Islandora. This is only available to the FEDORA Space, and is only required for that space.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Pipelines ==&lt;br /&gt;
&lt;br /&gt;
Archivematica installations are tracked in the Storage Service as Pipelines.  Locations are associated with Pipelines, which gives them access to that storage. If a Location is not associated with a Pipeline, it doesn't exist as far as that pipeline is concerned.&lt;br /&gt;
&lt;br /&gt;
== Package ==&lt;br /&gt;
&lt;br /&gt;
Packages are a file or directory (collection of files) that Archivematica knows about and can track. Most Packages are AIPs in long term storage, but they could also be Transfers in backlog or stored DIPs.&lt;br /&gt;
&lt;br /&gt;
Most of the additional functionality in the storage service not directly related to moving files around is implemented on the Package class.&lt;br /&gt;
&lt;br /&gt;
=== Status ===&lt;br /&gt;
&lt;br /&gt;
Packages can have several different statuses, indicating where they are in terms of being stored. &lt;br /&gt;
&lt;br /&gt;
* Upload Pending: Still on Archivematica&lt;br /&gt;
* Staged on Storage Service: In Storage Service staging directory&lt;br /&gt;
* Uploaded: In final storage location&lt;br /&gt;
* Verified: Verified to be in final storage location&lt;br /&gt;
* Failed: Error occurred - may or may not be at final location&lt;br /&gt;
* Delete requested: Delete requested, package state unchanged&lt;br /&gt;
* Deleted: Storage service tried to delete it, considers it gone&lt;br /&gt;
* Deposit Finalized: For SWORD API accepting deposits (unused for AIPs)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Upload Pending&amp;quot; is set when storing an AIP, before it's been moved from the pipeline to the staging directory of the final destination.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Staging&amp;quot; is set when storing an AIP after it's been moved to the staging directory of the destination Space.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Uploaded&amp;quot; is set when storing an AIP after it has been moved to the final location, unless it's LOCKSS or Arkivum.  Arkivum packages move to &amp;quot;Uploaded&amp;quot; once the replication status is &amp;quot;green&amp;quot;, and LOCKSS once all server states are &amp;quot;agreement&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Verified&amp;quot; exists but is never used.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Failed&amp;quot; is the default state if none is set (eg if it doesn't get to Upload Pending), but is otherwise unused.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Delete requested&amp;quot; is set when a request is deleted. Note that this replaces the previous state, so if the delete request is rejected the previous state is lost.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Deleted&amp;quot; happens when a delete request is approved. The package entry still exists, but is assumed to be gone. A package can be in this state but still exist if the delete failed.  The storage service doesn't enforce not interacting with deleted packages&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Deposit Finalized&amp;quot; is the state of a FEDORA transfer after the deposit is finalized and the transfer has been started.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: Make &amp;quot;Uploaded&amp;quot; more consistent - state is always Uploaded after the AIP has been moved to the final location, and start using &amp;quot;Verified&amp;quot; for what Arkivum &amp;amp; LOCKSS currently use &amp;quot;Uploaded&amp;quot; for.  Perhaps &amp;quot;Uploaded&amp;quot; should be renamed, since in the case of LOCKSS/Arkivum it may not have been actually uploaded yet.  This is potentially confused though, because the 'completely stored' state (Uploaded vs Verified) is different depending on the Space.&lt;br /&gt;
|} &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: Start using &amp;quot;Failed&amp;quot;. Use cases might include Arkivum status going from Green to Red, or otherwise failing a fixity check.&lt;br /&gt;
|} &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: Store the package state as set or a list. This would allow a package to be Uploaded and Delete requested, instead of losing that state. We could also mark something as both Uploaded and Verified, resolving how to handle Arkivum status.  Failed could coexist with the last known good state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== API ==&lt;br /&gt;
&lt;br /&gt;
See [[Storage Service API]]&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
The Storage service keeps a log at /var/log/archivematica/storage-service.log and errors may also be logged to the nginx and uwsgi logs as well at: /var/log/uwsgi/app/storage.log&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[Administrator manual 1.1#Storage service]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Development documentation]]&lt;/div&gt;</summary>
		<author><name>Jdunham</name></author>
	</entry>
	<entry>
		<id>https://wiki.archivematica.org/index.php?title=Storage_Service&amp;diff=11689</id>
		<title>Storage Service</title>
		<link rel="alternate" type="text/html" href="https://wiki.archivematica.org/index.php?title=Storage_Service&amp;diff=11689"/>
		<updated>2017-03-21T20:32:16Z</updated>

		<summary type="html">&lt;p&gt;Jdunham: /* Troubleshooting */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Main Page]] &amp;gt; [[Development]] &amp;gt; [[:Category:Development documentation|Development documentation]] &amp;gt; Storage Service&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;status&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
Design&lt;br /&gt;
&amp;lt;div class=&amp;quot;description&amp;quot;&amp;gt;This page proposes a new feature and reviews design options&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div&amp;gt;&lt;br /&gt;
Development&lt;br /&gt;
&amp;lt;div class=&amp;quot;description&amp;quot;&amp;gt;This page describes a feature that's in development&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;active&amp;quot;&amp;gt;&lt;br /&gt;
Documentation&lt;br /&gt;
&amp;lt;div class=&amp;quot;description&amp;quot;&amp;gt;This page documents an implemented feature&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The Archivematica Storage Service is a standalone web application that handles moving files to Archivematica for processing, from Archivematica into long term storage, and keeps track of their location for later retrieval.&lt;br /&gt;
&lt;br /&gt;
There are 2 main configuration levels in the Storage Service: Spaces and Locations.&lt;br /&gt;
* [[#Space | Space]]: '''where''' the files are stored. This is the protocol used to fetch and store the files in a storage system.  Examples: Local filesystem, Duracloud.  Spaces contain Locations.&lt;br /&gt;
* [[#Location | Location]]: '''why''' the files are there. This is what purpose Archivematica is using them for. Examples: Transfer Source, AIP Storage.  Locations are inside Spaces.&lt;br /&gt;
&lt;br /&gt;
[[Storage API | Initial design requirements]] and [[Storage Service API | API documentation]] also exist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Space ==&lt;br /&gt;
&lt;br /&gt;
A storage Space contains all the information necessary to connect to the physical storage. It is '''where''' the files are stored. Protocol-specific information, like an NFS export path and hostname, or the username of a system accessible only via SSH, is stored here. All locations must be contained in a space.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Because Spaces deal with many different protocols and transportation needs, there are many different types of them. Each different Space type defines its own Django model (class), which has an associated Space instance.&lt;br /&gt;
&lt;br /&gt;
For path-based spaces, the Space is the immediate parent of the Location folders. For example, if you had transfer source locations at &amp;lt;code&amp;gt;/home/artefactual/archivematica-sampledata-2013-10-10-09-17-20&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;/home/artefactual/maildir_transfers&amp;lt;/code&amp;gt;, the Space’s path could be &amp;lt;code&amp;gt;/home/artefactual/&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All protocols require a staging path. This is a temporary location on the Storage Service server that is used when moving files.  The storage service moves files by first copying them to the destination Space's staging directory, and then to the actual destination space. This reduces complexity, because each Space only needs to know how to get files between the locally-accessible staging directory &amp;amp; its own protocol, not between all other protocols.&lt;br /&gt;
&lt;br /&gt;
There are 4 core methods that a Space should implement&lt;br /&gt;
* &amp;lt;code&amp;gt;browse&amp;lt;/code&amp;gt;&lt;br /&gt;
** Allows seeing the files available or stored here.&lt;br /&gt;
* &amp;lt;code&amp;gt;move_to_storage_service&amp;lt;/code&amp;gt;&lt;br /&gt;
** Moves files from the remote storage to the staging path&lt;br /&gt;
* &amp;lt;code&amp;gt;move_from_storage_service&amp;lt;/code&amp;gt;&lt;br /&gt;
** Moves files from the staging path to the remote storage.&lt;br /&gt;
* &amp;lt;code&amp;gt;delete_path&amp;lt;/code&amp;gt;&lt;br /&gt;
** Deletes files at a path.&lt;br /&gt;
&lt;br /&gt;
Additionally, several other functions enable custom behaviour&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;post_move_to_storage_service&amp;lt;/code&amp;gt;&lt;br /&gt;
** Allows post-processing after fetching files. E.g. putting a split package back together&lt;br /&gt;
* &amp;lt;code&amp;gt;post_move_from_storage_service&amp;lt;/code&amp;gt;&lt;br /&gt;
** Allows post-processing after storing files. E.g. Notifying the storage system of the new files&lt;br /&gt;
* &amp;lt;code&amp;gt;update_package_status&amp;lt;/code&amp;gt;&lt;br /&gt;
** Allow the status of a package in this system to be checked and updated. E.g. ensure replication has completed&lt;br /&gt;
* &amp;lt;code&amp;gt;check_package_fixity&amp;lt;/code&amp;gt;&lt;br /&gt;
** Allow a space's fixity check to be called, instead of downloading and running bagit manually&lt;br /&gt;
&lt;br /&gt;
Spaces can also be configured with a maximum quota to allow in that space, and track how much data has been stored in them through the storage service. &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: Quota and storage tracking is a stub feature, and does not properly track how much has been stored, especially with uncompressed AIPs and deleting AIPs.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: Currently, the Spaces are distinct models with a OnetoOneField back to Space. This was done because of warnings against concrete inheritance in models [https://jacobian.org/writing/concrete-inheritance/] [http://stackoverflow.com/questions/23466577/should-i-avoid-multi-table-concrete-inheritance-in-django-by-any-means]. However, in the Storage Service we never want to access a child space without also accessing its parent, so that concern is probably not founded.  A better future design would use concrete multi-table inheritance for the different types of Spaces.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: When originally written, the only Spaces conceived of were path-based (local filesystem, NFS, etc), so the Space/Location information reflected that. However, most new Spaces are object based, or otherwise don’t use the Space.path &amp;amp; Location.relative_path, and shouldn’t use os.path.join to join the two.  A better future design would move all path-related features out of Space into LocalFilesystem etc and remove the implicit os.path.join with Location.relative_path&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Spaces are sorted alphabetically in the docs.&lt;br /&gt;
&lt;br /&gt;
=== Arkivum ===&lt;br /&gt;
&lt;br /&gt;
* '''Uses Space.path''': Yes&lt;br /&gt;
* '''Supported purposes''': [[#AIP Storage | AIP Storage]]&lt;br /&gt;
* '''Database code''': ARKIVUM&lt;br /&gt;
&lt;br /&gt;
This uses Arkivum's A-Stor.  A-Stor exposes a CIFS share, which is mounted on the Storage Service and treated like a local filesystem. After files are copied to the share, a release request is sent to A-Stor to start its internal processing (copying the files to multiple datapools).  While the mount is exposed as a CIFS share, it is only imitating the behaviour. The files may not exist, and the package info must be checked before accessing files to ensure they are actually present and avoid long waits.&lt;br /&gt;
&lt;br /&gt;
=== Dataverse ===&lt;br /&gt;
&lt;br /&gt;
* '''Uses Space.path''': No&lt;br /&gt;
* '''Supported purposes''': [[#Transfer Source | Transfer Source]]&lt;br /&gt;
* '''Database code''': DV&lt;br /&gt;
&lt;br /&gt;
Dataverse is a prototype Space that requires support in Archivematica that is [https://github.com/artefactual/archivematica/pull/347 not yet merged]. It uses the search interface to 'browse' datasets by querying with the provided path.  It uses the returned JSON to fetch all files associated with that dataset, and the returned JSON is stored as &amp;lt;code&amp;gt;dataset.json&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| When fetching datasets to start a transfer with, it assumes that the identifier is a digit, and the Location &amp;amp; Space paths contain no digits.  This is a likely source of bugs.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Duracloud ===&lt;br /&gt;
&lt;br /&gt;
* '''Uses Space.path''': No&lt;br /&gt;
* '''Supported purposes''': [[#Transfer Source | Transfer Source]], [[#Transfer Backlog | Transfer Backlog]], [[#AIP Storage | AIP Storage ]], [[#DIP Storage | DIP Storage]], [[#AIP Recovery | AIP Recovery]]&lt;br /&gt;
* '''Database code''': DC&lt;br /&gt;
&lt;br /&gt;
A Duracloud Space corresponds with a Space in Archivematica, so to support multiple Duracloud Spaces, multiple storage service spaces must be created. The Location path is used as a prefix to the path. Duracloud is used in hosted Archivematica.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: The Location path should track which Space in Duracloud to upload to, instead of Duracloud.duraspace.  This would also remove the unnecessary prefixes in paths when uploading.  Care would have to be taken to migrate existing Duracloud configurations correctly. An optional path prefix could be useful. This would benefit from having Space.path removed first (see above improvement notes). &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== DSpace ===&lt;br /&gt;
&lt;br /&gt;
* '''Uses Space.path''': No&lt;br /&gt;
* '''Supported purposes''': [[#AIP Storage | AIP Storage]]&lt;br /&gt;
* '''Database code''': DSPACE&lt;br /&gt;
&lt;br /&gt;
DSpace uses the SWORD2 API &amp;amp; DSpace REST API to upload the AIP.  Before uploading, the AIP is split into two packages: one containing the objects, and one containing everything else (metadata, logs, bagit structure).  It also uploads Dublin Core information to DSpace if available. For the Dublin Core upload to work, some configuration changes in DSpace are required.&lt;br /&gt;
&lt;br /&gt;
To make DSpace fit with the path-based structure of Spaces, the &amp;lt;code&amp;gt;Space.path&amp;lt;/code&amp;gt; is unused, and the service document URL is stored in the Service Document IRI field.  The &amp;lt;code&amp;gt;Location.relative_path&amp;lt;/code&amp;gt; is overloaded to represent the collection.&lt;br /&gt;
&lt;br /&gt;
* Example service document IRI: http://dspace.institution.org:8080/swordv2/servicedocument&lt;br /&gt;
* Example location relative path: http://dspace.institution.org:8080/swordv2/collection/123456789/2&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: DSpace does not support fetching files from DSpace, so downloading the AIP, fixity check, and AIP reingest do not work. This should be implemented.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== FEDORA via SWORD2 ===&lt;br /&gt;
&lt;br /&gt;
* '''Uses Space.path''': Yes&lt;br /&gt;
* '''Supported purposes''': [[#FEDORA Deposit|FEDORA Deposit]]&lt;br /&gt;
* '''Database code''': FEDORA&lt;br /&gt;
&lt;br /&gt;
This offers a SWORD2 server API to allow another system (developed for [https://wiki.duraspace.org/display/ISLANDORA/Archidora Archidora], but could be others) to deposit content into Archivematica and trigger a Transfer. This is contrasted with the other Spaces, which require Archivematica to initiate contact. Examples and documentation at [[Sword API]].&lt;br /&gt;
&lt;br /&gt;
=== Local Filesystem ===&lt;br /&gt;
&lt;br /&gt;
* '''Uses Space.path''': Yes&lt;br /&gt;
* '''Supported purposes''': [[#Transfer Source | Transfer Source]], [[#Currently Processing | Currently Processing]], [[#Transfer Backlog | Transfer Backlog]], [[#AIP Storage | AIP Storage ]], [[#DIP Storage | DIP Storage]], [[#AIP Recovery | AIP Recovery]], [[#Storage Service Internal | Storage Service Internal]]&lt;br /&gt;
* '''Database code''': FS&lt;br /&gt;
&lt;br /&gt;
Local Filesystem spaces handle storage that is available locally on the machine running the storage service. This can be a hard drive, or a mounted remote filesystem. This is the default configured space.&lt;br /&gt;
&lt;br /&gt;
=== LOCKSS-o-matic ===&lt;br /&gt;
&lt;br /&gt;
* '''Uses Space.path''': Yes&lt;br /&gt;
* '''Supported purposes''': [[#AIP Storage | AIP Storage]]&lt;br /&gt;
* '''Database code''': LOM&lt;br /&gt;
&lt;br /&gt;
This support storing AIPs in a LOCKSS network via LOCKSS-O-Matic, which uses SWORD to communicate between the Storage Service and a Private LOCKSS Network (PLN). The Space.path is used as a staging location when making files available for harvesting.&lt;br /&gt;
&lt;br /&gt;
=== NFS ===&lt;br /&gt;
&lt;br /&gt;
* '''Uses Space.path''': Yes&lt;br /&gt;
* '''Supported purposes''': [[#Transfer Source | Transfer Source]], [[#Currently Processing | Currently Processing]], [[#Transfer Backlog | Transfer Backlog]], [[#AIP Storage | AIP Storage ]], [[#DIP Storage | DIP Storage]], [[#AIP Recovery | AIP Recovery]], [[#Storage Service Internal | Storage Service Internal]]&lt;br /&gt;
* '''Database code''': NFS&lt;br /&gt;
&lt;br /&gt;
NFS is a stub space. It was intended to support auto mounting NFS shares, but is not significantly different from [[#Local Filesystem | Local Filesystem]]. Currently, NFS handling should be done outside of Archivematica.&lt;br /&gt;
&lt;br /&gt;
=== Pipeline Local Filesystem ===&lt;br /&gt;
&lt;br /&gt;
* '''Uses Space.path''': Yes&lt;br /&gt;
* '''Supported purposes''': [[#Transfer Source | Transfer Source]], [[#Currently Processing | Currently Processing]], [[#Transfer Backlog | Transfer Backlog]], [[#AIP Storage | AIP Storage ]], [[#DIP Storage | DIP Storage]], [[#AIP Recovery | AIP Recovery]]&lt;br /&gt;
* '''Database code''': PIPE_FS&lt;br /&gt;
&lt;br /&gt;
Pipeline Local Filesystems refer to the storage that is local to the Archivematica pipeline, but remote to the storage service. For this Space to work properly, passwordless SSH must be set up between the Storage Service host and the Archivematica host.  This is the easiest way to support having the Pipeline and Storage Service on different machines.&lt;br /&gt;
&lt;br /&gt;
=== Swift ===&lt;br /&gt;
&lt;br /&gt;
* '''Uses Space.path''': No&lt;br /&gt;
* '''Supported purposes''': [[#Transfer Source | Transfer Source]], [[#Transfer Backlog | Transfer Backlog]], [[#AIP Storage | AIP Storage ]], [[#DIP Storage | DIP Storage]]&lt;br /&gt;
* '''Database code''': SWIFT&lt;br /&gt;
&lt;br /&gt;
This stores in OpenStack's Swift using the [https://pypi.python.org/pypi/python-swiftclient swiftclient] library.&lt;br /&gt;
&lt;br /&gt;
== Locations ==&lt;br /&gt;
&lt;br /&gt;
A storage Location is contained in a Space, and knows its purpose in the Archivematica system.   This is '''why''' the files are there.  A Location allows Archivematica to query for only storage that has been marked for a particular purpose.&lt;br /&gt;
&lt;br /&gt;
Each Location should be associated with at least one pipeline.   A pipeline can have multiple instances of any location, except for Backlog and Currently Processing locations which should only be one of. If you want the same directory on disk to have multiple purposes, multiple Locations with different purposes can be created.&lt;br /&gt;
&lt;br /&gt;
Not all Spaces support all Location purposes. For example, several Spaces only allow AIP storage, because they are only suitable for long term storage and do not provide temporary storage (eg Transfer backlog) or easy access to files (eg Transfer source). When creating a new Location, only allowed purposes are selectable in the menu.&lt;br /&gt;
&lt;br /&gt;
Locations are sorted by order of appearance in processing in the docs.&lt;br /&gt;
&lt;br /&gt;
=== Transfer Source ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Input into Archivematica&lt;br /&gt;
* '''Required''': Yes&lt;br /&gt;
* '''Multiples allowed''': Yes&lt;br /&gt;
* '''Database code''': TS&lt;br /&gt;
&lt;br /&gt;
Trasfer source locations are where Transfers can be started from and where metadata files can be added to a unit from.  Transfer source locations display in Archivematica’s Transfer tab. Any folder in a transfer source can be selected to become a Transfer. The default value is &amp;lt;code&amp;gt;/home&amp;lt;/code&amp;gt; in a Local Filesystem.&lt;br /&gt;
&lt;br /&gt;
=== Currently Processing ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': For Archivematica's internal processing&lt;br /&gt;
* '''Required''': Yes&lt;br /&gt;
* '''Multiples allowed''': No&lt;br /&gt;
* '''Database code''': CP&lt;br /&gt;
&lt;br /&gt;
During processing, Archivematica uses the currently processing location associated with that pipeline. Exactly one currently processing location should be associated with a given pipeline. The default value is &amp;lt;code&amp;gt;/var/archivematica/sharedDirectory&amp;lt;/code&amp;gt; in a Local Filesystem. This is required for Archivematica to run.&lt;br /&gt;
&lt;br /&gt;
=== Transfer Backlog ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Store Transfers in backlog&lt;br /&gt;
* '''Required''': No (Yes if using Backlog)&lt;br /&gt;
* '''Multiples allowed''': No&lt;br /&gt;
* '''Database code''': BL&lt;br /&gt;
&lt;br /&gt;
Transfer backlog stores transfers until such a time that the user continues processing them. The default value is &amp;lt;code&amp;gt;/var/archivematica/sharedDirectory/www/AIPsStore/transferBacklog&amp;lt;/code&amp;gt; in a Local Filesystem. This is required to store and retrieve transfers in backlog.&lt;br /&gt;
&lt;br /&gt;
=== AIP Storage ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Store AIPs for long term storage&lt;br /&gt;
* '''Required''': Yes&lt;br /&gt;
* '''Multiples allowed''': Yes&lt;br /&gt;
* '''Database code''': AS&lt;br /&gt;
&lt;br /&gt;
AIP storage locations are where the completed AIPs are put for long-term storage. The default value is &amp;lt;code&amp;gt;/var/archivematica/sharedDirectory/www/AIPsStore&amp;lt;/code&amp;gt; in a Local Filesystem. This is required to store and retrieve AIPs.&lt;br /&gt;
&lt;br /&gt;
=== DIP Storage ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Store DIPs before uploading to access systems&lt;br /&gt;
* '''Required''': No&lt;br /&gt;
* '''Multiples allowed''': Yes&lt;br /&gt;
* '''Database code''': DS&lt;br /&gt;
&lt;br /&gt;
DIP storage is used for storing DIPs until such a time that they can be uploaded to an access system. The default value is &amp;lt;code&amp;gt;/var/archivematica/sharedDirectory/www/DIPsStore&amp;lt;/code&amp;gt; in a Local Filesystem. This is required to store and retrieve DIPs. This is not required to upload DIPs to access systems.&lt;br /&gt;
&lt;br /&gt;
=== AIP Recovery ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Recover a corrupted AIP&lt;br /&gt;
* '''Required''': No&lt;br /&gt;
* '''Multiples allowed''': No&lt;br /&gt;
* '''Database code''': AR&lt;br /&gt;
&lt;br /&gt;
AIP Recovery is where the AIP recovery feature looks for an AIP to recover. No more than one AIP recovery location should be associated with a given pipeline. The default value is &amp;lt;code&amp;gt;/var/archivematica/storage_service/recover&amp;lt;/code&amp;gt; in a Local Filesystem. This is only required if AIP recovery is used.&lt;br /&gt;
&lt;br /&gt;
Needs clarification: Is this to stored the corrupted AIP, or stores a duplicated copy of the AIP so it can be recovered from, or something else?&lt;br /&gt;
&lt;br /&gt;
=== Storage Service Internal ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Internal staging area for the Storage Service&lt;br /&gt;
* '''Required''': Yes&lt;br /&gt;
* '''Multiples allowed''': No&lt;br /&gt;
* '''Database code''': SS&lt;br /&gt;
* '''Associated with a pipeline''': No&lt;br /&gt;
&lt;br /&gt;
There should only be exactly one Storage Service Internal Processing location for each Storage Service installation. The default value is &amp;lt;code&amp;gt;/var/archivematica/storage_service&amp;lt;/code&amp;gt; in a Local Filesystem. This is required for the Storage Service to run, and must be locally available to the storage service. It should not be associated with any pipelines.&lt;br /&gt;
&lt;br /&gt;
=== FEDORA Deposit ===&lt;br /&gt;
&lt;br /&gt;
* '''Purpose''': Store deposited transfers from Archidora before starting as a Transfer.&lt;br /&gt;
* '''Required''': No&lt;br /&gt;
* '''Multiples allowed''': Yes&lt;br /&gt;
* '''Database code''': SD&lt;br /&gt;
&lt;br /&gt;
FEDORA Deposit is used with the Archidora plugin to ingest material from Islandora. This is only available to the FEDORA Space, and is only required for that space.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Pipelines ==&lt;br /&gt;
&lt;br /&gt;
Archivematica installations are tracked in the Storage Service as Pipelines.  Locations are associated with Pipelines, which gives them access to that storage. If a Location is not associated with a Pipeline, it doesn't exist as far as that pipeline is concerned.&lt;br /&gt;
&lt;br /&gt;
== Package ==&lt;br /&gt;
&lt;br /&gt;
Packages are a file or directory (collection of files) that Archivematica knows about and can track. Most Packages are AIPs in long term storage, but they could also be Transfers in backlog or stored DIPs.&lt;br /&gt;
&lt;br /&gt;
Most of the additional functionality in the storage service not directly related to moving files around is implemented on the Package class.&lt;br /&gt;
&lt;br /&gt;
=== Status ===&lt;br /&gt;
&lt;br /&gt;
Packages can have several different statuses, indicating where they are in terms of being stored. &lt;br /&gt;
&lt;br /&gt;
* Upload Pending: Still on Archivematica&lt;br /&gt;
* Staged on Storage Service: In Storage Service staging directory&lt;br /&gt;
* Uploaded: In final storage location&lt;br /&gt;
* Verified: Verified to be in final storage location&lt;br /&gt;
* Failed: Error occurred - may or may not be at final location&lt;br /&gt;
* Delete requested: Delete requested, package state unchanged&lt;br /&gt;
* Deleted: Storage service tried to delete it, considers it gone&lt;br /&gt;
* Deposit Finalized: For SWORD API accepting deposits (unused for AIPs)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Upload Pending&amp;quot; is set when storing an AIP, before it's been moved from the pipeline to the staging directory of the final destination.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Staging&amp;quot; is set when storing an AIP after it's been moved to the staging directory of the destination Space.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Uploaded&amp;quot; is set when storing an AIP after it has been moved to the final location, unless it's LOCKSS or Arkivum.  Arkivum packages move to &amp;quot;Uploaded&amp;quot; once the replication status is &amp;quot;green&amp;quot;, and LOCKSS once all server states are &amp;quot;agreement&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Verified&amp;quot; exists but is never used.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Failed&amp;quot; is the default state if none is set (eg if it doesn't get to Upload Pending), but is otherwise unused.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Delete requested&amp;quot; is set when a request is deleted. Note that this replaces the previous state, so if the delete request is rejected the previous state is lost.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Deleted&amp;quot; happens when a delete request is approved. The package entry still exists, but is assumed to be gone. A package can be in this state but still exist if the delete failed.  The storage service doesn't enforce not interacting with deleted packages&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Deposit Finalized&amp;quot; is the state of a FEDORA transfer after the deposit is finalized and the transfer has been started.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: Make &amp;quot;Uploaded&amp;quot; more consistent - state is always Uploaded after the AIP has been moved to the final location, and start using &amp;quot;Verified&amp;quot; for what Arkivum &amp;amp; LOCKSS currently use &amp;quot;Uploaded&amp;quot; for.  Perhaps &amp;quot;Uploaded&amp;quot; should be renamed, since in the case of LOCKSS/Arkivum it may not have been actually uploaded yet.  This is potentially confused though, because the 'completely stored' state (Uploaded vs Verified) is different depending on the Space.&lt;br /&gt;
|} &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: Start using &amp;quot;Failed&amp;quot;. Use cases might include Arkivum status going from Green to Red, or otherwise failing a fixity check.&lt;br /&gt;
|} &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#ffeecc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;;&lt;br /&gt;
| Improvement Note: Store the package state as set or a list. This would allow a package to be Uploaded and Delete requested, instead of losing that state. We could also mark something as both Uploaded and Verified, resolving how to handle Arkivum status.  Failed could coexist with the last known good state.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== API ==&lt;br /&gt;
&lt;br /&gt;
See [[Storage Service API]]&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
The Storage service keeps a log at /var/log/archivematica/storage-service.log and errors may also be logged to the nginx and uwsgi logs as well at: /var/log/uwsgi/app/storage.log&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[Administrator manual 1.1#Storage service]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Development documentation]]&lt;/div&gt;</summary>
		<author><name>Jdunham</name></author>
	</entry>
</feed>