1# Copyright 2010 United States Government as represented by the
2# Administrator of the National Aeronautics and Space Administration.
3# All Rights Reserved.
4#
5#    Licensed under the Apache License, Version 2.0 (the "License"); you may
6#    not use this file except in compliance with the License. You may obtain
7#    a copy of the License at
8#
9#         http://www.apache.org/licenses/LICENSE-2.0
10#
11#    Unless required by applicable law or agreed to in writing, software
12#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14#    License for the specific language governing permissions and limitations
15#    under the License.
16
17"""Cinder base exception handling.
18
19Includes decorator for re-raising Cinder-type exceptions.
20
21SHOULD include dedicated exception logging.
22
23"""
24
25from oslo_config import cfg
26from oslo_log import log as logging
27from oslo_versionedobjects import exception as obj_exc
28import six
29import webob.exc
30from webob.util import status_generic_reasons
31from webob.util import status_reasons
32
33from cinder.i18n import _
34
35
36LOG = logging.getLogger(__name__)
37
38# TODO(smcginnis) Remove in Rocky
39exc_log_opts = [
40    cfg.BoolOpt('fatal_exception_format_errors',
41                default=False,
42                help='Make exception message format errors fatal.',
43                deprecated_for_removal=True,
44                deprecated_since='12.0.0',
45                deprecated_reason='This is only used for internal testing.'),
46]
47
48CONF = cfg.CONF
49CONF.register_opts(exc_log_opts)
50
51
52class ConvertedException(webob.exc.WSGIHTTPException):
53    def __init__(self, code=500, title="", explanation=""):
54        self.code = code
55        # There is a strict rule about constructing status line for HTTP:
56        # '...Status-Line, consisting of the protocol version followed by a
57        # numeric status code and its associated textual phrase, with each
58        # element separated by SP characters'
59        # (http://www.faqs.org/rfcs/rfc2616.html)
60        # 'code' and 'title' can not be empty because they correspond
61        # to numeric status code and its associated text
62        if title:
63            self.title = title
64        else:
65            try:
66                self.title = status_reasons[self.code]
67            except KeyError:
68                generic_code = self.code // 100
69                self.title = status_generic_reasons[generic_code]
70        self.explanation = explanation
71        super(ConvertedException, self).__init__()
72
73
74class Error(Exception):
75    pass
76
77
78class CinderException(Exception):
79    """Base Cinder Exception
80
81    To correctly use this class, inherit from it and define
82    a 'message' property. That message will get printf'd
83    with the keyword arguments provided to the constructor.
84
85    """
86    message = _("An unknown exception occurred.")
87    code = 500
88    headers = {}
89    safe = False
90
91    def __init__(self, message=None, **kwargs):
92        self.kwargs = kwargs
93        self.kwargs['message'] = message
94
95        if 'code' not in self.kwargs:
96            try:
97                self.kwargs['code'] = self.code
98            except AttributeError:
99                pass
100
101        for k, v in self.kwargs.items():
102            if isinstance(v, Exception):
103                # NOTE(tommylikehu): If this is a cinder exception it will
104                # return the msg object, so we won't be preventing
105                # translations.
106                self.kwargs[k] = six.text_type(v)
107
108        if self._should_format():
109            try:
110                message = self.message % kwargs
111
112            except Exception:
113                # NOTE(melwitt): This is done in a separate method so it can be
114                # monkey-patched during testing to make it a hard failure.
115                self._log_exception()
116                message = self.message
117        elif isinstance(message, Exception):
118            # NOTE(tommylikehu): If this is a cinder exception it will
119            # return the msg object, so we won't be preventing
120            # translations.
121            message = six.text_type(message)
122
123        # NOTE(luisg): We put the actual message in 'msg' so that we can access
124        # it, because if we try to access the message via 'message' it will be
125        # overshadowed by the class' message attribute
126        self.msg = message
127        super(CinderException, self).__init__(message)
128        # Oslo.messaging use the argument 'message' to rebuild exception
129        # directly at the rpc client side, therefore we should not use it
130        # in our keyword arguments, otherwise, the rebuild process will fail
131        # with duplicate keyword exception.
132        self.kwargs.pop('message', None)
133
134    def _log_exception(self):
135        # kwargs doesn't match a variable in the message
136        # log the issue and the kwargs
137        LOG.exception('Exception in string format operation:')
138        for name, value in self.kwargs.items():
139            LOG.error("%(name)s: %(value)s",
140                      {'name': name, 'value': value})
141
142    def _should_format(self):
143        return self.kwargs['message'] is None or '%(message)' in self.message
144
145    # NOTE(tommylikehu): self.msg is already an unicode compatible object
146    # as the __init__ method ensures of it, and we should not be modifying
147    # it in any way with str(), unicode(), or six.text_type() as we would
148    # be preventing translations from happening.
149    def __unicode__(self):
150        return self.msg
151
152
153class VolumeBackendAPIException(CinderException):
154    message = _("Bad or unexpected response from the storage volume "
155                "backend API: %(data)s")
156
157
158class VolumeDriverException(CinderException):
159    message = _("Volume driver reported an error: %(message)s")
160
161
162class BackupDriverException(CinderException):
163    message = _("Backup driver reported an error: %(message)s")
164
165
166class GlanceConnectionFailed(CinderException):
167    message = _("Connection to glance failed: %(reason)s")
168
169
170class ProgrammingError(CinderException):
171    message = _('Programming error in Cinder: %(reason)s')
172
173
174class NotAuthorized(CinderException):
175    message = _("Not authorized.")
176    code = 403
177
178
179class AdminRequired(NotAuthorized):
180    message = _("User does not have admin privileges")
181
182
183class PolicyNotAuthorized(NotAuthorized):
184    message = _("Policy doesn't allow %(action)s to be performed.")
185
186
187class ImageNotAuthorized(CinderException):
188    message = _("Not authorized for image %(image_id)s.")
189
190
191class DriverNotInitialized(CinderException):
192    message = _("Volume driver not ready.")
193
194
195class Invalid(CinderException):
196    message = _("Unacceptable parameters.")
197    code = 400
198
199
200class InvalidSnapshot(Invalid):
201    message = _("Invalid snapshot: %(reason)s")
202
203
204class InvalidVolumeAttachMode(Invalid):
205    message = _("Invalid attaching mode '%(mode)s' for "
206                "volume %(volume_id)s.")
207
208
209class VolumeAttached(Invalid):
210    message = _("Volume %(volume_id)s is still attached, detach volume first.")
211
212
213class InvalidResults(Invalid):
214    message = _("The results are invalid.")
215
216
217class InvalidInput(Invalid):
218    message = _("Invalid input received: %(reason)s")
219
220
221class InvalidAvailabilityZone(Invalid):
222    message = _("Availability zone '%(az)s' is invalid.")
223
224
225class InvalidVolumeType(Invalid):
226    message = _("Invalid volume type: %(reason)s")
227
228
229class InvalidGroupType(Invalid):
230    message = _("Invalid group type: %(reason)s")
231
232
233class InvalidVolume(Invalid):
234    message = _("Invalid volume: %(reason)s")
235
236
237class InvalidContentType(Invalid):
238    message = _("Invalid content type %(content_type)s.")
239
240
241class InvalidHost(Invalid):
242    message = _("Invalid host: %(reason)s")
243
244
245# Cannot be templated as the error syntax varies.
246# msg needs to be constructed when raised.
247class InvalidParameterValue(Invalid):
248    message = "%(err)s"
249
250
251class InvalidAuthKey(Invalid):
252    message = _("Invalid auth key: %(reason)s")
253
254
255class InvalidConfigurationValue(Invalid):
256    message = _('Value "%(value)s" is not valid for '
257                'configuration option "%(option)s"')
258
259
260class ServiceUnavailable(Invalid):
261    message = _("Service is unavailable at this time.")
262
263
264class UnavailableDuringUpgrade(Invalid):
265    message = _('Cannot perform %(action)s during system upgrade.')
266
267
268class ImageUnacceptable(Invalid):
269    message = _("Image %(image_id)s is unacceptable: %(reason)s")
270
271
272class ImageTooBig(Invalid):
273    message = _("Image %(image_id)s size exceeded available "
274                "disk space: %(reason)s")
275
276
277class DeviceUnavailable(Invalid):
278    message = _("The device in the path %(path)s is unavailable: %(reason)s")
279
280
281class SnapshotUnavailable(VolumeBackendAPIException):
282    message = _("The snapshot is unavailable: %(data)s")
283
284
285class InvalidUUID(Invalid):
286    message = _("Expected a UUID but received %(uuid)s.")
287
288
289class InvalidAPIVersionString(Invalid):
290    message = _("API Version String %(version)s is of invalid format. Must "
291                "be of format MajorNum.MinorNum.")
292
293
294class VersionNotFoundForAPIMethod(Invalid):
295    message = _("API version %(version)s is not supported on this method.")
296
297
298class InvalidGlobalAPIVersion(Invalid):
299    message = _("Version %(req_ver)s is not supported by the API. Minimum "
300                "is %(min_ver)s and maximum is %(max_ver)s.")
301
302
303class MissingRequired(Invalid):
304    message = _("Missing required element '%(element)s' in request body.")
305
306
307class ValidationError(Invalid):
308    message = "%(detail)s"
309
310
311class APIException(CinderException):
312    message = _("Error while requesting %(service)s API.")
313
314    def __init__(self, message=None, **kwargs):
315        if 'service' not in kwargs:
316            kwargs['service'] = 'unknown'
317        super(APIException, self).__init__(message, **kwargs)
318
319
320class APITimeout(APIException):
321    message = _("Timeout while requesting %(service)s API.")
322
323
324class RPCTimeout(CinderException):
325    message = _("Timeout while requesting capabilities from backend "
326                "%(service)s.")
327    code = 502
328
329
330class Duplicate(CinderException):
331    pass
332
333
334class NotFound(CinderException):
335    message = _("Resource could not be found.")
336    code = 404
337    safe = True
338
339
340class VolumeNotFound(NotFound):
341    message = _("Volume %(volume_id)s could not be found.")
342
343
344class MessageNotFound(NotFound):
345    message = _("Message %(message_id)s could not be found.")
346
347
348class VolumeAttachmentNotFound(NotFound):
349    message = _("Volume attachment could not be found with "
350                "filter: %(filter)s.")
351
352
353class VolumeMetadataNotFound(NotFound):
354    message = _("Volume %(volume_id)s has no metadata with "
355                "key %(metadata_key)s.")
356
357
358class VolumeAdminMetadataNotFound(NotFound):
359    message = _("Volume %(volume_id)s has no administration metadata with "
360                "key %(metadata_key)s.")
361
362
363class InvalidVolumeMetadata(Invalid):
364    message = _("Invalid metadata: %(reason)s")
365
366
367class InvalidVolumeMetadataSize(Invalid):
368    message = _("Invalid metadata size: %(reason)s")
369
370
371class SnapshotMetadataNotFound(NotFound):
372    message = _("Snapshot %(snapshot_id)s has no metadata with "
373                "key %(metadata_key)s.")
374
375
376class VolumeTypeNotFound(NotFound):
377    message = _("Volume type %(volume_type_id)s could not be found.")
378
379
380class VolumeTypeNotFoundByName(VolumeTypeNotFound):
381    message = _("Volume type with name %(volume_type_name)s "
382                "could not be found.")
383
384
385class VolumeTypeAccessNotFound(NotFound):
386    message = _("Volume type access not found for %(volume_type_id)s / "
387                "%(project_id)s combination.")
388
389
390class VolumeTypeExtraSpecsNotFound(NotFound):
391    message = _("Volume Type %(volume_type_id)s has no extra specs with "
392                "key %(extra_specs_key)s.")
393
394
395class VolumeTypeInUse(CinderException):
396    message = _("Volume Type %(volume_type_id)s deletion is not allowed with "
397                "volumes present with the type.")
398
399
400class GroupTypeNotFound(NotFound):
401    message = _("Group type %(group_type_id)s could not be found.")
402
403
404class GroupTypeNotFoundByName(GroupTypeNotFound):
405    message = _("Group type with name %(group_type_name)s "
406                "could not be found.")
407
408
409class GroupTypeAccessNotFound(NotFound):
410    message = _("Group type access not found for %(group_type_id)s / "
411                "%(project_id)s combination.")
412
413
414class GroupTypeSpecsNotFound(NotFound):
415    message = _("Group Type %(group_type_id)s has no specs with "
416                "key %(group_specs_key)s.")
417
418
419class GroupTypeInUse(CinderException):
420    message = _("Group Type %(group_type_id)s deletion is not allowed with "
421                "groups present with the type.")
422
423
424class SnapshotNotFound(NotFound):
425    message = _("Snapshot %(snapshot_id)s could not be found.")
426
427
428class ServerNotFound(NotFound):
429    message = _("Instance %(uuid)s could not be found.")
430
431
432class VolumeSnapshotNotFound(NotFound):
433    message = _("No snapshots found for volume %(volume_id)s.")
434
435
436class VolumeIsBusy(CinderException):
437    message = _("deleting volume %(volume_name)s that has snapshot")
438
439
440class SnapshotIsBusy(CinderException):
441    message = _("deleting snapshot %(snapshot_name)s that has "
442                "dependent volumes")
443
444
445class ISCSITargetNotFoundForVolume(NotFound):
446    message = _("No target id found for volume %(volume_id)s.")
447
448
449class InvalidImageRef(Invalid):
450    message = _("Invalid image href %(image_href)s.")
451
452
453class ImageNotFound(NotFound):
454    message = _("Image %(image_id)s could not be found.")
455
456
457class ServiceNotFound(NotFound):
458
459    def __init__(self, message=None, **kwargs):
460        if not message:
461            if kwargs.get('host', None):
462                self.message = _("Service %(service_id)s could not be "
463                                 "found on host %(host)s.")
464            else:
465                self.message = _("Service %(service_id)s could not be found.")
466        super(ServiceNotFound, self).__init__(message, **kwargs)
467
468
469class ServiceTooOld(Invalid):
470    message = _("Service is too old to fulfil this request.")
471
472
473class WorkerNotFound(NotFound):
474    message = _("Worker with %s could not be found.")
475
476    def __init__(self, message=None, **kwargs):
477        keys_list = ('{0}=%({0})s'.format(key) for key in kwargs)
478        placeholder = ', '.join(keys_list)
479        self.message = self.message % placeholder
480        super(WorkerNotFound, self).__init__(message, **kwargs)
481
482
483class WorkerExists(Duplicate):
484    message = _("Worker for %(type)s %(id)s already exists.")
485
486
487class CleanableInUse(Invalid):
488    message = _('%(type)s with id %(id)s is already being cleaned up or '
489                'another host has taken over it.')
490
491
492class ClusterNotFound(NotFound):
493    message = _('Cluster %(id)s could not be found.')
494
495
496class ClusterHasHosts(Invalid):
497    message = _("Cluster %(id)s still has hosts.")
498
499
500class ClusterExists(Duplicate):
501    message = _("Cluster %(name)s already exists.")
502
503
504class HostNotFound(NotFound):
505    message = _("Host %(host)s could not be found.")
506
507
508class SchedulerHostFilterNotFound(NotFound):
509    message = _("Scheduler Host Filter %(filter_name)s could not be found.")
510
511
512class SchedulerHostWeigherNotFound(NotFound):
513    message = _("Scheduler Host Weigher %(weigher_name)s could not be found.")
514
515
516class InvalidReservationExpiration(Invalid):
517    message = _("Invalid reservation expiration %(expire)s.")
518
519
520class InvalidQuotaValue(Invalid):
521    message = _("Change would make usage less than 0 for the following "
522                "resources: %(unders)s")
523
524
525class InvalidNestedQuotaSetup(CinderException):
526    message = _("Project quotas are not properly setup for nested quotas: "
527                "%(reason)s.")
528
529
530class QuotaNotFound(NotFound):
531    message = _("Quota could not be found")
532
533
534class QuotaResourceUnknown(QuotaNotFound):
535    message = _("Unknown quota resources %(unknown)s.")
536
537
538class ProjectQuotaNotFound(QuotaNotFound):
539    message = _("Quota for project %(project_id)s could not be found.")
540
541
542class QuotaClassNotFound(QuotaNotFound):
543    message = _("Quota class %(class_name)s could not be found.")
544
545
546class QuotaUsageNotFound(QuotaNotFound):
547    message = _("Quota usage for project %(project_id)s could not be found.")
548
549
550class ReservationNotFound(QuotaNotFound):
551    message = _("Quota reservation %(uuid)s could not be found.")
552
553
554class OverQuota(CinderException):
555    message = _("Quota exceeded for resources: %(overs)s")
556
557
558class FileNotFound(NotFound):
559    message = _("File %(file_path)s could not be found.")
560
561
562class VolumeTypeExists(Duplicate):
563    message = _("Volume Type %(id)s already exists.")
564
565
566class VolumeTypeAccessExists(Duplicate):
567    message = _("Volume type access for %(volume_type_id)s / "
568                "%(project_id)s combination already exists.")
569
570
571class VolumeTypeEncryptionExists(Invalid):
572    message = _("Volume type encryption for type %(type_id)s already exists.")
573
574
575class VolumeTypeEncryptionNotFound(NotFound):
576    message = _("Volume type encryption for type %(type_id)s does not exist.")
577
578
579class GroupTypeExists(Duplicate):
580    message = _("Group Type %(id)s already exists.")
581
582
583class GroupTypeAccessExists(Duplicate):
584    message = _("Group type access for %(group_type_id)s / "
585                "%(project_id)s combination already exists.")
586
587
588class GroupVolumeTypeMappingExists(Duplicate):
589    message = _("Group volume type mapping for %(group_id)s / "
590                "%(volume_type_id)s combination already exists.")
591
592
593class GroupTypeEncryptionExists(Invalid):
594    message = _("Group type encryption for type %(type_id)s already exists.")
595
596
597class GroupTypeEncryptionNotFound(NotFound):
598    message = _("Group type encryption for type %(type_id)s does not exist.")
599
600
601class MalformedRequestBody(CinderException):
602    message = _("Malformed message body: %(reason)s")
603
604
605class ConfigNotFound(NotFound):
606    message = _("Could not find config at %(path)s")
607
608
609class ParameterNotFound(NotFound):
610    message = _("Could not find parameter %(param)s")
611
612
613class NoValidBackend(CinderException):
614    message = _("No valid backend was found. %(reason)s")
615
616
617class NoMoreTargets(CinderException):
618    """No more available targets."""
619    pass
620
621
622class QuotaError(CinderException):
623    message = _("Quota exceeded: code=%(code)s")
624    code = 413
625    headers = {'Retry-After': '0'}
626    safe = True
627
628
629class VolumeSizeExceedsAvailableQuota(QuotaError):
630    message = _("Requested volume or snapshot exceeds allowed %(name)s "
631                "quota. Requested %(requested)sG, quota is %(quota)sG and "
632                "%(consumed)sG has been consumed.")
633
634    def __init__(self, message=None, **kwargs):
635        kwargs.setdefault('name', 'gigabytes')
636        super(VolumeSizeExceedsAvailableQuota, self).__init__(
637            message, **kwargs)
638
639
640class VolumeSizeExceedsLimit(QuotaError):
641    message = _("Requested volume size %(size)dG is larger than "
642                "maximum allowed limit %(limit)dG.")
643
644
645class VolumeBackupSizeExceedsAvailableQuota(QuotaError):
646    message = _("Requested backup exceeds allowed Backup gigabytes "
647                "quota. Requested %(requested)sG, quota is %(quota)sG and "
648                "%(consumed)sG has been consumed.")
649
650
651class VolumeLimitExceeded(QuotaError):
652    message = _("Maximum number of volumes allowed (%(allowed)d) exceeded for "
653                "quota '%(name)s'.")
654
655    def __init__(self, message=None, **kwargs):
656        kwargs.setdefault('name', 'volumes')
657        super(VolumeLimitExceeded, self).__init__(message, **kwargs)
658
659
660class SnapshotLimitExceeded(QuotaError):
661    message = _("Maximum number of snapshots allowed (%(allowed)d) exceeded")
662
663
664class UnexpectedOverQuota(QuotaError):
665    message = _("Unexpected over quota on %(name)s.")
666
667
668class BackupLimitExceeded(QuotaError):
669    message = _("Maximum number of backups allowed (%(allowed)d) exceeded")
670
671
672class ImageLimitExceeded(QuotaError):
673    message = _("Image quota exceeded")
674
675
676class DuplicateSfVolumeNames(Duplicate):
677    message = _("Detected more than one volume with name %(vol_name)s")
678
679
680class VolumeTypeCreateFailed(CinderException):
681    message = _("Cannot create volume_type with "
682                "name %(name)s and specs %(extra_specs)s")
683
684
685class VolumeTypeUpdateFailed(CinderException):
686    message = _("Cannot update volume_type %(id)s")
687
688
689class GroupTypeCreateFailed(CinderException):
690    message = _("Cannot create group_type with "
691                "name %(name)s and specs %(group_specs)s")
692
693
694class GroupTypeUpdateFailed(CinderException):
695    message = _("Cannot update group_type %(id)s")
696
697
698class GroupLimitExceeded(QuotaError):
699    message = _("Maximum number of groups allowed (%(allowed)d) exceeded")
700
701
702class UnknownCmd(VolumeDriverException):
703    message = _("Unknown or unsupported command %(cmd)s")
704
705
706class MalformedResponse(VolumeDriverException):
707    message = _("Malformed response to command %(cmd)s: %(reason)s")
708
709
710class FailedCmdWithDump(VolumeDriverException):
711    message = _("Operation failed with status=%(status)s. Full dump: %(data)s")
712
713
714class InvalidConnectorException(VolumeDriverException):
715    message = _("Connector doesn't have required information: %(missing)s")
716
717
718class GlanceMetadataExists(Invalid):
719    message = _("Glance metadata cannot be updated, key %(key)s"
720                " exists for volume id %(volume_id)s")
721
722
723class GlanceMetadataNotFound(NotFound):
724    message = _("Glance metadata for volume/snapshot %(id)s cannot be found.")
725
726
727class ImageDownloadFailed(CinderException):
728    message = _("Failed to download image %(image_href)s, reason: %(reason)s")
729
730
731class ExportFailure(Invalid):
732    message = _("Failed to export for volume: %(reason)s")
733
734
735class RemoveExportException(VolumeDriverException):
736    message = _("Failed to remove export for volume %(volume)s: %(reason)s")
737
738
739class MetadataCreateFailure(Invalid):
740    message = _("Failed to create metadata for volume: %(reason)s")
741
742
743class MetadataUpdateFailure(Invalid):
744    message = _("Failed to update metadata for volume: %(reason)s")
745
746
747class MetadataCopyFailure(Invalid):
748    message = _("Failed to copy metadata to volume: %(reason)s")
749
750
751class InvalidMetadataType(Invalid):
752    message = _("The type of metadata: %(metadata_type)s for volume/snapshot "
753                "%(id)s is invalid.")
754
755
756class ImageCopyFailure(Invalid):
757    message = _("Failed to copy image to volume: %(reason)s")
758
759
760class BackupInvalidCephArgs(BackupDriverException):
761    message = _("Invalid Ceph args provided for backup rbd operation")
762
763
764class BackupOperationError(Invalid):
765    message = _("An error has occurred during backup operation")
766
767
768class BackupMetadataUnsupportedVersion(BackupDriverException):
769    message = _("Unsupported backup metadata version requested")
770
771
772class BackupMetadataNotFound(NotFound):
773    message = _("Backup %(backup_id)s has no metadata with "
774                "key %(metadata_key)s.")
775
776
777class BackupVerifyUnsupportedDriver(BackupDriverException):
778    message = _("Unsupported backup verify driver")
779
780
781class VolumeMetadataBackupExists(BackupDriverException):
782    message = _("Metadata backup already exists for this volume")
783
784
785class BackupRBDOperationFailed(BackupDriverException):
786    message = _("Backup RBD operation failed")
787
788
789class EncryptedBackupOperationFailed(BackupDriverException):
790    message = _("Backup operation of an encrypted volume failed.")
791
792
793class BackupNotFound(NotFound):
794    message = _("Backup %(backup_id)s could not be found.")
795
796
797class BackupFailedToGetVolumeBackend(NotFound):
798    message = _("Failed to identify volume backend.")
799
800
801class InvalidBackup(Invalid):
802    message = _("Invalid backup: %(reason)s")
803
804
805class SwiftConnectionFailed(BackupDriverException):
806    message = _("Connection to swift failed: %(reason)s")
807
808
809class TransferNotFound(NotFound):
810    message = _("Transfer %(transfer_id)s could not be found.")
811
812
813class VolumeMigrationFailed(CinderException):
814    message = _("Volume migration failed: %(reason)s")
815
816
817class SSHInjectionThreat(CinderException):
818    message = _("SSH command injection detected: %(command)s")
819
820
821class QoSSpecsExists(Duplicate):
822    message = _("QoS Specs %(specs_id)s already exists.")
823
824
825class QoSSpecsCreateFailed(CinderException):
826    message = _("Failed to create qos_specs: "
827                "%(name)s with specs %(qos_specs)s.")
828
829
830class QoSSpecsUpdateFailed(CinderException):
831    message = _("Failed to update qos_specs: "
832                "%(specs_id)s with specs %(qos_specs)s.")
833
834
835class QoSSpecsNotFound(NotFound):
836    message = _("No such QoS spec %(specs_id)s.")
837
838
839class QoSSpecsAssociateFailed(CinderException):
840    message = _("Failed to associate qos_specs: "
841                "%(specs_id)s with type %(type_id)s.")
842
843
844class QoSSpecsDisassociateFailed(CinderException):
845    message = _("Failed to disassociate qos_specs: "
846                "%(specs_id)s with type %(type_id)s.")
847
848
849class QoSSpecsKeyNotFound(NotFound):
850    message = _("QoS spec %(specs_id)s has no spec with "
851                "key %(specs_key)s.")
852
853
854class InvalidQoSSpecs(Invalid):
855    message = _("Invalid qos specs: %(reason)s")
856
857
858class QoSSpecsInUse(CinderException):
859    message = _("QoS Specs %(specs_id)s is still associated with entities.")
860
861
862class KeyManagerError(CinderException):
863    message = _("key manager error: %(reason)s")
864
865
866class ManageExistingInvalidReference(CinderException):
867    message = _("Manage existing volume failed due to invalid backend "
868                "reference %(existing_ref)s: %(reason)s")
869
870
871class ManageExistingAlreadyManaged(CinderException):
872    message = _("Unable to manage existing volume. "
873                "Volume %(volume_ref)s already managed.")
874
875
876class InvalidReplicationTarget(Invalid):
877    message = _("Invalid Replication Target: %(reason)s")
878
879
880class UnableToFailOver(CinderException):
881    message = _("Unable to failover to replication target: %(reason)s).")
882
883
884class ReplicationError(CinderException):
885    message = _("Volume %(volume_id)s replication "
886                "error: %(reason)s")
887
888
889class ReplicationGroupError(CinderException):
890    message = _("Group %(group_id)s replication "
891                "error: %(reason)s.")
892
893
894class ReplicationNotFound(NotFound):
895    message = _("Volume replication for %(volume_id)s "
896                "could not be found.")
897
898
899class ManageExistingVolumeTypeMismatch(CinderException):
900    message = _("Manage existing volume failed due to volume type mismatch: "
901                "%(reason)s")
902
903
904class ExtendVolumeError(CinderException):
905    message = _("Error extending volume: %(reason)s")
906
907
908class EvaluatorParseException(Exception):
909    message = _("Error during evaluator parsing: %(reason)s")
910
911
912class LockCreationFailed(CinderException):
913    message = _('Unable to create lock. Coordination backend not started.')
914
915
916class LockingFailed(CinderException):
917    message = _('Lock acquisition failed.')
918
919
920UnsupportedObjectError = obj_exc.UnsupportedObjectError
921OrphanedObjectError = obj_exc.OrphanedObjectError
922IncompatibleObjectVersion = obj_exc.IncompatibleObjectVersion
923ReadOnlyFieldError = obj_exc.ReadOnlyFieldError
924ObjectActionError = obj_exc.ObjectActionError
925ObjectFieldInvalid = obj_exc.ObjectFieldInvalid
926
927
928class CappedVersionUnknown(CinderException):
929    message = _("Unrecoverable Error: Versioned Objects in DB are capped to "
930                "unknown version %(version)s. Most likely your environment "
931                "contains only new services and you're trying to start an "
932                "older one. Use `cinder-manage service list` to check that "
933                "and upgrade this service.")
934
935
936class VolumeGroupNotFound(CinderException):
937    message = _('Unable to find Volume Group: %(vg_name)s')
938
939
940class VolumeGroupCreationFailed(CinderException):
941    message = _('Failed to create Volume Group: %(vg_name)s')
942
943
944class VolumeNotDeactivated(CinderException):
945    message = _('Volume %(name)s was not deactivated in time.')
946
947
948class VolumeDeviceNotFound(CinderException):
949    message = _('Volume device not found at %(device)s.')
950
951
952# Driver specific exceptions
953# Dell
954class DellDriverRetryableException(VolumeBackendAPIException):
955    message = _("Retryable Dell Exception encountered")
956
957
958class DellDriverUnknownSpec(VolumeDriverException):
959    message = _("Dell driver failure: %(reason)s")
960
961
962# Pure Storage
963class PureDriverException(VolumeDriverException):
964    message = _("Pure Storage Cinder driver failure: %(reason)s")
965
966
967class PureRetryableException(VolumeBackendAPIException):
968    message = _("Retryable Pure Storage Exception encountered")
969
970
971# SolidFire
972class SolidFireAPIException(VolumeBackendAPIException):
973    message = _("Bad response from SolidFire API")
974
975
976class SolidFireDriverException(VolumeDriverException):
977    message = _("SolidFire Cinder Driver exception")
978
979
980class SolidFireAPIDataException(SolidFireAPIException):
981    message = _("Error in SolidFire API response: data=%(data)s")
982
983
984class SolidFireAccountNotFound(SolidFireDriverException):
985    message = _("Unable to locate account %(account_name)s on "
986                "Solidfire device")
987
988
989class SolidFireRetryableException(VolumeBackendAPIException):
990    message = _("Retryable SolidFire Exception encountered")
991
992
993# HP 3Par
994class Invalid3PARDomain(VolumeDriverException):
995    message = _("Invalid 3PAR Domain: %(err)s")
996
997
998# RemoteFS drivers
999class RemoteFSException(VolumeDriverException):
1000    message = _("Unknown RemoteFS exception")
1001
1002
1003class RemoteFSConcurrentRequest(RemoteFSException):
1004    message = _("A concurrent, possibly contradictory, request "
1005                "has been made.")
1006
1007
1008class RemoteFSNoSharesMounted(RemoteFSException):
1009    message = _("No mounted shares found")
1010
1011
1012class RemoteFSNoSuitableShareFound(RemoteFSException):
1013    message = _("There is no share which can host %(volume_size)sG")
1014
1015
1016class RemoteFSInvalidBackingFile(VolumeDriverException):
1017    message = _("File %(path)s has invalid backing file %(backing_file)s.")
1018
1019
1020# NFS driver
1021class NfsException(RemoteFSException):
1022    message = _("Unknown NFS exception")
1023
1024
1025class NfsNoSharesMounted(RemoteFSNoSharesMounted):
1026    message = _("No mounted NFS shares found")
1027
1028
1029class NfsNoSuitableShareFound(RemoteFSNoSuitableShareFound):
1030    message = _("There is no share which can host %(volume_size)sG")
1031
1032
1033# Smbfs driver
1034class SmbfsException(RemoteFSException):
1035    message = _("Unknown SMBFS exception.")
1036
1037
1038class SmbfsNoSharesMounted(RemoteFSNoSharesMounted):
1039    message = _("No mounted SMBFS shares found.")
1040
1041
1042class SmbfsNoSuitableShareFound(RemoteFSNoSuitableShareFound):
1043    message = _("There is no share which can host %(volume_size)sG.")
1044
1045
1046# Virtuozzo Storage Driver
1047
1048class VzStorageException(RemoteFSException):
1049    message = _("Unknown Virtuozzo Storage exception")
1050
1051
1052class VzStorageNoSharesMounted(RemoteFSNoSharesMounted):
1053    message = _("No mounted Virtuozzo Storage shares found")
1054
1055
1056class VzStorageNoSuitableShareFound(RemoteFSNoSuitableShareFound):
1057    message = _("There is no share which can host %(volume_size)sG")
1058
1059
1060# Fibre Channel Zone Manager
1061class ZoneManagerException(CinderException):
1062    message = _("Fibre Channel connection control failure: %(reason)s")
1063
1064
1065class FCZoneDriverException(CinderException):
1066    message = _("Fibre Channel Zone operation failed: %(reason)s")
1067
1068
1069class FCSanLookupServiceException(CinderException):
1070    message = _("Fibre Channel SAN Lookup failure: %(reason)s")
1071
1072
1073class ZoneManagerNotInitialized(CinderException):
1074    message = _("Fibre Channel Zone Manager not initialized")
1075
1076
1077class BrocadeZoningCliException(CinderException):
1078    message = _("Brocade Fibre Channel Zoning CLI error: %(reason)s")
1079
1080
1081class BrocadeZoningHttpException(CinderException):
1082    message = _("Brocade Fibre Channel Zoning HTTP error: %(reason)s")
1083
1084
1085class CiscoZoningCliException(CinderException):
1086    message = _("Cisco Fibre Channel Zoning CLI error: %(reason)s")
1087
1088
1089class NetAppDriverException(VolumeDriverException):
1090    message = _("NetApp Cinder Driver exception.")
1091
1092
1093class EMCVnxCLICmdError(VolumeBackendAPIException):
1094    message = _("EMC VNX Cinder Driver CLI exception: %(cmd)s "
1095                "(Return Code: %(rc)s) (Output: %(out)s).")
1096
1097
1098class EMCSPUnavailableException(EMCVnxCLICmdError):
1099    message = _("EMC VNX Cinder Driver SPUnavailableException: %(cmd)s "
1100                "(Return Code: %(rc)s) (Output: %(out)s).")
1101
1102
1103# ConsistencyGroup
1104class ConsistencyGroupNotFound(NotFound):
1105    message = _("ConsistencyGroup %(consistencygroup_id)s could not be found.")
1106
1107
1108class InvalidConsistencyGroup(Invalid):
1109    message = _("Invalid ConsistencyGroup: %(reason)s")
1110
1111
1112# Group
1113class GroupNotFound(NotFound):
1114    message = _("Group %(group_id)s could not be found.")
1115
1116
1117class InvalidGroup(Invalid):
1118    message = _("Invalid Group: %(reason)s")
1119
1120
1121class InvalidGroupStatus(Invalid):
1122    message = _("Invalid Group Status: %(reason)s")
1123
1124
1125# CgSnapshot
1126class CgSnapshotNotFound(NotFound):
1127    message = _("CgSnapshot %(cgsnapshot_id)s could not be found.")
1128
1129
1130class InvalidCgSnapshot(Invalid):
1131    message = _("Invalid CgSnapshot: %(reason)s")
1132
1133
1134# GroupSnapshot
1135class GroupSnapshotNotFound(NotFound):
1136    message = _("GroupSnapshot %(group_snapshot_id)s could not be found.")
1137
1138
1139class InvalidGroupSnapshot(Invalid):
1140    message = _("Invalid GroupSnapshot: %(reason)s")
1141
1142
1143class InvalidGroupSnapshotStatus(Invalid):
1144    message = _("Invalid GroupSnapshot Status: %(reason)s")
1145
1146
1147# Datera driver
1148class DateraAPIException(VolumeBackendAPIException):
1149    message = _("Bad response from Datera API")
1150
1151
1152# Target drivers
1153class ISCSITargetCreateFailed(CinderException):
1154    message = _("Failed to create iscsi target for volume %(volume_id)s.")
1155
1156
1157class ISCSITargetRemoveFailed(CinderException):
1158    message = _("Failed to remove iscsi target for volume %(volume_id)s.")
1159
1160
1161class ISCSITargetAttachFailed(CinderException):
1162    message = _("Failed to attach iSCSI target for volume %(volume_id)s.")
1163
1164
1165class ISCSITargetDetachFailed(CinderException):
1166    message = _("Failed to detach iSCSI target for volume %(volume_id)s.")
1167
1168
1169class TargetUpdateFailed(CinderException):
1170    message = _("Failed to update target for volume %(volume_id)s.")
1171
1172
1173class ISCSITargetHelperCommandFailed(CinderException):
1174    message = "%(error_message)s"
1175
1176
1177class BadHTTPResponseStatus(VolumeDriverException):
1178    message = _("Bad HTTP response status %(status)s")
1179
1180
1181class BadResetResourceStatus(CinderException):
1182    message = _("Bad reset resource status : %(message)s")
1183
1184
1185# ZADARA STORAGE VPSA driver exception
1186class ZadaraServerCreateFailure(VolumeDriverException):
1187    message = _("Unable to create server object for initiator %(name)s")
1188
1189
1190class ZadaraServerNotFound(NotFound):
1191    message = _("Unable to find server object for initiator %(name)s")
1192
1193
1194class ZadaraVPSANoActiveController(VolumeDriverException):
1195    message = _("Unable to find any active VPSA controller")
1196
1197
1198class ZadaraAttachmentsNotFound(NotFound):
1199    message = _("Failed to retrieve attachments for volume %(name)s")
1200
1201
1202class ZadaraInvalidAttachmentInfo(Invalid):
1203    message = _("Invalid attachment info for volume %(name)s: %(reason)s")
1204
1205
1206class ZadaraVolumeNotFound(VolumeDriverException):
1207    message = "%(reason)s"
1208
1209
1210# ZFSSA NFS driver exception.
1211class WebDAVClientError(VolumeDriverException):
1212    message = _("The WebDAV request failed. Reason: %(msg)s, "
1213                "Return code/reason: %(code)s, Source Volume: %(src)s, "
1214                "Destination Volume: %(dst)s, Method: %(method)s.")
1215
1216
1217# XtremIO Drivers
1218class XtremIOAlreadyMappedError(VolumeDriverException):
1219    message = _("Volume to Initiator Group mapping already exists")
1220
1221
1222class XtremIOArrayBusy(VolumeDriverException):
1223    message = _("System is busy, retry operation.")
1224
1225
1226class XtremIOSnapshotsLimitExceeded(VolumeDriverException):
1227    message = _("Exceeded the limit of snapshots per volume")
1228
1229
1230# StorPool driver
1231class StorPoolConfigurationInvalid(CinderException):
1232    message = _("Invalid parameter %(param)s in the %(section)s section "
1233                "of the /etc/storpool.conf file: %(error)s")
1234
1235
1236# DOTHILL drivers
1237class DotHillInvalidBackend(VolumeDriverException):
1238    message = _("Backend doesn't exist (%(backend)s)")
1239
1240
1241class DotHillConnectionError(VolumeDriverException):
1242    message = "%(message)s"
1243
1244
1245class DotHillAuthenticationError(VolumeDriverException):
1246    message = "%(message)s"
1247
1248
1249class DotHillNotEnoughSpace(VolumeDriverException):
1250    message = _("Not enough space on backend (%(backend)s)")
1251
1252
1253class DotHillRequestError(VolumeDriverException):
1254    message = "%(message)s"
1255
1256
1257class DotHillNotTargetPortal(VolumeDriverException):
1258    message = _("No active iSCSI portals with supplied iSCSI IPs")
1259
1260
1261class DotHillDriverNotSupported(VolumeDriverException):
1262    message = _("The Dot Hill driver is no longer supported.")
1263
1264
1265# Sheepdog
1266class SheepdogError(VolumeBackendAPIException):
1267    message = _("An error has occurred in SheepdogDriver. "
1268                "(Reason: %(reason)s)")
1269
1270
1271class SheepdogCmdError(SheepdogError):
1272    message = _("(Command: %(cmd)s) "
1273                "(Return Code: %(exit_code)s) "
1274                "(Stdout: %(stdout)s) "
1275                "(Stderr: %(stderr)s)")
1276
1277
1278class MetadataAbsent(CinderException):
1279    message = _("There is no metadata in DB object.")
1280
1281
1282class NotSupportedOperation(Invalid):
1283    message = _("Operation not supported: %(operation)s.")
1284    code = 405
1285
1286
1287# NexentaStor driver exception
1288class NexentaException(VolumeDriverException):
1289    message = "%(message)s"
1290
1291
1292# Google Cloud Storage(GCS) backup driver
1293class GCSConnectionFailure(BackupDriverException):
1294    message = _("Google Cloud Storage connection failure: %(reason)s")
1295
1296
1297class GCSApiFailure(BackupDriverException):
1298    message = _("Google Cloud Storage api failure: %(reason)s")
1299
1300
1301class GCSOAuth2Failure(BackupDriverException):
1302    message = _("Google Cloud Storage oauth2 failure: %(reason)s")
1303
1304
1305# Kaminario K2
1306class KaminarioCinderDriverException(VolumeDriverException):
1307    message = _("KaminarioCinderDriver failure: %(reason)s")
1308
1309
1310class KaminarioRetryableException(VolumeDriverException):
1311    message = _("Kaminario retryable exception: %(reason)s")
1312
1313
1314# Synology driver
1315class SynoAPIHTTPError(VolumeDriverException):
1316    message = _("HTTP exit code: [%(code)s]")
1317
1318
1319class SynoAuthError(VolumeDriverException):
1320    message = _("Synology driver authentication failed: %(reason)s.")
1321
1322
1323class SynoLUNNotExist(VolumeDriverException):
1324    message = _("LUN not found by UUID: %(uuid)s.")
1325
1326
1327class AttachmentSpecsNotFound(NotFound):
1328    message = _("Attachment %(attachment_id)s has no "
1329                "key %(specs_key)s.")
1330
1331
1332class InvalidAttachment(Invalid):
1333    message = _("Invalid attachment: %(reason)s")
1334
1335
1336# Veritas driver
1337class UnableToExecuteHyperScaleCmd(VolumeDriverException):
1338    message = _("Failed HyperScale command for '%(message)s'")
1339
1340
1341class UnableToProcessHyperScaleCmdOutput(VolumeDriverException):
1342    message = _("Failed processing command output '%(cmd_out)s'"
1343                " for HyperScale command")
1344
1345
1346class ErrorInFetchingConfiguration(VolumeDriverException):
1347    message = _("Error in fetching configuration for '%(persona)s'")
1348
1349
1350class ErrorInSendingMsg(VolumeDriverException):
1351    message = _("Error in sending message '%(cmd_error)s'")
1352
1353
1354class ErrorInHyperScaleVersion(VolumeDriverException):
1355    message = _("Error in getting HyperScale version '%(cmd_error)s'")
1356
1357
1358class ErrorInParsingArguments(VolumeDriverException):
1359    message = _("Error in parsing message arguments : Invalid Payload")
1360
1361
1362# GPFS driver
1363class GPFSDriverUnsupportedOperation(VolumeBackendAPIException):
1364    message = _("GPFS driver unsupported operation: %(msg)s")
1365
1366
1367class InvalidName(Invalid):
1368    message = _("An invalid 'name' value was provided. %(reason)s")
1369
1370
1371class ServiceUserTokenNoAuth(CinderException):
1372    message = _("The [service_user] send_service_user_token option was "
1373                "requested, but no service auth could be loaded. Please check "
1374                "the [service_user] configuration section.")
1375