Merge branch 'master' into feature/crypto
Conflicts: swift/obj/server.py test/probe/test_object_async_update.py test/unit/obj/test_server.py Change-Id: Ifeba1cfe8c4244eff069ab10b2c77f8ea5e2a39b
This commit is contained in:
commit
ce0e16bcc5
|
@ -134,6 +134,7 @@ Usage: %%prog [options] [conf_file]
|
|||
retries = int(conf.get('retries', 5))
|
||||
concurrency = int(conf.get('concurrency', 25))
|
||||
endpoint_type = str(conf.get('endpoint_type', 'publicURL'))
|
||||
region_name = str(conf.get('region_name', ''))
|
||||
user_domain_name = str(conf.get('user_domain_name', ''))
|
||||
project_domain_name = str(conf.get('project_domain_name', ''))
|
||||
project_name = str(conf.get('project_name', ''))
|
||||
|
@ -157,6 +158,8 @@ Usage: %%prog [options] [conf_file]
|
|||
os_options['project_domain_name'] = project_domain_name
|
||||
if project_name:
|
||||
os_options['project_name'] = project_name
|
||||
if region_name:
|
||||
os_options['region_name'] = region_name
|
||||
|
||||
url, token = get_auth(conf['auth_url'], conf['auth_user'],
|
||||
conf['auth_key'],
|
||||
|
|
|
@ -353,6 +353,7 @@ Usage: %%prog [options] [conf_file]
|
|||
retries = int(conf.get('retries', 5))
|
||||
concurrency = int(conf.get('concurrency', 25))
|
||||
endpoint_type = str(conf.get('endpoint_type', 'publicURL'))
|
||||
region_name = str(conf.get('region_name', ''))
|
||||
if options.dump_json or config_true_value(conf.get('dump_json', 'no')):
|
||||
json_output = True
|
||||
container_report = config_true_value(conf.get('container_report', 'yes')) \
|
||||
|
@ -378,6 +379,8 @@ Usage: %%prog [options] [conf_file]
|
|||
os_options['project_domain_name'] = project_domain_name
|
||||
if project_name:
|
||||
os_options['project_name'] = project_name
|
||||
if region_name:
|
||||
os_options['region_name'] = region_name
|
||||
|
||||
url, token = get_auth(conf['auth_url'], conf['auth_user'],
|
||||
conf['auth_key'],
|
||||
|
|
|
@ -425,7 +425,7 @@ cluster: region 1 in San Francisco (SF), and region 2 in New York
|
|||
read_affinity
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
This setting makes the proxy server prefer local backend servers for
|
||||
This setting, combined with sorting_method setting, makes the proxy server prefer local backend servers for
|
||||
GET and HEAD requests over non-local ones. For example, it is
|
||||
preferable for an SF proxy server to service object GET requests
|
||||
by talking to SF object servers, as the client will receive lower
|
||||
|
@ -440,6 +440,7 @@ This is where the read_affinity setting comes in.
|
|||
Example::
|
||||
|
||||
[app:proxy-server]
|
||||
sorting_method = affinity
|
||||
read_affinity = r1=100
|
||||
|
||||
This will make the proxy attempt to service GET and HEAD requests from
|
||||
|
@ -451,6 +452,7 @@ fall back to backend servers in other regions.
|
|||
Example::
|
||||
|
||||
[app:proxy-server]
|
||||
sorting_method = affinity
|
||||
read_affinity = r1z1=100, r1=200
|
||||
|
||||
This will make the proxy attempt to service GET and HEAD requests from
|
||||
|
|
|
@ -109,8 +109,8 @@ Other
|
|||
* `Better Staticweb <https://github.com/CloudVPS/better-staticweb>`_ - Makes swift containers accessible by default.
|
||||
* `Django Swiftbrowser <https://github.com/cschwede/django-swiftbrowser>`_ - Simple Django web app to access OpenStack Swift.
|
||||
* `Swift-account-stats <https://github.com/enovance/swift-account-stats>`_ - Swift-account-stats is a tool to report statistics on Swift usage at tenant and global levels.
|
||||
* `PyECLib <https://bitbucket.org/kmgreen2/pyeclib>`_ - High Level Erasure Code library used by Swift
|
||||
* `liberasurecode <http://www.bytebucket.org/tsg-/liberasurecode>`_ - Low Level Erasure Code library used by PyECLib
|
||||
* `PyECLib <https://github.com/openstack/pyeclib>`_ - High Level Erasure Code library used by Swift
|
||||
* `liberasurecode <https://github.com/openstack/liberasurecode>`_ - Low Level Erasure Code library used by PyECLib
|
||||
* `Swift Browser <https://github.com/zerovm/swift-browser>`_ - JavaScript interface for Swift
|
||||
* `swift-ui <https://github.com/fanatic/swift-ui>`_ - OpenStack Swift web browser
|
||||
* `Swift Durability Calculator <https://github.com/enovance/swift-durability-calculator>`_ - Data Durability Calculation Tool for Swift
|
||||
|
|
|
@ -96,7 +96,7 @@ advantage of many well-known C libraries such as:
|
|||
PyECLib uses a C based library called liberasurecode to implement the plug in
|
||||
infrastructure; liberasure code is available at:
|
||||
|
||||
* liberasurecode: https://bitbucket.org/tsg-/liberasurecode
|
||||
* liberasurecode: https://github.com/openstack/liberasurecode
|
||||
|
||||
PyECLib itself therefore allows for not only choice but further extensibility as
|
||||
well. PyECLib also comes with a handy utility to help determine the best
|
||||
|
@ -105,7 +105,7 @@ configurations may vary in performance per algorithm). More on this will be
|
|||
covered in the configuration section. PyECLib is included as a Swift
|
||||
requirement.
|
||||
|
||||
For complete details see `PyECLib <https://bitbucket.org/kmgreen2/pyeclib>`_
|
||||
For complete details see `PyECLib <https://github.com/openstack/pyeclib>`_
|
||||
|
||||
------------------------------
|
||||
Storing and Retrieving Objects
|
||||
|
@ -215,7 +215,7 @@ Let's take a closer look at each configuration parameter:
|
|||
PyECLib back-end. This specifies the EC scheme that is to be used. For
|
||||
example the option shown here selects Vandermonde Reed-Solomon encoding while
|
||||
an option of ``flat_xor_hd_3`` would select Flat-XOR based HD combination
|
||||
codes. See the `PyECLib <https://bitbucket.org/kmgreen2/pyeclib>`_ page for
|
||||
codes. See the `PyECLib <https://github.com/openstack/pyeclib>`_ page for
|
||||
full details.
|
||||
* ``ec_num_data_fragments``: The total number of fragments that will be
|
||||
comprised of data.
|
||||
|
@ -270,7 +270,7 @@ Region Support
|
|||
--------------
|
||||
|
||||
For at least the initial version of EC, it is not recommended that an EC scheme
|
||||
span beyond a single region, neither performance nor functional validation has
|
||||
span beyond a single region, neither performance nor functional validation has
|
||||
be been done in such a configuration.
|
||||
|
||||
--------------
|
||||
|
|
|
@ -24,6 +24,10 @@ auth_key = testing
|
|||
# user_domain_name = user_domain
|
||||
#
|
||||
# endpoint_type = publicURL
|
||||
#
|
||||
# NOTE: If you have only 1 region with a swift endpoint, no need to specify it
|
||||
# region_name =
|
||||
#
|
||||
# keystone_api_insecure = no
|
||||
#
|
||||
# swift_dir = /etc/swift
|
||||
|
|
|
@ -163,7 +163,7 @@ __all__ = ['TempURL', 'filter_factory',
|
|||
|
||||
|
||||
from os.path import basename
|
||||
from time import time
|
||||
from time import time, strftime, gmtime
|
||||
|
||||
from six.moves.urllib.parse import parse_qs
|
||||
from six.moves.urllib.parse import urlencode
|
||||
|
@ -425,6 +425,11 @@ class TempURL(object):
|
|||
# newline into existing_disposition
|
||||
value = disposition_value.replace('\n', '%0A')
|
||||
out_headers.append(('Content-Disposition', value))
|
||||
|
||||
# include Expires header for better cache-control
|
||||
out_headers.append(('Expires', strftime(
|
||||
"%a, %d %b %Y %H:%M:%S GMT",
|
||||
gmtime(temp_url_expires))))
|
||||
headers = out_headers
|
||||
return start_response(status, headers, exc_info)
|
||||
|
||||
|
|
|
@ -9,14 +9,14 @@
|
|||
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: swift 2.7.1.dev50\n"
|
||||
"Project-Id-Version: swift 2.7.1.dev175\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
|
||||
"POT-Creation-Date: 2016-04-17 21:20+0000\n"
|
||||
"POT-Creation-Date: 2016-06-03 04:47+0000\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"PO-Revision-Date: 2016-03-24 03:15+0000\n"
|
||||
"Last-Translator: Monika Wolf <vcomas3@de.ibm.com>\n"
|
||||
"PO-Revision-Date: 2016-06-02 07:02+0000\n"
|
||||
"Last-Translator: Andreas Jaeger <jaegerandi@gmail.com>\n"
|
||||
"Language: de\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"Generated-By: Babel 2.0\n"
|
||||
|
@ -71,6 +71,10 @@ msgstr ""
|
|||
"%(replicated)d/%(total)d (%(percentage).2f%%) Partitionen repliziert in "
|
||||
"%(time).2fs (%(rate).2f/s, %(remaining)s verbleibend)"
|
||||
|
||||
#, python-format
|
||||
msgid "%(server)s (%(pid)s) appears to have stopped"
|
||||
msgstr "%(server)s (%(pid)s) scheinbar gestoppt"
|
||||
|
||||
#, python-format
|
||||
msgid "%(success)s successes, %(failure)s failures"
|
||||
msgstr "%(success)s Erfolge, %(failure)s Fehlschläge"
|
||||
|
@ -79,6 +83,10 @@ msgstr "%(success)s Erfolge, %(failure)s Fehlschläge"
|
|||
msgid "%(type)s returning 503 for %(statuses)s"
|
||||
msgstr "%(type)s gab 503 für %(statuses)s zurück"
|
||||
|
||||
#, python-format
|
||||
msgid "%(type)s: %(value)s"
|
||||
msgstr "%(type)s: %(value)s"
|
||||
|
||||
#, python-format
|
||||
msgid "%s already started..."
|
||||
msgstr "%s bereits gestartet..."
|
||||
|
@ -133,6 +141,10 @@ msgstr ", Rückgabecodes: "
|
|||
msgid "Account"
|
||||
msgstr "Konto"
|
||||
|
||||
#, python-format
|
||||
msgid "Account %(account)s has not been reaped since %(time)s"
|
||||
msgstr "Konto %(account)s wurde nicht aufgeräumt seit %(time)s"
|
||||
|
||||
#, python-format
|
||||
msgid "Account audit \"once\" mode completed: %.02fs"
|
||||
msgstr "Kontoprüfungsmodus \"once\" abgeschlossen: %.02fs"
|
||||
|
@ -148,6 +160,10 @@ msgstr ""
|
|||
"Versuch, %(count)d Datenbanken in %(time).5f Sekunden zu replizieren "
|
||||
"(%(rate).5f/s)"
|
||||
|
||||
#, python-format
|
||||
msgid "Audit Failed for %(path)s: %(err)s"
|
||||
msgstr "Prüfung fehlgeschlagen für %(path)s: %(err)s"
|
||||
|
||||
#, python-format
|
||||
msgid "Bad rsync return code: %(ret)d <- %(args)s"
|
||||
msgstr "Falscher rsync-Rückgabecode: %(ret)d <- %(args)s"
|
||||
|
@ -199,6 +215,14 @@ msgstr "Kann nicht auf die Datei %s zugreifen."
|
|||
msgid "Can not load profile data from %s."
|
||||
msgstr "Die Profildaten von %s können nicht geladen werden."
|
||||
|
||||
#, python-format
|
||||
msgid "Cannot read %(auditor_status)s (%(err)s)"
|
||||
msgstr "%(auditor_status)s (%(err)s) kann nicht gelesen werden."
|
||||
|
||||
#, python-format
|
||||
msgid "Cannot write %(auditor_status)s (%(err)s)"
|
||||
msgstr "Schreiben von %(auditor_status)s (%(err)s) nicht möglich."
|
||||
|
||||
#, python-format
|
||||
msgid "Client did not read from proxy within %ss"
|
||||
msgstr "Client konnte nicht innerhalb von %ss vom Proxy lesen"
|
||||
|
@ -273,12 +297,15 @@ msgstr ""
|
|||
"Änderungen"
|
||||
|
||||
#, python-format
|
||||
msgid "Could not bind to %s:%s after trying for %s seconds"
|
||||
msgstr "Keine Bindung an %s:%s möglich nach Versuch über %s Sekunden"
|
||||
msgid ""
|
||||
"Could not bind to %(addr)s:%(port)s after trying for %(timeout)s seconds"
|
||||
msgstr ""
|
||||
"Keine Bindung an %(addr)s:%(port)s möglich nach Versuch über %(timeout)s "
|
||||
"Sekunden"
|
||||
|
||||
#, python-format
|
||||
msgid "Could not load %r: %s"
|
||||
msgstr "Konnte %r nicht laden: %s"
|
||||
msgid "Could not load %(conf)r: %(error)s"
|
||||
msgstr "%(conf)r konnte nicht geladen werden: %(error)s"
|
||||
|
||||
#, python-format
|
||||
msgid "Data download error: %s"
|
||||
|
@ -289,9 +316,10 @@ msgid "Devices pass completed: %.02fs"
|
|||
msgstr "Gerätedurchgang abgeschlossen: %.02fs"
|
||||
|
||||
#, python-format
|
||||
msgid "Directory %r does not map to a valid policy (%s)"
|
||||
msgid "Directory %(directory)r does not map to a valid policy (%(error)s)"
|
||||
msgstr ""
|
||||
"Das Verzeichnis %r kann keiner gültigen Richtlinie (%s) zugeordnet werden."
|
||||
"Das Verzeichnis %(directory)r kann keiner gültigen Richtlinie (%(error)s) "
|
||||
"zugeordnet werden."
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR %(db_file)s: %(validate_sync_to_err)s"
|
||||
|
@ -325,10 +353,10 @@ msgstr ""
|
|||
#, python-format
|
||||
msgid ""
|
||||
"ERROR Account update failed: different numbers of hosts and devices in "
|
||||
"request: \"%s\" vs \"%s\""
|
||||
"request: \"%(hosts)s\" vs \"%(devices)s\""
|
||||
msgstr ""
|
||||
"FEHLER Kontoaktualisierung fehlgeschlagen: Unterschiedliche Anzahl von Hosts "
|
||||
"und Einheiten in der Anforderung: \"%s\" contra \"%s\""
|
||||
"und Einheiten in der Anforderung: \"%(hosts)s\" contra \"%(devices)s\""
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR Bad response %(status)s from %(host)s"
|
||||
|
@ -347,14 +375,6 @@ msgstr ""
|
|||
"Aktualisierung zu einem späteren Zeitpunkt gespeichert): %(status)d Antwort "
|
||||
"von %(ip)s:%(port)s/%(dev)s"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"ERROR Container update failed: different numbers of hosts and devices in "
|
||||
"request: \"%s\" vs \"%s\""
|
||||
msgstr ""
|
||||
"FEHLER Containeraktualisierung fehlgeschlagen: Unterschiedliche Anzahl von "
|
||||
"Hosts und Einheiten in der Anforderung: \"%s\" contra \"%s\""
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR Could not get account info %s"
|
||||
msgstr "FEHLER Kontoinfo %s konnte nicht abgerufen werden"
|
||||
|
@ -514,8 +534,8 @@ msgid "Error hashing suffix"
|
|||
msgstr "Fehler beim Hashing des Suffix"
|
||||
|
||||
#, python-format
|
||||
msgid "Error in %r with mtime_check_interval: %s"
|
||||
msgstr "Fehler in %r mit mtime_check_interval: %s"
|
||||
msgid "Error in %(conf)r with mtime_check_interval: %(error)s"
|
||||
msgstr "Fehler in %(conf)r mit mtime_check_interval: %(error)s"
|
||||
|
||||
#, python-format
|
||||
msgid "Error limiting server %s"
|
||||
|
@ -656,6 +676,10 @@ msgstr ""
|
|||
msgid "Killing long-running rsync: %s"
|
||||
msgstr "Lange laufendes rsync wird gekillt: %s"
|
||||
|
||||
#, python-format
|
||||
msgid "Loading JSON from %(auditor_status)s failed (%(err)s)"
|
||||
msgstr "Laden von JSON aus %(auditor_status)s fehlgeschlagen: (%(err)s)"
|
||||
|
||||
msgid "Lockup detected.. killing live coros."
|
||||
msgstr "Suche erkannt. Live-Coros werden gelöscht."
|
||||
|
||||
|
@ -668,8 +692,8 @@ msgid "No %s running"
|
|||
msgstr "Kein %s läuft"
|
||||
|
||||
#, python-format
|
||||
msgid "No cluster endpoint for %r %r"
|
||||
msgstr "Kein Cluster-Endpunkt für %r %r"
|
||||
msgid "No cluster endpoint for %(realm)r %(cluster)r"
|
||||
msgstr "Kein Cluster-Endpunkt für %(realm)r %(cluster)r"
|
||||
|
||||
#, python-format
|
||||
msgid "No permission to signal PID %d"
|
||||
|
@ -683,6 +707,10 @@ msgstr "Keine Richtlinie mit Index %s"
|
|||
msgid "No realm key for %r"
|
||||
msgstr "Kein Bereichsschlüssel für %r"
|
||||
|
||||
#, python-format
|
||||
msgid "No space left on device for %(file)s (%(err)s)"
|
||||
msgstr "Kein freier Speicherplatz im Gerät für %(file)s (%(err)s) vorhanden."
|
||||
|
||||
#, python-format
|
||||
msgid "Node error limited %(ip)s:%(port)s (%(device)s)"
|
||||
msgstr "Knotenfehler begrenzt %(ip)s:%(port)s (%(device)s)"
|
||||
|
@ -800,21 +828,13 @@ msgid "Partition times: max %(max).4fs, min %(min).4fs, med %(med).4fs"
|
|||
msgstr ""
|
||||
"Partitionszeiten: max. %(max).4fs, min. %(min).4fs, durchschnittl. %(med).4fs"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass beginning; %s possible containers; %s possible objects"
|
||||
msgstr "Durchlauf wird gestartet; %s mögliche Container; %s mögliche Objekte"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass completed in %ds; %d objects expired"
|
||||
msgstr "Durchgang abgeschlossen in %ds; %d Objekte abgelaufen"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass so far %ds; %d objects expired"
|
||||
msgstr "Bisherige Durchgänge %ds; %d Objekte abgelaufen"
|
||||
|
||||
msgid "Path required in X-Container-Sync-To"
|
||||
msgstr "Pfad in X-Container-Sync-To ist erforderlich"
|
||||
|
||||
#, python-format
|
||||
msgid "Problem cleaning up %(datadir)s (%(err)s)"
|
||||
msgstr "Problem bei der Bereinigung von %(datadir)s (%(err)s)"
|
||||
|
||||
#, python-format
|
||||
msgid "Problem cleaning up %s"
|
||||
msgstr "Problem bei der Bereinigung von %s"
|
||||
|
@ -903,6 +923,10 @@ msgstr "Objektrekonstruktor läuft im Skriptmodus."
|
|||
msgid "Running object replicator in script mode."
|
||||
msgstr "Objektreplikator läuft im Skriptmodus."
|
||||
|
||||
#, python-format
|
||||
msgid "Signal %(server)s pid: %(pid)s signal: %(signal)s"
|
||||
msgstr "Signal %(server)s PID: %(pid)s Signal: %(signal)s"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Since %(time)s: %(sync)s synced [%(delete)s deletes, %(put)s puts], %(skip)s "
|
||||
|
@ -1007,9 +1031,15 @@ msgid "UNCAUGHT EXCEPTION"
|
|||
msgstr "NICHT ABGEFANGENE AUSNAHME"
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to load internal client from config: %r (%s)"
|
||||
msgid "Unable to find %(section)s config section in %(conf)s"
|
||||
msgstr ""
|
||||
"Interner Client konnte nicht aus der Konfiguration geladen werden: %r (%s)"
|
||||
"%(section)s-Konfigurationsabschnitt in %(conf)s kann nicht gefunden werden"
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to load internal client from config: %(conf)r (%(error)s)"
|
||||
msgstr ""
|
||||
"Interner Client konnte nicht aus der Konfiguration geladen werden: %(conf)r "
|
||||
"(%(error)s)"
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to locate %s in libc. Leaving as a no-op."
|
||||
|
@ -1020,12 +1050,20 @@ msgstr ""
|
|||
msgid "Unable to locate config for %s"
|
||||
msgstr "Konfiguration für %s wurde nicht gefunden."
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to locate config number %(number)s for %(server)s"
|
||||
msgstr "Konfigurationsnummer %(number)s für %(server)s wurde nicht gefunden."
|
||||
|
||||
msgid ""
|
||||
"Unable to locate fallocate, posix_fallocate in libc. Leaving as a no-op."
|
||||
msgstr ""
|
||||
"fallocate, posix_fallocate konnte nicht in libc gefunden werden. Wird als "
|
||||
"Nullbefehl verlassen."
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to perform fsync() on directory %(dir)s: %(err)s"
|
||||
msgstr "fsync() kann für Verzeichnis %(dir)s nicht ausgeführt werden: %(err)s"
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to read config from %s"
|
||||
msgstr "Konfiguration aus %s kann nicht gelesen werden"
|
||||
|
@ -1076,6 +1114,17 @@ msgstr ""
|
|||
"WARNUNG: Grenzwert für Speicher kann nicht geändert werden. Wird nicht als "
|
||||
"Root ausgeführt?"
|
||||
|
||||
#, python-format
|
||||
msgid "Waited %(kill_wait)s seconds for %(server)s to die; giving up"
|
||||
msgstr ""
|
||||
"Hat %(kill_wait)s Sekunden für %(server)s zum Erlöschen gewartet; Gibt auf"
|
||||
|
||||
#, python-format
|
||||
msgid "Waited %(kill_wait)s seconds for %(server)s to die; killing"
|
||||
msgstr ""
|
||||
"Hat %(kill_wait)s Sekunden für %(server)s zum Erlöschen gewartet. Wird "
|
||||
"abgebrochen."
|
||||
|
||||
msgid "Warning: Cannot ratelimit without a memcached client"
|
||||
msgstr ""
|
||||
"Warnung: Geschwindigkeitsbegrenzung kann nicht ohne memcached-Client "
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: swift 2.7.1.dev50\n"
|
||||
"Project-Id-Version: swift 2.7.1.dev169\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
|
||||
"POT-Creation-Date: 2016-04-17 21:20+0000\n"
|
||||
"POT-Creation-Date: 2016-06-02 04:58+0000\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
@ -267,14 +267,6 @@ msgstr ""
|
|||
"%(elapsed).02fs, %(success)s con éxito, %(fail)s fallos, %(no_change)s sin "
|
||||
"cambios"
|
||||
|
||||
#, python-format
|
||||
msgid "Could not bind to %s:%s after trying for %s seconds"
|
||||
msgstr "No se puede enlazar a %s:%s después de intentar por %s segundos"
|
||||
|
||||
#, python-format
|
||||
msgid "Could not load %r: %s"
|
||||
msgstr "No se ha podido cargar %r: %s"
|
||||
|
||||
#, python-format
|
||||
msgid "Data download error: %s"
|
||||
msgstr "Error de descarga de datos: %s"
|
||||
|
@ -283,10 +275,6 @@ msgstr "Error de descarga de datos: %s"
|
|||
msgid "Devices pass completed: %.02fs"
|
||||
msgstr "Paso de dispositivos finalizado: %.02fs"
|
||||
|
||||
#, python-format
|
||||
msgid "Directory %r does not map to a valid policy (%s)"
|
||||
msgstr "El directory %r no está correlacionado con una política válida (%s)"
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR %(db_file)s: %(validate_sync_to_err)s"
|
||||
msgstr "ERROR %(db_file)s: %(validate_sync_to_err)s"
|
||||
|
@ -317,14 +305,6 @@ msgstr ""
|
|||
"ERROR La actualización de la cuenta ha fallado con %(ip)s:%(port)s/"
|
||||
"%(device)s (se volverá a intentar más tarde): Respuesta %(status)s %(reason)s"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"ERROR Account update failed: different numbers of hosts and devices in "
|
||||
"request: \"%s\" vs \"%s\""
|
||||
msgstr ""
|
||||
"ERROR La actualización de la cuenta ha fallado: hay números distintos de "
|
||||
"hosts y dispositivos en la solicitud: \"%s\" frente a \"%s\""
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR Bad response %(status)s from %(host)s"
|
||||
msgstr "ERROR Respuesta errónea %(status)s desde %(host)s"
|
||||
|
@ -342,14 +322,6 @@ msgstr ""
|
|||
"actualización asíncrona posterior): %(status)d respuesta desde %(ip)s:"
|
||||
"%(port)s/%(dev)s"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"ERROR Container update failed: different numbers of hosts and devices in "
|
||||
"request: \"%s\" vs \"%s\""
|
||||
msgstr ""
|
||||
"ERROR La actualización del contenedor ha fallado: hay números distintos de "
|
||||
"hosts y dispositivos en la solicitud: \"%s\" frente a \"%s\""
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR Could not get account info %s"
|
||||
msgstr "ERROR No se ha podido obtener la información de cuenta %s"
|
||||
|
@ -508,10 +480,6 @@ msgstr "Error en la codificación a UTF-8: %s"
|
|||
msgid "Error hashing suffix"
|
||||
msgstr "Error en el hash del sufijo"
|
||||
|
||||
#, python-format
|
||||
msgid "Error in %r with mtime_check_interval: %s"
|
||||
msgstr "Error en %r con mtime_check_interval: %s"
|
||||
|
||||
#, python-format
|
||||
msgid "Error limiting server %s"
|
||||
msgstr "Error al limitar el servidor %s"
|
||||
|
@ -662,10 +630,6 @@ msgstr "Se ha correlacionado %(given_domain)s con %(found_domain)s"
|
|||
msgid "No %s running"
|
||||
msgstr "Ningún %s en ejecución"
|
||||
|
||||
#, python-format
|
||||
msgid "No cluster endpoint for %r %r"
|
||||
msgstr "No hay punto final de clúster para %r %r"
|
||||
|
||||
#, python-format
|
||||
msgid "No permission to signal PID %d"
|
||||
msgstr "No hay permiso para señalar el PID %d"
|
||||
|
@ -796,18 +760,6 @@ msgid "Partition times: max %(max).4fs, min %(min).4fs, med %(med).4fs"
|
|||
msgstr ""
|
||||
"Tiempos de partición: máximo %(max).4fs, mínimo %(min).4fs, medio %(med).4fs"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass beginning; %s possible containers; %s possible objects"
|
||||
msgstr "Inicio del paso; %s posibles contenedores; %s posibles objetos"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass completed in %ds; %d objects expired"
|
||||
msgstr "Paso completado en %ds; %d objetos caducados"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass so far %ds; %d objects expired"
|
||||
msgstr "Paso hasta ahora %ds; %d objetos caducados"
|
||||
|
||||
msgid "Path required in X-Container-Sync-To"
|
||||
msgstr "Vía de acceso necesaria en X-Container-Sync-To"
|
||||
|
||||
|
@ -1003,11 +955,6 @@ msgstr "Intentando escribir en %s"
|
|||
msgid "UNCAUGHT EXCEPTION"
|
||||
msgstr "UNCAUGHT EXCEPTION"
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to load internal client from config: %r (%s)"
|
||||
msgstr ""
|
||||
"No se puede cargar el cliente interno a partir de la configuración: %r (%s)"
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to locate %s in libc. Leaving as a no-op."
|
||||
msgstr "No se ha podido localizar %s en libc. Se dejará como no operativo."
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: swift 2.7.1.dev50\n"
|
||||
"Project-Id-Version: swift 2.7.1.dev169\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
|
||||
"POT-Creation-Date: 2016-04-17 21:20+0000\n"
|
||||
"POT-Creation-Date: 2016-06-02 04:58+0000\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
@ -270,14 +270,6 @@ msgstr ""
|
|||
"%(elapsed).02fs, %(success)s succès, %(fail)s échec(s), %(no_change)s "
|
||||
"inchangé(s)"
|
||||
|
||||
#, python-format
|
||||
msgid "Could not bind to %s:%s after trying for %s seconds"
|
||||
msgstr "Liaison impossible à %s:%s après une tentative de %s secondes"
|
||||
|
||||
#, python-format
|
||||
msgid "Could not load %r: %s"
|
||||
msgstr "Impossible de charger %r: %s"
|
||||
|
||||
#, python-format
|
||||
msgid "Data download error: %s"
|
||||
msgstr "Erreur de téléchargement des données: %s"
|
||||
|
@ -286,10 +278,6 @@ msgstr "Erreur de téléchargement des données: %s"
|
|||
msgid "Devices pass completed: %.02fs"
|
||||
msgstr "Session d'audit d'unité terminée : %.02fs"
|
||||
|
||||
#, python-format
|
||||
msgid "Directory %r does not map to a valid policy (%s)"
|
||||
msgstr "Le répertoire %r n'est pas mappé à une stratégie valide (%s)"
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR %(db_file)s: %(validate_sync_to_err)s"
|
||||
msgstr "ERREUR %(db_file)s : %(validate_sync_to_err)s"
|
||||
|
@ -322,14 +310,6 @@ msgstr ""
|
|||
"(une nouvelle tentative sera effectuée ultérieurement). Réponse %(status)s "
|
||||
"%(reason)s"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"ERROR Account update failed: different numbers of hosts and devices in "
|
||||
"request: \"%s\" vs \"%s\""
|
||||
msgstr ""
|
||||
"ERREUR Echec de la mise à jour du compte. Le nombre d'hôtes et le nombre "
|
||||
"d'unités diffèrent dans la demande : \"%s\" / \"%s\""
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR Bad response %(status)s from %(host)s"
|
||||
msgstr "ERREUR Réponse incorrecte %(status)s de %(host)s"
|
||||
|
@ -347,14 +327,6 @@ msgstr ""
|
|||
"asynchrone ultérieure) : réponse %(status)d renvoyée par %(ip)s:%(port)s/"
|
||||
"%(dev)s"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"ERROR Container update failed: different numbers of hosts and devices in "
|
||||
"request: \"%s\" vs \"%s\""
|
||||
msgstr ""
|
||||
"ERREUR Echec de la mise à jour du conteneur. Le nombre d'hôtes et le nombre "
|
||||
"d'unités diffèrent dans la demande : \"%s\" / \"%s\""
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR Could not get account info %s"
|
||||
msgstr "ERREUR Impossible d'obtenir les infos de compte %s"
|
||||
|
@ -515,10 +487,6 @@ msgstr "Erreur encodage UTF-8: %s"
|
|||
msgid "Error hashing suffix"
|
||||
msgstr "Erreur suffixe hashing"
|
||||
|
||||
#, python-format
|
||||
msgid "Error in %r with mtime_check_interval: %s"
|
||||
msgstr "Erreur dans %r liée à mtime_check_interval : %s"
|
||||
|
||||
#, python-format
|
||||
msgid "Error limiting server %s"
|
||||
msgstr "Erreur limitation du serveur %s"
|
||||
|
@ -671,10 +639,6 @@ msgstr "%(given_domain)s mappé avec %(found_domain)s"
|
|||
msgid "No %s running"
|
||||
msgstr "Non démarré %s"
|
||||
|
||||
#, python-format
|
||||
msgid "No cluster endpoint for %r %r"
|
||||
msgstr "Aucun noeud final de cluster pour %r %r"
|
||||
|
||||
#, python-format
|
||||
msgid "No permission to signal PID %d"
|
||||
msgstr "Aucun droit pour signaler le PID %d"
|
||||
|
@ -812,18 +776,6 @@ msgstr ""
|
|||
"Temps de partition : maximum %(max).4fs, minimum %(min).4fs, moyenne "
|
||||
"%(med).4fs"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass beginning; %s possible containers; %s possible objects"
|
||||
msgstr "Début de session. %s conteneur(s) possible(s). %s objet(s) possible(s)"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass completed in %ds; %d objects expired"
|
||||
msgstr "Session terminée dans %ds. %d objet(s) arrivé(s) à expiration"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass so far %ds; %d objects expired"
|
||||
msgstr "Session jusqu'à %ds. %d objet(s) arrivé(s) à expiration"
|
||||
|
||||
msgid "Path required in X-Container-Sync-To"
|
||||
msgstr "Chemin requis dans X-Container-Sync-To"
|
||||
|
||||
|
@ -1020,11 +972,6 @@ msgstr "Tentative d'écriture sur %s"
|
|||
msgid "UNCAUGHT EXCEPTION"
|
||||
msgstr "EXCEPTION NON INTERCEPTEE"
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to load internal client from config: %r (%s)"
|
||||
msgstr ""
|
||||
"Impossible de charger le client interne depuis la configuration : %r (%s)"
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to locate %s in libc. Leaving as a no-op."
|
||||
msgstr ""
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: swift 2.7.1.dev50\n"
|
||||
"Project-Id-Version: swift 2.7.1.dev169\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
|
||||
"POT-Creation-Date: 2016-04-17 21:20+0000\n"
|
||||
"POT-Creation-Date: 2016-06-02 04:58+0000\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
@ -272,15 +272,6 @@ msgstr ""
|
|||
"%(success)s operazioni con esito positivo, %(fail)s errori, %(no_change)s "
|
||||
"senza modifiche"
|
||||
|
||||
#, python-format
|
||||
msgid "Could not bind to %s:%s after trying for %s seconds"
|
||||
msgstr ""
|
||||
"Impossibile effettuare il bind a %s:%s dopo aver provato per %s secondi"
|
||||
|
||||
#, python-format
|
||||
msgid "Could not load %r: %s"
|
||||
msgstr "Impossibile caricare %r: %s"
|
||||
|
||||
#, python-format
|
||||
msgid "Data download error: %s"
|
||||
msgstr "Errore di download dei dati: %s"
|
||||
|
@ -289,10 +280,6 @@ msgstr "Errore di download dei dati: %s"
|
|||
msgid "Devices pass completed: %.02fs"
|
||||
msgstr "Trasmissione dei dispositivi completata: %.02fs"
|
||||
|
||||
#, python-format
|
||||
msgid "Directory %r does not map to a valid policy (%s)"
|
||||
msgstr "La directory %r non è associata ad una politica valida (%s)"
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR %(db_file)s: %(validate_sync_to_err)s"
|
||||
msgstr "ERRORE %(db_file)s: %(validate_sync_to_err)s"
|
||||
|
@ -323,14 +310,6 @@ msgstr ""
|
|||
"%(device)s (verrà eseguito un nuovo tentativo successivamente): Risposta "
|
||||
"%(status)s %(reason)s"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"ERROR Account update failed: different numbers of hosts and devices in "
|
||||
"request: \"%s\" vs \"%s\""
|
||||
msgstr ""
|
||||
"ERRORE Aggiornamento dell'account non riuscito: numero differente di host e "
|
||||
"dispositivi nella richiesta: \"%s\" vs \"%s\""
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR Bad response %(status)s from %(host)s"
|
||||
msgstr "ERRORE Risposta errata %(status)s da %(host)s"
|
||||
|
@ -348,14 +327,6 @@ msgstr ""
|
|||
"l'aggiornamento asincrono successivamente): %(status)d risposta da %(ip)s:"
|
||||
"%(port)s/%(dev)s"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"ERROR Container update failed: different numbers of hosts and devices in "
|
||||
"request: \"%s\" vs \"%s\""
|
||||
msgstr ""
|
||||
"ERRORE Aggiornamento del contenitore non riuscito: numero differente di host "
|
||||
"e dispositivi nella richiesta: \"%s\" vs \"%s\""
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR Could not get account info %s"
|
||||
msgstr "ERRORE Impossibile ottenere le informazioni sull'account %s"
|
||||
|
@ -512,10 +483,6 @@ msgstr "Errore durante la codifica in UTF-8: %s"
|
|||
msgid "Error hashing suffix"
|
||||
msgstr "Errore durante l'hash del suffisso"
|
||||
|
||||
#, python-format
|
||||
msgid "Error in %r with mtime_check_interval: %s"
|
||||
msgstr "Errore in %r con mtime_check_interval: %s"
|
||||
|
||||
#, python-format
|
||||
msgid "Error limiting server %s"
|
||||
msgstr "Errore durante la limitazione del server %s"
|
||||
|
@ -670,10 +637,6 @@ msgstr "%(given_domain)s associato a %(found_domain)s"
|
|||
msgid "No %s running"
|
||||
msgstr "Nessun %s in esecuzione"
|
||||
|
||||
#, python-format
|
||||
msgid "No cluster endpoint for %r %r"
|
||||
msgstr "Nessun endpoint del cluster per %r %r"
|
||||
|
||||
#, python-format
|
||||
msgid "No permission to signal PID %d"
|
||||
msgstr "Nessuna autorizzazione per la segnalazione del PID %d"
|
||||
|
@ -799,19 +762,6 @@ msgstr "Parametri, query e frammenti non consentiti in X-Container-Sync-To"
|
|||
msgid "Partition times: max %(max).4fs, min %(min).4fs, med %(med).4fs"
|
||||
msgstr "Tempi partizione: max %(max).4fs, min %(min).4fs, med %(med).4fs"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass beginning; %s possible containers; %s possible objects"
|
||||
msgstr ""
|
||||
"Avvio della trasmissione; %s contenitori possibili; %s oggetti possibili"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass completed in %ds; %d objects expired"
|
||||
msgstr "Trasmissione completata in %ds; %d oggetti scaduti"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass so far %ds; %d objects expired"
|
||||
msgstr "Trasmissione eseguita fino ad ora %ds; %d oggetti scaduti"
|
||||
|
||||
msgid "Path required in X-Container-Sync-To"
|
||||
msgstr "Percorso richiesto in X-Container-Sync-To"
|
||||
|
||||
|
@ -1009,10 +959,6 @@ msgstr "Tentativo di scrittura in %s"
|
|||
msgid "UNCAUGHT EXCEPTION"
|
||||
msgstr "ECCEZIONE NON RILEVATA"
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to load internal client from config: %r (%s)"
|
||||
msgstr "Impossibile caricare il client interno dalla configurazione: %r (%s)"
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to locate %s in libc. Leaving as a no-op."
|
||||
msgstr "Impossibile individuare %s in libc. Lasciato come no-op."
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: swift 2.7.1.dev50\n"
|
||||
"Project-Id-Version: swift 2.7.1.dev169\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
|
||||
"POT-Creation-Date: 2016-04-17 21:20+0000\n"
|
||||
"POT-Creation-Date: 2016-06-02 04:58+0000\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
@ -262,14 +262,6 @@ msgstr ""
|
|||
"%(path)s のコンテナー更新スイープが完了しました: %(elapsed).02fs、成功 "
|
||||
"%(success)s、失敗 %(fail)s、未変更 %(no_change)s"
|
||||
|
||||
#, python-format
|
||||
msgid "Could not bind to %s:%s after trying for %s seconds"
|
||||
msgstr "%s 秒間の試行後に %s:%s にバインドできませんでした"
|
||||
|
||||
#, python-format
|
||||
msgid "Could not load %r: %s"
|
||||
msgstr "%r をロードできませんでした: %s"
|
||||
|
||||
#, python-format
|
||||
msgid "Data download error: %s"
|
||||
msgstr "データダウンロードエラー: %s"
|
||||
|
@ -278,10 +270,6 @@ msgstr "データダウンロードエラー: %s"
|
|||
msgid "Devices pass completed: %.02fs"
|
||||
msgstr "デバイスの処理が完了しました: %.02fs"
|
||||
|
||||
#, python-format
|
||||
msgid "Directory %r does not map to a valid policy (%s)"
|
||||
msgstr "ディレクトリー %r は有効なポリシーにマップしていません (%s) "
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR %(db_file)s: %(validate_sync_to_err)s"
|
||||
msgstr "エラー %(db_file)s: %(validate_sync_to_err)s"
|
||||
|
@ -310,14 +298,6 @@ msgstr ""
|
|||
"エラー: アカウント更新が %(ip)s:%(port)s/%(device)s で失敗しました(後で再試行"
|
||||
"されます): 応答 %(status)s %(reason)s"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"ERROR Account update failed: different numbers of hosts and devices in "
|
||||
"request: \"%s\" vs \"%s\""
|
||||
msgstr ""
|
||||
"エラー: アカウント更新に失敗しました。要求内のホスト数およびデバイス数が異な"
|
||||
"ります: 「%s」vs「%s」"
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR Bad response %(status)s from %(host)s"
|
||||
msgstr "エラー: ホスト %(host)s からの応答 %(status)s が正しくありません"
|
||||
|
@ -334,14 +314,6 @@ msgstr ""
|
|||
"エラー: コンテナー更新に失敗しました (後の非同期更新のために保存中): %(ip)s:"
|
||||
"%(port)s/%(dev)s からの %(status)d 応答"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"ERROR Container update failed: different numbers of hosts and devices in "
|
||||
"request: \"%s\" vs \"%s\""
|
||||
msgstr ""
|
||||
"エラー: コンテナー更新に失敗しました。要求内のホスト数およびデバイス数が異な"
|
||||
"ります: 「%s」vs「%s」"
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR Could not get account info %s"
|
||||
msgstr "ERROR アカウント情報 %s が取得できませんでした"
|
||||
|
@ -496,10 +468,6 @@ msgstr "UTF-8 へのエンコードエラー: %s"
|
|||
msgid "Error hashing suffix"
|
||||
msgstr "サフィックスのハッシュエラー"
|
||||
|
||||
#, python-format
|
||||
msgid "Error in %r with mtime_check_interval: %s"
|
||||
msgstr "mtime_check_interval で %r にエラーがあります: %s"
|
||||
|
||||
#, python-format
|
||||
msgid "Error limiting server %s"
|
||||
msgstr "サーバー %s の制限エラー"
|
||||
|
@ -651,10 +619,6 @@ msgstr "%(given_domain)s が %(found_domain)s にマップされました"
|
|||
msgid "No %s running"
|
||||
msgstr "%s が実行されていません"
|
||||
|
||||
#, python-format
|
||||
msgid "No cluster endpoint for %r %r"
|
||||
msgstr "%r %r のエンドポイントクラスターがありません"
|
||||
|
||||
#, python-format
|
||||
msgid "No permission to signal PID %d"
|
||||
msgstr "PID %d にシグナル通知する許可がありません"
|
||||
|
@ -783,19 +747,6 @@ msgstr ""
|
|||
msgid "Partition times: max %(max).4fs, min %(min).4fs, med %(med).4fs"
|
||||
msgstr "パーティション時間: 最大 %(max).4fs、最小 %(min).4fs、中間 %(med).4fs"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass beginning; %s possible containers; %s possible objects"
|
||||
msgstr ""
|
||||
"パスの開始中。%s コンテナーおよび %s オブジェクトが存在する可能性があります"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass completed in %ds; %d objects expired"
|
||||
msgstr "%d でパスが完了しました。%d オブジェクトの有効期限が切れました"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass so far %ds; %d objects expired"
|
||||
msgstr "現在までのパス %d。%d オブジェクトの有効期限が切れました"
|
||||
|
||||
msgid "Path required in X-Container-Sync-To"
|
||||
msgstr "X-Container-Sync-To にパスが必要です"
|
||||
|
||||
|
@ -984,10 +935,6 @@ msgstr "%s への書き込みを試行中"
|
|||
msgid "UNCAUGHT EXCEPTION"
|
||||
msgstr "キャッチされていない例外"
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to load internal client from config: %r (%s)"
|
||||
msgstr "設定から内部クライアントをロードできません: %r (%s)"
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to locate %s in libc. Leaving as a no-op."
|
||||
msgstr "%s が libc に見つかりません。no-op として終了します。"
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: swift 2.7.1.dev50\n"
|
||||
"Project-Id-Version: swift 2.7.1.dev169\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
|
||||
"POT-Creation-Date: 2016-04-17 21:20+0000\n"
|
||||
"POT-Creation-Date: 2016-06-02 04:58+0000\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
@ -263,14 +263,6 @@ msgstr ""
|
|||
"%(path)s의 컨테이너 업데이트 스윕 완료: %(elapsed).02fs, %(success)s개 성공, "
|
||||
"%(fail)s개 실패, %(no_change)s개 변경 없음"
|
||||
|
||||
#, python-format
|
||||
msgid "Could not bind to %s:%s after trying for %s seconds"
|
||||
msgstr "%s초 동안 시도한 후 %s:%s에 바인드할 수 없음"
|
||||
|
||||
#, python-format
|
||||
msgid "Could not load %r: %s"
|
||||
msgstr "%r을(를) 로드할 수 없음: %s"
|
||||
|
||||
#, python-format
|
||||
msgid "Data download error: %s"
|
||||
msgstr "데이터 다운로드 오류: %s"
|
||||
|
@ -279,10 +271,6 @@ msgstr "데이터 다운로드 오류: %s"
|
|||
msgid "Devices pass completed: %.02fs"
|
||||
msgstr "장치 패스 완료 : %.02fs"
|
||||
|
||||
#, python-format
|
||||
msgid "Directory %r does not map to a valid policy (%s)"
|
||||
msgstr "%r 디렉토리가 올바른 정책(%s)에 맵핑되지 않음"
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR %(db_file)s: %(validate_sync_to_err)s"
|
||||
msgstr "오류 %(db_file)s: %(validate_sync_to_err)s"
|
||||
|
@ -311,14 +299,6 @@ msgstr ""
|
|||
"오류. %(ip)s:%(port)s/%(device)s(으)로 계정 업데이트 실패(나중에 다시 시도): "
|
||||
"응답 %(status)s %(reason)s"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"ERROR Account update failed: different numbers of hosts and devices in "
|
||||
"request: \"%s\" vs \"%s\""
|
||||
msgstr ""
|
||||
"오류. 계정 업데이트 실패: 다음 요청에서 호스트 및 디바이스 수가 서로 다름: "
|
||||
"\"%s\" 대 \"%s\""
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR Bad response %(status)s from %(host)s"
|
||||
msgstr "오류. %(host)s의 잘못된 응답 %(status)s"
|
||||
|
@ -335,14 +315,6 @@ msgstr ""
|
|||
"오류. 컨테이너 업데이트 실패(이후 비동기 업데이트용으로 저장): %(status)d응"
|
||||
"답. 출처: %(ip)s:%(port)s/%(dev)s"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"ERROR Container update failed: different numbers of hosts and devices in "
|
||||
"request: \"%s\" vs \"%s\""
|
||||
msgstr ""
|
||||
"오류. 컨테이너 업데이트 실패: 다음 요청에서 호스트 및 디바이스 수가 서로 다"
|
||||
"름: \"%s\" 대 \"%s\""
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR Could not get account info %s"
|
||||
msgstr "오류는 %s의 계정 정보를 얻을 수 없습니다"
|
||||
|
@ -493,10 +465,6 @@ msgstr "UTF-8: %s 으로 변환 오류"
|
|||
msgid "Error hashing suffix"
|
||||
msgstr "접미부를 해싱하는 중 오류 발생"
|
||||
|
||||
#, python-format
|
||||
msgid "Error in %r with mtime_check_interval: %s"
|
||||
msgstr "%r에서 mtime_check_interval 오류 발생: %s"
|
||||
|
||||
#, python-format
|
||||
msgid "Error limiting server %s"
|
||||
msgstr "서버 %s 제한 오류"
|
||||
|
@ -646,10 +614,6 @@ msgstr "%(given_domain)s을(를) %(found_domain)s(으)로 맵핑함"
|
|||
msgid "No %s running"
|
||||
msgstr "%s이(가) 실행되지 않음"
|
||||
|
||||
#, python-format
|
||||
msgid "No cluster endpoint for %r %r"
|
||||
msgstr "%r %r에 대한 클러스터 엔드포인트가 없음"
|
||||
|
||||
#, python-format
|
||||
msgid "No permission to signal PID %d"
|
||||
msgstr "PID %d을(를) 표시할 권한이 없음"
|
||||
|
@ -775,18 +739,6 @@ msgstr "X-Container-Sync-To에 매개변수, 조회, 단편이 허용되지 않
|
|||
msgid "Partition times: max %(max).4fs, min %(min).4fs, med %(med).4fs"
|
||||
msgstr "파티션 시간: 최대 %(max).4f초, 최소 %(min).4f초, 중간 %(med).4f초"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass beginning; %s possible containers; %s possible objects"
|
||||
msgstr "전달 시작, %s개의 컨테이너 사용 가능, %s개의 오브젝트 사용 가능"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass completed in %ds; %d objects expired"
|
||||
msgstr "%d초 안에 전달이 완료됨. %d개의 오브젝트가 만료됨"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass so far %ds; %d objects expired"
|
||||
msgstr "현재 %d개 전달, %d개의 오브젝트가 만료됨"
|
||||
|
||||
msgid "Path required in X-Container-Sync-To"
|
||||
msgstr "X-Container-Sync-To에 경로가 필요함"
|
||||
|
||||
|
@ -970,10 +922,6 @@ msgstr "%s에 쓰기 시도 중"
|
|||
msgid "UNCAUGHT EXCEPTION"
|
||||
msgstr "미발견 예외"
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to load internal client from config: %r (%s)"
|
||||
msgstr "구성에서 내부 클라이언트를 로드할 수 없음: %r (%s)"
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to locate %s in libc. Leaving as a no-op."
|
||||
msgstr "libc에서 %s을(를) 찾을 수 없습니다. no-op로 남겨 둡니다."
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: swift 2.7.1.dev50\n"
|
||||
"Project-Id-Version: swift 2.7.1.dev169\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
|
||||
"POT-Creation-Date: 2016-04-17 21:20+0000\n"
|
||||
"POT-Creation-Date: 2016-06-02 04:58+0000\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
@ -267,14 +267,6 @@ msgstr ""
|
|||
"%(elapsed).02fs, %(success)s com êxito, %(fail)s com falha, %(no_change)s "
|
||||
"sem alterações"
|
||||
|
||||
#, python-format
|
||||
msgid "Could not bind to %s:%s after trying for %s seconds"
|
||||
msgstr "Não foi possível conectar a %s:%s após tentar por %s segundos"
|
||||
|
||||
#, python-format
|
||||
msgid "Could not load %r: %s"
|
||||
msgstr "Não é possível carregar %r: %s"
|
||||
|
||||
#, python-format
|
||||
msgid "Data download error: %s"
|
||||
msgstr "Erro ao fazer download de dados: %s"
|
||||
|
@ -283,10 +275,6 @@ msgstr "Erro ao fazer download de dados: %s"
|
|||
msgid "Devices pass completed: %.02fs"
|
||||
msgstr "Dispositivos finalizados: %.02fs"
|
||||
|
||||
#, python-format
|
||||
msgid "Directory %r does not map to a valid policy (%s)"
|
||||
msgstr "O diretório %r não está mapeado para uma política válida (%s)"
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR %(db_file)s: %(validate_sync_to_err)s"
|
||||
msgstr "ERRO %(db_file)s: %(validate_sync_to_err)s"
|
||||
|
@ -315,14 +303,6 @@ msgstr ""
|
|||
"ERRO A atualização da conta falhou com %(ip)s:%(port)s/%(device)s (tente "
|
||||
"novamente mais tarde): Resposta %(status)s %(reason)s"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"ERROR Account update failed: different numbers of hosts and devices in "
|
||||
"request: \"%s\" vs \"%s\""
|
||||
msgstr ""
|
||||
"ERRO A atualização da conta falhou: números diferentes de hosts e "
|
||||
"dispositivos na solicitação: \"%s\" vs \"%s\""
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR Bad response %(status)s from %(host)s"
|
||||
msgstr "ERRO Resposta inválida %(status)s a partir de %(host)s"
|
||||
|
@ -339,14 +319,6 @@ msgstr ""
|
|||
"ERRO A atualização do contêiner falhou (salvando para atualização assíncrona "
|
||||
"posterior): %(status)d resposta do %(ip)s:%(port)s/%(dev)s"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"ERROR Container update failed: different numbers of hosts and devices in "
|
||||
"request: \"%s\" vs \"%s\""
|
||||
msgstr ""
|
||||
"ERRO A atualização do contêiner falhou: números diferentes de hosts e "
|
||||
"dispositivos na solicitação: \"%s\" vs \"%s\""
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR Could not get account info %s"
|
||||
msgstr "ERRO Não foi possível recuperar as informações da conta %s"
|
||||
|
@ -499,10 +471,6 @@ msgstr "Erro encodificando para UTF-8: %s"
|
|||
msgid "Error hashing suffix"
|
||||
msgstr "Erro ao efetuar hash do sufixo"
|
||||
|
||||
#, python-format
|
||||
msgid "Error in %r with mtime_check_interval: %s"
|
||||
msgstr "Erro em %r com mtime_check_interval: %s"
|
||||
|
||||
#, python-format
|
||||
msgid "Error limiting server %s"
|
||||
msgstr "Erro ao limitar o servidor %s"
|
||||
|
@ -652,10 +620,6 @@ msgstr "%(given_domain)s mapeado para %(found_domain)s"
|
|||
msgid "No %s running"
|
||||
msgstr "Nenhum %s rodando"
|
||||
|
||||
#, python-format
|
||||
msgid "No cluster endpoint for %r %r"
|
||||
msgstr "Nenhum terminal de cluster para %r %r"
|
||||
|
||||
#, python-format
|
||||
msgid "No permission to signal PID %d"
|
||||
msgstr "Nenhuma permissão para PID do sinal %d"
|
||||
|
@ -786,18 +750,6 @@ msgid "Partition times: max %(max).4fs, min %(min).4fs, med %(med).4fs"
|
|||
msgstr ""
|
||||
"Tempos de partição: máximo %(max).4fs, mínimo %(min).4fs, médio %(med).4fs"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass beginning; %s possible containers; %s possible objects"
|
||||
msgstr "Início da aprovação; %s contêineres possíveis; %s objetos possíveis"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass completed in %ds; %d objects expired"
|
||||
msgstr "Aprovação concluída em %ds; %d objetos expirados"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass so far %ds; %d objects expired"
|
||||
msgstr "Aprovados até aqui %ds; %d objetos expirados"
|
||||
|
||||
msgid "Path required in X-Container-Sync-To"
|
||||
msgstr "Caminho necessário em X-Container-Sync-To"
|
||||
|
||||
|
@ -991,11 +943,6 @@ msgstr "Tentando escrever para %s"
|
|||
msgid "UNCAUGHT EXCEPTION"
|
||||
msgstr "EXCEÇÃO NÃO CAPTURADA"
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to load internal client from config: %r (%s)"
|
||||
msgstr ""
|
||||
"Não é possível carregar cliente interno a partir da configuração: %r (%s)"
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to locate %s in libc. Leaving as a no-op."
|
||||
msgstr "Não é possível localizar %s em libc. Saindo como um não operacional."
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: swift 2.7.1.dev50\n"
|
||||
"Project-Id-Version: swift 2.7.1.dev169\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
|
||||
"POT-Creation-Date: 2016-04-17 21:20+0000\n"
|
||||
"POT-Creation-Date: 2016-06-02 04:58+0000\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
@ -265,14 +265,6 @@ msgstr ""
|
|||
"%(elapsed).02fs, успешно: %(success)s, сбоев: %(fail)s, без изменений: "
|
||||
"%(no_change)s"
|
||||
|
||||
#, python-format
|
||||
msgid "Could not bind to %s:%s after trying for %s seconds"
|
||||
msgstr "Не удалось подключиться к порту %s:%s по истечении %s секунд"
|
||||
|
||||
#, python-format
|
||||
msgid "Could not load %r: %s"
|
||||
msgstr "Не удалось загрузить %r: %s"
|
||||
|
||||
#, python-format
|
||||
msgid "Data download error: %s"
|
||||
msgstr "Ошибка загрузки данных: %s"
|
||||
|
@ -281,10 +273,6 @@ msgstr "Ошибка загрузки данных: %s"
|
|||
msgid "Devices pass completed: %.02fs"
|
||||
msgstr "Проход устройств выполнен: %.02fs"
|
||||
|
||||
#, python-format
|
||||
msgid "Directory %r does not map to a valid policy (%s)"
|
||||
msgstr "Каталог %r не связан со стратегией policy (%s)"
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR %(db_file)s: %(validate_sync_to_err)s"
|
||||
msgstr "Ошибка %(db_file)s: %(validate_sync_to_err)s"
|
||||
|
@ -315,14 +303,6 @@ msgstr ""
|
|||
"Ошибка: обновление учетной записи не выполнено для %(ip)s:%(port)s/"
|
||||
"%(device)s (операция будет повторена позднее): Ответ: %(status)s %(reason)s"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"ERROR Account update failed: different numbers of hosts and devices in "
|
||||
"request: \"%s\" vs \"%s\""
|
||||
msgstr ""
|
||||
"Ошибка: обновление учетной записи не выполнено, в запросе указано разное "
|
||||
"число хостов и устройств: \"%s\" и \"%s\""
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR Bad response %(status)s from %(host)s"
|
||||
msgstr "Ошибка: Неправильный запрос %(status)s из %(host)s"
|
||||
|
@ -340,14 +320,6 @@ msgstr ""
|
|||
"обновлений будет выполнено позднее): %(status)d ответ от %(ip)s:%(port)s/"
|
||||
"%(dev)s"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"ERROR Container update failed: different numbers of hosts and devices in "
|
||||
"request: \"%s\" vs \"%s\""
|
||||
msgstr ""
|
||||
"Ошибка: обновление контейнера не выполнено, в запросе указано разное число "
|
||||
"хостов и устройств: \"%s\" и \"%s\""
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR Could not get account info %s"
|
||||
msgstr "Ошибка: не удалось получить сведения об учетной записи %s"
|
||||
|
@ -506,10 +478,6 @@ msgstr "Ошибка кодирования в UTF-8: %s"
|
|||
msgid "Error hashing suffix"
|
||||
msgstr "Ошибка хэширования суффикса"
|
||||
|
||||
#, python-format
|
||||
msgid "Error in %r with mtime_check_interval: %s"
|
||||
msgstr "Ошибка в %r с mtime_check_interval: %s"
|
||||
|
||||
#, python-format
|
||||
msgid "Error limiting server %s"
|
||||
msgstr "Ошибка ограничения сервера %s"
|
||||
|
@ -662,10 +630,6 @@ msgstr "Преобразовано %(given_domain)s в %(found_domain)s"
|
|||
msgid "No %s running"
|
||||
msgstr "%s не выполняется"
|
||||
|
||||
#, python-format
|
||||
msgid "No cluster endpoint for %r %r"
|
||||
msgstr "Отсутствует конечная точка кластера для %r %r"
|
||||
|
||||
#, python-format
|
||||
msgid "No permission to signal PID %d"
|
||||
msgstr "Нет прав доступа для отправки сигнала в PID %d"
|
||||
|
@ -794,18 +758,6 @@ msgid "Partition times: max %(max).4fs, min %(min).4fs, med %(med).4fs"
|
|||
msgstr ""
|
||||
"Время раздела: максимум: %(max).4fs, минимум: %(min).4fs, среднее: %(med).4fs"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass beginning; %s possible containers; %s possible objects"
|
||||
msgstr "Проход запущен; возможных контейнеров: %s; возможных объектов: %s"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass completed in %ds; %d objects expired"
|
||||
msgstr "Проход выполнен за %ds; устарело объектов: %d"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass so far %ds; %d objects expired"
|
||||
msgstr "Проход выполняется до настоящего времени %ds; устарело объектов: %d"
|
||||
|
||||
msgid "Path required in X-Container-Sync-To"
|
||||
msgstr "Требуется путь в X-Container-Sync-To"
|
||||
|
||||
|
@ -1002,10 +954,6 @@ msgstr "Попытка записи в %s"
|
|||
msgid "UNCAUGHT EXCEPTION"
|
||||
msgstr "Необрабатываемая исключительная ситуация"
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to load internal client from config: %r (%s)"
|
||||
msgstr "Не удалось загрузить клиент из конфигурации: %r (%s)"
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to locate %s in libc. Leaving as a no-op."
|
||||
msgstr "Не удалось найти %s в libc. Оставлено как no-op."
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -7,9 +7,9 @@
|
|||
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: swift 2.7.1.dev50\n"
|
||||
"Project-Id-Version: swift 2.7.1.dev169\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
|
||||
"POT-Creation-Date: 2016-04-17 21:20+0000\n"
|
||||
"POT-Creation-Date: 2016-06-02 04:58+0000\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
@ -259,14 +259,6 @@ msgstr ""
|
|||
"%(path)s in kap güncelleme süpürmesi tamamlandı: %(elapsed).02fs, "
|
||||
"%(success)s başarılı, %(fail)s başarısız, %(no_change)s değişiklik yok"
|
||||
|
||||
#, python-format
|
||||
msgid "Could not bind to %s:%s after trying for %s seconds"
|
||||
msgstr "%s:%s'e bağlanılamadı, %s saniye beklendi"
|
||||
|
||||
#, python-format
|
||||
msgid "Could not load %r: %s"
|
||||
msgstr "%r yüklenemedi: %s"
|
||||
|
||||
#, python-format
|
||||
msgid "Data download error: %s"
|
||||
msgstr "Veri indirme hatası: %s"
|
||||
|
@ -275,10 +267,6 @@ msgstr "Veri indirme hatası: %s"
|
|||
msgid "Devices pass completed: %.02fs"
|
||||
msgstr "Aygıtlar geçişi tamamlandı: %.02fs"
|
||||
|
||||
#, python-format
|
||||
msgid "Directory %r does not map to a valid policy (%s)"
|
||||
msgstr "Dizin %r geçerli bir ilkeye eşleştirilmemiş (%s)"
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR %(db_file)s: %(validate_sync_to_err)s"
|
||||
msgstr "HATA %(db_file)s: %(validate_sync_to_err)s"
|
||||
|
@ -307,14 +295,6 @@ msgstr ""
|
|||
"HATA %(ip)s:%(port)s/%(device)s ile hesap güncelleme başarısız (sonra tekrar "
|
||||
"denenecek): Yanıt %(status)s %(reason)s"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"ERROR Account update failed: different numbers of hosts and devices in "
|
||||
"request: \"%s\" vs \"%s\""
|
||||
msgstr ""
|
||||
"HATA Hesap güncelleme başarısız: istekte farklı sayıda istemci ve aygıt "
|
||||
"var: \"%s\" \"%s\""
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR Bad response %(status)s from %(host)s"
|
||||
msgstr "HATA %(host)s dan kötü yanıt %(status)s"
|
||||
|
@ -331,14 +311,6 @@ msgstr ""
|
|||
"HATA Kap güncelleme başarısız (daha sonraki async güncellemesi için "
|
||||
"kaydediliyor): %(ip)s:%(port)s/%(dev)s den %(status)d yanıtı"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"ERROR Container update failed: different numbers of hosts and devices in "
|
||||
"request: \"%s\" vs \"%s\""
|
||||
msgstr ""
|
||||
"HATA Kap güncelleme başarısız: istekte farklı sayıda istemci ve aygıt var: "
|
||||
"\"%s\" e karşı \"%s\""
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR Could not get account info %s"
|
||||
msgstr "HATA hesap bilgisi %s alınamadı"
|
||||
|
@ -488,10 +460,6 @@ msgstr "UTF-8 ile kodlama hatası: %s"
|
|||
msgid "Error hashing suffix"
|
||||
msgstr "Sonek özetini çıkarmada hata"
|
||||
|
||||
#, python-format
|
||||
msgid "Error in %r with mtime_check_interval: %s"
|
||||
msgstr "mtime_check_interval ile %r de hata: %s"
|
||||
|
||||
#, python-format
|
||||
msgid "Error limiting server %s"
|
||||
msgstr "%s sunucusu sınırlandırılırken hata"
|
||||
|
@ -633,10 +601,6 @@ msgstr "%(given_domain)s %(found_domain)s eşleştirildi"
|
|||
msgid "No %s running"
|
||||
msgstr "Çalışan %s yok"
|
||||
|
||||
#, python-format
|
||||
msgid "No cluster endpoint for %r %r"
|
||||
msgstr "%r %r için küme uç noktası yok"
|
||||
|
||||
#, python-format
|
||||
msgid "No permission to signal PID %d"
|
||||
msgstr "%d PID'ine sinyalleme izni yok"
|
||||
|
@ -750,18 +714,6 @@ msgid "Partition times: max %(max).4fs, min %(min).4fs, med %(med).4fs"
|
|||
msgstr ""
|
||||
"Bölüm zamanları: azami %(max).4fs, asgari %(min).4fs, ortalama %(med).4fs"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass beginning; %s possible containers; %s possible objects"
|
||||
msgstr "Geçiş başlıyor; %s olası kap; %s olası nesne"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass completed in %ds; %d objects expired"
|
||||
msgstr "Geçiş %ds de tamamlandı; %d nesnenin süresi doldu"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass so far %ds; %d objects expired"
|
||||
msgstr "Şimdiye kadarki geçiş %ds; %d nesnenin süresi doldu"
|
||||
|
||||
msgid "Path required in X-Container-Sync-To"
|
||||
msgstr "X-Container-Sync-To'de yol gerekli"
|
||||
|
||||
|
@ -947,10 +899,6 @@ msgstr "%s'e yazmaya çalışılıyor"
|
|||
msgid "UNCAUGHT EXCEPTION"
|
||||
msgstr "YAKALANMAYAN İSTİSNA"
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to load internal client from config: %r (%s)"
|
||||
msgstr "Yapılandırmadan dahili istemci yüklenemedi: %r (%s)"
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to locate %s in libc. Leaving as a no-op."
|
||||
msgstr "%s libc'de bulunamadı. No-op olarak çıkılıyor."
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: swift 2.7.1.dev50\n"
|
||||
"Project-Id-Version: swift 2.7.1.dev169\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
|
||||
"POT-Creation-Date: 2016-04-17 21:20+0000\n"
|
||||
"POT-Creation-Date: 2016-06-02 04:58+0000\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
@ -257,14 +257,6 @@ msgstr ""
|
|||
"通过路径%(path)s容器更新扫除完成:%(elapsed).02fs, %(success)s 成功, "
|
||||
"%(fail)s 失败, %(no_change)s 无更改"
|
||||
|
||||
#, python-format
|
||||
msgid "Could not bind to %s:%s after trying for %s seconds"
|
||||
msgstr "尝试过%s秒后无法捆绑%s:%s"
|
||||
|
||||
#, python-format
|
||||
msgid "Could not load %r: %s"
|
||||
msgstr "无法下载%r: %s"
|
||||
|
||||
#, python-format
|
||||
msgid "Data download error: %s"
|
||||
msgstr "数据下载错误:%s"
|
||||
|
@ -273,10 +265,6 @@ msgstr "数据下载错误:%s"
|
|||
msgid "Devices pass completed: %.02fs"
|
||||
msgstr "设备通过完成: %.02fs"
|
||||
|
||||
#, python-format
|
||||
msgid "Directory %r does not map to a valid policy (%s)"
|
||||
msgstr "目录 %r 未映射至有效策略 (%s)"
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR %(db_file)s: %(validate_sync_to_err)s"
|
||||
msgstr "错误 %(db_file)s: %(validate_sync_to_err)s"
|
||||
|
@ -305,12 +293,6 @@ msgstr ""
|
|||
"出现错误 账号更新失败: %(ip)s:%(port)s/%(device)s (稍后尝试): 回应 "
|
||||
"%(status)s %(reason)s"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"ERROR Account update failed: different numbers of hosts and devices in "
|
||||
"request: \"%s\" vs \"%s\""
|
||||
msgstr "出现错误 账号更新失败:本机数量与设备数量不符: \"%s\" vs \"%s\""
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR Bad response %(status)s from %(host)s"
|
||||
msgstr "失败响应错误%(status)s来自%(host)s"
|
||||
|
@ -327,12 +309,6 @@ msgstr ""
|
|||
"错误 容器更新失败(正在保存 稍后同步更新):%(status)d回应来自%(ip)s:%(port)s/"
|
||||
"%(dev)s"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"ERROR Container update failed: different numbers of hosts and devices in "
|
||||
"request: \"%s\" vs \"%s\""
|
||||
msgstr "错误 容器更新失败:主机数量和设备数量不符合请求: \"%s\" vs \"%s\""
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR Could not get account info %s"
|
||||
msgstr "错误:无法获取账号信息%s"
|
||||
|
@ -479,10 +455,6 @@ msgstr "UTF-8编码错误:%s"
|
|||
msgid "Error hashing suffix"
|
||||
msgstr "执行Hashing后缀时发生错误"
|
||||
|
||||
#, python-format
|
||||
msgid "Error in %r with mtime_check_interval: %s"
|
||||
msgstr "%r中mtime_check_interval出现错误:%s"
|
||||
|
||||
#, python-format
|
||||
msgid "Error limiting server %s"
|
||||
msgstr "服务器出现错误%s "
|
||||
|
@ -627,10 +599,6 @@ msgstr "集合%(given_domain)s到%(found_domain)s"
|
|||
msgid "No %s running"
|
||||
msgstr "无%s账号运行"
|
||||
|
||||
#, python-format
|
||||
msgid "No cluster endpoint for %r %r"
|
||||
msgstr "%r %r的集群节点不存在"
|
||||
|
||||
#, python-format
|
||||
msgid "No permission to signal PID %d"
|
||||
msgstr "无权限发送信号PID%d"
|
||||
|
@ -753,18 +721,6 @@ msgstr "在X-Container-Sync-To中,变量,查询和碎片不被允许"
|
|||
msgid "Partition times: max %(max).4fs, min %(min).4fs, med %(med).4fs"
|
||||
msgstr "分区时间: max %(max).4fs, min %(min).4fs, med %(med).4fs"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass beginning; %s possible containers; %s possible objects"
|
||||
msgstr "开始通过;%s可能容器;%s可能对象"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass completed in %ds; %d objects expired"
|
||||
msgstr "%ds通过完成; %d对象过期"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass so far %ds; %d objects expired"
|
||||
msgstr "%ds目前通过;%d对象过期"
|
||||
|
||||
msgid "Path required in X-Container-Sync-To"
|
||||
msgstr "在X-Container-Sync-To中路径是必须的"
|
||||
|
||||
|
@ -945,10 +901,6 @@ msgstr "尝试执行书写%s"
|
|||
msgid "UNCAUGHT EXCEPTION"
|
||||
msgstr "未捕获的异常"
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to load internal client from config: %r (%s)"
|
||||
msgstr "无法从配置装入内部客户机:%r (%s)"
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to locate %s in libc. Leaving as a no-op."
|
||||
msgstr "无法查询到%s 保留为no-op"
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
# Andreas Jaeger <jaegerandi@gmail.com>, 2016. #zanata
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: swift 2.7.1.dev50\n"
|
||||
"Project-Id-Version: swift 2.7.1.dev169\n"
|
||||
"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n"
|
||||
"POT-Creation-Date: 2016-04-17 21:20+0000\n"
|
||||
"POT-Creation-Date: 2016-06-02 04:58+0000\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
@ -257,14 +257,6 @@ msgstr ""
|
|||
"%(path)s 的儲存器更新清理已完成:%(elapsed).02fs,%(success)s 個成"
|
||||
"功,%(fail)s 個失敗,%(no_change)s 個無變更"
|
||||
|
||||
#, python-format
|
||||
msgid "Could not bind to %s:%s after trying for %s seconds"
|
||||
msgstr "嘗試 %s 秒後仍無法連結至 %s:%s"
|
||||
|
||||
#, python-format
|
||||
msgid "Could not load %r: %s"
|
||||
msgstr "無法載入 %r:%s"
|
||||
|
||||
#, python-format
|
||||
msgid "Data download error: %s"
|
||||
msgstr "資料下載錯誤:%s"
|
||||
|
@ -273,10 +265,6 @@ msgstr "資料下載錯誤:%s"
|
|||
msgid "Devices pass completed: %.02fs"
|
||||
msgstr "裝置通過已完成:%.02fs"
|
||||
|
||||
#, python-format
|
||||
msgid "Directory %r does not map to a valid policy (%s)"
|
||||
msgstr "目錄 %r 未對映至有效的原則 (%s)"
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR %(db_file)s: %(validate_sync_to_err)s"
|
||||
msgstr "錯誤:%(db_file)s:%(validate_sync_to_err)s"
|
||||
|
@ -305,12 +293,6 @@ msgstr ""
|
|||
"錯誤:%(ip)s:%(port)s/%(device)s 的帳戶更新失敗(將稍後重試):回應 "
|
||||
"%(status)s %(reason)s"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"ERROR Account update failed: different numbers of hosts and devices in "
|
||||
"request: \"%s\" vs \"%s\""
|
||||
msgstr "錯誤:帳戶更新失敗:要求中的主機與裝置數目不同:\"%s\" 對 \"%s\""
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR Bad response %(status)s from %(host)s"
|
||||
msgstr "錯誤:來自 %(host)s 的回應 %(status)s 不當"
|
||||
|
@ -327,12 +309,6 @@ msgstr ""
|
|||
"錯誤:儲存器更新失敗(儲存以稍後進行非同步更新):%(status)d回應(來自 "
|
||||
"%(ip)s:%(port)s/%(dev)s)"
|
||||
|
||||
#, python-format
|
||||
msgid ""
|
||||
"ERROR Container update failed: different numbers of hosts and devices in "
|
||||
"request: \"%s\" vs \"%s\""
|
||||
msgstr "錯誤:儲存器更新失敗:要求中的主機與裝置數目不同:\"%s\" 對 \"%s\""
|
||||
|
||||
#, python-format
|
||||
msgid "ERROR Could not get account info %s"
|
||||
msgstr "錯誤:無法取得帳戶資訊 %s"
|
||||
|
@ -480,10 +456,6 @@ msgstr "編碼為 UTF-8 時發生錯誤:%s"
|
|||
msgid "Error hashing suffix"
|
||||
msgstr "混合字尾時發生錯誤"
|
||||
|
||||
#, python-format
|
||||
msgid "Error in %r with mtime_check_interval: %s"
|
||||
msgstr "在 mtime_check_interval 中,%r 發生錯誤:%s"
|
||||
|
||||
#, python-format
|
||||
msgid "Error limiting server %s"
|
||||
msgstr "限制伺服器 %s 時發生錯誤"
|
||||
|
@ -628,10 +600,6 @@ msgstr "已將 %(given_domain)s 對映至 %(found_domain)s"
|
|||
msgid "No %s running"
|
||||
msgstr "沒有 %s 在執行中"
|
||||
|
||||
#, python-format
|
||||
msgid "No cluster endpoint for %r %r"
|
||||
msgstr "沒有 %r %r 的叢集端點"
|
||||
|
||||
#, python-format
|
||||
msgid "No permission to signal PID %d"
|
||||
msgstr "沒有信號 PID %d 的許可權"
|
||||
|
@ -755,18 +723,6 @@ msgstr "X-Container-Sync-To 中不容許參數、查詢及片段"
|
|||
msgid "Partition times: max %(max).4fs, min %(min).4fs, med %(med).4fs"
|
||||
msgstr "分割區時間:最大 %(max).4fs,最小 %(min).4fs,中間 %(med).4fs"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass beginning; %s possible containers; %s possible objects"
|
||||
msgstr "通過正在開始;%s 個可能儲存器;%s 個可能物件"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass completed in %ds; %d objects expired"
|
||||
msgstr "已完成通過 %ds 個;%d 個物件已過期"
|
||||
|
||||
#, python-format
|
||||
msgid "Pass so far %ds; %d objects expired"
|
||||
msgstr "目前為止通過 %ds 個;%d 個物件過期"
|
||||
|
||||
msgid "Path required in X-Container-Sync-To"
|
||||
msgstr "X-Container-Sync-To 中需要路徑"
|
||||
|
||||
|
@ -950,10 +906,6 @@ msgstr "正在嘗試寫入至 %s"
|
|||
msgid "UNCAUGHT EXCEPTION"
|
||||
msgstr "未捕捉的異常狀況"
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to load internal client from config: %r (%s)"
|
||||
msgstr "無法從配置載入內部用戶端:%r (%s)"
|
||||
|
||||
#, python-format
|
||||
msgid "Unable to locate %s in libc. Leaving as a no-op."
|
||||
msgstr "在 libc 中找不到 %s。保留為 no-op。"
|
||||
|
|
|
@ -559,8 +559,8 @@ class ObjectController(BaseStorageServer):
|
|||
except (DiskFileXattrNotSupported, DiskFileNoSpace):
|
||||
return HTTPInsufficientStorage(drive=device, request=request)
|
||||
|
||||
if (content_type_headers['Content-Type-Timestamp'] !=
|
||||
disk_file.data_timestamp):
|
||||
if (content_type_headers['Content-Type-Timestamp']
|
||||
!= disk_file.data_timestamp):
|
||||
# Current content-type is not from the datafile, but the datafile
|
||||
# content-type may have a swift_bytes param that was appended by
|
||||
# SLO and we must continue to send that with the container update.
|
||||
|
@ -583,15 +583,19 @@ class ObjectController(BaseStorageServer):
|
|||
'x-meta-timestamp': metadata['X-Timestamp'],
|
||||
'x-etag': orig_metadata['ETag']})
|
||||
|
||||
# Special cases for backwards compatibility.
|
||||
# For EC policy, send X-Object-Sysmeta-Ec-Etag which is same as the
|
||||
# X-Backend-Container-Update-Override-Etag value sent with the original
|
||||
# PUT. Similarly send X-Object-Sysmeta-Ec-Content-Length which is the
|
||||
# same as the X-Backend-Container-Update-Override-Size value. We have
|
||||
# to send Etag and size with a POST container update because the
|
||||
# original PUT container update may have failed or be in async_pending.
|
||||
if 'X-Object-Sysmeta-Ec-Etag' in orig_metadata:
|
||||
# Special case for backwards compatibility.
|
||||
# For EC policy, send X-Object-Sysmeta-Ec-Etag which is same as the
|
||||
# X-Backend-Container-Update-Override-Etag value sent with the
|
||||
# original PUT. We have to send Etag (and size etc) with a POST
|
||||
# container update because the original PUT container update may
|
||||
# have failed or be in async_pending.
|
||||
update_headers['X-Etag'] = orig_metadata[
|
||||
'X-Object-Sysmeta-Ec-Etag']
|
||||
if 'X-Object-Sysmeta-Ec-Content-Length' in orig_metadata:
|
||||
update_headers['X-Size'] = orig_metadata[
|
||||
'X-Object-Sysmeta-Ec-Content-Length']
|
||||
|
||||
self._check_container_override(update_headers, orig_metadata)
|
||||
|
||||
|
|
|
@ -58,18 +58,16 @@ def get_server_number(ipport, ipport2server):
|
|||
return server, number
|
||||
|
||||
|
||||
def start_server(ipport, ipport2server, pids, check=True):
|
||||
def start_server(ipport, ipport2server):
|
||||
server, number = get_server_number(ipport, ipport2server)
|
||||
err = Manager([server]).start(number=number, wait=False)
|
||||
if err:
|
||||
raise Exception('unable to start %s' % (
|
||||
server if not number else '%s%s' % (server, number)))
|
||||
if check:
|
||||
return check_server(ipport, ipport2server, pids)
|
||||
return None
|
||||
return check_server(ipport, ipport2server)
|
||||
|
||||
|
||||
def check_server(ipport, ipport2server, pids, timeout=CHECK_SERVER_TIMEOUT):
|
||||
def check_server(ipport, ipport2server):
|
||||
server = ipport2server[ipport]
|
||||
if server[:-1] in ('account', 'container', 'object'):
|
||||
if int(server[-1]) > 4:
|
||||
|
@ -79,7 +77,7 @@ def check_server(ipport, ipport2server, pids, timeout=CHECK_SERVER_TIMEOUT):
|
|||
path += '/3'
|
||||
elif server[:-1] == 'object':
|
||||
path += '/3/4'
|
||||
try_until = time() + timeout
|
||||
try_until = time() + CHECK_SERVER_TIMEOUT
|
||||
while True:
|
||||
try:
|
||||
conn = HTTPConnection(*ipport)
|
||||
|
@ -95,11 +93,11 @@ def check_server(ipport, ipport2server, pids, timeout=CHECK_SERVER_TIMEOUT):
|
|||
if time() > try_until:
|
||||
print(err)
|
||||
print('Giving up on %s:%s after %s seconds.' % (
|
||||
server, ipport, timeout))
|
||||
server, ipport, CHECK_SERVER_TIMEOUT))
|
||||
raise err
|
||||
sleep(0.1)
|
||||
else:
|
||||
try_until = time() + timeout
|
||||
try_until = time() + CHECK_SERVER_TIMEOUT
|
||||
while True:
|
||||
try:
|
||||
url, token = get_auth('http://%s:%d/auth/v1.0' % ipport,
|
||||
|
@ -116,7 +114,7 @@ def check_server(ipport, ipport2server, pids, timeout=CHECK_SERVER_TIMEOUT):
|
|||
return None
|
||||
|
||||
|
||||
def kill_server(ipport, ipport2server, pids):
|
||||
def kill_server(ipport, ipport2server):
|
||||
server, number = get_server_number(ipport, ipport2server)
|
||||
err = Manager([server]).kill(number=number)
|
||||
if err:
|
||||
|
@ -136,7 +134,7 @@ def kill_server(ipport, ipport2server, pids):
|
|||
sleep(0.1)
|
||||
|
||||
|
||||
def kill_nonprimary_server(primary_nodes, ipport2server, pids):
|
||||
def kill_nonprimary_server(primary_nodes, ipport2server):
|
||||
primary_ipports = [(n['ip'], n['port']) for n in primary_nodes]
|
||||
for ipport, server in ipport2server.items():
|
||||
if ipport in primary_ipports:
|
||||
|
@ -146,7 +144,7 @@ def kill_nonprimary_server(primary_nodes, ipport2server, pids):
|
|||
raise Exception('Cannot figure out server type for %r' % primary_nodes)
|
||||
for ipport, server in list(ipport2server.items()):
|
||||
if server[:-1] == server_type and ipport not in primary_ipports:
|
||||
kill_server(ipport, ipport2server, pids)
|
||||
kill_server(ipport, ipport2server)
|
||||
return ipport
|
||||
|
||||
|
||||
|
@ -322,7 +320,6 @@ class ProbeTest(unittest.TestCase):
|
|||
|
||||
def setUp(self):
|
||||
resetswift()
|
||||
self.pids = {}
|
||||
try:
|
||||
self.ipport2server = {}
|
||||
self.configs = defaultdict(dict)
|
||||
|
@ -354,11 +351,11 @@ class ProbeTest(unittest.TestCase):
|
|||
|
||||
Manager(['main']).start(wait=False)
|
||||
for ipport in self.ipport2server:
|
||||
check_server(ipport, self.ipport2server, self.pids)
|
||||
check_server(ipport, self.ipport2server)
|
||||
proxy_ipport = ('127.0.0.1', 8080)
|
||||
self.ipport2server[proxy_ipport] = 'proxy'
|
||||
self.url, self.token, self.account = check_server(
|
||||
proxy_ipport, self.ipport2server, self.pids)
|
||||
proxy_ipport, self.ipport2server)
|
||||
self.replicators = Manager(
|
||||
['account-replicator', 'container-replicator',
|
||||
'object-replicator'])
|
||||
|
@ -443,10 +440,13 @@ class ProbeTest(unittest.TestCase):
|
|||
swift_dir = /etc/swift
|
||||
|
||||
[pipeline:main]
|
||||
pipeline = catch_errors cache proxy-server
|
||||
pipeline = catch_errors cache copy proxy-server
|
||||
|
||||
[app:proxy-server]
|
||||
use = egg:swift#proxy
|
||||
|
||||
[filter:copy]
|
||||
use = egg:swift#copy
|
||||
object_post_as_copy = %s
|
||||
|
||||
[filter:cache]
|
||||
|
|
|
@ -97,9 +97,8 @@ class TestAccountFailures(ReplProbeTest):
|
|||
self.assertTrue(found2)
|
||||
|
||||
apart, anodes = self.account_ring.get_nodes(self.account)
|
||||
kill_nonprimary_server(anodes, self.ipport2server, self.pids)
|
||||
kill_server((anodes[0]['ip'], anodes[0]['port']),
|
||||
self.ipport2server, self.pids)
|
||||
kill_nonprimary_server(anodes, self.ipport2server)
|
||||
kill_server((anodes[0]['ip'], anodes[0]['port']), self.ipport2server)
|
||||
# Kill account servers excepting two of the primaries
|
||||
|
||||
# Delete container1
|
||||
|
@ -147,8 +146,7 @@ class TestAccountFailures(ReplProbeTest):
|
|||
self.assertTrue(found2)
|
||||
|
||||
# Restart other primary account server
|
||||
start_server((anodes[0]['ip'], anodes[0]['port']),
|
||||
self.ipport2server, self.pids)
|
||||
start_server((anodes[0]['ip'], anodes[0]['port']), self.ipport2server)
|
||||
|
||||
# Assert that server doesn't know about container1's deletion or the
|
||||
# new container2/object2 yet
|
||||
|
|
|
@ -49,16 +49,14 @@ class TestContainerFailures(ReplProbeTest):
|
|||
client.put_container(self.url, self.token, container1)
|
||||
|
||||
# Kill container1 servers excepting two of the primaries
|
||||
kill_nonprimary_server(cnodes, self.ipport2server, self.pids)
|
||||
kill_server((cnodes[0]['ip'], cnodes[0]['port']),
|
||||
self.ipport2server, self.pids)
|
||||
kill_nonprimary_server(cnodes, self.ipport2server)
|
||||
kill_server((cnodes[0]['ip'], cnodes[0]['port']), self.ipport2server)
|
||||
|
||||
# Delete container1
|
||||
client.delete_container(self.url, self.token, container1)
|
||||
|
||||
# Restart other container1 primary server
|
||||
start_server((cnodes[0]['ip'], cnodes[0]['port']),
|
||||
self.ipport2server, self.pids)
|
||||
start_server((cnodes[0]['ip'], cnodes[0]['port']), self.ipport2server)
|
||||
|
||||
# Create container1/object1 (allowed because at least server thinks the
|
||||
# container exists)
|
||||
|
@ -89,12 +87,11 @@ class TestContainerFailures(ReplProbeTest):
|
|||
client.put_container(self.url, self.token, container1)
|
||||
|
||||
# Kill container1 servers excepting one of the primaries
|
||||
cnp_ipport = kill_nonprimary_server(cnodes, self.ipport2server,
|
||||
self.pids)
|
||||
cnp_ipport = kill_nonprimary_server(cnodes, self.ipport2server)
|
||||
kill_server((cnodes[0]['ip'], cnodes[0]['port']),
|
||||
self.ipport2server, self.pids)
|
||||
self.ipport2server)
|
||||
kill_server((cnodes[1]['ip'], cnodes[1]['port']),
|
||||
self.ipport2server, self.pids)
|
||||
self.ipport2server)
|
||||
|
||||
# Delete container1 directly to the one primary still up
|
||||
direct_client.direct_delete_container(cnodes[2], cpart, self.account,
|
||||
|
@ -102,10 +99,10 @@ class TestContainerFailures(ReplProbeTest):
|
|||
|
||||
# Restart other container1 servers
|
||||
start_server((cnodes[0]['ip'], cnodes[0]['port']),
|
||||
self.ipport2server, self.pids)
|
||||
self.ipport2server)
|
||||
start_server((cnodes[1]['ip'], cnodes[1]['port']),
|
||||
self.ipport2server, self.pids)
|
||||
start_server(cnp_ipport, self.ipport2server, self.pids)
|
||||
self.ipport2server)
|
||||
start_server(cnp_ipport, self.ipport2server)
|
||||
|
||||
# Get to a final state
|
||||
self.get_to_final_state()
|
||||
|
|
|
@ -58,8 +58,7 @@ class TestEmptyDevice(ReplProbeTest):
|
|||
onode = onodes[0]
|
||||
|
||||
# Kill one container/obj primary server
|
||||
kill_server((onode['ip'], onode['port']),
|
||||
self.ipport2server, self.pids)
|
||||
kill_server((onode['ip'], onode['port']), self.ipport2server)
|
||||
|
||||
# Delete the default data directory for objects on the primary server
|
||||
obj_dir = '%s/%s' % (self._get_objects_dir(onode),
|
||||
|
@ -84,8 +83,7 @@ class TestEmptyDevice(ReplProbeTest):
|
|||
# Kill other two container/obj primary servers
|
||||
# to ensure GET handoff works
|
||||
for node in onodes[1:]:
|
||||
kill_server((node['ip'], node['port']),
|
||||
self.ipport2server, self.pids)
|
||||
kill_server((node['ip'], node['port']), self.ipport2server)
|
||||
|
||||
# Indirectly through proxy assert we can get container/obj
|
||||
odata = client.get_object(self.url, self.token, container, obj)[-1]
|
||||
|
@ -94,8 +92,7 @@ class TestEmptyDevice(ReplProbeTest):
|
|||
'returned: %s' % repr(odata))
|
||||
# Restart those other two container/obj primary servers
|
||||
for node in onodes[1:]:
|
||||
start_server((node['ip'], node['port']),
|
||||
self.ipport2server, self.pids)
|
||||
start_server((node['ip'], node['port']), self.ipport2server)
|
||||
self.assertFalse(os.path.exists(obj_dir))
|
||||
# We've indirectly verified the handoff node has the object, but
|
||||
# let's directly verify it.
|
||||
|
@ -132,8 +129,7 @@ class TestEmptyDevice(ReplProbeTest):
|
|||
missing)
|
||||
|
||||
# Bring the first container/obj primary server back up
|
||||
start_server((onode['ip'], onode['port']),
|
||||
self.ipport2server, self.pids)
|
||||
start_server((onode['ip'], onode['port']), self.ipport2server)
|
||||
|
||||
# Assert that it doesn't have container/obj yet
|
||||
self.assertFalse(os.path.exists(obj_dir))
|
||||
|
|
|
@ -14,21 +14,16 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import os
|
||||
import shutil
|
||||
|
||||
from io import StringIO
|
||||
from tempfile import mkdtemp
|
||||
from textwrap import dedent
|
||||
from unittest import main
|
||||
from uuid import uuid4
|
||||
|
||||
from swiftclient import client
|
||||
|
||||
from swift.common import direct_client, internal_client
|
||||
from swift.common import direct_client
|
||||
from swift.common.manager import Manager
|
||||
from test.probe.common import kill_nonprimary_server, \
|
||||
kill_server, ReplProbeTest, start_server
|
||||
kill_server, ReplProbeTest, start_server, ECProbeTest
|
||||
|
||||
|
||||
class TestObjectAsyncUpdate(ReplProbeTest):
|
||||
|
@ -41,17 +36,15 @@ class TestObjectAsyncUpdate(ReplProbeTest):
|
|||
# Kill container servers excepting two of the primaries
|
||||
cpart, cnodes = self.container_ring.get_nodes(self.account, container)
|
||||
cnode = cnodes[0]
|
||||
kill_nonprimary_server(cnodes, self.ipport2server, self.pids)
|
||||
kill_server((cnode['ip'], cnode['port']),
|
||||
self.ipport2server, self.pids)
|
||||
kill_nonprimary_server(cnodes, self.ipport2server)
|
||||
kill_server((cnode['ip'], cnode['port']), self.ipport2server)
|
||||
|
||||
# Create container/obj
|
||||
obj = 'object-%s' % uuid4()
|
||||
client.put_object(self.url, self.token, container, obj, '')
|
||||
|
||||
# Restart other primary server
|
||||
start_server((cnode['ip'], cnode['port']),
|
||||
self.ipport2server, self.pids)
|
||||
start_server((cnode['ip'], cnode['port']), self.ipport2server)
|
||||
|
||||
# Assert it does not know about container/obj
|
||||
self.assertFalse(direct_client.direct_get_container(
|
||||
|
@ -73,39 +66,9 @@ class TestUpdateOverrides(ReplProbeTest):
|
|||
Verify that the update override headers take effect and override
|
||||
values propagate to the container server.
|
||||
"""
|
||||
def setUp(self):
|
||||
"""
|
||||
Reset all environment and start all servers.
|
||||
"""
|
||||
super(TestUpdateOverrides, self).setUp()
|
||||
self.tempdir = mkdtemp()
|
||||
conf_path = os.path.join(self.tempdir, 'internal_client.conf')
|
||||
conf_body = """
|
||||
[DEFAULT]
|
||||
swift_dir = /etc/swift
|
||||
|
||||
[pipeline:main]
|
||||
pipeline = catch_errors cache proxy-server
|
||||
|
||||
[app:proxy-server]
|
||||
use = egg:swift#proxy
|
||||
|
||||
[filter:cache]
|
||||
use = egg:swift#memcache
|
||||
|
||||
[filter:catch_errors]
|
||||
use = egg:swift#catch_errors
|
||||
"""
|
||||
with open(conf_path, 'w') as f:
|
||||
f.write(dedent(conf_body))
|
||||
self.int_client = internal_client.InternalClient(conf_path, 'test', 1)
|
||||
|
||||
def tearDown(self):
|
||||
super(TestUpdateOverrides, self).tearDown()
|
||||
shutil.rmtree(self.tempdir)
|
||||
|
||||
def _test_update_override_headers(self, override_headers):
|
||||
# verify that update override headers are sent in container updates
|
||||
int_client = self.make_internal_client()
|
||||
container_name = 'c-%s' % uuid4()
|
||||
obj_name = 'o-%s' % uuid4()
|
||||
client.put_container(self.url, self.token, container_name,
|
||||
|
@ -113,24 +76,26 @@ class TestUpdateOverrides(ReplProbeTest):
|
|||
self.policy.name})
|
||||
|
||||
override_headers['Content-Type'] = 'text/plain'
|
||||
self.int_client.upload_object(StringIO(u'stuff'), self.account,
|
||||
container_name, obj_name,
|
||||
override_headers)
|
||||
int_client.upload_object(StringIO(u'stuff'), self.account,
|
||||
container_name, obj_name,
|
||||
override_headers)
|
||||
|
||||
# Run the object-updaters to be sure updates are done
|
||||
Manager(['object-updater']).once()
|
||||
|
||||
meta = self.int_client.get_object_metadata(
|
||||
meta = int_client.get_object_metadata(
|
||||
self.account, container_name, obj_name)
|
||||
|
||||
self.assertEqual('text/plain', meta['content-type'])
|
||||
self.assertEqual('c13d88cb4cb02003daedb8a84e5d272a', meta['etag'])
|
||||
self.assertEqual('5', meta['content-length'])
|
||||
|
||||
obj_iter = self.int_client.iter_objects(self.account, container_name)
|
||||
obj_iter = int_client.iter_objects(self.account, container_name)
|
||||
for obj in obj_iter:
|
||||
if obj['name'] == obj_name:
|
||||
self.assertEqual('override-etag', obj['hash'])
|
||||
self.assertEqual('override-type', obj['content_type'])
|
||||
self.assertEqual(1999, obj['bytes'])
|
||||
break
|
||||
else:
|
||||
self.fail('Failed to find object %s in listing for %s' %
|
||||
|
@ -140,7 +105,8 @@ class TestUpdateOverrides(ReplProbeTest):
|
|||
headers = {
|
||||
'X-Object-Sysmeta-Container-Update-Override-Etag': 'override-etag',
|
||||
'X-Object-Sysmeta-Container-Update-Override-Content-Type':
|
||||
'override-type'
|
||||
'override-type',
|
||||
'X-Object-Sysmeta-Container-Update-Override-Size': '1999'
|
||||
}
|
||||
self._test_update_override_headers(headers)
|
||||
|
||||
|
@ -148,9 +114,167 @@ class TestUpdateOverrides(ReplProbeTest):
|
|||
# older proxies used these headers to override container update values
|
||||
headers = {
|
||||
'X-Backend-Container-Update-Override-Etag': 'override-etag',
|
||||
'X-Backend-Container-Update-Override-Content-Type': 'override-type'
|
||||
'X-Backend-Container-Update-Override-Content-Type':
|
||||
'override-type',
|
||||
'X-Backend-Container-Update-Override-Size': '1999'
|
||||
}
|
||||
self._test_update_override_headers(headers)
|
||||
|
||||
|
||||
class TestUpdateOverridesEC(ECProbeTest):
|
||||
# verify that the container update overrides used with EC policies make
|
||||
# it to the container servers when container updates are sync or async
|
||||
# and possibly re-ordered with respect to object PUT and POST requests.
|
||||
def test_async_update_after_PUT(self):
|
||||
cpart, cnodes = self.container_ring.get_nodes(self.account, 'c1')
|
||||
client.put_container(self.url, self.token, 'c1',
|
||||
headers={'X-Storage-Policy':
|
||||
self.policy.name})
|
||||
|
||||
# put an object while one container server is stopped so that we force
|
||||
# an async update to it
|
||||
kill_server((cnodes[0]['ip'], cnodes[0]['port']), self.ipport2server)
|
||||
content = u'stuff'
|
||||
client.put_object(self.url, self.token, 'c1', 'o1', contents=content)
|
||||
meta = client.head_object(self.url, self.token, 'c1', 'o1')
|
||||
|
||||
# re-start the container server and assert that it does not yet know
|
||||
# about the object
|
||||
start_server((cnodes[0]['ip'], cnodes[0]['port']), self.ipport2server)
|
||||
self.assertFalse(direct_client.direct_get_container(
|
||||
cnodes[0], cpart, self.account, 'c1')[1])
|
||||
|
||||
# Run the object-updaters to be sure updates are done
|
||||
Manager(['object-updater']).once()
|
||||
|
||||
# check the re-started container server got same update as others.
|
||||
# we cannot assert the actual etag value because it may be encrypted
|
||||
listing_etags = set()
|
||||
for cnode in cnodes:
|
||||
obj = direct_client.direct_get_container(
|
||||
cnode, cpart, self.account, 'c1')[1][0]
|
||||
self.assertEqual(len(content), obj['bytes'])
|
||||
listing_etags.add(obj['hash'])
|
||||
self.assertEqual(1, len(listing_etags))
|
||||
|
||||
# check that listing meta returned to client is consistent with object
|
||||
# meta returned to client
|
||||
hdrs, listing = client.get_container(self.url, self.token, 'c1')
|
||||
self.assertEqual(1, len(listing))
|
||||
self.assertEqual('o1', listing[0]['name'])
|
||||
self.assertEqual(len(content), listing[0]['bytes'])
|
||||
self.assertEqual(meta['etag'], listing[0]['hash'])
|
||||
|
||||
def test_update_during_POST_only(self):
|
||||
# verify correct update values when PUT update is missed but then a
|
||||
# POST update succeeds *before* the PUT async pending update is sent
|
||||
cpart, cnodes = self.container_ring.get_nodes(self.account, 'c1')
|
||||
client.put_container(self.url, self.token, 'c1',
|
||||
headers={'X-Storage-Policy':
|
||||
self.policy.name})
|
||||
|
||||
# put an object while one container server is stopped so that we force
|
||||
# an async update to it
|
||||
kill_server((cnodes[0]['ip'], cnodes[0]['port']), self.ipport2server)
|
||||
content = u'stuff'
|
||||
client.put_object(self.url, self.token, 'c1', 'o1', contents=content)
|
||||
meta = client.head_object(self.url, self.token, 'c1', 'o1')
|
||||
|
||||
# re-start the container server and assert that it does not yet know
|
||||
# about the object
|
||||
start_server((cnodes[0]['ip'], cnodes[0]['port']), self.ipport2server)
|
||||
self.assertFalse(direct_client.direct_get_container(
|
||||
cnodes[0], cpart, self.account, 'c1')[1])
|
||||
|
||||
# use internal client for POST so we can force fast-post mode
|
||||
int_client = self.make_internal_client(object_post_as_copy=False)
|
||||
int_client.set_object_metadata(
|
||||
self.account, 'c1', 'o1', {'X-Object-Meta-Fruit': 'Tomato'})
|
||||
self.assertEqual(
|
||||
'Tomato',
|
||||
int_client.get_object_metadata(self.account, 'c1', 'o1')
|
||||
['x-object-meta-fruit']) # sanity
|
||||
|
||||
# check the re-started container server got same update as others.
|
||||
# we cannot assert the actual etag value because it may be encrypted
|
||||
listing_etags = set()
|
||||
for cnode in cnodes:
|
||||
obj = direct_client.direct_get_container(
|
||||
cnode, cpart, self.account, 'c1')[1][0]
|
||||
self.assertEqual(len(content), obj['bytes'])
|
||||
listing_etags.add(obj['hash'])
|
||||
self.assertEqual(1, len(listing_etags))
|
||||
|
||||
# check that listing meta returned to client is consistent with object
|
||||
# meta returned to client
|
||||
hdrs, listing = client.get_container(self.url, self.token, 'c1')
|
||||
self.assertEqual(1, len(listing))
|
||||
self.assertEqual('o1', listing[0]['name'])
|
||||
self.assertEqual(len(content), listing[0]['bytes'])
|
||||
self.assertEqual(meta['etag'], listing[0]['hash'])
|
||||
|
||||
# Run the object-updaters to send the async pending from the PUT
|
||||
Manager(['object-updater']).once()
|
||||
|
||||
# check container listing metadata is still correct
|
||||
for cnode in cnodes:
|
||||
obj = direct_client.direct_get_container(
|
||||
cnode, cpart, self.account, 'c1')[1][0]
|
||||
self.assertEqual(len(content), obj['bytes'])
|
||||
listing_etags.add(obj['hash'])
|
||||
self.assertEqual(1, len(listing_etags))
|
||||
|
||||
def test_async_updates_after_PUT_and_POST(self):
|
||||
# verify correct update values when PUT update and POST updates are
|
||||
# missed but then async updates are sent
|
||||
cpart, cnodes = self.container_ring.get_nodes(self.account, 'c1')
|
||||
client.put_container(self.url, self.token, 'c1',
|
||||
headers={'X-Storage-Policy':
|
||||
self.policy.name})
|
||||
|
||||
# PUT and POST to object while one container server is stopped so that
|
||||
# we force async updates to it
|
||||
kill_server((cnodes[0]['ip'], cnodes[0]['port']), self.ipport2server)
|
||||
content = u'stuff'
|
||||
client.put_object(self.url, self.token, 'c1', 'o1', contents=content)
|
||||
meta = client.head_object(self.url, self.token, 'c1', 'o1')
|
||||
|
||||
# use internal client for POST so we can force fast-post mode
|
||||
int_client = self.make_internal_client(object_post_as_copy=False)
|
||||
int_client.set_object_metadata(
|
||||
self.account, 'c1', 'o1', {'X-Object-Meta-Fruit': 'Tomato'})
|
||||
self.assertEqual(
|
||||
'Tomato',
|
||||
int_client.get_object_metadata(self.account, 'c1', 'o1')
|
||||
['x-object-meta-fruit']) # sanity
|
||||
|
||||
# re-start the container server and assert that it does not yet know
|
||||
# about the object
|
||||
start_server((cnodes[0]['ip'], cnodes[0]['port']), self.ipport2server)
|
||||
self.assertFalse(direct_client.direct_get_container(
|
||||
cnodes[0], cpart, self.account, 'c1')[1])
|
||||
|
||||
# Run the object-updaters to send the async pendings
|
||||
Manager(['object-updater']).once()
|
||||
|
||||
# check the re-started container server got same update as others.
|
||||
# we cannot assert the actual etag value because it may be encrypted
|
||||
listing_etags = set()
|
||||
for cnode in cnodes:
|
||||
obj = direct_client.direct_get_container(
|
||||
cnode, cpart, self.account, 'c1')[1][0]
|
||||
self.assertEqual(len(content), obj['bytes'])
|
||||
listing_etags.add(obj['hash'])
|
||||
self.assertEqual(1, len(listing_etags))
|
||||
|
||||
# check that listing meta returned to client is consistent with object
|
||||
# meta returned to client
|
||||
hdrs, listing = client.get_container(self.url, self.token, 'c1')
|
||||
self.assertEqual(1, len(listing))
|
||||
self.assertEqual('o1', listing[0]['name'])
|
||||
self.assertEqual(len(content), listing[0]['bytes'])
|
||||
self.assertEqual(meta['etag'], listing[0]['hash'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
@ -46,8 +46,7 @@ class TestObjectHandoff(ReplProbeTest):
|
|||
opart, onodes = self.object_ring.get_nodes(
|
||||
self.account, container, obj)
|
||||
onode = onodes[0]
|
||||
kill_server((onode['ip'], onode['port']),
|
||||
self.ipport2server, self.pids)
|
||||
kill_server((onode['ip'], onode['port']), self.ipport2server)
|
||||
|
||||
# Create container/obj (goes to two primary servers and one handoff)
|
||||
client.put_object(self.url, self.token, container, obj, 'VERIFY')
|
||||
|
@ -66,8 +65,7 @@ class TestObjectHandoff(ReplProbeTest):
|
|||
# Kill other two container/obj primary servers
|
||||
# to ensure GET handoff works
|
||||
for node in onodes[1:]:
|
||||
kill_server((node['ip'], node['port']),
|
||||
self.ipport2server, self.pids)
|
||||
kill_server((node['ip'], node['port']), self.ipport2server)
|
||||
|
||||
# Indirectly through proxy assert we can get container/obj
|
||||
odata = client.get_object(self.url, self.token, container, obj)[-1]
|
||||
|
@ -77,8 +75,7 @@ class TestObjectHandoff(ReplProbeTest):
|
|||
|
||||
# Restart those other two container/obj primary servers
|
||||
for node in onodes[1:]:
|
||||
start_server((node['ip'], node['port']),
|
||||
self.ipport2server, self.pids)
|
||||
start_server((node['ip'], node['port']), self.ipport2server)
|
||||
|
||||
# We've indirectly verified the handoff node has the container/object,
|
||||
# but let's directly verify it.
|
||||
|
@ -119,8 +116,7 @@ class TestObjectHandoff(ReplProbeTest):
|
|||
(cnode['ip'], cnode['port']))
|
||||
|
||||
# Bring the first container/obj primary server back up
|
||||
start_server((onode['ip'], onode['port']),
|
||||
self.ipport2server, self.pids)
|
||||
start_server((onode['ip'], onode['port']), self.ipport2server)
|
||||
|
||||
# Assert that it doesn't have container/obj yet
|
||||
try:
|
||||
|
@ -180,8 +176,7 @@ class TestObjectHandoff(ReplProbeTest):
|
|||
|
||||
# Kill the first container/obj primary server again (we have two
|
||||
# primaries and the handoff up now)
|
||||
kill_server((onode['ip'], onode['port']),
|
||||
self.ipport2server, self.pids)
|
||||
kill_server((onode['ip'], onode['port']), self.ipport2server)
|
||||
|
||||
# Delete container/obj
|
||||
try:
|
||||
|
@ -218,8 +213,7 @@ class TestObjectHandoff(ReplProbeTest):
|
|||
(cnode['ip'], cnode['port']))
|
||||
|
||||
# Restart the first container/obj primary server again
|
||||
start_server((onode['ip'], onode['port']),
|
||||
self.ipport2server, self.pids)
|
||||
start_server((onode['ip'], onode['port']), self.ipport2server)
|
||||
|
||||
# Assert it still has container/obj
|
||||
direct_client.direct_get_object(
|
||||
|
|
|
@ -30,9 +30,10 @@
|
|||
|
||||
import hmac
|
||||
import itertools
|
||||
import mock
|
||||
import unittest
|
||||
from hashlib import sha1
|
||||
from time import time
|
||||
from time import time, strftime, gmtime
|
||||
|
||||
from swift.common.middleware import tempauth, tempurl
|
||||
from swift.common.header_key_dict import HeaderKeyDict
|
||||
|
@ -135,6 +136,9 @@ class TestTempURL(unittest.TestCase):
|
|||
self.assertEqual(resp.status_int, 200)
|
||||
self.assertEqual(resp.headers['content-disposition'],
|
||||
'attachment; filename="o"; ' + "filename*=UTF-8''o")
|
||||
self.assertEqual(resp.headers['expires'],
|
||||
strftime('%a, %d %b %Y %H:%M:%S GMT',
|
||||
gmtime(expires)))
|
||||
self.assertEqual(req.environ['swift.authorize_override'], True)
|
||||
self.assertEqual(req.environ['REMOTE_USER'], '.wsgi.tempurl')
|
||||
|
||||
|
@ -183,9 +187,10 @@ class TestTempURL(unittest.TestCase):
|
|||
for sig in (sig1, sig2):
|
||||
self.assert_valid_sig(expires, path, account_keys, sig, environ)
|
||||
|
||||
def test_get_valid_with_filename(self):
|
||||
@mock.patch('swift.common.middleware.tempurl.time', return_value=0)
|
||||
def test_get_valid_with_filename(self, mock_time):
|
||||
method = 'GET'
|
||||
expires = int(time() + 86400)
|
||||
expires = (((24 + 1) * 60 + 1) * 60) + 1
|
||||
path = '/v1/a/c/o'
|
||||
key = 'abc'
|
||||
hmac_body = '%s\n%s\n%s' % (method, expires, path)
|
||||
|
@ -199,10 +204,13 @@ class TestTempURL(unittest.TestCase):
|
|||
self.assertEqual(resp.headers['content-disposition'],
|
||||
'attachment; filename="bob %22killer%22.txt"; ' +
|
||||
"filename*=UTF-8''bob%20%22killer%22.txt")
|
||||
self.assertIn('expires', resp.headers)
|
||||
self.assertEqual('Fri, 02 Jan 1970 01:01:01 GMT',
|
||||
resp.headers['expires'])
|
||||
self.assertEqual(req.environ['swift.authorize_override'], True)
|
||||
self.assertEqual(req.environ['REMOTE_USER'], '.wsgi.tempurl')
|
||||
|
||||
def test_head_valid(self):
|
||||
def test_head_valid_with_filename(self):
|
||||
method = 'HEAD'
|
||||
expires = int(time() + 86400)
|
||||
path = '/v1/a/c/o'
|
||||
|
@ -211,11 +219,14 @@ class TestTempURL(unittest.TestCase):
|
|||
sig = hmac.new(key, hmac_body, sha1).hexdigest()
|
||||
req = self._make_request(path, keys=[key], environ={
|
||||
'REQUEST_METHOD': 'HEAD',
|
||||
'QUERY_STRING': 'temp_url_sig=%s&temp_url_expires=%s'
|
||||
% (sig, expires)})
|
||||
'QUERY_STRING': 'temp_url_sig=%s&temp_url_expires=%s&'
|
||||
'filename=bob_killer.txt' % (sig, expires)})
|
||||
self.tempurl.app = FakeApp(iter([('200 Ok', (), '123')]))
|
||||
resp = req.get_response(self.tempurl)
|
||||
self.assertEqual(resp.status_int, 200)
|
||||
self.assertEqual(resp.headers['content-disposition'],
|
||||
'attachment; filename="bob_killer.txt"; ' +
|
||||
"filename*=UTF-8''bob_killer.txt")
|
||||
|
||||
def test_head_and_get_headers_match(self):
|
||||
method = 'HEAD'
|
||||
|
@ -242,9 +253,10 @@ class TestTempURL(unittest.TestCase):
|
|||
get_resp = get_req.get_response(self.tempurl)
|
||||
self.assertEqual(resp.headers, get_resp.headers)
|
||||
|
||||
def test_get_valid_with_filename_and_inline(self):
|
||||
@mock.patch('swift.common.middleware.tempurl.time', return_value=0)
|
||||
def test_get_valid_with_filename_and_inline(self, mock_time):
|
||||
method = 'GET'
|
||||
expires = int(time() + 86400)
|
||||
expires = 1
|
||||
path = '/v1/a/c/o'
|
||||
key = 'abc'
|
||||
hmac_body = '%s\n%s\n%s' % (method, expires, path)
|
||||
|
@ -256,6 +268,9 @@ class TestTempURL(unittest.TestCase):
|
|||
resp = req.get_response(self.tempurl)
|
||||
self.assertEqual(resp.status_int, 200)
|
||||
self.assertEqual(resp.headers['content-disposition'], 'inline')
|
||||
self.assertIn('expires', resp.headers)
|
||||
self.assertEqual('Thu, 01 Jan 1970 00:00:01 GMT',
|
||||
resp.headers['expires'])
|
||||
self.assertEqual(req.environ['swift.authorize_override'], True)
|
||||
self.assertEqual(req.environ['REMOTE_USER'], '.wsgi.tempurl')
|
||||
|
||||
|
@ -273,6 +288,7 @@ class TestTempURL(unittest.TestCase):
|
|||
resp = req.get_response(self.tempurl)
|
||||
self.assertEqual(resp.status_int, 200)
|
||||
self.assertEqual(resp.headers['content-disposition'], 'inline')
|
||||
self.assertIn('expires', resp.headers)
|
||||
self.assertEqual(req.environ['swift.authorize_override'], True)
|
||||
self.assertEqual(req.environ['REMOTE_USER'], '.wsgi.tempurl')
|
||||
|
||||
|
@ -292,6 +308,7 @@ class TestTempURL(unittest.TestCase):
|
|||
self.assertEqual(resp.headers['content-disposition'],
|
||||
'attachment; filename="a%0D%0Ab"; ' +
|
||||
"filename*=UTF-8''a%0D%0Ab")
|
||||
self.assertIn('expires', resp.headers)
|
||||
self.assertEqual(req.environ['swift.authorize_override'], True)
|
||||
self.assertEqual(req.environ['REMOTE_USER'], '.wsgi.tempurl')
|
||||
|
||||
|
@ -311,6 +328,7 @@ class TestTempURL(unittest.TestCase):
|
|||
self.assertEqual(resp.status_int, 200)
|
||||
self.assertEqual(resp.headers['content-disposition'],
|
||||
'attachment; filename="fu%0Abar"')
|
||||
self.assertIn('expires', resp.headers)
|
||||
self.assertEqual(req.environ['swift.authorize_override'], True)
|
||||
self.assertEqual(req.environ['REMOTE_USER'], '.wsgi.tempurl')
|
||||
|
||||
|
@ -330,6 +348,7 @@ class TestTempURL(unittest.TestCase):
|
|||
self.assertEqual(resp.headers['content-disposition'],
|
||||
'attachment; filename="o"; ' +
|
||||
"filename*=UTF-8''o")
|
||||
self.assertIn('expires', resp.headers)
|
||||
self.assertEqual(req.environ['swift.authorize_override'], True)
|
||||
self.assertEqual(req.environ['REMOTE_USER'], '.wsgi.tempurl')
|
||||
|
||||
|
@ -350,6 +369,7 @@ class TestTempURL(unittest.TestCase):
|
|||
resp.headers['content-disposition'],
|
||||
'attachment; filename="/i/want/this/just/as/it/is/"; ' +
|
||||
"filename*=UTF-8''/i/want/this/just/as/it/is/")
|
||||
self.assertIn('expires', resp.headers)
|
||||
self.assertEqual(req.environ['swift.authorize_override'], True)
|
||||
self.assertEqual(req.environ['REMOTE_USER'], '.wsgi.tempurl')
|
||||
|
||||
|
@ -366,7 +386,8 @@ class TestTempURL(unittest.TestCase):
|
|||
sig, expires)})
|
||||
resp = req.get_response(self.tempurl)
|
||||
self.assertEqual(resp.status_int, 404)
|
||||
self.assertFalse('content-disposition' in resp.headers)
|
||||
self.assertNotIn('content-disposition', resp.headers)
|
||||
self.assertNotIn('expires', resp.headers)
|
||||
self.assertEqual(req.environ['swift.authorize_override'], True)
|
||||
self.assertEqual(req.environ['REMOTE_USER'], '.wsgi.tempurl')
|
||||
|
||||
|
|
|
@ -507,21 +507,27 @@ class TestObjectController(unittest.TestCase):
|
|||
headers_out, objdevice, policy):
|
||||
calls_made.append((headers_out, policy))
|
||||
|
||||
body = 'test'
|
||||
headers = {
|
||||
'X-Timestamp': t[1].internal,
|
||||
'Content-Type': 'application/octet-stream;swift_bytes=123456789',
|
||||
'Content-Length': '4',
|
||||
'X-Backend-Storage-Policy-Index': int(policy)}
|
||||
if policy.policy_type == EC_POLICY:
|
||||
# EC fragments will typically have a different size to the body and
|
||||
# for small bodies the fragments may be longer. For this test all
|
||||
# that matters is that the fragment and body lengths differ.
|
||||
body = body + 'ec_overhead'
|
||||
headers['X-Object-Sysmeta-Container-Update-Override-Etag'] = \
|
||||
update_etag
|
||||
headers['X-Object-Sysmeta-Container-Update-Override-Size'] = '4'
|
||||
headers['X-Object-Sysmeta-Ec-Etag'] = update_etag
|
||||
headers['X-Object-Sysmeta-Ec-Content-Length'] = '4'
|
||||
headers['X-Object-Sysmeta-Ec-Frag-Index'] = 2
|
||||
headers['Content-Length'] = str(len(body))
|
||||
|
||||
req = Request.blank('/sda1/p/a/c/o',
|
||||
req = Request.blank('/sda1/p/a/c/o', body=body,
|
||||
environ={'REQUEST_METHOD': 'PUT'},
|
||||
headers=headers, body='test')
|
||||
|
||||
headers=headers)
|
||||
with mock.patch('swift.obj.server.ObjectController.container_update',
|
||||
mock_container_update):
|
||||
resp = req.get_response(self.object_controller)
|
||||
|
@ -725,10 +731,12 @@ class TestObjectController(unittest.TestCase):
|
|||
|
||||
# make PUT with given headers and verify correct etag is sent in
|
||||
# container update
|
||||
body = 'test ec overhead'
|
||||
headers['X-Timestamp'] = ts_put.internal
|
||||
headers['Content-Length'] = len(body)
|
||||
req = Request.blank('/sda1/p/a/c/o',
|
||||
environ={'REQUEST_METHOD': 'PUT'},
|
||||
headers=headers, body='test')
|
||||
headers=headers, body=body)
|
||||
|
||||
with mock.patch(
|
||||
'swift.obj.server.ObjectController.container_update',
|
||||
|
@ -774,13 +782,13 @@ class TestObjectController(unittest.TestCase):
|
|||
|
||||
base_headers = {
|
||||
'Content-Type': 'application/octet-stream;swift_bytes=123456789',
|
||||
'Content-Length': '4',
|
||||
'X-Backend-Storage-Policy-Index': int(policy),
|
||||
'X-Object-Sysmeta-Ec-Frag-Index': 2}
|
||||
|
||||
# PUT - old style headers are sufficient
|
||||
headers = dict(base_headers)
|
||||
headers['X-Backend-Container-Update-Override-Etag'] = 'expected'
|
||||
headers['X-Object-Sysmeta-Container-Update-Override-Size'] = '4'
|
||||
headers['X-Object-Sysmeta-Ec-Etag'] = 'expected'
|
||||
do_test(headers)
|
||||
|
||||
|
@ -790,6 +798,7 @@ class TestObjectController(unittest.TestCase):
|
|||
# update with the correct etag).
|
||||
headers = dict(base_headers)
|
||||
headers['X-Object-Sysmeta-Container-Update-Override-Etag'] = 'expected'
|
||||
headers['X-Object-Sysmeta-Container-Update-Override-Size'] = '4'
|
||||
do_test(headers)
|
||||
|
||||
# PUT - X-Object-Sysmeta-Container-Update-Override-Etag trumps
|
||||
|
@ -797,6 +806,7 @@ class TestObjectController(unittest.TestCase):
|
|||
headers = dict(base_headers)
|
||||
headers['X-Object-Sysmeta-Ec-Etag'] = 'ec etag'
|
||||
headers['X-Object-Sysmeta-Container-Update-Override-Etag'] = 'expected'
|
||||
headers['X-Object-Sysmeta-Container-Update-Override-Size'] = '4'
|
||||
do_test(headers)
|
||||
|
||||
def _test_PUT_then_POST_async_pendings(self, policy, update_etag=None):
|
||||
|
|
Loading…
Reference in New Issue