{ "info": { "author": "bibby", "author_email": "andrew.bibby@nantomics.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Environment :: Console", "Intended Audience :: Science/Research", "License :: OSI Approved :: MIT License", "Operating System :: POSIX :: Linux", "Programming Language :: Python :: 2.7", "Topic :: System :: Filesystems" ], "description": "radula\n======\n\nradula is a small utility to add some friendliness to\n`RadosGW `__ for our team\nworking with `Ceph `__ for S3-like storage. Little\nmore than a wrapper for\n`boto `__ radula saves us time\nand headache by using nice defaults.\n\nThe primary functions for the current version are\n\n- Inspect radosgw bucket/key ACLs\n- Spot differences between bucket and key ACLs\n- Allow or disallow user read/write to buckets and keys\n- When modifying a bucket ACL, modify the ACLs for keys as well\n- Verify uploads using checksums\n- Upload using multiple threads\n\nThe name, \"radula\", is a `cephalopod-related\nterm `__ that hit\nclose to RADOS. It's not a tongue, or really even teeth; it's more like\nif your tongue had teeth. Spooky.\n\nInstallation\n------------\n\nInstall radula from `pypi `__ using\n``pip``.\n\n::\n\n pip install radula\n\nThe ``radula`` command should be available in your ``$PATH``.\n\nTesting\n-------\n\nInstall the pip packages listed in ``testing-requirements.txt`` and run ``nosetests``.\n\n::\n\n $ pip install -U -r testing-requirements.txt\n $ nosetests --with-coverage --cover-package=radula\n\nThe effort to increase code coverage is ongoing.\n\n\n\nConfigure\n---------\n\nradula uses *boto*, so all configuration is really `boto\nconfiguration `__,\nwith some extensions to support streaming copy operations, see the Streaming Copy section below for those custom items.\nNotable changes are replacing the url to amazon aws with that of one of your gateways.\nWhere applicable, you may have to disable SSL as a default option.\n\n::\n\n # example shared /etc/boto.cfg\n [s3]\n host = radosgw1.your_company.com\n\n [Boto]\n is_secure = False\n\nTo add your personal credentials, fill in the following in ``~/.boto``:\n\n::\n\n [Credentials]\n aws_access_key_id = abcdef...\n aws_secret_access_key = 0123456...\n\n [profile other_role]\n aws_access_key_id = wxyz...\n aws_secret_access_key = 9765432...\n\nThe configuration file can be read from different paths. This is\ndetermined by the boto library, and the order of paths that are checked is:\n\n1. The path specified by the ``BOTO_CONFIG`` environment variable.\n2. The file ``~/.boto``\n3. The file ``~/.aws/credentials``\n4. The file ``/etc/boto.cfg``\n\nUsage\n-----\n\nThe command structure for radula is\n``radula [flags] command subject [target]``. The \"subject\" matter or\n\"target\" of a request could be a local resource or a remote one,\ndepending on the command being executed. These could be read as \"source\"\nand \"destination\" in some cases, but the intent is simply to flow left\nto right.\n\n::\n\n $ usage: radula [-h] [--version] [-r] [-w] [-t THREADS] [-p PROFILE]\n [-d DESTINATION] [-f] [-y] [-c CHUNK_SIZE] [-l] [-L LOG_LEVEL]\n [-v] [-n] [-z] [-e] [-A] [-i] [-k] [--no-acl]\n [{acls,get-acl,set-acl,compare-acl,sync-acl,allow,allow-user,disallow,disallow-user,mb,make-bucket,rb,remove-bucket,lb,list-buckets,put,\n up,upload,get,dl,download,mpl,mp-list,multipart-list,mpc,mp-clean,multipart-clean,rm,remove,keys,ls,list,info,size,etag,remote-md5,remote-rehash,verif\n y,sc,streaming-copy,copy,cat,url,get-url,local-md5,profiles}]\n [subject] [target] ...\n\n RadosGW client\n\n positional arguments:\n {acls,get-acl,set-acl,compare-acl,sync-acl,allow,allow-user,disallow,disallow-user,mb,make-bucket,rb,remove-bucket,lb,list-buckets,put,up,upload,\n get,dl,download,mpl,mp-list,multipart-list,mpc,mp-clean,multipart-clean,rm,remove,keys,ls,list,info,size,etag,remote-md5,remote-rehash,verify,sc,\n streaming-copy,copy,cat,url,get-url,local-md5,profiles}\n command\n subject Subject\n target Target\n remainder Additional targets for supporting commands. See README\n\n optional arguments:\n -h, --help show this help message and exit\n --version Prints version number\n -r, --read During a user grant, permission includes reads\n -w, --write During a user grant, permission includes writes\n -t THREADS, --threads THREADS\n Number of threads to use for uploads. Default=3\n -p PROFILE, --profile PROFILE\n Boto profile. Overrides AWS_PROFILE environment var\n -d DESTINATION, --destination DESTINATION\n Destination boto profile, required for streaming copy\n -f, --force Overwrite local files without confirmation\n -y, --verify Verify uploads after they complete. Uses --threads.\n When passed a destination profile, download and hash\n keys on both ends\n -c CHUNK_SIZE, --chunk CHUNK_SIZE\n multipart upload chunk size in bytes.\n -l, --long-keys prepends bucketname to key results.\n -L LOG_LEVEL, --log-level LOG_LEVEL\n Log level, [DEBUG, 10, INFO, 20, etc]\n -v, --verbose Verbose. Equiv to -L DEBUG\n -n, --dry-run Print would-be deletions without deleting\n -z, --resume Resume uploads if needed.\n -e, --encrypt Store content encrypted at rest\n -A, --all-buckets act upon all buckets (info only)\n -i, --ignore-existing\n Calmly skip existing files; an opposite -f (otherwise\n errors)\n -k, --preserve-key When downloading, preserve paths in keys\n --no-acl When uploading, do not sync key ACL with the bucket\n ACL. Normally would.\n\n\n\nExamples\n--------\n\nThis is a quick walkthrough of the features so far. In these scenarios,\nwe acting as the user ``bibby``, who owns the rados bucket ``mybucket``.\nIn some of the examples, we'll be manipulating the access to this bucket\nfor a second user called ``fred``.\n\nContained in the bucket are two regular files: ``hello`` and ``world``.\n\nList available profiles\n~~~~~~~~~~~~~~~~~~~~~~~\n\nSee `Boto docs `__ for working with profiles.\n\n::\n\n [bibby@machine ~]$ radula profiles\n here\n there\n * DEFAULT\n\n\nDisplaying bucket ACL\n~~~~~~~~~~~~~~~~~~~~~\n\n::\n\n [bibby@machine ~]$ radula get-acl mybucket\n ACL for bucket: mybucket\n [CanonicalUser:OWNER] Andrew Bibby = FULL_CONTROL\n\nThe command ``get-acl`` prints the acl. radula assumed that the term\n``mybucket`` was a bucket, being that it was a lone term.\n\nDisplaying key ACL\n~~~~~~~~~~~~~~~~~~\n\n::\n\n [bibby@machine ~]$ radula get-acl mybucket/hello\n ACL for key: mybucket/hello\n [CanonicalUser:OWNER] Andrew Bibby = FULL_CONTROL\n\nBecause the term contained a slash, the subject is correctly identified\nas ``hello`` within the bucket ``mybucket``.\n\nComparing ACLs - Keys in bucket\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n::\n\n [bibby@machine ~]$ radula compare-acl mybucket\n Bucket ACL for: mybucket\n [CanonicalUser:OWNER] Andrew Bibby = FULL_CONTROL\n ---------\n\n Keys with identical ACL: 2\n Keys with different ACL: 0\n\nThe ``compare-acl`` command on a bucket will report of the *sameness* of\nACLs across the keys as compared to the bucket. We'll see this again\nlater in another example.\n\nThis *can* be run against one key, limiting the compared objects to the\none key against its bucket\n\n::\n\n [bibby@machine ~]$ radula check-acl mybucket/hello\n Bucket ACL for: mybucket\n [CanonicalUser:OWNER] Andrew Bibby = FULL_CONTROL\n ---------\n\n Keys with identical ACL: 1\n Keys with different ACL: 0\n\nSet a canned ACL\n~~~~~~~~~~~~~~~~\n\nCan set the ACL of a bucket or key to one of the four AWS \"canned\"\npolicies using ``set-acl``. In this scenario, the *subject* can be a\nbucket or a key, with the *target* being a canned policy name.\n\n::\n\n [bibby@machine ~]$ radula set-acl mybucket/hello public-read\n << prints the output of get-acl after completing the operation\n\nChanging the ACL on a bucket **will** will be applied to the keys as\nwell, potentially overwriting any custom access given to keys. Run\n``compare-acl`` before setting the bucket ACL to discover any special\ndifferences, as they may need to be recreated after the ``set-acl``\noperation completes.\n\nSync ACLs\n~~~~~~~~~\n\nShould a difference of ACL had appeared, we could forcefully replace all\nkey ACLs with the bucket's ACL using ``sync-acl``.\n\n::\n\n [bibby@machine ~]$ radula sync-acl mybucket\n Bucket ACL for: mybucket\n [CanonicalUser:OWNER] Andrew Bibby = FULL_CONTROL\n ---------\n\n Setting bucket's ACL on hello\n Setting bucket's ACL on world\n\nThis is a ``PUT`` command, so it doesn't bother to look at the current\nACL for the keys; it just puts a copy of the bucket's own ACL.\n\n``sync-acl`` can be done on a single key as well.\n\n::\n\n [bibby@machine ~]$ radula sync-acl mybucket/world\n Setting bucket's ACL on world\n\nGranting access to a key\n~~~~~~~~~~~~~~~~~~~~~~~~\n\nTo grant access to another user, we'll make use of some new flags.\n``-r`` and/or ``-w`` to indicate read and write. A grant may have one or\nboth of ``rw``. If both are absent, ``read`` is assumed. Permissions are\nseparate, so it is possible to have a *write-only* grant.\n\nFor permission grants the *subject* is the **user** (as far as the usage\nformat in the help text goes), and the *target* is the **key or\nbucket**.\n\n::\n\n [bibby@machine ~]$ radula allow fred mybucket/hello\n granting READ to fred on key hello\n\nMultiple grants to the same user for the same permission are possible in\nrados and on s3, but radula will guard against that and ignore the\nduplicate entry. Here, we'll add \"read-write\":\n\n::\n\n [bibby@machine ~]$ radula -wr allow fred mybucket/hello\n User fred already has READ for key hello, skipping\n granting WRITE to fred on key hello\n\nGranting access to a bucket\n~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n| Granting access to a bucket works the same way.\n| When a bucket ACL is modified, **so are all of its keys**. That action is really the whole purpose behind radula.\n\n::\n\n [bibby@machine ~]$ radula -wr allow fred mybucket\n granting READ to fred on bucket mybucket\n granting WRITE to fred on bucket mybucket\n User fred already has READ for key , skipping\n User fred already has WRITE for key , skipping\n granting READ to fred on key \n granting WRITE to fred on key \n\nWith both ``allow`` and ``disallow``, if an ACL difference exists\nbetween the bucket and a key, that difference may still exist after the\nmodification. With these commands, we aren't **syncing** a modified\nbucket ACL down to the keys; we're applying the same singular change to\neach target individually.\n\nDisallow (buckets and keys)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nRemoving permissions works similarly to granting access, but with some\ndifferences. One assumption is about the omission of the read-write\nflags; If neither are present, both permissions are removed.\n\n+---------+---------+----------+\n| start | flags | result |\n+=========+=========+==========+\n| RW | -r | W |\n+---------+---------+----------+\n| RW | -w | R |\n+---------+---------+----------+\n| RW | -rw | - |\n+---------+---------+----------+\n| RW | - | - |\n+---------+---------+----------+\n\nACLs for the keys are modified first. The user's access cannot be taken\naway from the bucket if it still exists for one of its keys, so the\nchanges take place from bottom up.\n\nCreating an difference and syncing down\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nStarting with a blank slate:\n\n::\n\n [bibby@machine ~]$ radula -wr disallow fred mybucket\n No change for \n No change for \n No change for mybucket\n\nGive ``fred`` read on the bucket\n\n::\n\n [bibby@machine ~]$ radula -r allow fred mybucket\n granting READ to fred on bucket mybucket\n granting READ to fred on key \n granting READ to fred on key \n\nGive ``fred`` write on one key\n\n::\n\n [bibby@machine ~]$ radula -w allow fred mybucket/world\n granting WRITE to fred on key world\n\nConfirm the difference..\n\n::\n\n [bibby@machine ~]$ radula compare-acl mybucket\n Bucket ACL for: mybucket\n [CanonicalUser:OWNER] Andrew Bibby = FULL_CONTROL\n [CanonicalUser] Fred Fredricks = READ\n ---------\n\n Difference in world:\n [CanonicalUser:OWNER] Andrew Bibby = FULL_CONTROL\n [CanonicalUser] Fred Fredricks = READ\n [CanonicalUser] Fred Fredricks = WRITE\n\n Keys with identical ACL: 1\n Keys with different ACL: 1\n\nPlow the keys with the bucket's settings.\n\n::\n\n [bibby@machine ~]$ radula sync-acl mybucket\n Bucket ACL for: mybucket\n [CanonicalUser:OWNER] Andrew Bibby = FULL_CONTROL\n [CanonicalUser] Fred Fredricks = READ\n ---------\n\n Setting bucket's ACL on hello\n Setting bucket's ACL on world\n\n [bibby@machine ~]$ radula check-acl mybucket\n Bucket ACL for: mybucket\n [CanonicalUser:OWNER] Andrew Bibby = FULL_CONTROL\n [CanonicalUser] Fred Fredricks = READ\n ---------\n\n Keys with identical ACL: 2\n Keys with different ACL: 0\n\nUpload and Download\n-------------------\n\nThese functions are similar for moving files in and out of the radosgw.\nIts intention is not to replace better tools like ``s3cmd``, but rather\nto cover some very common use cases so that the installation and\nconfiguration of additional libraries *might* not be needed.\n\nput, up, upload\n~~~~~~~~~~~~~~~\n\nThe commands ``put``, ``up``, and ``upload`` are equivalent. For these\nexamples, I've chosen to use ``up``.\n\nThe syntax is ``radula up {source} {target}``, where *source* is a local\nfile or a glob. The *target* is a in radosgw path, and its behavior\ndepends on the singularity or plurality of the source given.\n\nIf the target path ends with a slash (``/``), then the key is presumed\nto be the basename of the object appended at that path. *See table\nbelow.*\n\nIf multiple source files are given, the key will always assume it is\npart of a path, making an ending slash wholly optional.\n\nWhen using globs, it's important to know that the argument must be\nquoted to avoid shell expansion. For example to upload all files\nstarting with the letter ``a`` from ``path``, the command would be\n\n::\n\n radula up 'path/a*' bucket/path\n\n+--------------+-----------------+-----------------------------------------+\n| source | target | result |\n+==============+=================+=========================================+\n| /some/file | bucket | bucket/file |\n+--------------+-----------------+-----------------------------------------+\n| /some/file | bucket/file | bucket/file |\n+--------------+-----------------+-----------------------------------------+\n| /some/file | bucket/named | bucket/named |\n+--------------+-----------------+-----------------------------------------+\n| /some/file | bucket/named/ | bucket/named/file |\n+--------------+-----------------+-----------------------------------------+\n| /some/f\\* | bucket/named | bucket/named/file, bucket/named/file2 |\n+--------------+-----------------+-----------------------------------------+\n| /some/f\\* | bucket/named/ | bucket/named/file, bucket/named/file2 |\n+--------------+-----------------+-----------------------------------------+\n\nFor faster multipart uploads, the default number of threads used is\n``3``, but this can be set during upload using the ``-t`` option.\n\n::\n\n # upload a large file using 16 threads\n radula -t 16 up large_file bucket\n\nUpload verification via checksum can be enabled by adding the ``-y``,\n``--verify`` flag.\n\nAs of ``radula v0.6.6``, uploads to a remote key that already exists\nwill abort if `-f, --force` is not also given. The reason is to guard\nagainst accidentally loss of data in ceph.\n\nShould portions of a multipart upload fail, there is a chance that it\ncan be resumed. A reattempt at upload should abort citing the presence\nof a lingering multipart upload in progress. The `multipart-list` command\nshould confirm as much. Adding the ``-z,--resume`` flag to the original\nupload command will inspect the uploaded parts and upload those that are absent\nor differ in checksum. The resume will be slower for each part, as the local\nparts are hashed and compared to the uploaded parts. Adding a verification step\nwith ``-y,--verify`` is recommended.\n\n::\n\n # an upload resumation with verification\n radula -t 16 -zy up large_file bucket\n\n\nget, dl, download\n~~~~~~~~~~~~~~~~~\n\nThe commands ``get``, ``dl``, and ``downlaod`` are equivalent. For these\nexamples, I've chosen to use ``dl``.\n\nThe the syntax is ``radula dl {source} [{target}]``. The *target* is\noptional, and will default to the basename of the remote file to be\nstored in the current working directory.\n\nUnlike ``up``, the download commands do not support globs.\n\n+--------------------+--------------+----------------+\n| source | target | result |\n+====================+==============+================+\n| bucket/path/file | | ./file |\n+--------------------+--------------+----------------+\n| bucket/path/file | some\\_file | ./some\\_file |\n+--------------------+--------------+----------------+\n| bucket/path/file | dir | dir/file |\n+--------------------+--------------+----------------+\n| bucket/path/file | dir/named | dir/named |\n+--------------------+--------------+----------------+\n\nNo attempt is made to create local paths that do not exist prior to\ndownload; in the table above ``dir`` is an existing directory.\n\nIf a file with the target name already exists, ``radula`` will ask if\nyou wish to overwrite it unless the ``-f, --force`` flag is enabled.\n\nAs of ``radula v0.6.6``, downloads are multi-threaded using 10 processes by default,\nwhich can be controlled with the ``-t, --threads`` flag.\nThis is known to have issues writing to glusterfs, so `-t 1` is recommended in that instance.\n\nIn ``radula v0.7.1``, default threads was reduced to 3.\n\nAs of ``radula v0.7.9``, uploads may include the ``-e,--encrypt`` flag to instruct Rados to store the data encrypted at rest, using its own internal mechanisms. When encrypted data is copied to another cluster, the remote copy should take on this setting without explicitly being told to.\n\nrecursive upload/download\n~~~~~~~~~~~~~~~~~\n\nYou can upload entire directories with its structure intact. Assume there is a directory such as this:\n\n::\n\n $ tree projroot/\n projroot/\n \u251c\u2500\u2500 subdir_a\n \u2502\u00a0\u00a0 \u251c\u2500\u2500 ef90d4f2\n \u2502\u00a0\u00a0 \u2514\u2500\u2500 efd7f715\n \u2514\u2500\u2500 subdir_b\n \u251c\u2500\u2500 10eaf5f0\n \u251c\u2500\u2500 80920f14\n \u251c\u2500\u2500 a6fcadbf\n \u251c\u2500\u2500 a8dd1085\n \u2514\u2500\u2500 third_dir\n \u251c\u2500\u2500 980a978f\n \u2514\u2500\u2500 e50f86fe\n\nUploading `projroot` will copy the directory structure at the location specified. *Beware: full paths (``/home/user/..``) given as sources will upload to keys using that full path.\n\n::\n\n $ radula up projroot bucket/projects\n \n $ radula -p abibby keys abibby/projects/\\*\n projects/projroot/subdir_a/ef90d4f2\n projects/projroot/subdir_a/efd7f715\n projects/projroot/subdir_b/10eaf5f0\n projects/projroot/subdir_b/80920f14\n projects/projroot/subdir_b/a6fcadbf\n projects/projroot/subdir_b/a8dd1085\n projects/projroot/subdir_b/third_dir/980a978f\n projects/projroot/subdir_b/third_dir/e50f86fe\n\n\nBecause keys are inherently flat on s3, to download recursively you'll need a combination of a glob pattern and the ``--preserve-key`` flag.\n\n::\n\n $ radula --preserve-key dl bucket/projects/projroot/\n\n\nThe entire key is used to create the local structure, so in this case, the ``projects`` dir will be recreated if it had gone missing.\n\n\ncat\n~~~\n\nAn alternative to `download` is `cat`, which prints the contents of a remote subject\nto `stdout`.\n\n::\n\n $ echo \"Hello there you\" > hello\n $ radula up hello mybucket/hello\n INFO:radula:Finished uploading 16.00 B in 0.08s (188.82 Bps)\n $ radula cat mybucket/hello\n Hello there you\n\nIn radula 0.7+, `cat` accept the `-c`,`--chunk-size` parameter to print part of the remote file.\nUnique to this command is that the chunk param can be a range of integers or humanized units.\nIf humanized units (ie, `2kb`) are used, they'll be converted into integer to conform with the\n[HTTP Range header spec](https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35).\n\nWhen using a range query, the end of the range may be omitted to include everything from\nthe starting position to the end of the file.\n\nOmitting the first argument is not supported. Starting a range with zero (`0-n`) *does work*, but it is recommended to simply provide `n` by itself, because the **range in inclusive**. The range `0-100` would\noutput 101 bytes, while input `100` returns 100.\n\nA `ValueError` will be raised if end of the range is before the starting position.\n\n::\n\n # first two bytes\n $ radula -c 2 cat mybucket/hello\n he\n\n # 2 bytes in until the end\n $ radula -c '2-' cat mybucket/hello\n llo\n\n # first byte to second byte (inclusive)\n $ radula -c '1-2' cat mybucket/hello\n el\n\nverify uploads\n~~~~~~~~~~~~~~\n\nChecksums can be obtained using ``local-md5`` and ``remote-md5``, and\neasily compared with ``verify``.\n\nThe ``local-md5`` command expects one local file argument, and will\ngenerate the same hash that is expected to be found on the remote.\nMultipart upload size matters, so the output hash may differ if uploaded\nby another mechanism.\n\nThe ``remote-md5`` command expects one remote file uri, ie\n*mybucket/path/myfile*. It will return the ``etag`` attribute associated\nwith the key, which will typically be a file md5 or conglomeration of\nmultipart upload hashs with a number tacked at the end.\n\nCalling ``verify [local_file] [remote_file]`` simply runs the operations\nmentioned above and tests their outputs for likeness.\n\nTo view raw metadata about a remote target, use ``info [remote_file]``.\nThe output will contain the etag and other data in JSON format.\nFor quick access to size and hash data, commands ``etag`` and ``size``\nare available to provide this data from the larger ``info`` set.\n\nsigned urls\n~~~~~~~~~~~\n\nSigned URLs can permit the download of private objects for a limited time. The command ``get-url`` (alias ```url``)\ncan generate these for one or more objects. The first argument is the remote path, which may use globs, and the optional\nsecond argument is an integer representing the minutes until the URL expires. Omitting the second argument will produce\na URL that expires in one day.\n\n::\n\n # one file with default expire\n [bibby@machine ~]$ radula get-url bibby/foo\n https://s3-host/bibby/foo?Signature={signature}&Expires={expire}&AWSAccessKeyId={access_key}\n\n # many files with 15 min custom expire\n [bibby@machine ~]$ radula get-url bibby/foo* 15\n https://s3-host/bibby/foo?Signature={signature}&Expires={expire}&AWSAccessKeyId={access_key}\n https://s3-host/bibby/foo_2?Signature={signature}&Expires={expire}&AWSAccessKeyId={access_key}\n\n\ndeletion\n~~~~~~~~\n\nRemote objects can be deleted using the commands `rm` or `remove`. While the majority of `radula` commands follow the position pattern of `subject, target`, the deletion command operates exclusively on remote objects. Therefore, it is one of the few that accept an arbitrary number of arguments. Globs are supported **if** they are quoted so as not to expand in the shell.\n\nUse the `-n`,`--dry-run` flag to preview deletions without making any changes.\n\n::\n\n [bibby@machine ~]$ radula --dry-run rm mybucket/x\n DRY-RUN: rm mybucket/x\n\n [bibby@machine ~]$ radula rm mybucket/x 'mybucket/y*'\n x\n y1\n y2\n\n\nCleaning up messes\n------------------\n\nIf multipart uploads go awry, they can leave behind some unfinished\nartifacts in the form of orphaned upload parts. ``radula`` can now list\nthese can clean up.\n\nThe commands ``multipart-list``, ``mp-list``, and ``mpl`` are\nequivalent. For these examples, I've chosen to use ``mp-list``.\n\nListing can be done by bucket or for a key:\n\n::\n\n # list multipart uploads for a bucket\n $ radula mp-list mybucket\n bibby ones.img 2~Q8r-pWTmMTbx_rhHa8-u3I3m-vjCF5F Andrew Bibby 2015-09-23T19:39:14.000Z\n bibby zeros.img 2~MvM7KTr2sMcS_SfVzWO7T0chzJRUqvm Andrew Bibby 2015-09-23T19:35:44.000Z\n\n # list multipart uploads for a key\n $ radula mp-list mybucket/zeros.img\n bibby zeros.img 2~MvM7KTr2sMcS_SfVzWO7T0chzJRUqvm Andrew Bibby 2015-09-23T19:35:44.000Z\n\nCleaning up a failed multi-part upload is as easy using a *clean*\ncommand in place of *list*.\n\nThe commands ``multipart-clean``, ``mp-clean``, and ``mpc`` are\nequivalent. For these examples, I've chosen to use ``mp-clean``.\n\n::\n\n # clean multipart uploads for a key\n $ radula mp-clean mybucket/zeros.img\n INFO:root:Canceling zeros.img 2~MvM7KTr2sMcS_SfVzWO7T0chzJRUqvm\n True\n\n # clean multipart uploads for a bucket\n $ radula mp-list mybucket\n INFO:root:Canceling ones.img 2~Q8r-pWTmMTbx_rhHa8-u3I3m-vjCF5F\n True\n\nStreaming Copy\n--------------\n\nSince radula 0.5.0, users are able to copy between different ceph\ninstallations, or different buckets within the same installation,\nwithout copying to the local disk. To facilitate this in the friendliest\npossible manner, we've extended the ``boto`` configuration slightly to\nbe able to specify a separate s3 host for a particular profile.\n\nThe ``profile`` sections of ``~/.boto`` or ``/etc/boto.cfg`` can now\naccept the following items that are not supported by regular boto:\n\n- host (string)\n- port (int)\n- is\\_secure (bool)\n\nAn example extended profile\n\n::\n\n [profile second_ceph]\n aws_access_key_id = wxyz...\n aws_secret_access_key = 9765432...\n host = second.ceph.of.mine\n port = 8184\n\nThe commans ``streaming-copy`` and ``sc`` are equivalent. For these\nexample, I've chosen to use ``sc``.\n\nWhen copying, the ``-p`` flag will apply the aws\\_profile for the\n*source*/subject. Omitting this flag will use the default boto\ncredentials for the source.\n\nThe ``-d`` flag will specify the profile used for the\n*destination*/target to receive the files. Naming ``-d Default`` will\nuse the default boto credentials for the destination.\n\nCopy a file from first-ceph to second-ceph\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n``radula -d second sc mybucket/file other_bucket/file``\n\nThe above command used the default boto profile to send ``file`` from\n``mybucket`` located on the default ceph to the ceph defined in the\nprofile named ``second``.\n\nCopy a file from second-ceph to first-ceph\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n``radula -p second -d Default sc other_bucket/file mybucket/file``\n\nThis is the inverse of the previous example. Using the ``second``\nprofile as the source/subject (as specified by ``-p second``), we're\ntransfering a file to ``mybucket/file`` located on the default s3 using\nthe default profile (as specified by ``-d Default``).\n\nCopy profile to profile\n~~~~~~~~~~~~~~~~~~~~~~~\n\nAvoiding the use of default profiles all together, you can copy using\nboth ``-p`` and ``-d`` flags.\n\n``radula -p here -d there sc here/stuff there/stuff``\n\n\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/bibby/radula", "keywords": "ceph radosgw s3", "license": "", "maintainer": "", "maintainer_email": "", "name": "radula", "package_url": "https://pypi.org/project/radula/", "platform": "", "project_url": "https://pypi.org/project/radula/", "project_urls": { "Homepage": "https://github.com/bibby/radula" }, "release_url": "https://pypi.org/project/radula/0.8.7/", "requires_dist": [ "boto", "filechunkio" ], "requires_python": "", "summary": "RadosGW client for Ceph S3 storage", "version": "0.8.7" }, "last_serial": 5105396, "releases": { "0.4.0": [ { "comment_text": "", "digests": { "md5": "964860fcf8d2056a6cb7d7f6ae287eff", "sha256": "f1efec18665fafa68a3d320cdbbd81b88ec04a4db3959be4586bd64841788008" }, "downloads": -1, "filename": "radula-0.4.0-py2-none-any.whl", "has_sig": false, "md5_digest": "964860fcf8d2056a6cb7d7f6ae287eff", "packagetype": "bdist_wheel", "python_version": "2.7", "requires_python": null, "size": 10117, "upload_time": "2015-09-08T23:41:14", "url": "https://files.pythonhosted.org/packages/17/df/bf8d32a5f5b5c0ee8772dfafeee7f82bf8ab55f9a1d58c154fc19286464e/radula-0.4.0-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "79bd1e211d065217e122cdabc0660473", "sha256": "e139f05a4df2aabbc42462ad52538428005cf97adc1e7400e1df88a0b07f5b19" }, "downloads": -1, "filename": "radula-0.4.0.tar.gz", "has_sig": false, "md5_digest": "79bd1e211d065217e122cdabc0660473", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22840, "upload_time": "2015-09-08T23:41:08", "url": "https://files.pythonhosted.org/packages/b5/ad/d95a8c0f0354c53292826c656ee5691a7252c2266ba0c702b15f643d5838/radula-0.4.0.tar.gz" } ], "0.4.1": [ { "comment_text": "", "digests": { "md5": "5a0e3e79c6cbdbc92b056741512843ec", "sha256": "1c59843f3483674f6e1febc57ccf5589025179b598973098f6cc9bfe2f95ef51" }, "downloads": -1, "filename": "radula-0.4.1-py2-none-any.whl", "has_sig": false, "md5_digest": "5a0e3e79c6cbdbc92b056741512843ec", "packagetype": "bdist_wheel", "python_version": "2.7", "requires_python": null, "size": 10227, "upload_time": "2015-09-18T15:26:50", "url": "https://files.pythonhosted.org/packages/8e/b9/e4dd7c7251c0c08a44004aca6c67bc8757a1ab72b958fee333ba19dbf17d/radula-0.4.1-py2-none-any.whl" } ], "0.4.2": [ { "comment_text": "", "digests": { "md5": "4a290653032575fac8b1167eabd83305", "sha256": "036acdb0c1526e8723c670740060688819ab62e1bb4c42bd694838e9c85712f1" }, "downloads": -1, "filename": "radula-0.4.2-py2-none-any.whl", "has_sig": false, "md5_digest": "4a290653032575fac8b1167eabd83305", "packagetype": "bdist_wheel", "python_version": "2.7", "requires_python": null, "size": 11622, "upload_time": "2015-09-23T20:24:31", "url": "https://files.pythonhosted.org/packages/3a/03/df19b67c88c62b9e85dad6c1e74556968b6e5b52c70dfb5a9497a9947a54/radula-0.4.2-py2-none-any.whl" } ], "0.4.4": [ { "comment_text": "", "digests": { "md5": "ad2b7eecc8ae3765024dc31b3ea5b211", "sha256": "2b0d0cb07b950934eec8e841e1f5af508351579e2490c7244c3ae26b52b62ba8" }, "downloads": -1, "filename": "radula-0.4.4-py2-none-any.whl", "has_sig": false, "md5_digest": "ad2b7eecc8ae3765024dc31b3ea5b211", "packagetype": "bdist_wheel", "python_version": "2.7", "requires_python": null, "size": 11887, "upload_time": "2015-10-02T15:52:24", "url": "https://files.pythonhosted.org/packages/be/b4/a16757a6f5cfc74daf742fbbc7e1577910ddf891144de627963086f34b8d/radula-0.4.4-py2-none-any.whl" } ], "0.5.1": [ { "comment_text": "", "digests": { "md5": "eb3edfa04eea731f62288d679fee5293", "sha256": "6c5e8c9c127eb0be4cd019a6c1e44d6aa194c11c9b9f8102501eb28618493ff9" }, "downloads": -1, "filename": "radula-0.5.1-py2-none-any.whl", "has_sig": false, "md5_digest": "eb3edfa04eea731f62288d679fee5293", "packagetype": "bdist_wheel", "python_version": "2.7", "requires_python": null, "size": 26034, "upload_time": "2015-11-02T21:37:47", "url": "https://files.pythonhosted.org/packages/44/c1/b646fac2b3fa46e0a3158b62cc9be1bbbb7b72caf94190712926325407c4/radula-0.5.1-py2-none-any.whl" } ], "0.6.3": [ { "comment_text": "", "digests": { "md5": "3f986b7fd043101a6949fed74479b3e5", "sha256": "d58ab79ee8ff2408ac345e5ea3db87741031e769eac8fb3e3ed2a3975014e9a4" }, "downloads": -1, "filename": "radula-0.6.3-py2-none-any.whl", "has_sig": false, "md5_digest": "3f986b7fd043101a6949fed74479b3e5", "packagetype": "bdist_wheel", "python_version": "2.7", "requires_python": null, "size": 31174, "upload_time": "2016-03-02T17:43:16", "url": "https://files.pythonhosted.org/packages/93/29/74f72d43883debb133559062bab1300a274c8a050d1d2d5369207c15e19b/radula-0.6.3-py2-none-any.whl" } ], "0.6.4": [ { "comment_text": "", "digests": { "md5": "faa16bda071c5d8c5b1741198f86c185", "sha256": "31e30ef859f988d8686465af5d061f71dabf1f3dfd4b7328017b9afc65887bda" }, "downloads": -1, "filename": "radula-0.6.4-py2-none-any.whl", "has_sig": false, "md5_digest": "faa16bda071c5d8c5b1741198f86c185", "packagetype": "bdist_wheel", "python_version": "2.7", "requires_python": null, "size": 31274, "upload_time": "2016-03-24T15:01:38", "url": "https://files.pythonhosted.org/packages/19/df/020345d808889a4bdd461b864dd7f841a2035b516d510fd02bc264e56872/radula-0.6.4-py2-none-any.whl" } ], "0.6.5": [ { "comment_text": "", "digests": { "md5": "4be73b25eb2c8073a5c277c7ec24ccd0", "sha256": "ad166928db9bc2a217e6c6dc66f06f7c9af84438b15d260964d43deb616e195c" }, "downloads": -1, "filename": "radula-0.6.5-py2-none-any.whl", "has_sig": false, "md5_digest": "4be73b25eb2c8073a5c277c7ec24ccd0", "packagetype": "bdist_wheel", "python_version": "2.7", "requires_python": null, "size": 31541, "upload_time": "2016-03-28T22:30:08", "url": "https://files.pythonhosted.org/packages/fc/de/59589e175916d4917dd33ac7a9252014e7ba9cc99aa1165e3c154afa5f74/radula-0.6.5-py2-none-any.whl" } ], "0.6.6": [ { "comment_text": "", "digests": { "md5": "1020cef81958c52a7f13298e0ac1c841", "sha256": "de013a4d916d7713a8f931bcfc7ce9a78c0c710f32ce23abbc147fd070e8198c" }, "downloads": -1, "filename": "radula-0.6.6-py2-none-any.whl", "has_sig": false, "md5_digest": "1020cef81958c52a7f13298e0ac1c841", "packagetype": "bdist_wheel", "python_version": "2.7", "requires_python": null, "size": 34307, "upload_time": "2016-04-12T21:50:23", "url": "https://files.pythonhosted.org/packages/cb/e1/602d6c51a1c6adbb5395c16bd083dc6f8b8c3737fb17fb41f9bd07f2ac2e/radula-0.6.6-py2-none-any.whl" } ], "0.6.7": [ { "comment_text": "", "digests": { "md5": "6a7c94038e6169481d4faed094c88ba3", "sha256": "db067a7c447a9bc8e932b9eaef12efa5e837c14a31c21f70e95ab1f98ac90820" }, "downloads": -1, "filename": "radula-0.6.7-py2-none-any.whl", "has_sig": false, "md5_digest": "6a7c94038e6169481d4faed094c88ba3", "packagetype": "bdist_wheel", "python_version": "2.7", "requires_python": null, "size": 34242, "upload_time": "2016-04-13T15:25:44", "url": "https://files.pythonhosted.org/packages/e0/e0/a33e09dfd5af892046c2094ce68f044292936d7bfdd396ab324656e2de05/radula-0.6.7-py2-none-any.whl" } ], "0.7.0": [ { "comment_text": "", "digests": { "md5": "8c553807ccfdde6d4261a1b918465377", "sha256": "6c57080599db664768ae34fbeef3e1b03ddd08922f44d80c57c4c2cc3cb8203f" }, "downloads": -1, "filename": "radula-0.7.0-py2-none-any.whl", "has_sig": false, "md5_digest": "8c553807ccfdde6d4261a1b918465377", "packagetype": "bdist_wheel", "python_version": "2.7", "requires_python": null, "size": 36642, "upload_time": "2016-05-25T18:03:10", "url": "https://files.pythonhosted.org/packages/0e/18/90a1ec1b2b4c0c06beedaf35d535865fdbff5010e12cade130e13ba844ce/radula-0.7.0-py2-none-any.whl" } ], "0.7.11": [ { "comment_text": "", "digests": { "md5": "fd2509131a8fd81d85cb0549f07707ab", "sha256": "a9c4aeb5e57e92c8ffc6ff372c8de0180309d35b8987db566366c7403c2d35a7" }, "downloads": -1, "filename": "radula-0.7.11-py2-none-any.whl", "has_sig": false, "md5_digest": "fd2509131a8fd81d85cb0549f07707ab", "packagetype": "bdist_wheel", "python_version": "2.7", "requires_python": null, "size": 39738, "upload_time": "2016-12-27T20:02:28", "url": "https://files.pythonhosted.org/packages/8d/e0/2b42de913f9249eaf210fad8994fa88286cd14f4c3caf10f7ea8c481956a/radula-0.7.11-py2-none-any.whl" } ], "0.7.12": [ { "comment_text": "", "digests": { "md5": "cb3e51155b2f589aa8cfae55444a9b62", "sha256": "66658389ef7ffdd762dde50c0e9032732eb61c82918453aa4e6d28ae6d14178f" }, "downloads": -1, "filename": "radula-0.7.12-py2-none-any.whl", "has_sig": false, "md5_digest": "cb3e51155b2f589aa8cfae55444a9b62", "packagetype": "bdist_wheel", "python_version": "2.7", "requires_python": null, "size": 40267, "upload_time": "2017-03-02T16:44:14", "url": "https://files.pythonhosted.org/packages/55/2b/7315480af043f357e2deefb711c40697fa5c60fc483ba448eb8717528916/radula-0.7.12-py2-none-any.whl" } ], "0.7.13": [ { "comment_text": "", "digests": { "md5": "dd5ceb2be564e3292ad8d0e122d9356b", "sha256": "0ad58016aa7f85328068cae89efd444a80e51d2cb97287902094751851e99a41" }, "downloads": -1, "filename": "radula-0.7.13-py2-none-any.whl", "has_sig": false, "md5_digest": "dd5ceb2be564e3292ad8d0e122d9356b", "packagetype": "bdist_wheel", "python_version": "2.7", "requires_python": null, "size": 40690, "upload_time": "2017-03-27T20:50:18", "url": "https://files.pythonhosted.org/packages/c9/8a/046d11e198cefd068161e3df43350b12b6000f0da8b56db090a1eccc3429/radula-0.7.13-py2-none-any.whl" } ], "0.7.5": [ { "comment_text": "", "digests": { "md5": "7303dd278bf493344497de232892f3f6", "sha256": "0106415e00152e4e7d20038b02feb9b7485542b922f1bd710dc83b25d5f50555" }, "downloads": -1, "filename": "radula-0.7.5-py2-none-any.whl", "has_sig": false, "md5_digest": "7303dd278bf493344497de232892f3f6", "packagetype": "bdist_wheel", "python_version": "2.7", "requires_python": null, "size": 38317, "upload_time": "2016-07-07T22:50:36", "url": "https://files.pythonhosted.org/packages/08/52/629d9d5b6691dc6b8f38256a208e912788b701926efdf0195f2ec5996b0a/radula-0.7.5-py2-none-any.whl" } ], "0.8.0": [ { "comment_text": "", "digests": { "md5": "7a49b00bab9e99090f22bf0b71be401d", "sha256": "65550b14fcafd8e244d29e510755bf26cc4377f41b58fa6df1100f37b7a5e590" }, "downloads": -1, "filename": "radula-0.8.0-py2-none-any.whl", "has_sig": false, "md5_digest": "7a49b00bab9e99090f22bf0b71be401d", "packagetype": "bdist_wheel", "python_version": "2.7", "requires_python": null, "size": 41443, "upload_time": "2017-05-15T17:19:57", "url": "https://files.pythonhosted.org/packages/e1/10/0b1020a2bf180365ec169aaa5e28ea0ba467f198f3d961524960f580e637/radula-0.8.0-py2-none-any.whl" } ], "0.8.1": [ { "comment_text": "", "digests": { "md5": "a0448918e22b9effee1ea5c98c62cb77", "sha256": "476b03c44905979037ea7f4e262d1d30c090cb1bcd9a0800fd9350f49b2a0820" }, "downloads": -1, "filename": "radula-0.8.1-py2-none-any.whl", "has_sig": false, "md5_digest": "a0448918e22b9effee1ea5c98c62cb77", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 44180, "upload_time": "2017-11-21T15:30:12", "url": "https://files.pythonhosted.org/packages/64/96/1ac50b25ecb90cbf5a0bff69191644162533fff7bdab3a703553d394f978/radula-0.8.1-py2-none-any.whl" } ], "0.8.5": [ { "comment_text": "", "digests": { "md5": "94094caa5abe0b91970934942a594398", "sha256": "3b9a126ff69934a2d91d1afcfd172641b6c05e38f1944726d2b73bb4160b8276" }, "downloads": -1, "filename": "radula-0.8.5-py2-none-any.whl", "has_sig": false, "md5_digest": "94094caa5abe0b91970934942a594398", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 44537, "upload_time": "2018-08-28T15:23:26", "url": "https://files.pythonhosted.org/packages/28/7a/f0c5a8c3fdea7d0222c9689e8bbf6f3e06d954312b7f97d903369d1ca386/radula-0.8.5-py2-none-any.whl" } ], "0.8.7": [ { "comment_text": "", "digests": { "md5": "458f4942880ae00ff50ee9e9b999708b", "sha256": "6754c271436cf98905ca216753d6ab775c5d107c803686ce8617e3a30d3b277f" }, "downloads": -1, "filename": "radula-0.8.7-py2-none-any.whl", "has_sig": false, "md5_digest": "458f4942880ae00ff50ee9e9b999708b", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 35806, "upload_time": "2019-04-05T19:58:03", "url": "https://files.pythonhosted.org/packages/32/76/e3831bd9a9d0868487ee54818e26b04faa8d1618f2e7cc9a6e4562c3a963/radula-0.8.7-py2-none-any.whl" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "458f4942880ae00ff50ee9e9b999708b", "sha256": "6754c271436cf98905ca216753d6ab775c5d107c803686ce8617e3a30d3b277f" }, "downloads": -1, "filename": "radula-0.8.7-py2-none-any.whl", "has_sig": false, "md5_digest": "458f4942880ae00ff50ee9e9b999708b", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 35806, "upload_time": "2019-04-05T19:58:03", "url": "https://files.pythonhosted.org/packages/32/76/e3831bd9a9d0868487ee54818e26b04faa8d1618f2e7cc9a6e4562c3a963/radula-0.8.7-py2-none-any.whl" } ] }