diff options
Diffstat (limited to 'openstackclient')
26 files changed, 3054 insertions, 829 deletions
diff --git a/openstackclient/compute/v2/availability_zone.py b/openstackclient/common/availability_zone.py index 0fe6c73a..e72732e7 100644 --- a/openstackclient/compute/v2/availability_zone.py +++ b/openstackclient/common/availability_zone.py @@ -11,7 +11,7 @@ # under the License. # -"""Compute v2 Availability Zone action implementations""" +"""Availability Zone action implementations""" import copy import logging @@ -24,15 +24,19 @@ from openstackclient.common import utils from openstackclient.i18n import _ # noqa -def _xform_availability_zone(az, include_extra): - result = [] - zone_info = {} +def _xform_common_availability_zone(az, zone_info): if hasattr(az, 'zoneState'): zone_info['zone_status'] = ('available' if az.zoneState['available'] else 'not available') if hasattr(az, 'zoneName'): zone_info['zone_name'] = az.zoneName + +def _xform_compute_availability_zone(az, include_extra): + result = [] + zone_info = {} + _xform_common_availability_zone(az, zone_info) + if not include_extra: result.append(zone_info) return result @@ -58,6 +62,14 @@ def _xform_availability_zone(az, include_extra): return result +def _xform_volume_availability_zone(az): + result = [] + zone_info = {} + _xform_common_availability_zone(az, zone_info) + result.append(zone_info) + return result + + class ListAvailabilityZone(lister.Lister): """List availability zones and their status""" @@ -66,6 +78,16 @@ class ListAvailabilityZone(lister.Lister): def get_parser(self, prog_name): parser = super(ListAvailabilityZone, self).get_parser(prog_name) parser.add_argument( + '--compute', + action='store_true', + default=False, + help='List compute availability zones') + parser.add_argument( + '--volume', + action='store_true', + default=False, + help='List volume availability zones') + parser.add_argument( '--long', action='store_true', default=False, @@ -73,15 +95,7 @@ class ListAvailabilityZone(lister.Lister): ) return parser - @utils.log_method(log) - def take_action(self, parsed_args): - - if parsed_args.long: - columns = ('Zone Name', 'Zone Status', - 'Host Name', 'Service Name', 'Service Status') - else: - columns = ('Zone Name', 'Zone Status') - + def get_compute_availability_zones(self, parsed_args): compute_client = self.app.client_manager.compute try: data = compute_client.availability_zones.list() @@ -94,7 +108,40 @@ class ListAvailabilityZone(lister.Lister): # Argh, the availability zones are not iterable... result = [] for zone in data: - result += _xform_availability_zone(zone, parsed_args.long) + result += _xform_compute_availability_zone(zone, parsed_args.long) + return result + + def get_volume_availability_zones(self, parsed_args): + volume_client = self.app.client_manager.volume + try: + data = volume_client.availability_zones.list() + except Exception: + message = "Availability zones list not supported by " \ + "Block Storage API" + self.log.warning(message) + + result = [] + for zone in data: + result += _xform_volume_availability_zone(zone) + return result + + @utils.log_method(log) + def take_action(self, parsed_args): + + if parsed_args.long: + columns = ('Zone Name', 'Zone Status', + 'Host Name', 'Service Name', 'Service Status') + else: + columns = ('Zone Name', 'Zone Status') + + # Show everything by default. + show_all = (not parsed_args.compute and not parsed_args.volume) + + result = [] + if parsed_args.compute or show_all: + result += self.get_compute_availability_zones(parsed_args) + if parsed_args.volume or show_all: + result += self.get_volume_availability_zones(parsed_args) return (columns, (utils.get_dict_properties( diff --git a/openstackclient/i18n.py b/openstackclient/i18n.py index 3a11c1d0..1d09772c 100644 --- a/openstackclient/i18n.py +++ b/openstackclient/i18n.py @@ -15,7 +15,7 @@ import oslo_i18n -_translators = oslo_i18n.TranslatorFactory(domain='python-openstackclient') +_translators = oslo_i18n.TranslatorFactory(domain='openstackclient') # The primary translation function using the well-known name "_" _ = _translators.primary diff --git a/openstackclient/image/v1/image.py b/openstackclient/image/v1/image.py index 0382501e..c18f3fc7 100644 --- a/openstackclient/image/v1/image.py +++ b/openstackclient/image/v1/image.py @@ -35,6 +35,7 @@ from glanceclient.common import utils as gc_utils from openstackclient.api import utils as api_utils from openstackclient.common import parseractions from openstackclient.common import utils +from openstackclient.i18n import _ # noqa DEFAULT_CONTAINER_FORMAT = 'bare' @@ -93,11 +94,6 @@ class CreateImage(show.ShowOne): "(default: %s)" % DEFAULT_DISK_FORMAT, ) parser.add_argument( - "--owner", - metavar="<project>", - help="Image owner project name or ID", - ) - parser.add_argument( "--size", metavar="<size>", help="Image size, in bytes (only used with --location and" @@ -178,12 +174,32 @@ class CreateImage(show.ShowOne): help="Set a property on this image " "(repeat option to set multiple properties)", ) + # NOTE(dtroyer): --owner is deprecated in Jan 2016 in an early + # 2.x release. Do not remove before Jan 2017 + # and a 3.x release. + project_group = parser.add_mutually_exclusive_group() + project_group.add_argument( + "--project", + metavar="<project>", + help="Set an alternate project on this image (name or ID)", + ) + project_group.add_argument( + "--owner", + metavar="<project>", + help=argparse.SUPPRESS, + ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) image_client = self.app.client_manager.image + if getattr(parsed_args, 'owner', None) is not None: + self.log.warning(_( + 'The --owner option is deprecated, ' + 'please use --project instead.' + )) + # Build an attribute dict from the parsed args, only include # attributes that were actually set on the command line kwargs = {} @@ -198,6 +214,12 @@ class CreateImage(show.ShowOne): # Only include a value in kwargs for attributes that are # actually present on the command line kwargs[attr] = val + + # Special case project option back to API attribute name 'owner' + val = getattr(parsed_args, 'project', None) + if val: + kwargs['owner'] = val + # Handle exclusive booleans with care # Avoid including attributes in kwargs if an option is not # present on the command line. These exclusive booleans are not @@ -383,7 +405,7 @@ class ListImage(lister.Lister): 'Status', 'Visibility', 'Protected', - 'Owner', + 'Project', 'Properties', ) else: @@ -477,11 +499,6 @@ class SetImage(command.Command): help="New image name", ) parser.add_argument( - "--owner", - metavar="<project>", - help="New image owner project (name or ID)", - ) - parser.add_argument( "--min-disk", metavar="<disk-gb>", type=int, @@ -590,12 +607,32 @@ class SetImage(command.Command): metavar="<checksum>", help="Image hash used for verification", ) + # NOTE(dtroyer): --owner is deprecated in Jan 2016 in an early + # 2.x release. Do not remove before Jan 2017 + # and a 3.x release. + project_group = parser.add_mutually_exclusive_group() + project_group.add_argument( + "--project", + metavar="<project>", + help="Set an alternate project on this image (name or ID)", + ) + project_group.add_argument( + "--owner", + metavar="<project>", + help=argparse.SUPPRESS, + ) return parser def take_action(self, parsed_args): self.log.debug("take_action(%s)", parsed_args) image_client = self.app.client_manager.image + if getattr(parsed_args, 'owner', None) is not None: + self.log.warning(_( + 'The --owner option is deprecated, ' + 'please use --project instead.' + )) + kwargs = {} copy_attrs = ('name', 'owner', 'min_disk', 'min_ram', 'properties', 'container_format', 'disk_format', 'size', 'store', @@ -607,6 +644,12 @@ class SetImage(command.Command): # Only include a value in kwargs for attributes that are # actually present on the command line kwargs[attr] = val + + # Special case project option back to API attribute name 'owner' + val = getattr(parsed_args, 'project', None) + if val: + kwargs['owner'] = val + # Handle exclusive booleans with care # Avoid including attributes in kwargs if an option is not # present on the command line. These exclusive booleans are not diff --git a/openstackclient/image/v2/image.py b/openstackclient/image/v2/image.py index ad536ba2..123599ed 100644 --- a/openstackclient/image/v2/image.py +++ b/openstackclient/image/v2/image.py @@ -28,6 +28,7 @@ from openstackclient.api import utils as api_utils from openstackclient.common import exceptions from openstackclient.common import parseractions from openstackclient.common import utils +from openstackclient.i18n import _ # noqa from openstackclient.identity import common @@ -148,11 +149,6 @@ class CreateImage(show.ShowOne): "(default: %s)" % DEFAULT_DISK_FORMAT, ) parser.add_argument( - "--owner", - metavar="<owner>", - help="Image owner project name or ID", - ) - parser.add_argument( "--min-disk", metavar="<disk-gb>", type=int, @@ -220,6 +216,20 @@ class CreateImage(show.ShowOne): help="Set a tag on this image " "(repeat option to set multiple tags)", ) + # NOTE(dtroyer): --owner is deprecated in Jan 2016 in an early + # 2.x release. Do not remove before Jan 2017 + # and a 3.x release. + project_group = parser.add_mutually_exclusive_group() + project_group.add_argument( + "--project", + metavar="<project>", + help="Set an alternate project on this image (name or ID)", + ) + project_group.add_argument( + "--owner", + metavar="<project>", + help=argparse.SUPPRESS, + ) common.add_project_domain_option_to_parser(parser) for deadopt in self.deadopts: parser.add_argument( @@ -246,8 +256,7 @@ class CreateImage(show.ShowOne): kwargs = {} copy_attrs = ('name', 'id', 'container_format', 'disk_format', - 'min_disk', 'min_ram', - 'tags', 'owner') + 'min_disk', 'min_ram', 'tags') for attr in copy_attrs: if attr in parsed_args: val = getattr(parsed_args, attr, None) @@ -255,6 +264,7 @@ class CreateImage(show.ShowOne): # Only include a value in kwargs for attributes that # are actually present on the command line kwargs[attr] = val + # properties should get flattened into the general kwargs if getattr(parsed_args, 'properties', None): for k, v in six.iteritems(parsed_args.properties): @@ -275,6 +285,21 @@ class CreateImage(show.ShowOne): if parsed_args.private: kwargs['visibility'] = 'private' + # Handle deprecated --owner option + project_arg = parsed_args.project + if parsed_args.owner: + project_arg = parsed_args.owner + self.log.warning(_( + 'The --owner option is deprecated, ' + 'please use --project instead.' + )) + if project_arg: + kwargs['owner'] = common.find_project( + identity_client, + project_arg, + parsed_args.project_domain, + ).id + # open the file first to ensure any failures are handled before the # image is created fp = gc_utils.get_data_file(parsed_args) @@ -458,7 +483,7 @@ class ListImage(lister.Lister): 'Status', 'Visibility', 'Protected', - 'Owner', + 'Project', 'Tags', ) else: @@ -599,11 +624,6 @@ class SetImage(command.Command): help="New image name" ) parser.add_argument( - "--owner", - metavar="<project>", - help="New image owner project (name or ID)", - ) - parser.add_argument( "--min-disk", type=int, metavar="<disk-gb>", @@ -713,6 +733,20 @@ class SetImage(command.Command): action="store_true", help="Activate the image", ) + # NOTE(dtroyer): --owner is deprecated in Jan 2016 in an early + # 2.x release. Do not remove before Jan 2017 + # and a 3.x release. + project_group = parser.add_mutually_exclusive_group() + project_group.add_argument( + "--project", + metavar="<project>", + help="Set an alternate project on this image (name or ID)", + ) + project_group.add_argument( + "--owner", + metavar="<project>", + help=argparse.SUPPRESS, + ) common.add_project_domain_option_to_parser(parser) for deadopt in self.deadopts: parser.add_argument( @@ -738,7 +772,7 @@ class SetImage(command.Command): copy_attrs = ('architecture', 'container_format', 'disk_format', 'file', 'instance_id', 'kernel_id', 'locations', 'min_disk', 'min_ram', 'name', 'os_distro', 'os_version', - 'owner', 'prefix', 'progress', 'ramdisk_id', 'tags') + 'prefix', 'progress', 'ramdisk_id', 'tags') for attr in copy_attrs: if attr in parsed_args: val = getattr(parsed_args, attr, None) @@ -767,6 +801,21 @@ class SetImage(command.Command): if parsed_args.private: kwargs['visibility'] = 'private' + # Handle deprecated --owner option + project_arg = parsed_args.project + if parsed_args.owner: + project_arg = parsed_args.owner + self.log.warning(_( + 'The --owner option is deprecated, ' + 'please use --project instead.' + )) + if project_arg: + kwargs['owner'] = common.find_project( + identity_client, + project_arg, + parsed_args.project_domain, + ).id + # Checks if anything that requires getting the image if not (kwargs or parsed_args.deactivate or parsed_args.activate): self.log.warning("No arguments specified") @@ -775,6 +824,7 @@ class SetImage(command.Command): image = utils.find_resource( image_client.images, parsed_args.image) + activation_status = None if parsed_args.deactivate: image_client.images.deactivate(image.id) activation_status = "deactivated" @@ -790,13 +840,6 @@ class SetImage(command.Command): # Tags should be extended, but duplicates removed kwargs['tags'] = list(set(image.tags).union(set(parsed_args.tags))) - if parsed_args.owner: - kwargs['owner'] = common.find_project( - identity_client, - parsed_args.owner, - parsed_args.project_domain, - ).id - try: image = image_client.images.update(image.id, **kwargs) except Exception as e: diff --git a/openstackclient/locale/de/LC_MESSAGES/openstackclient.po b/openstackclient/locale/de/LC_MESSAGES/openstackclient.po new file mode 100644 index 00000000..1c94b9d4 --- /dev/null +++ b/openstackclient/locale/de/LC_MESSAGES/openstackclient.po @@ -0,0 +1,600 @@ +# Translations template for python-openstackclient. +# Copyright (C) 2015 ORGANIZATION +# This file is distributed under the same license as the +# python-openstackclient project. +# +# Translators: +# Ettore Atalan <atalanttore@googlemail.com>, 2014-2015 +# Andreas Jaeger <jaegerandi@gmail.com>, 2015. #zanata +# OpenStack Infra <zanata@openstack.org>, 2015. #zanata +msgid "" +msgstr "" +"Project-Id-Version: python-openstackclient 2.0.1.dev168\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2016-01-19 02:20+0000\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"PO-Revision-Date: 2015-09-19 07:10+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" +"X-Generator: Zanata 3.7.3\n" +"Language-Team: German\n" + +msgid "" +"\n" +"Complete\n" +msgstr "" +"\n" +"Fertig\n" + +msgid "" +"\n" +"Error creating server" +msgstr "" +"\n" +"Fehler beim Erstellen des Servers" + +msgid "" +"\n" +"Error creating server snapshot" +msgstr "" +"\n" +"Fehler beim Erstellen der Server-Schattenkopie" + +msgid "" +"\n" +"Error deleting server" +msgstr "" +"\n" +"Fehler beim Löschen des Servers" + +msgid "" +"\n" +"Error migrating server" +msgstr "" +"\n" +"Fehler beim Migrieren des Servers" + +msgid "" +"\n" +"Error rebooting server\n" +msgstr "" +"\n" +"Fehler beim Neustarten des Servers\n" + +msgid "" +"\n" +"Error rebuilding server" +msgstr "" +"\n" +"Fehler bei der Wiederherstellung des Servers" + +msgid "" +"\n" +"Error resizing server" +msgstr "" +"\n" +"Fehler bei der Größenänderung des Servers" + +msgid "" +"\n" +"Reboot complete\n" +msgstr "" +"\n" +"Neustart abgeschlossen\n" + +msgid "Add a property to <name> (repeat option to set multiple properties)" +msgstr "" +"Fügen Sie eine Eigenschaft zu <Name> hinzu (wiederholen Sie die Option, um " +"mehrere Eigenschaften festzulegen)" + +msgid "Allow disk over-commit on the destination host" +msgstr "Festplattenüberladung auf dem Zielhost erlauben" + +msgid "Complete\n" +msgstr "Fertig\n" + +msgid "Confirm server resize is complete" +msgstr "Bestätigen Sie, ob die Größenänderung des Servers abgeschlossen ist" + +msgid "" +"Create a NIC on the server. Specify option multiple times to create multiple " +"NICs. Either net-id or port-id must be provided, but not both. net-id: " +"attach NIC to network with this UUID, port-id: attach NIC to port with this " +"UUID, v4-fixed-ip: IPv4 fixed address for NIC (optional), v6-fixed-ip: IPv6 " +"fixed address for NIC (optional)." +msgstr "" +"Erstellen Sie ein NIC auf dem Server. Geben Sie die Option mehrfach an, um " +"mehrere NICs zu erstellen. Entweder net-id oder port-id müssen " +"bereitgestellt werden, aber nicht beide. net-id: NIC an Netzwerk mit dieser " +"UUID binden, port-id: NIC an Port mit dieser UUID binden, v4-fixed-ip: Feste " +"IPv4-Adresse für NIC (optional), v6-fixed-ip: Feste IPv6-Adresse für NIC " +"(optional)." + +msgid "" +"Create credentials for user (name or ID; default: current authenticated user)" +msgstr "" +"Anmeldedaten für Benutzer erstellen (Name oder Kennung; Standard: aktuell " +"authentifizierter Benutzer)" + +msgid "" +"Create credentials in project (name or ID; default: current authenticated " +"project)" +msgstr "" +"Anmeldedaten in Projekt erstellen (Name oder Kennung; Standard: aktuell " +"authentifiziertes Projekt)" + +msgid "Credentials access key" +msgstr "Anmeldedaten-Zugriffsschlüssel" + +msgid "Default project (name or ID)" +msgstr "Standardprojekt (Name oder Kennung)" + +msgid "Delete credentials for user (name or ID)" +msgstr "Anmeldedaten für Benutzer löschen (name or ID)" + +msgid "Destination port (ssh -p option)" +msgstr "Zielport (ssh -p Option)" + +msgid "Disable project" +msgstr "Projekt deaktivieren" + +msgid "Disable user" +msgstr "Benutzer deaktivieren" + +msgid "Display server diagnostics information" +msgstr "Serverdiagnoseinformationen anzeigen" + +msgid "Do not over-commit disk on the destination host (default)" +msgstr "Festplatte auf dem Zielhost nicht überladen (Standard)" + +msgid "Enable project" +msgstr "Projekt aktivieren" + +msgid "Enable project (default)" +msgstr "Projekt aktivieren (Standardeinstellung)" + +msgid "Enable user (default)" +msgstr "Benutzer aktivieren (Standardeinstellung)" + +msgid "Endpoint ID to delete" +msgstr "Zu löschende Endpunktkennung" + +msgid "Endpoint ID to display" +msgstr "Anzuzeigende Endpunktkennung" + +#, python-format +msgid "Error creating server snapshot: %s" +msgstr "Fehler beim Erstellen der Server-Schattenkopie: %s" + +#, python-format +msgid "Error creating server: %s" +msgstr "Fehler beim Erstellen des Servers: %s" + +#, python-format +msgid "Error deleting server: %s" +msgstr "Fehler beim Löschen des Servers: %s" + +msgid "Error retrieving diagnostics data" +msgstr "Fehler beim Abrufen der Diagnosedaten" + +msgid "File to inject into image before boot (repeat for multiple files)" +msgstr "" +"Vor dem Start auf diesem Abbild einzufügende Datei (für mehrere Dateien " +"wiederholen)" + +msgid "Filter by parent region ID" +msgstr "Nach übergeordneter Regionskennung filtern" + +msgid "Filter list by user (name or ID)" +msgstr "Liste nach Benutzer filtern (Name oder Kennung)" + +msgid "Filter users by <project> (name or ID)" +msgstr "Benutzer nach <project> filtern (Name oder Kennung)" + +msgid "Filter users by project (name or ID)" +msgstr "Benutzer nach Projekt filtern (Name oder Kennung)" + +msgid "Hints for the scheduler (optional extension)" +msgstr "Hinweise für den Planer (optionale Erweiterung)" + +msgid "Include <project> (name or ID)" +msgstr "<project> miteinbeziehen (Name oder Kennung)" + +msgid "Include <user> (name or ID)" +msgstr "<user> miteinbeziehen (Name oder Kennung)" + +msgid "Include all projects (admin only)" +msgstr "Alle Projekte miteinbeziehen (nur Administrator)" + +msgid "Keypair to inject into this server (optional extension)" +msgstr "In diesem Server einzufügendes Schlüsselpaar (optionale Erweiterung)" + +msgid "List additional fields in output" +msgstr "Zusätzliche Felder in der Ausgabe auflisten" + +msgid "Login name (ssh -l option)" +msgstr "Anmeldename (ssh -l Option)" + +msgid "" +"Map block devices; map is <id>:<type>:<size(GB)>:<delete_on_terminate> " +"(optional extension)" +msgstr "" +"Blockorientierte Geräte abbilden; Abbildung ist <Kennung>:<Typ>:<Größe(GB)>:" +"<beim_Beenden_löschen> (optionale Erweiterung)" + +msgid "Maximum number of servers to launch (default=1)" +msgstr "Maximale Anzahl der zu startenden Server (Standard=1)" + +msgid "Minimum number of servers to launch (default=1)" +msgstr "Minimale Anzahl der zu startenden Server (Standard=1)" + +msgid "Name of new image (default is server name)" +msgstr "Name des neuen Abbilds (Servername ist Standard)" + +msgid "Name or ID of security group to remove from server" +msgstr "Name oder Kennung der vom Server zu entfernenden Sicherheitsgruppe" + +msgid "Name or ID of server to use" +msgstr "Name oder Kennung des zu verwendenden Servers" + +msgid "New endpoint admin URL" +msgstr "Administrator-URL des neuen Endpunktes" + +msgid "New endpoint internal URL" +msgstr "Interne URL des neuen Endpunktes" + +msgid "New endpoint public URL (required)" +msgstr "Öffentliche URL des neuen Endpunktes (erforderlich)" + +msgid "New endpoint region ID" +msgstr "Neue Endpunkt-Regionskennung" + +msgid "New endpoint service (name or ID)" +msgstr "Neuer Endpunktdienst (Name oder Kennung)" + +msgid "New parent region ID" +msgstr "Neue übergeordnete Regionskennung" + +msgid "New password: " +msgstr "Neues Passwort:" + +msgid "New project name" +msgstr "Name des neuen Projekts" + +msgid "New region ID" +msgstr "Neue Regionskennung" + +msgid "New region description" +msgstr "Beschreibung des neuen Bereichs" + +msgid "New role name" +msgstr "Name der neuen Rolle" + +msgid "New server name" +msgstr "Neuer Servername" + +msgid "New service description" +msgstr "Beschreibung des neuen Dienstes" + +msgid "New service name" +msgstr "Name des neuen Dienstes" + +msgid "New service type (compute, image, identity, volume, etc)" +msgstr "Neuer Diensttyp (Berechnen, Abbild, Identität, Datenträger, usw.)" + +msgid "New user name" +msgstr "Neuer Benutzername" + +#, python-format +msgid "No service catalog with a type, name or ID of '%s' exists." +msgstr "Kein Dienstkatalog mit Typ, Namen oder Kennung von '%s' ist vorhanden." + +msgid "Only return instances that match the reservation" +msgstr "Nur Instanzen zurückgeben, die der Einschränkung entsprechen" + +msgid "Options in ssh_config(5) format (ssh -o option)" +msgstr "Optionen im ssh_config(5)-Format (ssh -o Option)" + +msgid "Parent region ID" +msgstr "Übergeordnete Regionskennung" + +msgid "Passwords do not match, password unchanged" +msgstr "Passwörter stimmen nicht überein, Passwort unverändert" + +msgid "Perform a block live migration" +msgstr "Blockorientierte Live-Migration ausführen" + +msgid "Perform a hard reboot" +msgstr "Harten Neustart ausführen" + +msgid "Perform a shared live migration (default)" +msgstr "Gemeinsame Live-Migration ausführen (Standard)" + +msgid "Perform a soft reboot" +msgstr "Weichen Neustart ausführen" + +msgid "Private key file (ssh -i option)" +msgstr "Private Schlüsseldatei (ssh -i Option)" + +msgid "Project description" +msgstr "Projektbeschreibung" + +msgid "Project must be specified" +msgstr "Projekt muss angegeben werden" + +msgid "Project to display (name or ID)" +msgstr "Anzuzeigendes Projekt (Name oder Kennung)" + +msgid "Project to modify (name or ID)" +msgstr "Zu änderndes Projekt (Name oder Kennung)" + +msgid "Project(s) to delete (name or ID)" +msgstr "Zu löschende(s) Projekt(e) (Name oder Kennung)" + +msgid "Prompt interactively for password" +msgstr "Interaktiv nach dem Passwort abfragen" + +msgid "Property key to remove from server (repeat to unset multiple values)" +msgstr "" +"Vom Server zu entfernender Eigenschaftsschlüssel (zum Aufheben von mehreren " +"Werten wiederholen)" + +msgid "" +"Property to add/change for this server (repeat option to set multiple " +"properties)" +msgstr "" +"Zu hinzufügende/ändernde Eigenschaft für diesen Server (wiederholen Sie die " +"Option, um mehrere Eigenschaften festzulegen)" + +msgid "Region ID to delete" +msgstr "Zu löschende Regionskennung" + +msgid "Region to display" +msgstr "Anzuzeigende Region" + +msgid "Region to modify" +msgstr "Zu ändernde Region" + +msgid "Regular expression to match IP addresses" +msgstr "Regulärer Ausdruck zum Abgleichen mit IP-Adressen" + +msgid "Regular expression to match IPv6 addresses" +msgstr "Regulärer Ausdruck zum Abgleichen mit IPv6-Adressen" + +msgid "Regular expression to match instance name (admin only)" +msgstr "" +"Regulärer Ausdruck zum Abgleichen des Instanznamens (nur Administrator) " + +msgid "Regular expression to match names" +msgstr "Regulärer Ausdruck zum Abgleichen mit Namen" + +msgid "Resize server to specified flavor" +msgstr "Servergröße auf angegebene Variante ändern" + +msgid "Restore server state before resize" +msgstr "Serverstatus vor der Größenänderung wiederherstellen" + +msgid "Return existing domain" +msgstr "Vorhandene Domäne zurückgeben" + +msgid "Return existing group" +msgstr "Vorhandene Gruppe zurückgeben" + +msgid "Return existing project" +msgstr "Vorhandenes Projekt zurückgeben" + +msgid "Return existing role" +msgstr "Vorhandene Rolle zurückgeben" + +msgid "Return existing user" +msgstr "Vorhandenen Benutzer zurückgeben" + +msgid "Retype new password: " +msgstr "Neues Passwort erneut eingeben:" + +msgid "Role to add to <project>:<user> (name or ID)" +msgstr "Zu <project>:<user> hinzuzufügende Rolle (Name oder Kennung)" + +msgid "Role to display (name or ID)" +msgstr "Anzuzeigende Rolle (Name oder Kennung)" + +msgid "Role to remove (name or ID)" +msgstr "Zu entfernende Rolle (Name oder Kennung)" + +msgid "Role(s) to delete (name or ID)" +msgstr "Zu löschende Rolle(n) (Name oder Kennung)" + +msgid "Search by hostname" +msgstr "Nach Hostname suchen" + +msgid "Search by server status" +msgstr "Nach Serverstatus suchen" + +msgid "Search by user (admin only) (name or ID)" +msgstr "Nach Benutzer suchen (nur Administrator) (Name oder Kennung)" + +msgid "Security group to add (name or ID)" +msgstr "Zu hinzufügende Sicherheitsgruppe (Name oder Kennung)" + +msgid "Select an availability zone for the server" +msgstr "Wählen Sie eine Verfügbarkeitszone für den Server aus" + +msgid "Server (name or ID)" +msgstr "Server (Name oder Kennung)" + +msgid "Server internal device name for volume" +msgstr "Serverinterner Gerätename für Datenträger" + +msgid "Server(s) to delete (name or ID)" +msgstr "Zu löschende(r) Server (Name oder Kennung)" + +msgid "Service to delete (name or ID)" +msgstr "Zu löschender Dienst (Name oder Kennung)" + +msgid "Service to display (type or name)" +msgstr "Anzuzeigender Dienst (Typ oder Name)" + +msgid "Service to display (type, name or ID)" +msgstr "Anzuzeigender Dienst (Typ, Name oder Kennung)" + +msgid "Set a project property (repeat option to set multiple properties)" +msgstr "" +"Legen Sie eine Projekteigenschaft fest (wiederholen Sie die Option, um " +"mehrere Eigenschaften festzulegen)" + +msgid "Set a property on this server (repeat for multiple values)" +msgstr "" +"Legen Sie eine Eigenschaft auf diesem Server fest (für mehrere Werte " +"wiederholen)" + +msgid "" +"Set a scope, such as a project or domain, set a project scope with --os-" +"project-name, OS_PROJECT_NAME or auth.project_name, set a domain scope with " +"--os-domain-name, OS_DOMAIN_NAME or auth.domain_name" +msgstr "" +"Setzen Sie eine Eigenschaft, wie Projekt oder Domäne, setzen Sie eine " +"Projekteigenschaft mit --os-project-name, OS_PROJECT_NAME oder auth." +"project_name, setzen Sie eine Dömaneneigenschaft mit --os-domain-name, " +"OS_DOMAIN_NAME oder auth.domain_name." + +msgid "" +"Set a service AUTH_URL, with --os-auth-url, OS_AUTH_URL or auth.auth_url\n" +msgstr "" +"Legen Sie eine Dienst-AUTH_URL mit --os-auth-url, OS_AUTH_URL oder auth." +"auth_url fest\n" + +msgid "Set a service URL, with --os-url, OS_URL or auth.url\n" +msgstr "Legen Sie eine Dienst-URL mit --os-url, OS_URL oder auth.url fest\n" + +msgid "Set a token with --os-token, OS_TOKEN or auth.token\n" +msgstr "Legen Sie einen Token mit --os-token, OS_TOKEN oder auth.token fest\n" + +msgid "Set a username with --os-username, OS_USERNAME, or auth.username\n" +msgstr "" +"Legen Sie einen Benutzernamen mit --os-username, OS_USERNAME oder auth." +"username fest\n" + +msgid "" +"Set an authentication URL, with --os-auth-url, OS_AUTH_URL or auth.auth_url\n" +msgstr "" +"Legen Sie eine Authentifizierungs-URL mit --os-auth-url, OS_AUTH_URL oder " +"auth.auth_url fest\n" + +msgid "Set default project (name or ID)" +msgstr "Standardprojekt festlegen (Name oder Kennung)" + +msgid "Set new root password (interactive only)" +msgstr "Neues root-Passwort festlegen (Nur interaktiv)" + +msgid "Set project description" +msgstr "Projektbeschreibung festlegen" + +msgid "Set project name" +msgstr "Projektname festlegen" + +msgid "Set user email address" +msgstr "E-Mail-Adresse des Benutzers festlegen" + +msgid "Set user name" +msgstr "Benutzername festlegen" + +msgid "Set user password" +msgstr "Benutzerpasswort festlegen" + +msgid "Show credentials for user (name or ID)" +msgstr "Anmeldedaten für Benutzer anzeigen (name or ID)" + +msgid "Show service catalog information" +msgstr "Dienstkataloginformation anzeigen" + +msgid "Target hostname" +msgstr "Zielhostname" + +msgid "" +"The argument --type is deprecated, use service create --name <service-name> " +"type instead." +msgstr "" +"Das Argument --type ist veraltet, verwenden Sie stattdessen service create --" +"name <Dienstname> type." + +msgid "Token to be deleted" +msgstr "Zu löschender Token" + +msgid "Use only IPv4 addresses" +msgstr "Nur IPv4-Adressen verwenden" + +msgid "Use only IPv6 addresses" +msgstr "Nur IPv6-Adressen verwenden" + +msgid "Use other IP address (public, private, etc)" +msgstr "Andere IP-Adresse verwenden (öffentlich, privat, usw.)" + +msgid "Use private IP address" +msgstr "Private IP-Adresse verwenden" + +msgid "Use public IP address" +msgstr "Öffentliche IP-Adresse verwenden" + +msgid "" +"Use specified volume as the config drive, or 'True' to use an ephemeral drive" +msgstr "" +"Benutzerdefinierter Datenträger als Konfigurationslaufwerk oder 'True', um " +"ein flüchtiges Laufwerk zu verwenden" + +msgid "User data file to serve from the metadata server" +msgstr "Vom Metadatenserver anzubietende Benutzerdatendatei" + +msgid "User must be specified" +msgstr "Benutzer muss angegeben werden" + +msgid "User to change (name or ID)" +msgstr "Zu ändernder Benutzer (Name oder Kennung)" + +msgid "User to display (name or ID)" +msgstr "Anzuzeigender Benutzer (Name oder Kennung)" + +msgid "User to list (name or ID)" +msgstr "Aufzulistender Benutzer (Name oder Kennung)" + +msgid "User(s) to delete (name or ID)" +msgstr "Zu löschende(r) Benutzer (Name oder Kennung)" + +msgid "Volume to add (name or ID)" +msgstr "Zu hinzufügender Datenträger (Name oder Kennung)" + +msgid "Volume to remove (name or ID)" +msgstr "Zu entfernender Datenträger (Name oder Kennung)" + +msgid "Wait for build to complete" +msgstr "Warten Sie, bis die Herstellung abgeschlossen ist" + +msgid "Wait for delete to complete" +msgstr "Warten Sie, bis das Löschen abgeschlossen ist" + +msgid "Wait for image create to complete" +msgstr "Warten Sie, bis die Abbilderstellung abgeschlossen ist" + +msgid "Wait for reboot to complete" +msgstr "Warten Sie, bis der Neustart abgeschlossen ist" + +msgid "Wait for rebuild to complete" +msgstr "Warten Sie, bis die Wiederherstellung abgeschlossen ist" + +msgid "Wait for resize to complete" +msgstr "Warten Sie, bis die Größenänderung abgeschlossen ist" + +msgid "either net-id or port-id should be specified but not both" +msgstr "entweder net-id oder port-id sollten angegeben sein, aber nicht beide" + +msgid "max instances should be > 0" +msgstr "max. Instanzen sollten > 0 sein" + +msgid "min instances should be <= max instances" +msgstr "min. Instanzen sollten <= max. Instanzen sein" + +msgid "min instances should be > 0" +msgstr "min. Instanzen sollten > 0 sein" diff --git a/openstackclient/locale/openstackclient.pot b/openstackclient/locale/openstackclient.pot new file mode 100644 index 00000000..afc89266 --- /dev/null +++ b/openstackclient/locale/openstackclient.pot @@ -0,0 +1,829 @@ +# Translations template for python-openstackclient. +# Copyright (C) 2016 ORGANIZATION +# This file is distributed under the same license as the +# python-openstackclient project. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2016. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: python-openstackclient 2.0.1.dev168\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2016-01-19 06:03+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.2.0\n" + +#: openstackclient/api/auth.py:144 +msgid "Set a username with --os-username, OS_USERNAME, or auth.username\n" +msgstr "" + +#: openstackclient/api/auth.py:147 +msgid "" +"Set an authentication URL, with --os-auth-url, OS_AUTH_URL or " +"auth.auth_url\n" +msgstr "" + +#: openstackclient/api/auth.py:155 +msgid "" +"Set a scope, such as a project or domain, set a project scope with --os-" +"project-name, OS_PROJECT_NAME or auth.project_name, set a domain scope " +"with --os-domain-name, OS_DOMAIN_NAME or auth.domain_name" +msgstr "" + +#: openstackclient/api/auth.py:161 openstackclient/api/auth.py:167 +msgid "Set a token with --os-token, OS_TOKEN or auth.token\n" +msgstr "" + +#: openstackclient/api/auth.py:163 +msgid "Set a service AUTH_URL, with --os-auth-url, OS_AUTH_URL or auth.auth_url\n" +msgstr "" + +#: openstackclient/api/auth.py:169 +msgid "Set a service URL, with --os-url, OS_URL or auth.url\n" +msgstr "" + +#: openstackclient/compute/v2/availability_zone.py:72 +#: openstackclient/compute/v2/server.py:737 +#: openstackclient/identity/v2_0/endpoint.py:114 +#: openstackclient/identity/v2_0/project.py:145 +#: openstackclient/identity/v2_0/service.py:128 +#: openstackclient/identity/v2_0/user.py:174 +msgid "List additional fields in output" +msgstr "" + +#: openstackclient/compute/v2/server.py:183 +#: openstackclient/compute/v2/server.py:219 +#: openstackclient/compute/v2/server.py:569 +#: openstackclient/compute/v2/server.py:923 +#: openstackclient/compute/v2/server.py:1031 +#: openstackclient/compute/v2/server.py:1086 +#: openstackclient/compute/v2/server.py:1179 +#: openstackclient/compute/v2/server.py:1219 +#: openstackclient/compute/v2/server.py:1245 +#: openstackclient/compute/v2/server.py:1336 +#: openstackclient/compute/v2/server.py:1420 +#: openstackclient/compute/v2/server.py:1457 +#: openstackclient/compute/v2/server.py:1732 +#: openstackclient/compute/v2/server.py:1756 +msgid "Server (name or ID)" +msgstr "" + +#: openstackclient/compute/v2/server.py:188 +msgid "Security group to add (name or ID)" +msgstr "" + +#: openstackclient/compute/v2/server.py:224 +msgid "Volume to add (name or ID)" +msgstr "" + +#: openstackclient/compute/v2/server.py:229 +msgid "Server internal device name for volume" +msgstr "" + +#: openstackclient/compute/v2/server.py:265 +#: openstackclient/compute/v2/server.py:1341 +msgid "New server name" +msgstr "" + +#: openstackclient/compute/v2/server.py:273 +msgid "Create server from this image (name or ID)" +msgstr "" + +#: openstackclient/compute/v2/server.py:278 +msgid "Create server from this volume (name or ID)" +msgstr "" + +#: openstackclient/compute/v2/server.py:284 +msgid "Create server with this flavor (name or ID)" +msgstr "" + +#: openstackclient/compute/v2/server.py:291 +msgid "" +"Security group to assign to this server (name or ID) (repeat for multiple" +" groups)" +msgstr "" + +#: openstackclient/compute/v2/server.py:297 +msgid "Keypair to inject into this server (optional extension)" +msgstr "" + +#: openstackclient/compute/v2/server.py:303 +msgid "Set a property on this server (repeat for multiple values)" +msgstr "" + +#: openstackclient/compute/v2/server.py:311 +msgid "File to inject into image before boot (repeat for multiple files)" +msgstr "" + +#: openstackclient/compute/v2/server.py:317 +msgid "User data file to serve from the metadata server" +msgstr "" + +#: openstackclient/compute/v2/server.py:322 +msgid "Select an availability zone for the server" +msgstr "" + +#: openstackclient/compute/v2/server.py:329 +msgid "" +"Map block devices; map is <id>:<type>:<size(GB)>:<delete_on_terminate> " +"(optional extension)" +msgstr "" + +#: openstackclient/compute/v2/server.py:339 +msgid "" +"Create a NIC on the server. Specify option multiple times to create " +"multiple NICs. Either net-id or port-id must be provided, but not both. " +"net-id: attach NIC to network with this UUID, port-id: attach NIC to port" +" with this UUID, v4-fixed-ip: IPv4 fixed address for NIC (optional), v6" +"-fixed-ip: IPv6 fixed address for NIC (optional)." +msgstr "" + +#: openstackclient/compute/v2/server.py:352 +msgid "Hints for the scheduler (optional extension)" +msgstr "" + +#: openstackclient/compute/v2/server.py:358 +msgid "" +"Use specified volume as the config drive, or 'True' to use an ephemeral " +"drive" +msgstr "" + +#: openstackclient/compute/v2/server.py:366 +msgid "Minimum number of servers to launch (default=1)" +msgstr "" + +#: openstackclient/compute/v2/server.py:373 +msgid "Maximum number of servers to launch (default=1)" +msgstr "" + +#: openstackclient/compute/v2/server.py:378 +msgid "Wait for build to complete" +msgstr "" + +#: openstackclient/compute/v2/server.py:418 +msgid "min instances should be <= max instances" +msgstr "" + +#: openstackclient/compute/v2/server.py:421 +msgid "min instances should be > 0" +msgstr "" + +#: openstackclient/compute/v2/server.py:424 +msgid "max instances should be > 0" +msgstr "" + +#: openstackclient/compute/v2/server.py:453 +msgid "Volume name or ID must be specified if --block-device-mapping is specified" +msgstr "" + +#: openstackclient/compute/v2/server.py:465 +msgid "either net-id or port-id should be specified but not both" +msgstr "" + +#: openstackclient/compute/v2/server.py:485 +msgid "can't create server with port specified since network endpoint not enabled" +msgstr "" + +#: openstackclient/compute/v2/server.py:550 +#, python-format +msgid "Error creating server: %s" +msgstr "" + +#: openstackclient/compute/v2/server.py:552 +msgid "" +"\n" +"Error creating server" +msgstr "" + +#: openstackclient/compute/v2/server.py:574 +msgid "Name of new image (default is server name)" +msgstr "" + +#: openstackclient/compute/v2/server.py:579 +msgid "Wait for image create to complete" +msgstr "" + +#: openstackclient/compute/v2/server.py:609 +#, python-format +msgid "Error creating server snapshot: %s" +msgstr "" + +#: openstackclient/compute/v2/server.py:611 +msgid "" +"\n" +"Error creating server snapshot" +msgstr "" + +#: openstackclient/compute/v2/server.py:633 +msgid "Server(s) to delete (name or ID)" +msgstr "" + +#: openstackclient/compute/v2/server.py:638 +msgid "Wait for delete to complete" +msgstr "" + +#: openstackclient/compute/v2/server.py:657 +#, python-format +msgid "Error deleting server: %s" +msgstr "" + +#: openstackclient/compute/v2/server.py:659 +msgid "" +"\n" +"Error deleting server" +msgstr "" + +#: openstackclient/compute/v2/server.py:673 +msgid "Only return instances that match the reservation" +msgstr "" + +#: openstackclient/compute/v2/server.py:678 +msgid "Regular expression to match IP addresses" +msgstr "" + +#: openstackclient/compute/v2/server.py:683 +msgid "Regular expression to match IPv6 addresses" +msgstr "" + +#: openstackclient/compute/v2/server.py:688 +msgid "Regular expression to match names" +msgstr "" + +#: openstackclient/compute/v2/server.py:693 +msgid "Regular expression to match instance name (admin only)" +msgstr "" + +#: openstackclient/compute/v2/server.py:699 +msgid "Search by server status" +msgstr "" + +#: openstackclient/compute/v2/server.py:704 +msgid "Search by flavor (name or ID)" +msgstr "" + +#: openstackclient/compute/v2/server.py:709 +msgid "Search by image (name or ID)" +msgstr "" + +#: openstackclient/compute/v2/server.py:714 +msgid "Search by hostname" +msgstr "" + +#: openstackclient/compute/v2/server.py:720 +msgid "Include all projects (admin only)" +msgstr "" + +#: openstackclient/compute/v2/server.py:730 +msgid "Search by user (admin only) (name or ID)" +msgstr "" + +#: openstackclient/compute/v2/server.py:888 +msgid "Server(s) to lock (name or ID)" +msgstr "" + +#: openstackclient/compute/v2/server.py:928 +msgid "Target hostname" +msgstr "" + +#: openstackclient/compute/v2/server.py:936 +msgid "Perform a shared live migration (default)" +msgstr "" + +#: openstackclient/compute/v2/server.py:942 +msgid "Perform a block live migration" +msgstr "" + +#: openstackclient/compute/v2/server.py:949 +msgid "Allow disk over-commit on the destination host" +msgstr "" + +#: openstackclient/compute/v2/server.py:956 +msgid "Do not over-commit disk on the destination host (default)" +msgstr "" + +#: openstackclient/compute/v2/server.py:962 +#: openstackclient/compute/v2/server.py:1265 +msgid "Wait for resize to complete" +msgstr "" + +#: openstackclient/compute/v2/server.py:990 +#: openstackclient/compute/v2/server.py:1290 +msgid "Complete\n" +msgstr "" + +#: openstackclient/compute/v2/server.py:992 +msgid "" +"\n" +"Error migrating server" +msgstr "" + +#: openstackclient/compute/v2/server.py:1007 +msgid "Server(s) to pause (name or ID)" +msgstr "" + +#: openstackclient/compute/v2/server.py:1040 +msgid "Perform a hard reboot" +msgstr "" + +#: openstackclient/compute/v2/server.py:1048 +msgid "Perform a soft reboot" +msgstr "" + +#: openstackclient/compute/v2/server.py:1053 +msgid "Wait for reboot to complete" +msgstr "" + +#: openstackclient/compute/v2/server.py:1070 +msgid "" +"\n" +"Reboot complete\n" +msgstr "" + +#: openstackclient/compute/v2/server.py:1072 +msgid "" +"\n" +"Error rebooting server\n" +msgstr "" + +#: openstackclient/compute/v2/server.py:1091 +msgid "" +"Recreate server from the specified image (name or ID). Defaults to the " +"currently used one." +msgstr "" + +#: openstackclient/compute/v2/server.py:1102 +msgid "Wait for rebuild to complete" +msgstr "" + +#: openstackclient/compute/v2/server.py:1124 +msgid "" +"\n" +"Complete\n" +msgstr "" + +#: openstackclient/compute/v2/server.py:1126 +msgid "" +"\n" +"Error rebuilding server" +msgstr "" + +#: openstackclient/compute/v2/server.py:1143 +msgid "Name or ID of server to use" +msgstr "" + +#: openstackclient/compute/v2/server.py:1148 +msgid "Name or ID of security group to remove from server" +msgstr "" + +#: openstackclient/compute/v2/server.py:1184 +msgid "Volume to remove (name or ID)" +msgstr "" + +#: openstackclient/compute/v2/server.py:1250 +msgid "Resize server to specified flavor" +msgstr "" + +#: openstackclient/compute/v2/server.py:1255 +msgid "Confirm server resize is complete" +msgstr "" + +#: openstackclient/compute/v2/server.py:1260 +msgid "Restore server state before resize" +msgstr "" + +#: openstackclient/compute/v2/server.py:1292 +msgid "" +"\n" +"Error resizing server" +msgstr "" + +#: openstackclient/compute/v2/server.py:1311 +msgid "Server(s) to resume (name or ID)" +msgstr "" + +#: openstackclient/compute/v2/server.py:1346 +msgid "Set new root password (interactive only)" +msgstr "" + +#: openstackclient/compute/v2/server.py:1352 +msgid "" +"Property to add/change for this server (repeat option to set multiple " +"properties)" +msgstr "" + +#: openstackclient/compute/v2/server.py:1376 +msgid "New password: " +msgstr "" + +#: openstackclient/compute/v2/server.py:1377 +msgid "Retype new password: " +msgstr "" + +#: openstackclient/compute/v2/server.py:1381 +msgid "Passwords do not match, password unchanged" +msgstr "" + +#: openstackclient/compute/v2/server.py:1396 +msgid "Server(s) to shelve (name or ID)" +msgstr "" + +#: openstackclient/compute/v2/server.py:1426 +msgid "Display server diagnostics information" +msgstr "" + +#: openstackclient/compute/v2/server.py:1439 +msgid "Error retrieving diagnostics data" +msgstr "" + +#: openstackclient/compute/v2/server.py:1462 +msgid "Login name (ssh -l option)" +msgstr "" + +#: openstackclient/compute/v2/server.py:1474 +msgid "Destination port (ssh -p option)" +msgstr "" + +#: openstackclient/compute/v2/server.py:1486 +msgid "Private key file (ssh -i option)" +msgstr "" + +#: openstackclient/compute/v2/server.py:1497 +msgid "Options in ssh_config(5) format (ssh -o option)" +msgstr "" + +#: openstackclient/compute/v2/server.py:1511 +msgid "Use only IPv4 addresses" +msgstr "" + +#: openstackclient/compute/v2/server.py:1518 +msgid "Use only IPv6 addresses" +msgstr "" + +#: openstackclient/compute/v2/server.py:1527 +msgid "Use public IP address" +msgstr "" + +#: openstackclient/compute/v2/server.py:1535 +msgid "Use private IP address" +msgstr "" + +#: openstackclient/compute/v2/server.py:1542 +msgid "Use other IP address (public, private, etc)" +msgstr "" + +#: openstackclient/compute/v2/server.py:1605 +msgid "Server(s) to start (name or ID)" +msgstr "" + +#: openstackclient/compute/v2/server.py:1630 +msgid "Server(s) to stop (name or ID)" +msgstr "" + +#: openstackclient/compute/v2/server.py:1655 +msgid "Server(s) to suspend (name or ID)" +msgstr "" + +#: openstackclient/compute/v2/server.py:1681 +msgid "Server(s) to unlock (name or ID)" +msgstr "" + +#: openstackclient/compute/v2/server.py:1707 +msgid "Server(s) to unpause (name or ID)" +msgstr "" + +#: openstackclient/compute/v2/server.py:1763 +msgid "Property key to remove from server (repeat to unset multiple values)" +msgstr "" + +#: openstackclient/compute/v2/server.py:1794 +msgid "Server(s) to unshelve (name or ID)" +msgstr "" + +#: openstackclient/identity/v2_0/catalog.py:75 +#: openstackclient/identity/v3/catalog.py:72 +msgid "Service to display (type or name)" +msgstr "" + +#: openstackclient/identity/v2_0/ec2creds.py:40 +#: openstackclient/identity/v3/ec2creds.py:65 +msgid "" +"Create credentials in project (name or ID; default: current authenticated" +" project)" +msgstr "" + +#: openstackclient/identity/v2_0/ec2creds.py:48 +#: openstackclient/identity/v3/ec2creds.py:73 +msgid "" +"Create credentials for user (name or ID; default: current authenticated " +"user)" +msgstr "" + +#: openstackclient/identity/v2_0/ec2creds.py:99 +#: openstackclient/identity/v2_0/ec2creds.py:172 +#: openstackclient/identity/v3/ec2creds.py:129 +#: openstackclient/identity/v3/ec2creds.py:187 +msgid "Credentials access key" +msgstr "" + +#: openstackclient/identity/v2_0/ec2creds.py:104 +#: openstackclient/identity/v3/ec2creds.py:134 +msgid "Delete credentials for user (name or ID)" +msgstr "" + +#: openstackclient/identity/v2_0/ec2creds.py:134 +#: openstackclient/identity/v3/ec2creds.py:156 +msgid "Filter list by user (name or ID)" +msgstr "" + +#: openstackclient/identity/v2_0/ec2creds.py:177 +#: openstackclient/identity/v3/ec2creds.py:192 +msgid "Show credentials for user (name or ID)" +msgstr "" + +#: openstackclient/identity/v2_0/endpoint.py:40 +msgid "New endpoint service (name or ID)" +msgstr "" + +#: openstackclient/identity/v2_0/endpoint.py:46 +msgid "New endpoint public URL (required)" +msgstr "" + +#: openstackclient/identity/v2_0/endpoint.py:51 +msgid "New endpoint admin URL" +msgstr "" + +#: openstackclient/identity/v2_0/endpoint.py:56 +msgid "New endpoint internal URL" +msgstr "" + +#: openstackclient/identity/v2_0/endpoint.py:61 +msgid "New endpoint region ID" +msgstr "" + +#: openstackclient/identity/v2_0/endpoint.py:93 +msgid "Endpoint ID to delete" +msgstr "" + +#: openstackclient/identity/v2_0/endpoint.py:149 +msgid "Endpoint ID to display" +msgstr "" + +#: openstackclient/identity/v2_0/project.py:41 +msgid "New project name" +msgstr "" + +#: openstackclient/identity/v2_0/project.py:46 +msgid "Project description" +msgstr "" + +#: openstackclient/identity/v2_0/project.py:52 +msgid "Enable project (default)" +msgstr "" + +#: openstackclient/identity/v2_0/project.py:57 +#: openstackclient/identity/v2_0/project.py:194 +msgid "Disable project" +msgstr "" + +#: openstackclient/identity/v2_0/project.py:63 +msgid "Add a property to <name> (repeat option to set multiple properties)" +msgstr "" + +#: openstackclient/identity/v2_0/project.py:69 +#: openstackclient/identity/v3/project.py:80 +msgid "Return existing project" +msgstr "" + +#: openstackclient/identity/v2_0/project.py:117 +msgid "Project(s) to delete (name or ID)" +msgstr "" + +#: openstackclient/identity/v2_0/project.py:173 +#: openstackclient/identity/v2_0/project.py:313 +msgid "Project to modify (name or ID)" +msgstr "" + +#: openstackclient/identity/v2_0/project.py:178 +msgid "Set project name" +msgstr "" + +#: openstackclient/identity/v2_0/project.py:183 +msgid "Set project description" +msgstr "" + +#: openstackclient/identity/v2_0/project.py:189 +msgid "Enable project" +msgstr "" + +#: openstackclient/identity/v2_0/project.py:200 +msgid "Set a project property (repeat option to set multiple properties)" +msgstr "" + +#: openstackclient/identity/v2_0/project.py:253 +msgid "Project to display (name or ID)" +msgstr "" + +#: openstackclient/identity/v2_0/project.py:320 +msgid "Unset a project property (repeat option to unset multiple properties)" +msgstr "" + +#: openstackclient/identity/v2_0/role.py:41 +msgid "Role to add to <project>:<user> (name or ID)" +msgstr "" + +#: openstackclient/identity/v2_0/role.py:47 +#: openstackclient/identity/v2_0/role.py:309 +msgid "Include <project> (name or ID)" +msgstr "" + +#: openstackclient/identity/v2_0/role.py:53 +#: openstackclient/identity/v2_0/role.py:315 +msgid "Include <user> (name or ID)" +msgstr "" + +#: openstackclient/identity/v2_0/role.py:87 +msgid "New role name" +msgstr "" + +#: openstackclient/identity/v2_0/role.py:92 +#: openstackclient/identity/v3/role.py:165 +msgid "Return existing role" +msgstr "" + +#: openstackclient/identity/v2_0/role.py:127 +msgid "Role(s) to delete (name or ID)" +msgstr "" + +#: openstackclient/identity/v2_0/role.py:194 +#: openstackclient/identity/v2_0/role.py:257 +msgid "Project must be specified" +msgstr "" + +#: openstackclient/identity/v2_0/role.py:208 +#: openstackclient/identity/v2_0/role.py:263 +msgid "User must be specified" +msgstr "" + +#: openstackclient/identity/v2_0/role.py:236 +msgid "User to list (name or ID)" +msgstr "" + +#: openstackclient/identity/v2_0/role.py:241 +msgid "Filter users by <project> (name or ID)" +msgstr "" + +#: openstackclient/identity/v2_0/role.py:303 +msgid "Role to remove (name or ID)" +msgstr "" + +#: openstackclient/identity/v2_0/role.py:344 +msgid "Role to display (name or ID)" +msgstr "" + +#: openstackclient/identity/v2_0/service.py:42 +msgid "New service type (compute, image, identity, volume, etc)" +msgstr "" + +#: openstackclient/identity/v2_0/service.py:53 +msgid "New service name" +msgstr "" + +#: openstackclient/identity/v2_0/service.py:58 +msgid "New service description" +msgstr "" + +#: openstackclient/identity/v2_0/service.py:78 +msgid "" +"The argument --type is deprecated, use service create --name <service-" +"name> type instead." +msgstr "" + +#: openstackclient/identity/v2_0/service.py:105 +msgid "Service to delete (name or ID)" +msgstr "" + +#: openstackclient/identity/v2_0/service.py:156 +msgid "Service to display (type, name or ID)" +msgstr "" + +#: openstackclient/identity/v2_0/service.py:162 +msgid "Show service catalog information" +msgstr "" + +#: openstackclient/identity/v2_0/service.py:180 +#, python-format +msgid "No service catalog with a type, name or ID of '%s' exists." +msgstr "" + +#: openstackclient/identity/v2_0/token.py:55 +msgid "Token to be deleted" +msgstr "" + +#: openstackclient/identity/v2_0/user.py:40 +msgid "New user name" +msgstr "" + +#: openstackclient/identity/v2_0/user.py:45 +msgid "Default project (name or ID)" +msgstr "" + +#: openstackclient/identity/v2_0/user.py:50 +#: openstackclient/identity/v2_0/user.py:273 +msgid "Set user password" +msgstr "" + +#: openstackclient/identity/v2_0/user.py:56 +#: openstackclient/identity/v2_0/user.py:279 +msgid "Prompt interactively for password" +msgstr "" + +#: openstackclient/identity/v2_0/user.py:61 +#: openstackclient/identity/v2_0/user.py:284 +msgid "Set user email address" +msgstr "" + +#: openstackclient/identity/v2_0/user.py:67 +#: openstackclient/identity/v2_0/user.py:290 +msgid "Enable user (default)" +msgstr "" + +#: openstackclient/identity/v2_0/user.py:72 +#: openstackclient/identity/v2_0/user.py:295 +msgid "Disable user" +msgstr "" + +#: openstackclient/identity/v2_0/user.py:77 +#: openstackclient/identity/v3/user.py:90 +msgid "Return existing user" +msgstr "" + +#: openstackclient/identity/v2_0/user.py:141 +msgid "User(s) to delete (name or ID)" +msgstr "" + +#: openstackclient/identity/v2_0/user.py:168 +msgid "Filter users by project (name or ID)" +msgstr "" + +#: openstackclient/identity/v2_0/user.py:258 +msgid "User to change (name or ID)" +msgstr "" + +#: openstackclient/identity/v2_0/user.py:263 +msgid "Set user name" +msgstr "" + +#: openstackclient/identity/v2_0/user.py:268 +msgid "Set default project (name or ID)" +msgstr "" + +#: openstackclient/identity/v2_0/user.py:361 +msgid "User to display (name or ID)" +msgstr "" + +#: openstackclient/identity/v3/domain.py:62 +msgid "Return existing domain" +msgstr "" + +#: openstackclient/identity/v3/group.py:141 +msgid "Return existing group" +msgstr "" + +#: openstackclient/identity/v3/region.py:39 +msgid "New region ID" +msgstr "" + +#: openstackclient/identity/v3/region.py:44 +msgid "Parent region ID" +msgstr "" + +#: openstackclient/identity/v3/region.py:49 +#: openstackclient/identity/v3/region.py:144 +msgid "New region description" +msgstr "" + +#: openstackclient/identity/v3/region.py:79 +msgid "Region ID to delete" +msgstr "" + +#: openstackclient/identity/v3/region.py:101 +msgid "Filter by parent region ID" +msgstr "" + +#: openstackclient/identity/v3/region.py:134 +msgid "Region to modify" +msgstr "" + +#: openstackclient/identity/v3/region.py:139 +msgid "New parent region ID" +msgstr "" + +#: openstackclient/identity/v3/region.py:175 +msgid "Region to display" +msgstr "" + diff --git a/openstackclient/locale/zh_TW/LC_MESSAGES/openstackclient.po b/openstackclient/locale/zh_TW/LC_MESSAGES/openstackclient.po new file mode 100644 index 00000000..26032666 --- /dev/null +++ b/openstackclient/locale/zh_TW/LC_MESSAGES/openstackclient.po @@ -0,0 +1,495 @@ +# Translations template for python-openstackclient. +# Copyright (C) 2015 ORGANIZATION +# This file is distributed under the same license as the +# python-openstackclient project. +# +# Translators: +# OpenStack Infra <zanata@openstack.org>, 2015. #zanata +msgid "" +msgstr "" +"Project-Id-Version: python-openstackclient 2.0.1.dev168\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2016-01-19 02:20+0000\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"PO-Revision-Date: 2015-06-14 06:41+0000\n" +"Last-Translator: openstackjenkins <jenkins@openstack.org>\n" +"Language: zh-TW\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"Generated-By: Babel 2.0\n" +"X-Generator: Zanata 3.7.3\n" +"Language-Team: Chinese (Taiwan)\n" + +msgid "" +"\n" +"Complete\n" +msgstr "" +"\n" +"完成\n" + +msgid "" +"\n" +"Error creating server" +msgstr "" +"\n" +"新增雲實例時出錯" + +msgid "" +"\n" +"Error creating server snapshot" +msgstr "" +"\n" +"新增雲實例即時存檔時出錯" + +msgid "" +"\n" +"Error migrating server" +msgstr "" +"\n" +"轉移雲實例出錯" + +msgid "" +"\n" +"Error rebooting server\n" +msgstr "" +"\n" +"重開雲實例出錯\n" + +msgid "" +"\n" +"Error rebuilding server" +msgstr "" +"\n" +"重建雲實例出錯" + +msgid "" +"\n" +"Error resizing server" +msgstr "" +"\n" +"調整雲實例容量時出錯" + +msgid "" +"\n" +"Reboot complete\n" +msgstr "" +"\n" +"重開機完成\n" + +msgid "Add a property to <name> (repeat option to set multiple properties)" +msgstr "加入屬性到 <name>(重復這選項來設定多個屬性)" + +msgid "Allow disk over-commit on the destination host" +msgstr "允許目標主機過量使用" + +msgid "Complete\n" +msgstr "完成\n" + +msgid "Confirm server resize is complete" +msgstr "確認調整雲實例容量完成" + +msgid "Credentials access key" +msgstr "憑鑰存取密鑰" + +msgid "Default project (name or ID)" +msgstr "預設專案(名稱或識別號)" + +msgid "Destination port (ssh -p option)" +msgstr "目標埠口(ssh -p 選項)" + +msgid "Disable project" +msgstr "關閉專案" + +msgid "Disable user" +msgstr "關閉用戶" + +msgid "Display server diagnostics information" +msgstr "顯示雲實例診斷資訊" + +msgid "Do not over-commit disk on the destination host (default)" +msgstr "不準目標主機過量使用(預設)" + +msgid "Enable project" +msgstr "啟用專案" + +msgid "Enable project (default)" +msgstr "啟用專案(預設)" + +msgid "Enable user (default)" +msgstr "啟用用戶(預設)" + +msgid "Endpoint ID to delete" +msgstr "要刪除的端點識別號" + +msgid "Endpoint ID to display" +msgstr "要顯示的端點識別號" + +#, python-format +msgid "Error creating server snapshot: %s" +msgstr "新增雲實例即時存檔時出錯:%s" + +#, python-format +msgid "Error creating server: %s" +msgstr "新增雲實例時出錯:%s" + +msgid "Error retrieving diagnostics data" +msgstr "獲得診斷資料時出錯" + +msgid "File to inject into image before boot (repeat for multiple files)" +msgstr "在開機前要注入映像檔的檔案(為多個檔案重復指定)" + +msgid "Filter by parent region ID" +msgstr "以父地區識別號來篩選" + +msgid "Filter users by <project> (name or ID)" +msgstr "以 <project> 來篩選用戶(名稱或識別號)" + +msgid "Filter users by project (name or ID)" +msgstr "以專案篩選用戶(名稱或識別號)" + +msgid "Hints for the scheduler (optional extension)" +msgstr "給排程器的提示(選用)" + +msgid "Include <project> (name or ID)" +msgstr "包括 <project>(名稱或識別號)" + +msgid "Include <user> (name or ID)" +msgstr "包括 <user>(名稱或識別號)" + +msgid "Include all projects (admin only)" +msgstr "包括所有的專案(管理員專用)" + +msgid "Keypair to inject into this server (optional extension)" +msgstr "要注入到此伺服器的密鑰對(選用)" + +msgid "List additional fields in output" +msgstr "列出額外的欄位" + +msgid "Login name (ssh -l option)" +msgstr "登入名稱(ssh -l 選項)" + +msgid "" +"Map block devices; map is <id>:<type>:<size(GB)>:<delete_on_terminate> " +"(optional extension)" +msgstr "" +"映射區塊裝置;映射是 <id>:<type>:<size(GB)>:<delete_on_terminate>(選用)" + +msgid "Maximum number of servers to launch (default=1)" +msgstr "最多要發動的雲實例(預設為 1)" + +msgid "Minimum number of servers to launch (default=1)" +msgstr "最少要發動的雲實例(預設為 1)" + +msgid "Name of new image (default is server name)" +msgstr "新映像檔的名稱(預設為雲實例名稱)" + +msgid "Name or ID of security group to remove from server" +msgstr "要從雲實例移除的安全性群組名稱或識別號" + +msgid "Name or ID of server to use" +msgstr "要用的雲實例名稱或識別號" + +msgid "New endpoint admin URL" +msgstr "新端點管理員網址" + +msgid "New endpoint internal URL" +msgstr "新端點內部網址" + +msgid "New endpoint public URL (required)" +msgstr "新端點公開網址(需要)" + +msgid "New endpoint region ID" +msgstr "新端點地區識別號" + +msgid "New endpoint service (name or ID)" +msgstr "新端點伺服器(名稱或識別號)" + +msgid "New parent region ID" +msgstr "新父地區識別號" + +msgid "New password: " +msgstr "新密碼:" + +msgid "New project name" +msgstr "新專案名稱" + +msgid "New region ID" +msgstr "新地區識別號" + +msgid "New region description" +msgstr "新地區描述" + +msgid "New role name" +msgstr "新角色名稱" + +msgid "New server name" +msgstr "新雲實例名稱" + +msgid "New service description" +msgstr "新伺服器描述" + +msgid "New service name" +msgstr "新伺服器名稱" + +msgid "New service type (compute, image, identity, volume, etc)" +msgstr "新伺服器類型(compute、image、identity 或 volume 等等)" + +msgid "New user name" +msgstr "新用戶名稱" + +#, python-format +msgid "No service catalog with a type, name or ID of '%s' exists." +msgstr "沒有相似「%s」類型、名稱或識別號的伺服器分類。" + +msgid "Only return instances that match the reservation" +msgstr "只回傳要保留的雲實例" + +msgid "Options in ssh_config(5) format (ssh -o option)" +msgstr "ssh_config(5) 格式的選項(ssh -o 選項)" + +msgid "Parent region ID" +msgstr "父地區識別號" + +msgid "Passwords do not match, password unchanged" +msgstr "密碼不一樣,未更換密碼" + +msgid "Perform a block live migration" +msgstr "覆行區塊的即時轉移" + +msgid "Perform a hard reboot" +msgstr "履行強制重開機" + +msgid "Perform a shared live migration (default)" +msgstr "覆行已分享的即時轉移(預設)" + +msgid "Perform a soft reboot" +msgstr "履行重開機" + +msgid "Private key file (ssh -i option)" +msgstr "私鑰檔案(ssh -i 選項)" + +msgid "Project description" +msgstr "專案描述" + +msgid "Project must be specified" +msgstr "必須指定專案" + +msgid "Project to display (name or ID)" +msgstr "要顯示的專案(名稱或識別號)" + +msgid "Project to modify (name or ID)" +msgstr "要更改的專案(名稱或識別號)" + +msgid "Project(s) to delete (name or ID)" +msgstr "要刪除的專案(名稱或識別號)" + +msgid "Prompt interactively for password" +msgstr "為密碼互動提示" + +msgid "Property key to remove from server (repeat to unset multiple values)" +msgstr "要從雲實例上移除的屬性鍵(重復來取消選擇多個值)" + +msgid "" +"Property to add/change for this server (repeat option to set multiple " +"properties)" +msgstr "要加入這個雲實例的屬性(重復這選項來設定多個屬性)" + +msgid "Region ID to delete" +msgstr "要刪除的地區識別號" + +msgid "Region to display" +msgstr "要顯示的地區" + +msgid "Region to modify" +msgstr "要更改的地區" + +msgid "Regular expression to match IP addresses" +msgstr "以正規式來匹配 IP 位址" + +msgid "Regular expression to match IPv6 addresses" +msgstr "以正規式來匹配 IPv6 位址" + +msgid "Regular expression to match instance name (admin only)" +msgstr "以正規式來匹配雲實例名稱(管理員專用)" + +msgid "Regular expression to match names" +msgstr "以正規式來匹配名稱" + +msgid "Resize server to specified flavor" +msgstr "調整雲實例容量來符合指定的虛擬硬體樣板" + +msgid "Restore server state before resize" +msgstr "恢復雲實例狀態到未調整容量前" + +msgid "Return existing domain" +msgstr "回傳存在的地域" + +msgid "Return existing group" +msgstr "回傳存在的群組" + +msgid "Return existing project" +msgstr "回傳存在的專案" + +msgid "Return existing role" +msgstr "回傳存在的角色" + +msgid "Return existing user" +msgstr "回傳存在的用戶" + +msgid "Retype new password: " +msgstr "重新輸入新密碼:" + +msgid "Role to add to <project>:<user> (name or ID)" +msgstr "加入角色到 <project>:<user>(名稱或識別號)" + +msgid "Role to display (name or ID)" +msgstr "要顯示的角色(名稱或識別號)" + +msgid "Role to remove (name or ID)" +msgstr "要移除的角色(名稱或識別號)" + +msgid "Role(s) to delete (name or ID)" +msgstr "要刪除的角色(名稱或識別號)" + +msgid "Search by hostname" +msgstr "以主機名稱來尋找" + +msgid "Search by server status" +msgstr "以雲實例狀態來尋找" + +msgid "Security group to add (name or ID)" +msgstr "要加入的安全性群組(名稱或識別號)" + +msgid "Select an availability zone for the server" +msgstr "為雲實例選擇可用的區域。" + +msgid "Server (name or ID)" +msgstr "伺服器(名稱或識別號)" + +msgid "Server internal device name for volume" +msgstr "雲硬碟在雲實例內的裝置名稱" + +msgid "Server(s) to delete (name or ID)" +msgstr "要刪除的雲實例(名稱或識別號)" + +msgid "Service to delete (name or ID)" +msgstr "要刪除的伺服器(名稱或識別號)" + +msgid "Service to display (type or name)" +msgstr "要顯示的伺服器(類型或名稱)" + +msgid "Service to display (type, name or ID)" +msgstr "要顯示的伺服器(類型、名稱或識別號)" + +msgid "Set a project property (repeat option to set multiple properties)" +msgstr "設定專案屬性(重復這選項來設定多個屬性)" + +msgid "Set a property on this server (repeat for multiple values)" +msgstr "為此伺服器設定屬性(為多個值重複設定)" + +msgid "Set default project (name or ID)" +msgstr "設定預設專案(名稱或識別號)" + +msgid "Set new root password (interactive only)" +msgstr "設定新密碼(只限互動)" + +msgid "Set project description" +msgstr "設定專案描述" + +msgid "Set project name" +msgstr "設定專案名稱" + +msgid "Set user email address" +msgstr "設定用戶電子信箱位址" + +msgid "Set user name" +msgstr "設定用戶名稱" + +msgid "Set user password" +msgstr "設定用戶密碼" + +msgid "Show service catalog information" +msgstr "顯示伺服器分類資訊" + +msgid "Target hostname" +msgstr "目標主機名稱" + +msgid "" +"The argument --type is deprecated, use service create --name <service-name> " +"type instead." +msgstr "" +"已經淘汰 --type 參數,請用 service create --name <service-name> 來代替。" + +msgid "Token to be deleted" +msgstr "要刪除的記號" + +msgid "Use only IPv4 addresses" +msgstr "只使用 IPv4 位址" + +msgid "Use only IPv6 addresses" +msgstr "只使用 IPv6 位址" + +msgid "Use other IP address (public, private, etc)" +msgstr "使用其他 IP 位址(公開、私人等等)" + +msgid "Use private IP address" +msgstr "使用私人 IP 位址" + +msgid "Use public IP address" +msgstr "使用公開 IP 位址" + +msgid "" +"Use specified volume as the config drive, or 'True' to use an ephemeral drive" +msgstr "使用指定的雲硬碟為設定檔硬碟,或「True」來使用暫時性硬碟" + +msgid "User data file to serve from the metadata server" +msgstr "來自詮釋資料伺服器要服務的用戶資料檔案" + +msgid "User must be specified" +msgstr "必須指定用戶" + +msgid "User to change (name or ID)" +msgstr "要更換的用戶(名稱或識別號)" + +msgid "User to display (name or ID)" +msgstr "要顯示的用戶(名稱或識別號)" + +msgid "User to list (name or ID)" +msgstr "要列出的用戶(名稱或識別號)" + +msgid "User(s) to delete (name or ID)" +msgstr "要刪除的用戶(名稱或識別號)" + +msgid "Volume to add (name or ID)" +msgstr "要加入的雲硬碟(名稱或識別號)" + +msgid "Volume to remove (name or ID)" +msgstr "要移除的雲硬碟(名稱或識別號)" + +msgid "Wait for build to complete" +msgstr "等待完成建立" + +msgid "Wait for image create to complete" +msgstr "等待映像檔新增完成" + +msgid "Wait for reboot to complete" +msgstr "等待重開機完成" + +msgid "Wait for rebuild to complete" +msgstr "等待重建完成" + +msgid "Wait for resize to complete" +msgstr "等待調整容量完成" + +msgid "either net-id or port-id should be specified but not both" +msgstr "任選網路識別號或接口識別號,但不能兩者都指定" + +msgid "max instances should be > 0" +msgstr "雲實例發動的最大值要大於 0" + +msgid "min instances should be <= max instances" +msgstr "雲實例發動的最少值不應大於最大值" + +msgid "min instances should be > 0" +msgstr "雲實例發動的最少值要大於 0" diff --git a/openstackclient/network/v2/subnet.py b/openstackclient/network/v2/subnet.py new file mode 100644 index 00000000..62747125 --- /dev/null +++ b/openstackclient/network/v2/subnet.py @@ -0,0 +1,70 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +"""Subnet action implementations""" + +import logging + +from cliff import lister + +from openstackclient.common import utils + + +def _format_allocation_pools(data): + pool_formatted = ['%s-%s' % (pool.get('start', ''), pool.get('end', '')) + for pool in data] + return ','.join(pool_formatted) + + +_formatters = { + 'allocation_pools': _format_allocation_pools, + 'dns_nameservers': utils.format_list, + 'host_routes': utils.format_list, +} + + +class ListSubnet(lister.Lister): + """List subnets""" + + log = logging.getLogger(__name__ + '.ListSubnet') + + def get_parser(self, prog_name): + parser = super(ListSubnet, self).get_parser(prog_name) + parser.add_argument( + '--long', + action='store_true', + default=False, + help='List additional fields in output', + ) + return parser + + def take_action(self, parsed_args): + self.log.debug('take_action(%s)' % parsed_args) + + data = self.app.client_manager.network.subnets() + + headers = ('ID', 'Name', 'Network', 'Subnet') + columns = ('id', 'name', 'network_id', 'cidr') + if parsed_args.long: + headers += ('Project', 'DHCP', 'Name Servers', + 'Allocation Pools', 'Host Routes', 'IP Version', + 'Gateway') + columns += ('tenant_id', 'enable_dhcp', 'dns_nameservers', + 'allocation_pools', 'host_routes', 'ip_version', + 'gateway_ip') + + return (headers, + (utils.get_item_properties( + s, columns, + formatters=_formatters, + ) for s in data)) diff --git a/openstackclient/tests/common/test_availability_zone.py b/openstackclient/tests/common/test_availability_zone.py new file mode 100644 index 00000000..232b56c9 --- /dev/null +++ b/openstackclient/tests/common/test_availability_zone.py @@ -0,0 +1,192 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +import six + +from openstackclient.common import availability_zone +from openstackclient.tests.compute.v2 import fakes as compute_fakes +from openstackclient.tests import fakes +from openstackclient.tests import utils +from openstackclient.tests.volume.v2 import fakes as volume_fakes + + +def _build_compute_az_datalist(compute_az, long_datalist=False): + datalist = () + if not long_datalist: + datalist = ( + compute_az.zoneName, + 'available', + ) + else: + for host, services in six.iteritems(compute_az.hosts): + for service, state in six.iteritems(services): + datalist += ( + compute_az.zoneName, + 'available', + host, + service, + 'enabled :-) ' + state['updated_at'], + ) + return (datalist,) + + +def _build_volume_az_datalist(volume_az, long_datalist=False): + datalist = () + if not long_datalist: + datalist = ( + volume_az.zoneName, + 'available', + ) + else: + datalist = ( + volume_az.zoneName, + 'available', + '', '', '', + ) + return (datalist,) + + +class TestAvailabilityZone(utils.TestCommand): + + def setUp(self): + super(TestAvailabilityZone, self).setUp() + + compute_client = compute_fakes.FakeComputev2Client( + endpoint=fakes.AUTH_URL, + token=fakes.AUTH_TOKEN, + ) + self.app.client_manager.compute = compute_client + + self.compute_azs_mock = compute_client.availability_zones + self.compute_azs_mock.reset_mock() + + volume_client = volume_fakes.FakeVolumeClient( + endpoint=fakes.AUTH_URL, + token=fakes.AUTH_TOKEN, + ) + self.app.client_manager.volume = volume_client + + self.volume_azs_mock = volume_client.availability_zones + self.volume_azs_mock.reset_mock() + + +class TestAvailabilityZoneList(TestAvailabilityZone): + + compute_azs = \ + compute_fakes.FakeAvailabilityZone.create_availability_zones() + volume_azs = \ + volume_fakes.FakeAvailabilityZone.create_availability_zones(count=1) + + short_columnslist = ('Zone Name', 'Zone Status') + long_columnslist = ( + 'Zone Name', + 'Zone Status', + 'Host Name', + 'Service Name', + 'Service Status', + ) + + def setUp(self): + super(TestAvailabilityZoneList, self).setUp() + + self.compute_azs_mock.list.return_value = self.compute_azs + self.volume_azs_mock.list.return_value = self.volume_azs + + # Get the command object to test + self.cmd = availability_zone.ListAvailabilityZone(self.app, None) + + def test_availability_zone_list_no_options(self): + arglist = [] + verifylist = [] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # DisplayCommandBase.take_action() returns two tuples + columns, data = self.cmd.take_action(parsed_args) + + self.compute_azs_mock.list.assert_called_with() + self.volume_azs_mock.list.assert_called_with() + + self.assertEqual(self.short_columnslist, columns) + datalist = () + for compute_az in self.compute_azs: + datalist += _build_compute_az_datalist(compute_az) + for volume_az in self.volume_azs: + datalist += _build_volume_az_datalist(volume_az) + self.assertEqual(datalist, tuple(data)) + + def test_availability_zone_list_long(self): + arglist = [ + '--long', + ] + verifylist = [ + ('long', True), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # DisplayCommandBase.take_action() returns two tuples + columns, data = self.cmd.take_action(parsed_args) + + self.compute_azs_mock.list.assert_called_with() + self.volume_azs_mock.list.assert_called_with() + + self.assertEqual(self.long_columnslist, columns) + datalist = () + for compute_az in self.compute_azs: + datalist += _build_compute_az_datalist(compute_az, + long_datalist=True) + for volume_az in self.volume_azs: + datalist += _build_volume_az_datalist(volume_az, + long_datalist=True) + self.assertEqual(datalist, tuple(data)) + + def test_availability_zone_list_compute(self): + arglist = [ + '--compute', + ] + verifylist = [ + ('compute', True), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # DisplayCommandBase.take_action() returns two tuples + columns, data = self.cmd.take_action(parsed_args) + + self.compute_azs_mock.list.assert_called_with() + self.volume_azs_mock.list.assert_not_called() + + self.assertEqual(self.short_columnslist, columns) + datalist = () + for compute_az in self.compute_azs: + datalist += _build_compute_az_datalist(compute_az) + self.assertEqual(datalist, tuple(data)) + + def test_availability_zone_list_volume(self): + arglist = [ + '--volume', + ] + verifylist = [ + ('volume', True), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # DisplayCommandBase.take_action() returns two tuples + columns, data = self.cmd.take_action(parsed_args) + + self.compute_azs_mock.list.assert_not_called() + self.volume_azs_mock.list.assert_called_with() + + self.assertEqual(self.short_columnslist, columns) + datalist = () + for volume_az in self.volume_azs: + datalist += _build_volume_az_datalist(volume_az) + self.assertEqual(datalist, tuple(data)) diff --git a/openstackclient/tests/compute/v2/fakes.py b/openstackclient/tests/compute/v2/fakes.py index ecf7f599..a90c9ee7 100644 --- a/openstackclient/tests/compute/v2/fakes.py +++ b/openstackclient/tests/compute/v2/fakes.py @@ -88,6 +88,8 @@ SERVICE = { class FakeComputev2Client(object): def __init__(self, **kwargs): + self.availability_zones = mock.Mock() + self.availability_zones.resource_class = fakes.FakeResource(None, {}) self.images = mock.Mock() self.images.resource_class = fakes.FakeResource(None, {}) self.servers = mock.Mock() @@ -289,3 +291,63 @@ class FakeFlavor(object): if flavors is None: flavors = FakeServer.create_flavors(count) return mock.MagicMock(side_effect=flavors) + + +class FakeAvailabilityZone(object): + """Fake one or more compute availability zones (AZs).""" + + @staticmethod + def create_one_availability_zone(attrs={}, methods={}): + """Create a fake AZ. + + :param Dictionary attrs: + A dictionary with all attributes + :param Dictionary methods: + A dictionary with all methods + :return: + A FakeResource object with zoneName, zoneState, etc. + """ + # Set default attributes. + host_name = uuid.uuid4().hex + service_name = uuid.uuid4().hex + service_updated_at = uuid.uuid4().hex + availability_zone = { + 'zoneName': uuid.uuid4().hex, + 'zoneState': {'available': True}, + 'hosts': {host_name: {service_name: { + 'available': True, + 'active': True, + 'updated_at': service_updated_at, + }}}, + } + + # Overwrite default attributes. + availability_zone.update(attrs) + + availability_zone = fakes.FakeResource( + info=copy.deepcopy(availability_zone), + methods=methods, + loaded=True) + return availability_zone + + @staticmethod + def create_availability_zones(attrs={}, methods={}, count=2): + """Create multiple fake AZs. + + :param Dictionary attrs: + A dictionary with all attributes + :param Dictionary methods: + A dictionary with all methods + :param int count: + The number of AZs to fake + :return: + A list of FakeResource objects faking the AZs + """ + availability_zones = [] + for i in range(0, count): + availability_zone = \ + FakeAvailabilityZone.create_one_availability_zone( + attrs, methods) + availability_zones.append(availability_zone) + + return availability_zones diff --git a/openstackclient/tests/image/v1/test_image.py b/openstackclient/tests/image/v1/test_image.py index 4d964bdb..1e0b29aa 100644 --- a/openstackclient/tests/image/v1/test_image.py +++ b/openstackclient/tests/image/v1/test_image.py @@ -103,6 +103,7 @@ class TestImageCreate(TestImage): '--min-ram', '4', '--protected', '--private', + '--project', 'q', image_fakes.image_name, ] verifylist = [ @@ -114,6 +115,7 @@ class TestImageCreate(TestImage): ('unprotected', False), ('public', False), ('private', True), + ('project', 'q'), ('name', image_fakes.image_name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -130,6 +132,7 @@ class TestImageCreate(TestImage): min_ram=4, protected=True, is_public=False, + owner='q', data=mock.ANY, ) @@ -237,6 +240,19 @@ class TestImageDelete(TestImage): class TestImageList(TestImage): + columns = ( + 'ID', + 'Name', + 'Status', + ) + datalist = ( + ( + image_fakes.image_id, + image_fakes.image_name, + '', + ), + ) + def setUp(self): super(TestImageList, self).setUp() @@ -265,15 +281,8 @@ class TestImageList(TestImage): marker=image_fakes.image_id, ) - collist = ('ID', 'Name', 'Status') - - self.assertEqual(collist, columns) - datalist = (( - image_fakes.image_id, - image_fakes.image_name, - '', - ), ) - self.assertEqual(datalist, tuple(data)) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, tuple(data)) def test_image_list_public_option(self): arglist = [ @@ -294,15 +303,8 @@ class TestImageList(TestImage): marker=image_fakes.image_id, ) - collist = ('ID', 'Name', 'Status') - - self.assertEqual(collist, columns) - datalist = (( - image_fakes.image_id, - image_fakes.image_name, - '', - ), ) - self.assertEqual(datalist, tuple(data)) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, tuple(data)) def test_image_list_private_option(self): arglist = [ @@ -323,15 +325,8 @@ class TestImageList(TestImage): marker=image_fakes.image_id, ) - collist = ('ID', 'Name', 'Status') - - self.assertEqual(collist, columns) - datalist = (( - image_fakes.image_id, - image_fakes.image_name, - '', - ), ) - self.assertEqual(datalist, tuple(data)) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, tuple(data)) def test_image_list_long_option(self): arglist = [ @@ -358,7 +353,7 @@ class TestImageList(TestImage): 'Status', 'Visibility', 'Protected', - 'Owner', + 'Project', 'Properties', ) @@ -404,15 +399,8 @@ class TestImageList(TestImage): property_field='properties', ) - collist = ('ID', 'Name', 'Status') - - self.assertEqual(columns, collist) - datalist = (( - image_fakes.image_id, - image_fakes.image_name, - '', - ), ) - self.assertEqual(datalist, tuple(data)) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, tuple(data)) @mock.patch('openstackclient.common.utils.sort_items') def test_image_list_sort_option(self, si_mock): @@ -435,15 +423,8 @@ class TestImageList(TestImage): 'name:asc' ) - collist = ('ID', 'Name', 'Status') - - self.assertEqual(collist, columns) - datalist = (( - image_fakes.image_id, - image_fakes.image_name, - '', - ), ) - self.assertEqual(datalist, tuple(data)) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, tuple(data)) class TestImageSet(TestImage): @@ -484,22 +465,22 @@ class TestImageSet(TestImage): def test_image_set_options(self): arglist = [ '--name', 'new-name', - '--owner', 'new-owner', '--min-disk', '2', '--min-ram', '4', '--container-format', 'ovf', '--disk-format', 'vmdk', '--size', '35165824', + '--project', 'new-owner', image_fakes.image_name, ] verifylist = [ ('name', 'new-name'), - ('owner', 'new-owner'), ('min_disk', 2), ('min_ram', 4), ('container_format', 'ovf'), ('disk_format', 'vmdk'), ('size', 35165824), + ('project', 'new-owner'), ('image', image_fakes.image_name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) diff --git a/openstackclient/tests/image/v2/test_image.py b/openstackclient/tests/image/v2/test_image.py index 02182413..488eab20 100644 --- a/openstackclient/tests/image/v2/test_image.py +++ b/openstackclient/tests/image/v2/test_image.py @@ -131,11 +131,11 @@ class TestImageCreate(TestImage): '--disk-format', 'fs', '--min-disk', '10', '--min-ram', '4', - '--owner', self.new_image.owner, ('--protected' if self.new_image.protected else '--unprotected'), ('--private' if self.new_image.visibility == 'private' else '--public'), + '--project', self.new_image.owner, '--project-domain', identity_fakes.domain_id, self.new_image.name, ] @@ -144,11 +144,11 @@ class TestImageCreate(TestImage): ('disk_format', 'fs'), ('min_disk', 10), ('min_ram', 4), - ('owner', self.new_image.owner), ('protected', self.new_image.protected), ('unprotected', not self.new_image.protected), ('public', self.new_image.visibility == 'public'), ('private', self.new_image.visibility == 'private'), + ('project', self.new_image.owner), ('project_domain', identity_fakes.domain_id), ('name', self.new_image.name), ] @@ -217,6 +217,40 @@ class TestImageCreate(TestImage): parsed_args, ) + def test_image_create_with_unexist_project(self): + self.project_mock.get.side_effect = exceptions.NotFound(None) + self.project_mock.find.side_effect = exceptions.NotFound(None) + + arglist = [ + '--container-format', 'ovf', + '--disk-format', 'fs', + '--min-disk', '10', + '--min-ram', '4', + '--protected', + '--private', + '--project', 'unexist_owner', + image_fakes.image_name, + ] + verifylist = [ + ('container_format', 'ovf'), + ('disk_format', 'fs'), + ('min_disk', 10), + ('min_ram', 4), + ('protected', True), + ('unprotected', False), + ('public', False), + ('private', True), + ('project', 'unexist_owner'), + ('name', image_fakes.image_name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.assertRaises( + exceptions.CommandError, + self.cmd.take_action, + parsed_args, + ) + @mock.patch('glanceclient.common.utils.get_data_file', name='Open') def test_image_create_file(self, mock_open): mock_file = mock.MagicMock(name='File') @@ -299,6 +333,17 @@ class TestImageCreate(TestImage): class TestAddProjectToImage(TestImage): + columns = ( + 'image_id', + 'member_id', + 'status', + ) + datalist = ( + image_fakes.image_id, + identity_fakes.project_id, + image_fakes.member_status, + ) + def setUp(self): super(TestAddProjectToImage, self).setUp() @@ -341,14 +386,8 @@ class TestAddProjectToImage(TestImage): image_fakes.image_id, identity_fakes.project_id ) - collist = ('image_id', 'member_id', 'status') - self.assertEqual(collist, columns) - datalist = ( - image_fakes.image_id, - identity_fakes.project_id, - image_fakes.member_status - ) - self.assertEqual(datalist, data) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, data) def test_add_project_to_image_with_option(self): arglist = [ @@ -369,14 +408,8 @@ class TestAddProjectToImage(TestImage): image_fakes.image_id, identity_fakes.project_id ) - collist = ('image_id', 'member_id', 'status') - self.assertEqual(collist, columns) - datalist = ( - image_fakes.image_id, - identity_fakes.project_id, - image_fakes.member_status - ) - self.assertEqual(datalist, data) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, data) class TestImageDelete(TestImage): @@ -426,6 +459,19 @@ class TestImageDelete(TestImage): class TestImageList(TestImage): + columns = ( + 'ID', + 'Name', + 'Status', + ) + datalist = ( + ( + image_fakes.image_id, + image_fakes.image_name, + '', + ), + ) + def setUp(self): super(TestImageList, self).setUp() @@ -454,15 +500,8 @@ class TestImageList(TestImage): marker=image_fakes.image_id, ) - collist = ('ID', 'Name', 'Status') - - self.assertEqual(collist, columns) - datalist = (( - image_fakes.image_id, - image_fakes.image_name, - '', - ), ) - self.assertEqual(datalist, tuple(data)) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, tuple(data)) def test_image_list_public_option(self): arglist = [ @@ -483,15 +522,8 @@ class TestImageList(TestImage): marker=image_fakes.image_id, ) - collist = ('ID', 'Name', 'Status') - - self.assertEqual(collist, columns) - datalist = (( - image_fakes.image_id, - image_fakes.image_name, - '', - ), ) - self.assertEqual(datalist, tuple(data)) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, tuple(data)) def test_image_list_private_option(self): arglist = [ @@ -512,15 +544,8 @@ class TestImageList(TestImage): marker=image_fakes.image_id, ) - collist = ('ID', 'Name', 'Status') - - self.assertEqual(collist, columns) - datalist = (( - image_fakes.image_id, - image_fakes.image_name, - '', - ), ) - self.assertEqual(datalist, tuple(data)) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, tuple(data)) def test_image_list_shared_option(self): arglist = [ @@ -541,15 +566,8 @@ class TestImageList(TestImage): marker=image_fakes.image_id, ) - collist = ('ID', 'Name', 'Status') - - self.assertEqual(columns, collist) - datalist = (( - image_fakes.image_id, - image_fakes.image_name, - '', - ), ) - self.assertEqual(datalist, tuple(data)) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, tuple(data)) def test_image_list_long_option(self): arglist = [ @@ -575,7 +593,7 @@ class TestImageList(TestImage): 'Status', 'Visibility', 'Protected', - 'Owner', + 'Project', 'Tags', ) @@ -620,15 +638,8 @@ class TestImageList(TestImage): property_field='properties', ) - collist = ('ID', 'Name', 'Status') - - self.assertEqual(columns, collist) - datalist = (( - image_fakes.image_id, - image_fakes.image_name, - '', - ), ) - self.assertEqual(datalist, tuple(data)) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, tuple(data)) @mock.patch('openstackclient.common.utils.sort_items') def test_image_list_sort_option(self, si_mock): @@ -650,15 +661,8 @@ class TestImageList(TestImage): 'name:asc' ) - collist = ('ID', 'Name', 'Status') - - self.assertEqual(collist, columns) - datalist = (( - image_fakes.image_id, - image_fakes.image_name, - '', - ), ) - self.assertEqual(datalist, tuple(data)) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, tuple(data)) class TestRemoveProjectImage(TestImage): @@ -755,21 +759,21 @@ class TestImageSet(TestImage): def test_image_set_options(self): arglist = [ '--name', 'new-name', - '--owner', identity_fakes.project_name, '--min-disk', '2', '--min-ram', '4', '--container-format', 'ovf', '--disk-format', 'vmdk', + '--project', identity_fakes.project_name, '--project-domain', identity_fakes.domain_id, image_fakes.image_id, ] verifylist = [ ('name', 'new-name'), - ('owner', identity_fakes.project_name), ('min_disk', 2), ('min_ram', 4), ('container_format', 'ovf'), ('disk_format', 'vmdk'), + ('project', identity_fakes.project_name), ('project_domain', identity_fakes.domain_id), ('image', image_fakes.image_id), ] @@ -809,6 +813,25 @@ class TestImageSet(TestImage): exceptions.CommandError, self.cmd.take_action, parsed_args) + def test_image_set_with_unexist_project(self): + self.project_mock.get.side_effect = exceptions.NotFound(None) + self.project_mock.find.side_effect = exceptions.NotFound(None) + + arglist = [ + '--project', 'unexist_owner', + image_fakes.image_id, + ] + verifylist = [ + ('project', 'unexist_owner'), + ('image', image_fakes.image_id), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.assertRaises( + exceptions.CommandError, + self.cmd.take_action, parsed_args) + def test_image_set_bools1(self): arglist = [ '--protected', diff --git a/openstackclient/tests/network/v2/fakes.py b/openstackclient/tests/network/v2/fakes.py index 146ba616..88370feb 100644 --- a/openstackclient/tests/network/v2/fakes.py +++ b/openstackclient/tests/network/v2/fakes.py @@ -307,3 +307,71 @@ class FakeRouter(object): if routers is None: routers = FakeRouter.create_routers(count) return mock.MagicMock(side_effect=routers) + + +class FakeSubnet(object): + """Fake one or more subnets.""" + + @staticmethod + def create_one_subnet(attrs={}, methods={}): + """Create a fake subnet. + + :param Dictionary attrs: + A dictionary with all attributes + :param Dictionary methods: + A dictionary with all methods + :return: + A FakeResource object faking the subnet + """ + # Set default attributes. + subnet_attrs = { + 'id': 'subnet-id-' + uuid.uuid4().hex, + 'name': 'subnet-name-' + uuid.uuid4().hex, + 'network_id': 'network-id-' + uuid.uuid4().hex, + 'cidr': '10.10.10.0/24', + 'tenant_id': 'project-id-' + uuid.uuid4().hex, + 'enable_dhcp': True, + 'dns_nameservers': [], + 'allocation_pools': [], + 'host_routes': [], + 'ip_version': '4', + 'gateway_ip': '10.10.10.1', + } + + # Overwrite default attributes. + subnet_attrs.update(attrs) + + # Set default methods. + subnet_methods = { + 'keys': ['id', 'name', 'network_id', 'cidr', 'enable_dhcp', + 'allocation_pools', 'dns_nameservers', 'gateway_ip', + 'host_routes', 'ip_version', 'tenant_id'] + } + + # Overwrite default methods. + subnet_methods.update(methods) + + subnet = fakes.FakeResource(info=copy.deepcopy(subnet_attrs), + methods=copy.deepcopy(subnet_methods), + loaded=True) + + return subnet + + @staticmethod + def create_subnets(attrs={}, methods={}, count=2): + """Create multiple fake subnets. + + :param Dictionary attrs: + A dictionary with all attributes + :param Dictionary methods: + A dictionary with all methods + :param int count: + The number of subnets to fake + :return: + A list of FakeResource objects faking the subnets + """ + subnets = [] + for i in range(0, count): + subnets.append(FakeSubnet.create_one_subnet(attrs, methods)) + + return subnets diff --git a/openstackclient/tests/network/v2/test_subnet.py b/openstackclient/tests/network/v2/test_subnet.py new file mode 100644 index 00000000..5fca5edd --- /dev/null +++ b/openstackclient/tests/network/v2/test_subnet.py @@ -0,0 +1,108 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +import mock + +from openstackclient.common import utils +from openstackclient.network.v2 import subnet as subnet_v2 +from openstackclient.tests.network.v2 import fakes as network_fakes + + +class TestSubnet(network_fakes.TestNetworkV2): + def setUp(self): + super(TestSubnet, self).setUp() + + # Get a shortcut to the network client + self.network = self.app.client_manager.network + + +class TestListSubnet(TestSubnet): + # The subnets going to be listed up. + _subnet = network_fakes.FakeSubnet.create_subnets(count=3) + + columns = ( + 'ID', + 'Name', + 'Network', + 'Subnet' + ) + columns_long = columns + ( + 'Project', + 'DHCP', + 'Name Servers', + 'Allocation Pools', + 'Host Routes', + 'IP Version', + 'Gateway' + ) + + data = [] + for subnet in _subnet: + data.append(( + subnet.id, + subnet.name, + subnet.network_id, + subnet.cidr, + )) + + data_long = [] + for subnet in _subnet: + data_long.append(( + subnet.id, + subnet.name, + subnet.network_id, + subnet.cidr, + subnet.tenant_id, + subnet.enable_dhcp, + utils.format_list(subnet.dns_nameservers), + subnet_v2._format_allocation_pools(subnet.allocation_pools), + utils.format_list(subnet.host_routes), + subnet.ip_version, + subnet.gateway_ip + )) + + def setUp(self): + super(TestListSubnet, self).setUp() + + # Get the command object to test + self.cmd = subnet_v2.ListSubnet(self.app, self.namespace) + + self.network.subnets = mock.Mock(return_value=self._subnet) + + def test_subnet_list_no_options(self): + arglist = [] + verifylist = [ + ('long', False), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + self.network.subnets.assert_called_with() + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, list(data)) + + def test_subnet_list_long(self): + arglist = [ + '--long', + ] + verifylist = [ + ('long', True), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + self.network.subnets.assert_called_with() + self.assertEqual(self.columns_long, columns) + self.assertEqual(self.data_long, list(data)) diff --git a/openstackclient/tests/object/v1/test_container.py b/openstackclient/tests/object/v1/test_container.py index 2ef2f7b5..afcb3386 100644 --- a/openstackclient/tests/object/v1/test_container.py +++ b/openstackclient/tests/object/v1/test_container.py @@ -32,6 +32,9 @@ class FakeClient(object): class TestContainer(object_fakes.TestObjectv1): + + columns = ('Name',) + def setUp(self): super(TestContainer, self).setUp() self.app.client_manager.object_store = object_store.APIv1( @@ -73,8 +76,7 @@ class TestContainerList(TestContainer): **kwargs ) - collist = ('Name',) - self.assertEqual(collist, columns) + self.assertEqual(self.columns, columns) datalist = ( (object_fakes.container_name, ), (object_fakes.container_name_3, ), @@ -107,8 +109,7 @@ class TestContainerList(TestContainer): **kwargs ) - collist = ('Name',) - self.assertEqual(collist, columns) + self.assertEqual(self.columns, columns) datalist = ( (object_fakes.container_name, ), (object_fakes.container_name_3, ), @@ -143,8 +144,7 @@ class TestContainerList(TestContainer): **kwargs ) - collist = ('Name',) - self.assertEqual(collist, columns) + self.assertEqual(self.columns, columns) datalist = ( (object_fakes.container_name, ), (object_fakes.container_name_3, ), @@ -176,8 +176,7 @@ class TestContainerList(TestContainer): **kwargs ) - collist = ('Name',) - self.assertEqual(collist, columns) + self.assertEqual(self.columns, columns) datalist = ( (object_fakes.container_name, ), (object_fakes.container_name_3, ), @@ -250,8 +249,7 @@ class TestContainerList(TestContainer): **kwargs ) - collist = ('Name',) - self.assertEqual(collist, columns) + self.assertEqual(self.columns, columns) datalist = ( (object_fakes.container_name, ), (object_fakes.container_name_2, ), diff --git a/openstackclient/tests/object/v1/test_container_all.py b/openstackclient/tests/object/v1/test_container_all.py index 69fc0f39..c2dd02a5 100644 --- a/openstackclient/tests/object/v1/test_container_all.py +++ b/openstackclient/tests/object/v1/test_container_all.py @@ -29,6 +29,12 @@ class TestContainerAll(object_fakes.TestObjectv1): class TestContainerCreate(TestContainerAll): + columns = ( + 'account', + 'container', + 'x-trans-id', + ) + def setUp(self): super(TestContainerCreate, self).setUp() @@ -54,8 +60,7 @@ class TestContainerCreate(TestContainerAll): # DisplayCommandBase.take_action() returns two tuples columns, data = self.cmd.take_action(parsed_args) - collist = ('account', 'container', 'x-trans-id') - self.assertEqual(collist, columns) + self.assertEqual(self.columns, columns) datalist = [( object_fakes.ACCOUNT_ID, 'ernie', @@ -89,8 +94,7 @@ class TestContainerCreate(TestContainerAll): # DisplayCommandBase.take_action() returns two tuples columns, data = self.cmd.take_action(parsed_args) - collist = ('account', 'container', 'x-trans-id') - self.assertEqual(collist, columns) + self.assertEqual(self.columns, columns) datalist = [ ( object_fakes.ACCOUNT_ID, @@ -161,6 +165,8 @@ class TestContainerDelete(TestContainerAll): class TestContainerList(TestContainerAll): + columns = ('Name',) + def setUp(self): super(TestContainerList, self).setUp() @@ -187,8 +193,7 @@ class TestContainerList(TestContainerAll): # Lister.take_action() returns two tuples columns, data = self.cmd.take_action(parsed_args) - collist = ('Name',) - self.assertEqual(collist, columns) + self.assertEqual(self.columns, columns) datalist = [ (object_fakes.container_name, ), (object_fakes.container_name_3, ), @@ -219,8 +224,7 @@ class TestContainerList(TestContainerAll): # Lister.take_action() returns two tuples columns, data = self.cmd.take_action(parsed_args) - collist = ('Name',) - self.assertEqual(collist, columns) + self.assertEqual(self.columns, columns) datalist = [ (object_fakes.container_name, ), (object_fakes.container_name_3, ), diff --git a/openstackclient/tests/object/v1/test_object.py b/openstackclient/tests/object/v1/test_object.py index 305fe8f8..f0d62f6e 100644 --- a/openstackclient/tests/object/v1/test_object.py +++ b/openstackclient/tests/object/v1/test_object.py @@ -40,6 +40,13 @@ class TestObject(object_fakes.TestObjectv1): ) class TestObjectList(TestObject): + columns = ('Name',) + datalist = ( + ( + object_fakes.object_name_2, + ), + ) + def setUp(self): super(TestObjectList, self).setUp() @@ -67,8 +74,7 @@ class TestObjectList(TestObject): container=object_fakes.container_name, ) - collist = ('Name',) - self.assertEqual(collist, columns) + self.assertEqual(self.columns, columns) datalist = ( (object_fakes.object_name_1, ), (object_fakes.object_name_2, ), @@ -102,12 +108,8 @@ class TestObjectList(TestObject): **kwargs ) - collist = ('Name',) - self.assertEqual(collist, columns) - datalist = ( - (object_fakes.object_name_2, ), - ) - self.assertEqual(datalist, tuple(data)) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, tuple(data)) def test_object_list_objects_delimiter(self, o_mock): o_mock.return_value = [ @@ -136,12 +138,8 @@ class TestObjectList(TestObject): **kwargs ) - collist = ('Name',) - self.assertEqual(collist, columns) - datalist = ( - (object_fakes.object_name_2, ), - ) - self.assertEqual(datalist, tuple(data)) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, tuple(data)) def test_object_list_objects_marker(self, o_mock): o_mock.return_value = [ @@ -170,12 +168,8 @@ class TestObjectList(TestObject): **kwargs ) - collist = ('Name',) - self.assertEqual(collist, columns) - datalist = ( - (object_fakes.object_name_2, ), - ) - self.assertEqual(datalist, tuple(data)) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, tuple(data)) def test_object_list_objects_end_marker(self, o_mock): o_mock.return_value = [ @@ -204,12 +198,8 @@ class TestObjectList(TestObject): **kwargs ) - collist = ('Name',) - self.assertEqual(collist, columns) - datalist = ( - (object_fakes.object_name_2, ), - ) - self.assertEqual(datalist, tuple(data)) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, tuple(data)) def test_object_list_objects_limit(self, o_mock): o_mock.return_value = [ @@ -238,12 +228,8 @@ class TestObjectList(TestObject): **kwargs ) - collist = ('Name',) - self.assertEqual(collist, columns) - datalist = ( - (object_fakes.object_name_2, ), - ) - self.assertEqual(datalist, tuple(data)) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, tuple(data)) def test_object_list_objects_long(self, o_mock): o_mock.return_value = [ @@ -320,8 +306,7 @@ class TestObjectList(TestObject): **kwargs ) - collist = ('Name',) - self.assertEqual(collist, columns) + self.assertEqual(self.columns, columns) datalist = ( (object_fakes.object_name_1, ), (object_fakes.object_name_2, ), diff --git a/openstackclient/tests/object/v1/test_object_all.py b/openstackclient/tests/object/v1/test_object_all.py index 7a76ab76..a90e5b65 100644 --- a/openstackclient/tests/object/v1/test_object_all.py +++ b/openstackclient/tests/object/v1/test_object_all.py @@ -37,6 +37,8 @@ class TestObjectCreate(TestObjectAll): class TestObjectList(TestObjectAll): + columns = ('Name',) + def setUp(self): super(TestObjectList, self).setUp() @@ -69,8 +71,7 @@ class TestObjectList(TestObjectAll): # Lister.take_action() returns two tuples columns, data = self.cmd.take_action(parsed_args) - collist = ('Name',) - self.assertEqual(collist, columns) + self.assertEqual(self.columns, columns) datalist = [ (object_fakes.object_name_1, ), (object_fakes.object_name_2, ), @@ -104,8 +105,7 @@ class TestObjectList(TestObjectAll): # DisplayCommandBase.take_action() returns two tuples columns, data = self.cmd.take_action(parsed_args) - collist = ('Name',) - self.assertEqual(collist, columns) + self.assertEqual(self.columns, columns) datalist = ( (object_fakes.object_name_2, ), ) diff --git a/openstackclient/tests/volume/v1/test_qos_specs.py b/openstackclient/tests/volume/v1/test_qos_specs.py index c2e6c0af..7ecc8ee8 100644 --- a/openstackclient/tests/volume/v1/test_qos_specs.py +++ b/openstackclient/tests/volume/v1/test_qos_specs.py @@ -69,6 +69,18 @@ class TestQosAssociate(TestQos): class TestQosCreate(TestQos): + + columns = ( + 'consumer', + 'id', + 'name', + ) + datalist = ( + volume_fakes.qos_consumer, + volume_fakes.qos_id, + volume_fakes.qos_name + ) + def setUp(self): super(TestQosCreate, self).setUp() @@ -97,12 +109,7 @@ class TestQosCreate(TestQos): {'consumer': volume_fakes.qos_default_consumer} ) - collist = ( - 'consumer', - 'id', - 'name' - ) - self.assertEqual(collist, columns) + self.assertEqual(self.columns, columns) datalist = ( volume_fakes.qos_default_consumer, volume_fakes.qos_id, @@ -133,19 +140,8 @@ class TestQosCreate(TestQos): volume_fakes.qos_name, {'consumer': volume_fakes.qos_consumer} ) - - collist = ( - 'consumer', - 'id', - 'name' - ) - self.assertEqual(collist, columns) - datalist = ( - volume_fakes.qos_consumer, - volume_fakes.qos_id, - volume_fakes.qos_name - ) - self.assertEqual(datalist, data) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, data) def test_qos_create_with_properties(self): self.qos_mock.create.return_value = fakes.FakeResource( @@ -176,17 +172,11 @@ class TestQosCreate(TestQos): specs ) - collist = ( - 'consumer', - 'id', - 'name', + columns = self.columns + ( 'specs', ) - self.assertEqual(collist, columns) - datalist = ( - volume_fakes.qos_consumer, - volume_fakes.qos_id, - volume_fakes.qos_name, + self.assertEqual(columns, columns) + datalist = self.datalist + ( volume_fakes.qos_specs, ) self.assertEqual(datalist, data) diff --git a/openstackclient/tests/volume/v1/test_volume.py b/openstackclient/tests/volume/v1/test_volume.py index 70ff50de..33255aac 100644 --- a/openstackclient/tests/volume/v1/test_volume.py +++ b/openstackclient/tests/volume/v1/test_volume.py @@ -49,6 +49,29 @@ class TestVolume(volume_fakes.TestVolumev1): class TestVolumeCreate(TestVolume): + columns = ( + 'attach_status', + 'availability_zone', + 'display_description', + 'display_name', + 'id', + 'properties', + 'size', + 'status', + 'type', + ) + datalist = ( + 'detached', + volume_fakes.volume_zone, + volume_fakes.volume_description, + volume_fakes.volume_name, + volume_fakes.volume_id, + volume_fakes.volume_metadata_str, + volume_fakes.volume_size, + volume_fakes.volume_status, + volume_fakes.volume_type, + ) + def setUp(self): super(TestVolumeCreate, self).setUp() @@ -93,31 +116,8 @@ class TestVolumeCreate(TestVolume): None, None, ) - - collist = ( - 'attach_status', - 'availability_zone', - 'display_description', - 'display_name', - 'id', - 'properties', - 'size', - 'status', - 'type', - ) - self.assertEqual(collist, columns) - datalist = ( - 'detached', - volume_fakes.volume_zone, - volume_fakes.volume_description, - volume_fakes.volume_name, - volume_fakes.volume_id, - volume_fakes.volume_metadata_str, - volume_fakes.volume_size, - volume_fakes.volume_status, - volume_fakes.volume_type, - ) - self.assertEqual(datalist, data) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, data) def test_volume_create_options(self): arglist = [ @@ -158,30 +158,8 @@ class TestVolumeCreate(TestVolume): None, ) - collist = ( - 'attach_status', - 'availability_zone', - 'display_description', - 'display_name', - 'id', - 'properties', - 'size', - 'status', - 'type', - ) - self.assertEqual(collist, columns) - datalist = ( - 'detached', - volume_fakes.volume_zone, - volume_fakes.volume_description, - volume_fakes.volume_name, - volume_fakes.volume_id, - volume_fakes.volume_metadata_str, - volume_fakes.volume_size, - volume_fakes.volume_status, - volume_fakes.volume_type, - ) - self.assertEqual(datalist, data) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, data) def test_volume_create_user_project_id(self): # Return a project @@ -233,30 +211,8 @@ class TestVolumeCreate(TestVolume): None, ) - collist = ( - 'attach_status', - 'availability_zone', - 'display_description', - 'display_name', - 'id', - 'properties', - 'size', - 'status', - 'type', - ) - self.assertEqual(collist, columns) - datalist = ( - 'detached', - volume_fakes.volume_zone, - volume_fakes.volume_description, - volume_fakes.volume_name, - volume_fakes.volume_id, - volume_fakes.volume_metadata_str, - volume_fakes.volume_size, - volume_fakes.volume_status, - volume_fakes.volume_type, - ) - self.assertEqual(datalist, data) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, data) def test_volume_create_user_project_name(self): # Return a project @@ -308,30 +264,8 @@ class TestVolumeCreate(TestVolume): None, ) - collist = ( - 'attach_status', - 'availability_zone', - 'display_description', - 'display_name', - 'id', - 'properties', - 'size', - 'status', - 'type', - ) - self.assertEqual(collist, columns) - datalist = ( - 'detached', - volume_fakes.volume_zone, - volume_fakes.volume_description, - volume_fakes.volume_name, - volume_fakes.volume_id, - volume_fakes.volume_metadata_str, - volume_fakes.volume_size, - volume_fakes.volume_status, - volume_fakes.volume_type, - ) - self.assertEqual(datalist, data) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, data) def test_volume_create_properties(self): arglist = [ @@ -369,30 +303,8 @@ class TestVolumeCreate(TestVolume): None, ) - collist = ( - 'attach_status', - 'availability_zone', - 'display_description', - 'display_name', - 'id', - 'properties', - 'size', - 'status', - 'type', - ) - self.assertEqual(collist, columns) - datalist = ( - 'detached', - volume_fakes.volume_zone, - volume_fakes.volume_description, - volume_fakes.volume_name, - volume_fakes.volume_id, - volume_fakes.volume_metadata_str, - volume_fakes.volume_size, - volume_fakes.volume_status, - volume_fakes.volume_type, - ) - self.assertEqual(datalist, data) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, data) def test_volume_create_image_id(self): self.images_mock.get.return_value = fakes.FakeResource( @@ -435,30 +347,8 @@ class TestVolumeCreate(TestVolume): volume_fakes.image_id, ) - collist = ( - 'attach_status', - 'availability_zone', - 'display_description', - 'display_name', - 'id', - 'properties', - 'size', - 'status', - 'type', - ) - self.assertEqual(collist, columns) - datalist = ( - 'detached', - volume_fakes.volume_zone, - volume_fakes.volume_description, - volume_fakes.volume_name, - volume_fakes.volume_id, - volume_fakes.volume_metadata_str, - volume_fakes.volume_size, - volume_fakes.volume_status, - volume_fakes.volume_type, - ) - self.assertEqual(datalist, data) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, data) def test_volume_create_image_name(self): self.images_mock.get.return_value = fakes.FakeResource( @@ -501,34 +391,29 @@ class TestVolumeCreate(TestVolume): volume_fakes.image_id, ) - collist = ( - 'attach_status', - 'availability_zone', - 'display_description', - 'display_name', - 'id', - 'properties', - 'size', - 'status', - 'type', - ) - self.assertEqual(collist, columns) - datalist = ( - 'detached', - volume_fakes.volume_zone, - volume_fakes.volume_description, - volume_fakes.volume_name, - volume_fakes.volume_id, - volume_fakes.volume_metadata_str, - volume_fakes.volume_size, - volume_fakes.volume_status, - volume_fakes.volume_type, - ) - self.assertEqual(datalist, data) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, data) class TestVolumeList(TestVolume): + columns = ( + 'ID', + 'Display Name', + 'Status', + 'Size', + 'Attached to', + ) + datalist = ( + ( + volume_fakes.volume_id, + volume_fakes.volume_name, + volume_fakes.volume_status, + volume_fakes.volume_size, + '', + ), + ) + def setUp(self): super(TestVolumeList, self).setUp() @@ -555,23 +440,8 @@ class TestVolumeList(TestVolume): columns, data = self.cmd.take_action(parsed_args) - collist = ( - 'ID', - 'Display Name', - 'Status', - 'Size', - 'Attached to', - ) - self.assertEqual(collist, columns) - - datalist = (( - volume_fakes.volume_id, - volume_fakes.volume_name, - volume_fakes.volume_status, - volume_fakes.volume_size, - '', - ), ) - self.assertEqual(datalist, tuple(data)) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, tuple(data)) def test_volume_list_name(self): arglist = [ @@ -586,24 +456,8 @@ class TestVolumeList(TestVolume): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - - collist = ( - 'ID', - 'Display Name', - 'Status', - 'Size', - 'Attached to', - ) - self.assertEqual(collist, tuple(columns)) - - datalist = (( - volume_fakes.volume_id, - volume_fakes.volume_name, - volume_fakes.volume_status, - volume_fakes.volume_size, - '', - ), ) - self.assertEqual(datalist, tuple(data)) + self.assertEqual(self.columns, tuple(columns)) + self.assertEqual(self.datalist, tuple(data)) def test_volume_list_status(self): arglist = [ @@ -618,24 +472,8 @@ class TestVolumeList(TestVolume): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - - collist = ( - 'ID', - 'Display Name', - 'Status', - 'Size', - 'Attached to', - ) - self.assertEqual(collist, tuple(columns)) - - datalist = (( - volume_fakes.volume_id, - volume_fakes.volume_name, - volume_fakes.volume_status, - volume_fakes.volume_size, - '', - ), ) - self.assertEqual(datalist, tuple(data)) + self.assertEqual(self.columns, tuple(columns)) + self.assertEqual(self.datalist, tuple(data)) def test_volume_list_all_projects(self): arglist = [ @@ -650,24 +488,8 @@ class TestVolumeList(TestVolume): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - - collist = ( - 'ID', - 'Display Name', - 'Status', - 'Size', - 'Attached to', - ) - self.assertEqual(collist, columns) - - datalist = (( - volume_fakes.volume_id, - volume_fakes.volume_name, - volume_fakes.volume_status, - volume_fakes.volume_size, - '', - ), ) - self.assertEqual(datalist, tuple(data)) + self.assertEqual(self.columns, tuple(columns)) + self.assertEqual(self.datalist, tuple(data)) def test_volume_list_long(self): arglist = [ diff --git a/openstackclient/tests/volume/v2/fakes.py b/openstackclient/tests/volume/v2/fakes.py index 60cec335..2e58e58d 100644 --- a/openstackclient/tests/volume/v2/fakes.py +++ b/openstackclient/tests/volume/v2/fakes.py @@ -202,6 +202,8 @@ class FakeVolumeClient(object): self.restores.resource_class = fakes.FakeResource(None, {}) self.qos_specs = mock.Mock() self.qos_specs.resource_class = fakes.FakeResource(None, {}) + self.availability_zones = mock.Mock() + self.availability_zones.resource_class = fakes.FakeResource(None, {}) self.auth_token = kwargs['token'] self.management_url = kwargs['endpoint'] @@ -304,3 +306,55 @@ class FakeVolume(object): volumes = FakeVolume.create_volumes(count) return mock.MagicMock(side_effect=volumes) + + +class FakeAvailabilityZone(object): + """Fake one or more volume availability zones (AZs).""" + + @staticmethod + def create_one_availability_zone(attrs={}, methods={}): + """Create a fake AZ. + + :param Dictionary attrs: + A dictionary with all attributes + :param Dictionary methods: + A dictionary with all methods + :return: + A FakeResource object with zoneName, zoneState, etc. + """ + # Set default attributes. + availability_zone = { + 'zoneName': uuid.uuid4().hex, + 'zoneState': {'available': True}, + } + + # Overwrite default attributes. + availability_zone.update(attrs) + + availability_zone = fakes.FakeResource( + info=copy.deepcopy(availability_zone), + methods=methods, + loaded=True) + return availability_zone + + @staticmethod + def create_availability_zones(attrs={}, methods={}, count=2): + """Create multiple fake AZs. + + :param Dictionary attrs: + A dictionary with all attributes + :param Dictionary methods: + A dictionary with all methods + :param int count: + The number of AZs to fake + :return: + A list of FakeResource objects faking the AZs + """ + availability_zones = [] + for i in range(0, count): + availability_zone = \ + FakeAvailabilityZone.create_one_availability_zone( + attrs, methods) + availability_zones.append(availability_zone) + + return availability_zones diff --git a/openstackclient/tests/volume/v2/test_backup.py b/openstackclient/tests/volume/v2/test_backup.py index 7af22e8a..dc1d7877 100644 --- a/openstackclient/tests/volume/v2/test_backup.py +++ b/openstackclient/tests/volume/v2/test_backup.py @@ -166,6 +166,24 @@ class TestBackupRestore(TestBackup): class TestBackupList(TestBackup): + + columns = [ + 'ID', + 'Name', + 'Description', + 'Status', + 'Size', + ] + datalist = ( + ( + volume_fakes.backup_id, + volume_fakes.backup_name, + volume_fakes.backup_description, + volume_fakes.backup_status, + volume_fakes.backup_size + ), + ) + def setUp(self): super(TestBackupList, self).setUp() @@ -193,17 +211,8 @@ class TestBackupList(TestBackup): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - collist = ['ID', 'Name', 'Description', 'Status', 'Size'] - self.assertEqual(collist, columns) - - datalist = (( - volume_fakes.backup_id, - volume_fakes.backup_name, - volume_fakes.backup_description, - volume_fakes.backup_status, - volume_fakes.backup_size - ),) - self.assertEqual(datalist, tuple(data)) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, tuple(data)) def test_backup_list_with_options(self): arglist = ["--long"] @@ -212,9 +221,13 @@ class TestBackupList(TestBackup): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - collist = ['ID', 'Name', 'Description', 'Status', 'Size', - 'Availability Zone', 'Volume', 'Container'] - self.assertEqual(collist, columns) + columns = self.columns + [ + 'Availability Zone', + 'Volume', + 'Container', + ] + + self.assertEqual(columns, columns) datalist = (( volume_fakes.backup_id, diff --git a/openstackclient/tests/volume/v2/test_qos_specs.py b/openstackclient/tests/volume/v2/test_qos_specs.py index 4222ed07..403634a3 100644 --- a/openstackclient/tests/volume/v2/test_qos_specs.py +++ b/openstackclient/tests/volume/v2/test_qos_specs.py @@ -69,6 +69,18 @@ class TestQosAssociate(TestQos): class TestQosCreate(TestQos): + + columns = ( + 'consumer', + 'id', + 'name' + ) + datalist = ( + volume_fakes.qos_consumer, + volume_fakes.qos_id, + volume_fakes.qos_name + ) + def setUp(self): super(TestQosCreate, self).setUp() @@ -97,12 +109,7 @@ class TestQosCreate(TestQos): {'consumer': volume_fakes.qos_default_consumer} ) - collist = ( - 'consumer', - 'id', - 'name' - ) - self.assertEqual(collist, columns) + self.assertEqual(self.columns, columns) datalist = ( volume_fakes.qos_default_consumer, volume_fakes.qos_id, @@ -134,18 +141,8 @@ class TestQosCreate(TestQos): {'consumer': volume_fakes.qos_consumer} ) - collist = ( - 'consumer', - 'id', - 'name' - ) - self.assertEqual(collist, columns) - datalist = ( - volume_fakes.qos_consumer, - volume_fakes.qos_id, - volume_fakes.qos_name - ) - self.assertEqual(datalist, data) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, data) def test_qos_create_with_properties(self): self.qos_mock.create.return_value = fakes.FakeResource( @@ -176,17 +173,11 @@ class TestQosCreate(TestQos): specs ) - collist = ( - 'consumer', - 'id', - 'name', + columns = self.columns + ( 'specs', ) - self.assertEqual(collist, columns) - datalist = ( - volume_fakes.qos_consumer, - volume_fakes.qos_id, - volume_fakes.qos_name, + self.assertEqual(columns, columns) + datalist = self.datalist + ( volume_fakes.qos_specs, ) self.assertEqual(datalist, data) diff --git a/openstackclient/tests/volume/v2/test_snapshot.py b/openstackclient/tests/volume/v2/test_snapshot.py index 3b30d4ef..1c1dd437 100644 --- a/openstackclient/tests/volume/v2/test_snapshot.py +++ b/openstackclient/tests/volume/v2/test_snapshot.py @@ -202,6 +202,15 @@ class TestSnapshotUnset(TestSnapshot): class TestSnapshotList(TestSnapshot): + + columns = [ + "ID", + "Name", + "Description", + "Status", + "Size" + ] + def setUp(self): super(TestSnapshotList, self).setUp() @@ -231,8 +240,7 @@ class TestSnapshotList(TestSnapshot): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - collist = ["ID", "Name", "Description", "Status", "Size"] - self.assertEqual(collist, columns) + self.assertEqual(self.columns, columns) datalist = (( volume_fakes.snapshot_id, volume_fakes.snapshot_name, @@ -249,9 +257,12 @@ class TestSnapshotList(TestSnapshot): columns, data = self.cmd.take_action(parsed_args) - collist = ["ID", "Name", "Description", "Status", "Size", "Created At", - "Volume", "Properties"] - self.assertEqual(collist, columns) + columns = self.columns + [ + "Created At", + "Volume", + "Properties" + ] + self.assertEqual(columns, columns) datalist = (( volume_fakes.snapshot_id, @@ -277,14 +288,7 @@ class TestSnapshotList(TestSnapshot): columns, data = self.cmd.take_action(parsed_args) - collist = [ - "ID", - "Name", - "Description", - "Status", - "Size" - ] - self.assertEqual(collist, columns) + self.assertEqual(self.columns, columns) datalist = (( volume_fakes.snapshot_id, diff --git a/openstackclient/tests/volume/v2/test_type.py b/openstackclient/tests/volume/v2/test_type.py index c63cd1fa..9bf60363 100644 --- a/openstackclient/tests/volume/v2/test_type.py +++ b/openstackclient/tests/volume/v2/test_type.py @@ -44,6 +44,17 @@ class TestType(volume_fakes.TestVolume): class TestTypeCreate(TestType): + columns = ( + 'description', + 'id', + 'name', + ) + datalist = ( + volume_fakes.type_description, + volume_fakes.type_id, + volume_fakes.type_name, + ) + def setUp(self): super(TestTypeCreate, self).setUp() @@ -76,18 +87,8 @@ class TestTypeCreate(TestType): is_public=True, ) - collist = ( - 'description', - 'id', - 'name', - ) - self.assertEqual(collist, columns) - datalist = ( - volume_fakes.type_description, - volume_fakes.type_id, - volume_fakes.type_name, - ) - self.assertEqual(datalist, data) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, data) def test_type_create_private(self): arglist = [ @@ -110,21 +111,17 @@ class TestTypeCreate(TestType): is_public=False, ) - collist = ( - 'description', - 'id', - 'name', - ) - self.assertEqual(collist, columns) - datalist = ( - volume_fakes.type_description, - volume_fakes.type_id, - volume_fakes.type_name, - ) - self.assertEqual(datalist, data) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, data) class TestTypeList(TestType): + + columns = [ + "ID", + "Name" + ] + def setUp(self): super(TestTypeList, self).setUp() @@ -146,8 +143,7 @@ class TestTypeList(TestType): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - collist = ["ID", "Name"] - self.assertEqual(collist, columns) + self.assertEqual(self.columns, columns) datalist = (( volume_fakes.type_id, volume_fakes.type_name, @@ -160,8 +156,11 @@ class TestTypeList(TestType): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - collist = ["ID", "Name", "Description", "Properties"] - self.assertEqual(collist, columns) + columns = self.columns + [ + "Description", + "Properties" + ] + self.assertEqual(columns, columns) datalist = (( volume_fakes.type_id, volume_fakes.type_name, diff --git a/openstackclient/tests/volume/v2/test_volume.py b/openstackclient/tests/volume/v2/test_volume.py index 50826c31..d61a6c15 100644 --- a/openstackclient/tests/volume/v2/test_volume.py +++ b/openstackclient/tests/volume/v2/test_volume.py @@ -48,6 +48,32 @@ class TestVolume(volume_fakes.TestVolume): class TestVolumeCreate(TestVolume): + + columns = ( + 'attachments', + 'availability_zone', + 'description', + 'id', + 'name', + 'properties', + 'size', + 'snapshot_id', + 'status', + 'type', + ) + datalist = ( + volume_fakes.volume_attachments, + volume_fakes.volume_availability_zone, + volume_fakes.volume_description, + volume_fakes.volume_id, + volume_fakes.volume_name, + volume_fakes.volume_metadata_str, + volume_fakes.volume_size, + volume_fakes.volume_snapshot_id, + volume_fakes.volume_status, + volume_fakes.volume_type, + ) + def setUp(self): super(TestVolumeCreate, self).setUp() @@ -88,32 +114,8 @@ class TestVolumeCreate(TestVolume): source_volid=None ) - collist = ( - 'attachments', - 'availability_zone', - 'description', - 'id', - 'name', - 'properties', - 'size', - 'snapshot_id', - 'status', - 'type', - ) - self.assertEqual(collist, columns) - datalist = ( - volume_fakes.volume_attachments, - volume_fakes.volume_availability_zone, - volume_fakes.volume_description, - volume_fakes.volume_id, - volume_fakes.volume_name, - volume_fakes.volume_metadata_str, - volume_fakes.volume_size, - volume_fakes.volume_snapshot_id, - volume_fakes.volume_status, - volume_fakes.volume_type, - ) - self.assertEqual(datalist, data) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, data) def test_volume_create_options(self): arglist = [ @@ -149,32 +151,8 @@ class TestVolumeCreate(TestVolume): source_volid=None ) - collist = ( - 'attachments', - 'availability_zone', - 'description', - 'id', - 'name', - 'properties', - 'size', - 'snapshot_id', - 'status', - 'type', - ) - self.assertEqual(collist, columns) - datalist = ( - volume_fakes.volume_attachments, - volume_fakes.volume_availability_zone, - volume_fakes.volume_description, - volume_fakes.volume_id, - volume_fakes.volume_name, - volume_fakes.volume_metadata_str, - volume_fakes.volume_size, - volume_fakes.volume_snapshot_id, - volume_fakes.volume_status, - volume_fakes.volume_type, - ) - self.assertEqual(datalist, data) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, data) def test_volume_create_user_project_id(self): # Return a project @@ -221,32 +199,8 @@ class TestVolumeCreate(TestVolume): source_volid=None ) - collist = ( - 'attachments', - 'availability_zone', - 'description', - 'id', - 'name', - 'properties', - 'size', - 'snapshot_id', - 'status', - 'type', - ) - self.assertEqual(collist, columns) - datalist = ( - volume_fakes.volume_attachments, - volume_fakes.volume_availability_zone, - volume_fakes.volume_description, - volume_fakes.volume_id, - volume_fakes.volume_name, - volume_fakes.volume_metadata_str, - volume_fakes.volume_size, - volume_fakes.volume_snapshot_id, - volume_fakes.volume_status, - volume_fakes.volume_type, - ) - self.assertEqual(datalist, data) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, data) def test_volume_create_user_project_name(self): # Return a project @@ -293,32 +247,8 @@ class TestVolumeCreate(TestVolume): source_volid=None ) - collist = ( - 'attachments', - 'availability_zone', - 'description', - 'id', - 'name', - 'properties', - 'size', - 'snapshot_id', - 'status', - 'type', - ) - self.assertEqual(collist, columns) - datalist = ( - volume_fakes.volume_attachments, - volume_fakes.volume_availability_zone, - volume_fakes.volume_description, - volume_fakes.volume_id, - volume_fakes.volume_name, - volume_fakes.volume_metadata_str, - volume_fakes.volume_size, - volume_fakes.volume_snapshot_id, - volume_fakes.volume_status, - volume_fakes.volume_type, - ) - self.assertEqual(datalist, data) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, data) def test_volume_create_properties(self): arglist = [ @@ -351,32 +281,8 @@ class TestVolumeCreate(TestVolume): source_volid=None ) - collist = ( - 'attachments', - 'availability_zone', - 'description', - 'id', - 'name', - 'properties', - 'size', - 'snapshot_id', - 'status', - 'type', - ) - self.assertEqual(collist, columns) - datalist = ( - volume_fakes.volume_attachments, - volume_fakes.volume_availability_zone, - volume_fakes.volume_description, - volume_fakes.volume_id, - volume_fakes.volume_name, - volume_fakes.volume_metadata_str, - volume_fakes.volume_size, - volume_fakes.volume_snapshot_id, - volume_fakes.volume_status, - volume_fakes.volume_type, - ) - self.assertEqual(datalist, data) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, data) def test_volume_create_image_id(self): self.images_mock.get.return_value = fakes.FakeResource( @@ -411,35 +317,11 @@ class TestVolumeCreate(TestVolume): availability_zone=None, metadata=None, imageRef=volume_fakes.image_id, - source_volid=None + source_volid=None, ) - collist = ( - 'attachments', - 'availability_zone', - 'description', - 'id', - 'name', - 'properties', - 'size', - 'snapshot_id', - 'status', - 'type', - ) - self.assertEqual(collist, columns) - datalist = ( - volume_fakes.volume_attachments, - volume_fakes.volume_availability_zone, - volume_fakes.volume_description, - volume_fakes.volume_id, - volume_fakes.volume_name, - volume_fakes.volume_metadata_str, - volume_fakes.volume_size, - volume_fakes.volume_snapshot_id, - volume_fakes.volume_status, - volume_fakes.volume_type, - ) - self.assertEqual(datalist, data) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, data) def test_volume_create_image_name(self): self.images_mock.get.return_value = fakes.FakeResource( @@ -477,36 +359,20 @@ class TestVolumeCreate(TestVolume): source_volid=None ) - collist = ( - 'attachments', - 'availability_zone', - 'description', - 'id', - 'name', - 'properties', - 'size', - 'snapshot_id', - 'status', - 'type', - ) - self.assertEqual(collist, columns) - datalist = ( - volume_fakes.volume_attachments, - volume_fakes.volume_availability_zone, - volume_fakes.volume_description, - volume_fakes.volume_id, - volume_fakes.volume_name, - volume_fakes.volume_metadata_str, - volume_fakes.volume_size, - volume_fakes.volume_snapshot_id, - volume_fakes.volume_status, - volume_fakes.volume_type, - ) - self.assertEqual(datalist, data) + self.assertEqual(self.columns, columns) + self.assertEqual(self.datalist, data) class TestVolumeList(TestVolume): + columns = [ + 'ID', + 'Display Name', + 'Status', + 'Size', + 'Attached to', + ] + def setUp(self): super(TestVolumeList, self).setUp() @@ -549,14 +415,7 @@ class TestVolumeList(TestVolume): columns, data = self.cmd.take_action(parsed_args) - collist = [ - 'ID', - 'Display Name', - 'Status', - 'Size', - 'Attached to', - ] - self.assertEqual(collist, columns) + self.assertEqual(self.columns, columns) server = volume_fakes.volume_attachment_server['server_id'] device = volume_fakes.volume_attachment_server['device'] @@ -584,19 +443,11 @@ class TestVolumeList(TestVolume): columns, data = self.cmd.take_action(parsed_args) - collist = ( - 'ID', - 'Display Name', - 'Status', - 'Size', - 'Attached to', - ) - self.assertEqual(collist, tuple(columns)) + self.assertEqual(self.columns, columns) server = volume_fakes.volume_attachment_server['server_id'] device = volume_fakes.volume_attachment_server['device'] msg = 'Attached to %s on %s ' % (server, device) - datalist = (( volume_fakes.volume_id, volume_fakes.volume_name, @@ -622,19 +473,11 @@ class TestVolumeList(TestVolume): columns, data = self.cmd.take_action(parsed_args) - collist = ( - 'ID', - 'Display Name', - 'Status', - 'Size', - 'Attached to', - ) - self.assertEqual(collist, tuple(columns)) + self.assertEqual(self.columns, columns) server = volume_fakes.volume_attachment_server['server_id'] device = volume_fakes.volume_attachment_server['device'] msg = 'Attached to %s on %s ' % (server, device) - datalist = (( volume_fakes.volume_id, volume_fakes.volume_name, @@ -658,19 +501,10 @@ class TestVolumeList(TestVolume): columns, data = self.cmd.take_action(parsed_args) - collist = ( - 'ID', - 'Display Name', - 'Status', - 'Size', - 'Attached to', - ) - self.assertEqual(collist, tuple(columns)) - + self.assertEqual(self.columns, columns) server = volume_fakes.volume_attachment_server['server_id'] device = volume_fakes.volume_attachment_server['device'] msg = 'Attached to %s on %s ' % (server, device) - datalist = (( volume_fakes.volume_id, volume_fakes.volume_name, @@ -696,19 +530,11 @@ class TestVolumeList(TestVolume): columns, data = self.cmd.take_action(parsed_args) - collist = ( - 'ID', - 'Display Name', - 'Status', - 'Size', - 'Attached to', - ) - self.assertEqual(collist, tuple(columns)) + self.assertEqual(self.columns, columns) server = volume_fakes.volume_attachment_server['server_id'] device = volume_fakes.volume_attachment_server['device'] msg = 'Attached to %s on %s ' % (server, device) - datalist = (( volume_fakes.volume_id, volume_fakes.volume_name, @@ -732,19 +558,11 @@ class TestVolumeList(TestVolume): columns, data = self.cmd.take_action(parsed_args) - collist = ( - 'ID', - 'Display Name', - 'Status', - 'Size', - 'Attached to', - ) - self.assertEqual(collist, tuple(columns)) + self.assertEqual(self.columns, columns) server = volume_fakes.volume_attachment_server['server_id'] device = volume_fakes.volume_attachment_server['device'] msg = 'Attached to %s on %s ' % (server, device) - datalist = (( volume_fakes.volume_id, volume_fakes.volume_name, @@ -768,14 +586,7 @@ class TestVolumeList(TestVolume): columns, data = self.cmd.take_action(parsed_args) - collist = ( - 'ID', - 'Display Name', - 'Status', - 'Size', - 'Attached to', - ) - self.assertEqual(collist, tuple(columns)) + self.assertEqual(self.columns, columns) server = volume_fakes.volume_attachment_server['server_id'] device = volume_fakes.volume_attachment_server['device'] @@ -803,14 +614,7 @@ class TestVolumeList(TestVolume): columns, data = self.cmd.take_action(parsed_args) - collist = [ - 'ID', - 'Display Name', - 'Status', - 'Size', - 'Attached to', - ] - self.assertEqual(collist, columns) + self.assertEqual(self.columns, columns) server = volume_fakes.volume_attachment_server['server_id'] device = volume_fakes.volume_attachment_server['device'] |
