Internet of Things resource management service for OpenStack clouds.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

exception.py 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  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. """Iotronic base exception handling.
  17. Includes decorator for re-raising Iotronic-type exceptions.
  18. SHOULD include dedicated exception logging.
  19. """
  20. from oslo_config import cfg
  21. from oslo_log import log as logging
  22. import six
  23. from iotronic.common.i18n import _
  24. from iotronic.common.i18n import _LE
  25. LOG = logging.getLogger(__name__)
  26. exc_log_opts = [
  27. cfg.BoolOpt('fatal_exception_format_errors',
  28. default=False,
  29. help='Used if there is a formatting error when generating an '
  30. 'exception message (a programming error). If True, '
  31. 'raise an exception; if False, use the unformatted '
  32. 'message.'),
  33. ]
  34. CONF = cfg.CONF
  35. CONF.register_opts(exc_log_opts)
  36. def _cleanse_dict(original):
  37. """Strip all admin_password, new_pass, rescue_pass keys from a dict."""
  38. return dict((k, v) for k, v in original.iteritems() if "_pass" not in k)
  39. class IotronicException(Exception):
  40. """Base Iotronic Exception
  41. To correctly use this class, inherit from it and define
  42. a 'message' property. That message will get printf'd
  43. with the keyword arguments provided to the constructor.
  44. """
  45. message = _("An unknown exception occurred.")
  46. code = 500
  47. headers = {}
  48. safe = False
  49. def __init__(self, message=None, **kwargs):
  50. self.kwargs = kwargs
  51. if 'code' not in self.kwargs:
  52. try:
  53. self.kwargs['code'] = self.code
  54. except AttributeError:
  55. pass
  56. if not message:
  57. try:
  58. message = self.message % kwargs
  59. except Exception as e:
  60. # kwargs doesn't match a variable in the message
  61. # log the issue and the kwargs
  62. LOG.exception(_LE('Exception in string format operation'))
  63. for name, value in kwargs.items():
  64. LOG.error("%s: %s" % (name, value))
  65. if CONF.fatal_exception_format_errors:
  66. raise e
  67. else:
  68. # at least get the core message out if something happened
  69. message = self.message
  70. super(IotronicException, self).__init__(message)
  71. def __str__(self):
  72. """Encode to utf-8 then wsme api can consume it as well."""
  73. if not six.PY3:
  74. return unicode(self.args[0]).encode('utf-8')
  75. return self.args[0]
  76. def format_message(self):
  77. if self.__class__.__name__.endswith('_Remote'):
  78. return self.args[0]
  79. else:
  80. return six.text_type(self)
  81. class NotAuthorized(IotronicException):
  82. message = _("Not authorized.")
  83. code = 403
  84. class OperationNotPermitted(NotAuthorized):
  85. message = _("Operation not permitted.")
  86. class Invalid(IotronicException):
  87. message = _("Unacceptable parameters.")
  88. code = 400
  89. class Conflict(IotronicException):
  90. message = _('Conflict.')
  91. code = 409
  92. class TemporaryFailure(IotronicException):
  93. message = _("Resource temporarily unavailable, please retry.")
  94. code = 503
  95. class NotAcceptable(IotronicException):
  96. # TODO(deva): We need to set response headers in the API for this exception
  97. message = _("Request not acceptable.")
  98. code = 406
  99. class InvalidState(Conflict):
  100. message = _("Invalid resource state.")
  101. class BoardAlreadyExists(Conflict):
  102. message = _("A board with UUID %(uuid)s already exists.")
  103. class MACAlreadyExists(Conflict):
  104. message = _("A port with MAC address %(mac)s already exists.")
  105. class PortAlreadyExists(Conflict):
  106. message = _("A port with UUID %(uuid)s already exists.")
  107. class DuplicateName(Conflict):
  108. message = _("A board with name %(name)s already exists.")
  109. class DuplicateCode(Conflict):
  110. message = _("A board with code %(code)s already exists.")
  111. class InvalidUUID(Invalid):
  112. message = _("Expected a uuid but received %(uuid)s.")
  113. class InvalidUuidOrName(Invalid):
  114. message = _("Expected a logical name or uuid but received %(name)s.")
  115. class InvalidName(Invalid):
  116. message = _("Expected a logical name but received %(name)s.")
  117. class InvalidIdentity(Invalid):
  118. message = _("Expected an uuid or int but received %(identity)s.")
  119. class InvalidMAC(Invalid):
  120. message = _("Expected a MAC address but received %(mac)s.")
  121. class InvalidStateRequested(Invalid):
  122. message = _('The requested action "%(action)s" can not be performed '
  123. 'on board "%(board)s" while it is in state "%(state)s".')
  124. class PatchError(Invalid):
  125. message = _("Couldn't apply patch '%(patch)s'. Reason: %(reason)s")
  126. class InstanceDeployFailure(IotronicException):
  127. message = _("Failed to deploy instance: %(reason)s")
  128. class ImageUnacceptable(IotronicException):
  129. message = _("Image %(image_id)s is unacceptable: %(reason)s")
  130. class ImageConvertFailed(IotronicException):
  131. message = _("Image %(image_id)s is unacceptable: %(reason)s")
  132. # Cannot be templated as the error syntax varies.
  133. # msg needs to be constructed when raised.
  134. class InvalidParameterValue(Invalid):
  135. message = _("%(err)s")
  136. class MissingParameterValue(InvalidParameterValue):
  137. message = _("%(err)s")
  138. class Duplicate(IotronicException):
  139. message = _("Resource already exists.")
  140. class NotFound(IotronicException):
  141. message = _("Resource could not be found.")
  142. code = 404
  143. class DHCPLoadError(IotronicException):
  144. message = _("Failed to load DHCP provider %(dhcp_provider_name)s, "
  145. "reason: %(reason)s")
  146. class DriverNotFound(NotFound):
  147. message = _("Could not find the following driver(s): %(driver_name)s.")
  148. class ImageNotFound(NotFound):
  149. message = _("Image %(image_id)s could not be found.")
  150. class NoValidHost(NotFound):
  151. message = _("No valid host was found. Reason: %(reason)s")
  152. class InstanceNotFound(NotFound):
  153. message = _("Instance %(instance)s could not be found.")
  154. class BoardNotFound(NotFound):
  155. message = _("Board %(board)s could not be found.")
  156. class BoardNotConnected(Invalid):
  157. message = _("Board %(board)s is not connected.")
  158. class BoardAssociated(InvalidState):
  159. message = _("Board %(board)s is associated with instance %(instance)s.")
  160. class PortNotFound(NotFound):
  161. message = _("Port %(port)s could not be found.")
  162. class FailedToUpdateDHCPOptOnPort(IotronicException):
  163. message = _("Update DHCP options on port: %(port_id)s failed.")
  164. class FailedToGetIPAddressOnPort(IotronicException):
  165. message = _("Retrieve IP address on port: %(port_id)s failed.")
  166. class InvalidIPv4Address(IotronicException):
  167. message = _("Invalid IPv4 address %(ip_address)s.")
  168. class FailedToUpdateMacOnPort(IotronicException):
  169. message = _("Update MAC address on port: %(port_id)s failed.")
  170. class NoDriversLoaded(IotronicException):
  171. message = _("Conductor %(conductor)s cannot be started "
  172. "because no drivers were loaded.")
  173. class ConductorNotFound(NotFound):
  174. message = _("Conductor %(conductor)s could not be found.")
  175. class ConductorAlreadyRegistered(IotronicException):
  176. message = _("Conductor %(conductor)s already registered.")
  177. class WampAgentNotFound(NotFound):
  178. message = _("WampAgent %(wampagent)s could not be found.")
  179. class WampRegistrationAgentNotFound(NotFound):
  180. message = _("No Wamp Registration Agent could not be found.")
  181. class WampAgentAlreadyRegistered(IotronicException):
  182. message = _("WampAgent %(wampagent)s already registered.")
  183. class PowerStateFailure(InvalidState):
  184. message = _("Failed to set board power state to %(pstate)s.")
  185. class ExclusiveLockRequired(NotAuthorized):
  186. message = _("An exclusive lock is required, "
  187. "but the current context has a shared lock.")
  188. class BoardMaintenanceFailure(Invalid):
  189. message = _("Failed to toggle maintenance-mode flag "
  190. "for board %(board)s: %(reason)s")
  191. class BoardConsoleNotEnabled(Invalid):
  192. message = _("Console access is not enabled on board %(board)s")
  193. class BoardInMaintenance(Invalid):
  194. message = _("The %(op)s operation can't be performed on board "
  195. "%(board)s because it's in maintenance mode.")
  196. class IPMIFailure(IotronicException):
  197. message = _("IPMI call failed: %(cmd)s.")
  198. class AMTConnectFailure(IotronicException):
  199. message = _("Failed to connect to AMT service.")
  200. class AMTFailure(IotronicException):
  201. message = _("AMT call failed: %(cmd)s.")
  202. class MSFTOCSClientApiException(IotronicException):
  203. message = _("MSFT OCS call failed.")
  204. class SSHConnectFailed(IotronicException):
  205. message = _("Failed to establish SSH connection to host %(host)s.")
  206. class SSHCommandFailed(IotronicException):
  207. message = _("Failed to execute command via SSH: %(cmd)s.")
  208. class UnsupportedObjectError(IotronicException):
  209. message = _('Unsupported object type %(objtype)s')
  210. class OrphanedObjectError(IotronicException):
  211. message = _('Cannot call %(method)s on orphaned %(objtype)s object')
  212. class UnsupportedDriverExtension(Invalid):
  213. message = _('Driver %(driver)s does not support %(extension)s '
  214. '(disabled or not implemented).')
  215. class IncompatibleObjectVersion(IotronicException):
  216. message = _('Version %(objver)s of %(objname)s is not supported')
  217. class GlanceConnectionFailed(IotronicException):
  218. message = _("Connection to glance host %(host)s:%(port)s failed: "
  219. "%(reason)s")
  220. class ImageNotAuthorized(NotAuthorized):
  221. message = _("Not authorized for image %(image_id)s.")
  222. class InvalidImageRef(Invalid):
  223. message = _("Invalid image href %(image_href)s.")
  224. class ImageRefValidationFailed(IotronicException):
  225. message = _("Validation of image href %(image_href)s failed, "
  226. "reason: %(reason)s")
  227. class ImageDownloadFailed(IotronicException):
  228. message = _("Failed to download image %(image_href)s, reason: %(reason)s")
  229. class KeystoneUnauthorized(IotronicException):
  230. message = _("Not authorized in Keystone.")
  231. class KeystoneFailure(IotronicException):
  232. pass
  233. class CatalogNotFound(IotronicException):
  234. message = _("Service type %(service_type)s with endpoint type "
  235. "%(endpoint_type)s not found in keystone service catalog.")
  236. class ServiceUnavailable(IotronicException):
  237. message = _("Connection failed")
  238. class Forbidden(IotronicException):
  239. message = _("Requested Iotronic API is forbidden")
  240. class BadRequest(IotronicException):
  241. pass
  242. class InvalidEndpoint(IotronicException):
  243. message = _("The provided endpoint is invalid")
  244. class CommunicationError(IotronicException):
  245. message = _("Unable to communicate with the server.")
  246. class HTTPForbidden(NotAuthorized):
  247. message = _("Access was denied to the following resource: %(resource)s")
  248. class Unauthorized(IotronicException):
  249. pass
  250. class HTTPNotFound(NotFound):
  251. pass
  252. class ConfigNotFound(IotronicException):
  253. message = _("Could not find config at %(path)s")
  254. class BoardLocked(Conflict):
  255. message = _("Board %(board)s is locked by host %(host)s, please retry "
  256. "after the current operation is completed.")
  257. class BoardNotLocked(Invalid):
  258. message = _("Board %(board)s found not to be locked on release")
  259. class NoFreeConductorWorker(TemporaryFailure):
  260. message = _('Requested action cannot be performed due to lack of free '
  261. 'conductor workers.')
  262. code = 503 # Service Unavailable (temporary).
  263. class VendorPassthruException(IotronicException):
  264. pass
  265. class ConfigInvalid(IotronicException):
  266. message = _("Invalid configuration file. %(error_msg)s")
  267. class DriverLoadError(IotronicException):
  268. message = _("Driver %(driver)s could not be loaded. Reason: %(reason)s.")
  269. class ConsoleError(IotronicException):
  270. pass
  271. class NoConsolePid(ConsoleError):
  272. message = _("Could not find pid in pid file %(pid_path)s")
  273. class ConsoleSubprocessFailed(ConsoleError):
  274. message = _("Console subprocess failed to start. %(error)s")
  275. class PasswordFileFailedToCreate(IotronicException):
  276. message = _("Failed to create the password file. %(error)s")
  277. class IBootOperationError(IotronicException):
  278. pass
  279. class IloOperationError(IotronicException):
  280. message = _("%(operation)s failed, error: %(error)s")
  281. class IloOperationNotSupported(IotronicException):
  282. message = _("%(operation)s not supported. error: %(error)s")
  283. class DracRequestFailed(IotronicException):
  284. pass
  285. class DracClientError(DracRequestFailed):
  286. message = _('DRAC client failed. '
  287. 'Last error (cURL error code): %(last_error)s, '
  288. 'fault string: "%(fault_string)s" '
  289. 'response_code: %(response_code)s')
  290. class DracOperationFailed(DracRequestFailed):
  291. message = _('DRAC operation failed. Message: %(message)s')
  292. class DracUnexpectedReturnValue(DracRequestFailed):
  293. message = _('DRAC operation yielded return value %(actual_return_value)s '
  294. 'that is neither error nor expected %(expected_return_value)s')
  295. class DracPendingConfigJobExists(IotronicException):
  296. message = _('Another job with ID %(job_id)s is already created '
  297. 'to configure %(target)s. Wait until existing job '
  298. 'is completed or is canceled')
  299. class DracInvalidFilterDialect(IotronicException):
  300. message = _('Invalid filter dialect \'%(invalid_filter)s\'. '
  301. 'Supported options are %(supported)s')
  302. class FailedToGetSensorData(IotronicException):
  303. message = _("Failed to get sensor data for board %(board)s. "
  304. "Error: %(error)s")
  305. class FailedToParseSensorData(IotronicException):
  306. message = _("Failed to parse sensor data for board %(board)s. "
  307. "Error: %(error)s")
  308. class InsufficientDiskSpace(IotronicException):
  309. message = _("Disk volume where '%(path)s' is located doesn't have "
  310. "enough disk space. Required %(required)d MiB, "
  311. "only %(actual)d MiB available space present.")
  312. class ImageCreationFailed(IotronicException):
  313. message = _('Creating %(image_type)s image failed: %(error)s')
  314. class SwiftOperationError(IotronicException):
  315. message = _("Swift operation '%(operation)s' failed: %(error)s")
  316. class SNMPFailure(IotronicException):
  317. message = _("SNMP operation '%(operation)s' failed: %(error)s")
  318. class FileSystemNotSupported(IotronicException):
  319. message = _("Failed to create a file system. "
  320. "File system %(fs)s is not supported.")
  321. class IRMCOperationError(IotronicException):
  322. message = _('iRMC %(operation)s failed. Reason: %(error)s')
  323. class VirtualBoxOperationFailed(IotronicException):
  324. message = _("VirtualBox operation '%(operation)s' failed. "
  325. "Error: %(error)s")
  326. class HardwareInspectionFailure(IotronicException):
  327. message = _("Failed to inspect hardware. Reason: %(error)s")
  328. class BoardCleaningFailure(IotronicException):
  329. message = _("Failed to clean board %(board)s: %(reason)s")
  330. class PathNotFound(IotronicException):
  331. message = _("Path %(dir)s does not exist.")
  332. class DirectoryNotWritable(IotronicException):
  333. message = _("Directory %(dir)s is not writable.")
  334. class PluginNotFound(NotFound):
  335. message = _("Plugin %(plugin)s could not be found.")
  336. class InjectionPluginNotFound(NotFound):
  337. message = _("InjectionPlugin could not be found.")
  338. class InvalidPluginAction(Invalid):
  339. message = _("Invalid Action %(action)s for the plugin.")
  340. class NeedParams(Invalid):
  341. message = _("Action %(action)s needs parameters.")
  342. class ErrorExecutionOnBoard(IotronicException):
  343. message = _("Error in the execution of %(call)s on %(board)s: %(error)s")
  344. class ServiceNotFound(NotFound):
  345. message = _("Service %(Service)s could not be found.")
  346. class ServiceAlreadyExists(Conflict):
  347. message = _("A Service with UUID %(uuid)s already exists.")
  348. class ServiceAlreadyExposed(Conflict):
  349. message = _("A Service with UUID %(uuid)s already exposed.")
  350. class ExposedServiceNotFound(NotFound):
  351. message = _("ExposedService %(uuid)s could not be found.")
  352. class NoExposedServices(NotFound):
  353. message = _("No exposed services on the board %(uuid)s.")