github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/acceptancetests/jujupy/exceptions.py (about)

     1  # This file is part of JujuPy, a library for driving the Juju CLI.
     2  # Copyright 2013-2017 Canonical Ltd.
     3  #
     4  # This program is free software: you can redistribute it and/or modify it
     5  # under the terms of the Lesser GNU General Public License version 3, as
     6  # published by the Free Software Foundation.
     7  #
     8  # This program is distributed in the hope that it will be useful, but WITHOUT
     9  # ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
    10  # SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the Lesser
    11  # GNU General Public License for more details.
    12  #
    13  # You should have received a copy of the Lesser GNU General Public License
    14  # along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  import re
    17  import subprocess
    18  
    19  from datetime import timedelta
    20  
    21  
    22  __metaclass__ = type
    23  
    24  
    25  class StatusTimeout(Exception):
    26      """Raised when 'juju status' timed out."""
    27  
    28  class ControllersTimeout(Exception):
    29      """Raised when 'juju show-controller' timed out."""
    30  
    31  class SoftDeadlineExceeded(Exception):
    32      """Raised when an overall client operation takes too long."""
    33  
    34      def __init__(self):
    35          super(SoftDeadlineExceeded, self).__init__(
    36              'Operation exceeded deadline.')
    37  
    38  
    39  class NoProvider(Exception):
    40      """Raised when an environment defines no provider."""
    41  
    42  
    43  class TypeNotAccepted(Exception):
    44      """Raised when the provided type was not accepted."""
    45  
    46  
    47  class NameNotAccepted(Exception):
    48      """Raised when the provided name was not accepted."""
    49  
    50  
    51  class InvalidEndpoint(Exception):
    52      """Raised when the provided endpoint was deemed invalid."""
    53  
    54  
    55  class AuthNotAccepted(Exception):
    56      """Raised when the provided auth was not accepted."""
    57  
    58  
    59  class NoActiveModel(Exception):
    60      """Raised when no active model could be found."""
    61  
    62  
    63  class NoActiveControllers(Exception):
    64      """Raised when no active environment could be found."""
    65  
    66  
    67  class ErroredUnit(Exception):
    68  
    69      def __init__(self, unit_name, state):
    70          msg = '%s is in state %s' % (unit_name, state)
    71          Exception.__init__(self, msg)
    72          self.unit_name = unit_name
    73          self.state = state
    74  
    75  
    76  class UpgradeMongoNotSupported(Exception):
    77  
    78      def __init__(self):
    79          super(UpgradeMongoNotSupported, self).__init__(
    80              'This client does not support upgrade-mongo')
    81  
    82  
    83  class CannotConnectEnv(subprocess.CalledProcessError):
    84  
    85      def __init__(self, e):
    86          super(CannotConnectEnv, self).__init__(e.returncode, e.cmd, e.output)
    87  
    88  
    89  class StatusNotMet(Exception):
    90  
    91      _fmt = 'Expected status not reached in {env}.'
    92  
    93      def __init__(self, environment_name, status):
    94          self.env = environment_name
    95          self.status = status
    96  
    97      def __str__(self):
    98          return self._fmt.format(env=self.env)
    99  
   100  
   101  class AgentsNotStarted(StatusNotMet):
   102  
   103      _fmt = 'Timed out waiting for agents to start in {env}.'
   104  
   105  
   106  class VersionsNotUpdated(StatusNotMet):
   107  
   108      _fmt = 'Some versions did not update.'
   109  
   110  
   111  class WorkloadsNotReady(StatusNotMet):
   112  
   113      _fmt = 'Workloads not ready in {env}.'
   114  
   115  
   116  class ApplicationsNotStarted(StatusNotMet):
   117  
   118      _fmt = 'Timed out waiting for applications to start in {env}.'
   119  
   120  
   121  class VotingNotEnabled(StatusNotMet):
   122  
   123      _fmt = 'Timed out waiting for voting to be enabled in {env}.'
   124  
   125  class LXDProfileNotAvailable(Exception):
   126  
   127      _fmt = 'Timed out waiting for LXDProfile {profile_name} on machine-{machine}.'
   128  
   129      def __init__(self, machine, profile_name):
   130          self.profile_name = profile_name
   131          self.machine = machine
   132  
   133      def __str__(self):
   134          return self._fmt.format(env=self.profile_name)
   135  
   136  class StatusError(Exception):
   137      """Generic error for Status."""
   138  
   139      recoverable = True
   140  
   141      # This has to be filled in after the classes are declared.
   142      ordering = []
   143  
   144      @classmethod
   145      def priority(cls):
   146          """Get the priority of the StatusError as an number.
   147  
   148          Lower number means higher priority. This can be used as a key
   149          function in sorting."""
   150          return cls.ordering.index(cls)
   151  
   152  
   153  class MachineError(StatusError):
   154      """Error in machine-status."""
   155  
   156      recoverable = False
   157  
   158  
   159  class ProvisioningError(MachineError):
   160      """Machine experianced a 'provisioning error'."""
   161  
   162  
   163  class StuckAllocatingError(MachineError):
   164      """Machine did not transition out of 'allocating' state."""
   165  
   166      recoverable = True
   167  
   168  
   169  class UnitError(StatusError):
   170      """Error in a unit's status."""
   171  
   172  
   173  class HookFailedError(UnitError):
   174      """A unit hook has failed."""
   175  
   176      def __init__(self, item_name, msg):
   177          match = re.search('^hook failed: "([^"]+)"$', msg)
   178          if match:
   179              msg = match.group(1)
   180          super(HookFailedError, self).__init__(item_name, msg)
   181  
   182  
   183  class InstallError(HookFailedError):
   184      """The unit's install hook has failed."""
   185  
   186      recoverable = True
   187  
   188  
   189  class AppError(StatusError):
   190      """Error in an application's status."""
   191  
   192  
   193  class AgentError(StatusError):
   194      """Error in a juju agent."""
   195  
   196  
   197  class AgentUnresolvedError(AgentError):
   198      """Agent error has not recovered in a reasonable time."""
   199  
   200      # This is the time limit set by IS for recovery from an agent error.
   201      a_reasonable_time = timedelta(minutes=5)
   202  
   203  
   204  StatusError.ordering = [
   205      ProvisioningError, StuckAllocatingError, MachineError, InstallError,
   206      AgentUnresolvedError, HookFailedError, UnitError, AppError, AgentError,
   207      StatusError,
   208      ]