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.

api.py 30KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844
  1. # -*- encoding: utf-8 -*-
  2. #
  3. # Copyright 2013 Hewlett-Packard Development Company, L.P.
  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. """SQLAlchemy storage backend."""
  17. from oslo_config import cfg
  18. from oslo_db import exception as db_exc
  19. from oslo_db.sqlalchemy import session as db_session
  20. from oslo_db.sqlalchemy import utils as db_utils
  21. from oslo_utils import strutils
  22. from oslo_utils import timeutils
  23. from oslo_utils import uuidutils
  24. from sqlalchemy import or_
  25. from sqlalchemy.orm.exc import NoResultFound
  26. from iotronic.common import exception
  27. from iotronic.common.i18n import _
  28. from iotronic.common import states
  29. from iotronic.db import api
  30. from iotronic.db.sqlalchemy import models
  31. CONF = cfg.CONF
  32. CONF.import_opt('heartbeat_timeout',
  33. 'iotronic.conductor.manager',
  34. group='conductor')
  35. _FACADE = None
  36. def _create_facade_lazily():
  37. global _FACADE
  38. if _FACADE is None:
  39. _FACADE = db_session.EngineFacade.from_config(CONF)
  40. return _FACADE
  41. def get_engine():
  42. facade = _create_facade_lazily()
  43. return facade.get_engine()
  44. def get_session(**kwargs):
  45. facade = _create_facade_lazily()
  46. return facade.get_session(**kwargs)
  47. def get_backend():
  48. """The backend is this module itself."""
  49. return Connection()
  50. def model_query(model, *args, **kwargs):
  51. """Query helper for simpler session usage.
  52. :param session: if present, the session to use
  53. """
  54. session = kwargs.get('session') or get_session()
  55. query = session.query(model, *args)
  56. return query
  57. def add_identity_filter(query, value):
  58. """Adds an identity filter to a query.
  59. Filters results by ID, if supplied value is a valid integer.
  60. Otherwise attempts to filter results by UUID.
  61. :param query: Initial query to add filter to.
  62. :param value: Value for filtering results by.
  63. :return: Modified query.
  64. """
  65. if strutils.is_int_like(value):
  66. return query.filter_by(id=value)
  67. elif uuidutils.is_uuid_like(value):
  68. return query.filter_by(uuid=value)
  69. else:
  70. raise exception.InvalidIdentity(identity=value)
  71. def _paginate_query(model, limit=None, marker=None, sort_key=None,
  72. sort_dir=None, query=None):
  73. if not query:
  74. query = model_query(model)
  75. sort_keys = ['id']
  76. if sort_key and sort_key not in sort_keys:
  77. sort_keys.insert(0, sort_key)
  78. try:
  79. query = db_utils.paginate_query(query, model, limit, sort_keys,
  80. marker=marker, sort_dir=sort_dir)
  81. except db_exc.InvalidSortKey:
  82. raise exception.InvalidParameterValue(
  83. _('The sort_key value "%(key)s" is an invalid field for sorting')
  84. % {'key': sort_key})
  85. return query.all()
  86. class Connection(api.Connection):
  87. """SqlAlchemy connection."""
  88. def __init__(self):
  89. pass
  90. def _add_location_filter_by_board(self, query, value):
  91. if strutils.is_int_like(value):
  92. return query.filter_by(board_id=value)
  93. else:
  94. query = query.join(models.Board,
  95. models.Location.board_id == models.Board.id)
  96. return query.filter(models.Board.uuid == value)
  97. def _add_boards_filters(self, query, filters):
  98. if filters is None:
  99. filters = []
  100. if 'project_id' in filters:
  101. query = query.filter(models.Board.project == filters['project_id'])
  102. if 'status' in filters:
  103. query = query.filter(models.Board.status == filters['status'])
  104. return query
  105. def _add_plugins_filters(self, query, filters):
  106. if filters is None:
  107. filters = []
  108. if 'owner' in filters:
  109. if 'with_public' in filters and filters['with_public']:
  110. query = query.filter(
  111. or_(
  112. models.Plugin.owner == filters['owner'],
  113. models.Plugin.public == 1)
  114. )
  115. else:
  116. query = query.filter(models.Plugin.owner == filters['owner'])
  117. elif 'public' in filters and filters['public']:
  118. query = query.filter(models.Plugin.public == 1)
  119. return query
  120. def _add_services_filters(self, query, filters):
  121. if filters is None:
  122. filters = []
  123. if 'owner' in filters:
  124. query = query.filter(models.Plugin.owner == filters['owner'])
  125. return query
  126. def _add_wampagents_filters(self, query, filters):
  127. if filters is None:
  128. filters = []
  129. if 'online' in filters:
  130. if filters['online']:
  131. query = query.filter(models.WampAgent.online == 1)
  132. else:
  133. query = query.filter(models.WampAgent.online == 0)
  134. if 'no_ragent' in filters:
  135. if filters['no_ragent']:
  136. query = query.filter(models.WampAgent.ragent == 0)
  137. else:
  138. query = query.filter(models.WampAgent.ragent == 1)
  139. return query
  140. def _do_update_board(self, board_id, values):
  141. session = get_session()
  142. with session.begin():
  143. query = model_query(models.Board, session=session)
  144. query = add_identity_filter(query, board_id)
  145. try:
  146. ref = query.with_lockmode('update').one()
  147. except NoResultFound:
  148. raise exception.BoardNotFound(board=board_id)
  149. ref.update(values)
  150. return ref
  151. def _do_update_plugin(self, plugin_id, values):
  152. session = get_session()
  153. with session.begin():
  154. query = model_query(models.Plugin, session=session)
  155. query = add_identity_filter(query, plugin_id)
  156. try:
  157. ref = query.with_lockmode('update').one()
  158. except NoResultFound:
  159. raise exception.PluginNotFound(plugin=plugin_id)
  160. ref.update(values)
  161. return ref
  162. def _do_update_injection_plugin(self, injection_plugin_id, values):
  163. session = get_session()
  164. with session.begin():
  165. query = model_query(models.InjectionPlugin, session=session)
  166. query = add_identity_filter(query, injection_plugin_id)
  167. try:
  168. ref = query.with_lockmode('update').one()
  169. except NoResultFound:
  170. raise exception.InjectionPluginNotFound(
  171. injection_plugin=injection_plugin_id)
  172. ref.update(values)
  173. return ref
  174. # BOARD api
  175. def get_boardinfo_list(self, columns=None, filters=None, limit=None,
  176. marker=None, sort_key=None, sort_dir=None):
  177. # list-ify columns default values because it is bad form
  178. # to include a mutable list in function definitions.
  179. if columns is None:
  180. columns = [models.Board.id]
  181. else:
  182. columns = [getattr(models.Board, c) for c in columns]
  183. query = model_query(*columns, base_model=models.Board)
  184. query = self._add_boards_filters(query, filters)
  185. return _paginate_query(models.Board, limit, marker,
  186. sort_key, sort_dir, query)
  187. def get_board_list(self, filters=None, limit=None, marker=None,
  188. sort_key=None, sort_dir=None):
  189. query = model_query(models.Board)
  190. query = self._add_boards_filters(query, filters)
  191. return _paginate_query(models.Board, limit, marker,
  192. sort_key, sort_dir, query)
  193. def create_board(self, values):
  194. # ensure defaults are present for new boards
  195. if 'uuid' not in values:
  196. values['uuid'] = uuidutils.generate_uuid()
  197. if 'status' not in values:
  198. values['status'] = states.REGISTERED
  199. board = models.Board()
  200. board.update(values)
  201. try:
  202. board.save()
  203. except db_exc.DBDuplicateEntry as exc:
  204. if 'code' in exc.columns:
  205. raise exception.DuplicateCode(code=values['code'])
  206. raise exception.BoardAlreadyExists(uuid=values['uuid'])
  207. return board
  208. def get_board_by_id(self, board_id):
  209. query = model_query(models.Board).filter_by(id=board_id)
  210. try:
  211. return query.one()
  212. except NoResultFound:
  213. raise exception.BoardNotFound(board=board_id)
  214. def get_board_id_by_uuid(self, board_uuid):
  215. query = model_query(models.Board.id).filter_by(uuid=board_uuid)
  216. try:
  217. return query.one()
  218. except NoResultFound:
  219. raise exception.BoardNotFound(board=board_uuid)
  220. def get_board_by_uuid(self, board_uuid):
  221. query = model_query(models.Board).filter_by(uuid=board_uuid)
  222. try:
  223. return query.one()
  224. except NoResultFound:
  225. raise exception.BoardNotFound(board=board_uuid)
  226. def get_board_by_name(self, board_name):
  227. query = model_query(models.Board).filter_by(name=board_name)
  228. try:
  229. return query.one()
  230. except NoResultFound:
  231. raise exception.BoardNotFound(board=board_name)
  232. def get_board_by_code(self, board_code):
  233. query = model_query(models.Board).filter_by(code=board_code)
  234. try:
  235. return query.one()
  236. except NoResultFound:
  237. raise exception.BoardNotFound(board=board_code)
  238. def destroy_board(self, board_id):
  239. session = get_session()
  240. with session.begin():
  241. query = model_query(models.Board, session=session)
  242. query = add_identity_filter(query, board_id)
  243. try:
  244. board_ref = query.one()
  245. except NoResultFound:
  246. raise exception.BoardNotFound(board=board_id)
  247. # Get board ID, if an UUID was supplied. The ID is
  248. # required for deleting all ports, attached to the board.
  249. if uuidutils.is_uuid_like(board_id):
  250. board_id = board_ref['id']
  251. location_query = model_query(models.Location, session=session)
  252. location_query = self._add_location_filter_by_board(
  253. location_query, board_id)
  254. location_query.delete()
  255. query.delete()
  256. def update_board(self, board_id, values):
  257. # NOTE(dtantsur): this can lead to very strange errors
  258. if 'uuid' in values:
  259. msg = _("Cannot overwrite UUID for an existing Board.")
  260. raise exception.InvalidParameterValue(err=msg)
  261. try:
  262. return self._do_update_board(board_id, values)
  263. except db_exc.DBDuplicateEntry as e:
  264. if 'name' in e.columns:
  265. raise exception.DuplicateName(name=values['name'])
  266. elif 'uuid' in e.columns:
  267. raise exception.BoardAlreadyExists(uuid=values['uuid'])
  268. else:
  269. raise e
  270. # CONDUCTOR api
  271. def register_conductor(self, values, update_existing=False):
  272. session = get_session()
  273. with session.begin():
  274. query = (model_query(models.Conductor, session=session)
  275. .filter_by(hostname=values['hostname']))
  276. try:
  277. ref = query.one()
  278. if ref.online is True and not update_existing:
  279. raise exception.ConductorAlreadyRegistered(
  280. conductor=values['hostname'])
  281. except NoResultFound:
  282. ref = models.Conductor()
  283. ref.update(values)
  284. # always set online and updated_at fields when registering
  285. # a conductor, especially when updating an existing one
  286. ref.update({'updated_at': timeutils.utcnow(),
  287. 'online': True})
  288. ref.save(session)
  289. return ref
  290. def get_conductor(self, hostname):
  291. try:
  292. return (model_query(models.Conductor)
  293. .filter_by(hostname=hostname, online=True)
  294. .one())
  295. except NoResultFound:
  296. raise exception.ConductorNotFound(conductor=hostname)
  297. def unregister_conductor(self, hostname):
  298. session = get_session()
  299. with session.begin():
  300. query = (model_query(models.Conductor, session=session)
  301. .filter_by(hostname=hostname, online=True))
  302. count = query.update({'online': False})
  303. if count == 0:
  304. raise exception.ConductorNotFound(conductor=hostname)
  305. def touch_conductor(self, hostname):
  306. session = get_session()
  307. with session.begin():
  308. query = (model_query(models.Conductor, session=session)
  309. .filter_by(hostname=hostname))
  310. # since we're not changing any other field, manually set updated_at
  311. # and since we're heartbeating, make sure that online=True
  312. count = query.update({'updated_at': timeutils.utcnow(),
  313. 'online': True})
  314. if count == 0:
  315. raise exception.ConductorNotFound(conductor=hostname)
  316. # LOCATION api
  317. def create_location(self, values):
  318. location = models.Location()
  319. location.update(values)
  320. location.save()
  321. return location
  322. def update_location(self, location_id, values):
  323. # NOTE(dtantsur): this can lead to very strange errors
  324. session = get_session()
  325. try:
  326. with session.begin():
  327. query = model_query(models.Location, session=session)
  328. query = add_identity_filter(query, location_id)
  329. ref = query.one()
  330. ref.update(values)
  331. except NoResultFound:
  332. raise exception.LocationNotFound(location=location_id)
  333. return ref
  334. def destroy_location(self, location_id):
  335. session = get_session()
  336. with session.begin():
  337. query = model_query(models.Location, session=session)
  338. query = add_identity_filter(query, location_id)
  339. count = query.delete()
  340. if count == 0:
  341. raise exception.LocationNotFound(location=location_id)
  342. def get_locations_by_board_id(self, board_id, limit=None, marker=None,
  343. sort_key=None, sort_dir=None):
  344. query = model_query(models.Location)
  345. query = query.filter_by(board_id=board_id)
  346. return _paginate_query(models.Location, limit, marker,
  347. sort_key, sort_dir, query)
  348. # SESSION api
  349. def create_session(self, values):
  350. session = models.SessionWP()
  351. session.update(values)
  352. session.save()
  353. return session
  354. def update_session(self, ses_id, values):
  355. # NOTE(dtantsur): this can lead to very strange errors
  356. session = get_session()
  357. try:
  358. with session.begin():
  359. query = model_query(models.SessionWP, session=session)
  360. query = add_identity_filter(query, ses_id)
  361. ref = query.one()
  362. ref.update(values)
  363. except NoResultFound:
  364. raise exception.SessionWPNotFound(ses=ses_id)
  365. return ref
  366. def get_session_by_board_uuid(self, board_uuid, valid):
  367. query = model_query(
  368. models.SessionWP).filter_by(
  369. board_uuid=board_uuid).filter_by(
  370. valid=valid)
  371. try:
  372. return query.one()
  373. except NoResultFound:
  374. raise exception.BoardNotConnected(board=board_uuid)
  375. def get_session_by_id(self, session_id):
  376. query = model_query(models.SessionWP).filter_by(session_id=session_id)
  377. try:
  378. return query.one()
  379. except NoResultFound:
  380. return None
  381. def get_valid_wpsessions_list(self):
  382. query = model_query(models.SessionWP).filter_by(valid=1)
  383. return query.all()
  384. # WAMPAGENT api
  385. def register_wampagent(self, values, update_existing=False):
  386. session = get_session()
  387. with session.begin():
  388. query = (model_query(models.WampAgent, session=session)
  389. .filter_by(hostname=values['hostname']))
  390. try:
  391. ref = query.one()
  392. if ref.online is True and not update_existing:
  393. raise exception.WampAgentAlreadyRegistered(
  394. wampagent=values['hostname'])
  395. except NoResultFound:
  396. ref = models.WampAgent()
  397. ref.update(values)
  398. # always set online and updated_at fields when registering
  399. # a wampagent, especially when updating an existing one
  400. ref.update({'updated_at': timeutils.utcnow(),
  401. 'online': True})
  402. ref.save(session)
  403. return ref
  404. def get_wampagent(self, hostname):
  405. try:
  406. return (model_query(models.WampAgent)
  407. .filter_by(hostname=hostname, online=True)
  408. .one())
  409. except NoResultFound:
  410. raise exception.WampAgentNotFound(wampagent=hostname)
  411. def get_registration_wampagent(self):
  412. try:
  413. return (model_query(models.WampAgent)
  414. .filter_by(ragent=True, online=True)
  415. .one())
  416. except NoResultFound:
  417. raise exception.WampRegistrationAgentNotFound()
  418. def unregister_wampagent(self, hostname):
  419. session = get_session()
  420. with session.begin():
  421. query = (model_query(models.WampAgent, session=session)
  422. .filter_by(hostname=hostname, online=True))
  423. count = query.update({'online': False})
  424. if count == 0:
  425. raise exception.WampAgentNotFound(wampagent=hostname)
  426. def touch_wampagent(self, hostname):
  427. session = get_session()
  428. with session.begin():
  429. query = (model_query(models.WampAgent, session=session)
  430. .filter_by(hostname=hostname))
  431. # since we're not changing any other field, manually set updated_at
  432. # and since we're heartbeating, make sure that online=True
  433. count = query.update({'updated_at': timeutils.utcnow(),
  434. 'online': True})
  435. if count == 0:
  436. raise exception.WampAgentNotFound(wampagent=hostname)
  437. def get_wampagent_list(self, filters=None, limit=None, marker=None,
  438. sort_key=None, sort_dir=None):
  439. query = model_query(models.WampAgent)
  440. query = self._add_wampagents_filters(query, filters)
  441. return _paginate_query(models.WampAgent, limit, marker,
  442. sort_key, sort_dir, query)
  443. # PLUGIN api
  444. def get_plugin_by_id(self, plugin_id):
  445. query = model_query(models.Plugin).filter_by(id=plugin_id)
  446. try:
  447. return query.one()
  448. except NoResultFound:
  449. raise exception.PluginNotFound(plugin=plugin_id)
  450. def get_plugin_by_uuid(self, plugin_uuid):
  451. query = model_query(models.Plugin).filter_by(uuid=plugin_uuid)
  452. try:
  453. return query.one()
  454. except NoResultFound:
  455. raise exception.PluginNotFound(plugin=plugin_uuid)
  456. def get_plugin_by_name(self, plugin_name):
  457. query = model_query(models.Plugin).filter_by(name=plugin_name)
  458. try:
  459. return query.one()
  460. except NoResultFound:
  461. raise exception.PluginNotFound(plugin=plugin_name)
  462. def destroy_plugin(self, plugin_id):
  463. session = get_session()
  464. with session.begin():
  465. query = model_query(models.Plugin, session=session)
  466. query = add_identity_filter(query, plugin_id)
  467. try:
  468. plugin_ref = query.one()
  469. except NoResultFound:
  470. raise exception.PluginNotFound(plugin=plugin_id)
  471. # Get plugin ID, if an UUID was supplied. The ID is
  472. # required for deleting all ports, attached to the plugin.
  473. if uuidutils.is_uuid_like(plugin_id):
  474. plugin_id = plugin_ref['id']
  475. query.delete()
  476. def update_plugin(self, plugin_id, values):
  477. # NOTE(dtantsur): this can lead to very strange errors
  478. if 'uuid' in values:
  479. msg = _("Cannot overwrite UUID for an existing Plugin.")
  480. raise exception.InvalidParameterValue(err=msg)
  481. try:
  482. return self._do_update_plugin(plugin_id, values)
  483. except db_exc.DBDuplicateEntry as e:
  484. if 'name' in e.columns:
  485. raise exception.DuplicateName(name=values['name'])
  486. elif 'uuid' in e.columns:
  487. raise exception.PluginAlreadyExists(uuid=values['uuid'])
  488. else:
  489. raise e
  490. def create_plugin(self, values):
  491. # ensure defaults are present for new plugins
  492. if 'uuid' not in values:
  493. values['uuid'] = uuidutils.generate_uuid()
  494. plugin = models.Plugin()
  495. plugin.update(values)
  496. try:
  497. plugin.save()
  498. except db_exc.DBDuplicateEntry:
  499. raise exception.PluginAlreadyExists(uuid=values['uuid'])
  500. return plugin
  501. def get_plugin_list(self, filters=None, limit=None, marker=None,
  502. sort_key=None, sort_dir=None):
  503. query = model_query(models.Plugin)
  504. query = self._add_plugins_filters(query, filters)
  505. return _paginate_query(models.Plugin, limit, marker,
  506. sort_key, sort_dir, query)
  507. # INJECTION PLUGIN api
  508. def get_injection_plugin_by_board_uuid(self, board_uuid):
  509. query = model_query(
  510. models.InjectionPlugin).filter_by(
  511. board_uuid=board_uuid)
  512. try:
  513. return query.one()
  514. except NoResultFound:
  515. raise exception.InjectionPluginNotFound()
  516. def create_injection_plugin(self, values):
  517. # ensure defaults are present for new plugins
  518. if 'uuid' not in values:
  519. values['uuid'] = uuidutils.generate_uuid()
  520. inj_plug = models.InjectionPlugin()
  521. inj_plug.update(values)
  522. try:
  523. inj_plug.save()
  524. except db_exc.DBDuplicateEntry:
  525. raise exception.PluginAlreadyExists(uuid=values['uuid'])
  526. return inj_plug
  527. def update_injection_plugin(self, plugin_injection_id, values):
  528. if 'uuid' in values:
  529. msg = _("Cannot overwrite UUID for an existing Plugin.")
  530. raise exception.InvalidParameterValue(err=msg)
  531. try:
  532. return self._do_update_injection_plugin(
  533. plugin_injection_id, values)
  534. except db_exc.DBDuplicateEntry as e:
  535. if 'name' in e.columns:
  536. raise exception.DuplicateName(name=values['name'])
  537. elif 'uuid' in e.columns:
  538. raise exception.PluginAlreadyExists(uuid=values['uuid'])
  539. else:
  540. raise e
  541. def get_injection_plugin_by_uuids(self, board_uuid, plugin_uuid):
  542. query = model_query(
  543. models.InjectionPlugin).filter_by(
  544. board_uuid=board_uuid).filter_by(
  545. plugin_uuid=plugin_uuid)
  546. try:
  547. return query.one()
  548. except NoResultFound:
  549. raise exception.InjectionPluginNotFound()
  550. def destroy_injection_plugin(self, injection_plugin_id):
  551. session = get_session()
  552. with session.begin():
  553. query = model_query(models.InjectionPlugin, session=session)
  554. query = add_identity_filter(query, injection_plugin_id)
  555. try:
  556. query.delete()
  557. except NoResultFound:
  558. raise exception.InjectionPluginNotFound()
  559. def get_injection_plugin_list(self, board_uuid):
  560. query = model_query(
  561. models.InjectionPlugin).filter_by(
  562. board_uuid=board_uuid)
  563. return query.all()
  564. # SERVICE api
  565. def get_service_by_id(self, service_id):
  566. query = model_query(models.Service).filter_by(id=service_id)
  567. try:
  568. return query.one()
  569. except NoResultFound:
  570. raise exception.ServiceNotFound(service=service_id)
  571. def get_service_by_uuid(self, service_uuid):
  572. query = model_query(models.Service).filter_by(uuid=service_uuid)
  573. try:
  574. return query.one()
  575. except NoResultFound:
  576. raise exception.ServiceNotFound(service=service_uuid)
  577. def get_service_by_name(self, service_name):
  578. query = model_query(models.Service).filter_by(name=service_name)
  579. try:
  580. return query.one()
  581. except NoResultFound:
  582. raise exception.ServiceNotFound(service=service_name)
  583. def destroy_service(self, service_id):
  584. session = get_session()
  585. with session.begin():
  586. query = model_query(models.Service, session=session)
  587. query = add_identity_filter(query, service_id)
  588. try:
  589. service_ref = query.one()
  590. except NoResultFound:
  591. raise exception.ServiceNotFound(service=service_id)
  592. # Get service ID, if an UUID was supplied. The ID is
  593. # required for deleting all ports, attached to the service.
  594. if uuidutils.is_uuid_like(service_id):
  595. service_id = service_ref['id']
  596. query.delete()
  597. def update_service(self, service_id, values):
  598. # NOTE(dtantsur): this can lead to very strange errors
  599. if 'uuid' in values:
  600. msg = _("Cannot overwrite UUID for an existing Service.")
  601. raise exception.InvalidParameterValue(err=msg)
  602. try:
  603. return self._do_update_service(service_id, values)
  604. except db_exc.DBDuplicateEntry as e:
  605. if 'name' in e.columns:
  606. raise exception.DuplicateName(name=values['name'])
  607. elif 'uuid' in e.columns:
  608. raise exception.ServiceAlreadyExists(uuid=values['uuid'])
  609. else:
  610. raise e
  611. def create_service(self, values):
  612. # ensure defaults are present for new services
  613. if 'uuid' not in values:
  614. values['uuid'] = uuidutils.generate_uuid()
  615. service = models.Service()
  616. service.update(values)
  617. try:
  618. service.save()
  619. except db_exc.DBDuplicateEntry:
  620. raise exception.ServiceAlreadyExists(uuid=values['uuid'])
  621. return service
  622. def get_service_list(self, filters=None, limit=None, marker=None,
  623. sort_key=None, sort_dir=None):
  624. query = model_query(models.Service)
  625. query = self._add_services_filters(query, filters)
  626. return _paginate_query(models.Service, limit, marker,
  627. sort_key, sort_dir, query)
  628. def _do_update_service(self, service_id, values):
  629. session = get_session()
  630. with session.begin():
  631. query = model_query(models.Service, session=session)
  632. query = add_identity_filter(query, service_id)
  633. try:
  634. ref = query.with_lockmode('update').one()
  635. except NoResultFound:
  636. raise exception.ServiceNotFound(service=service_id)
  637. ref.update(values)
  638. return ref
  639. # EXPOSED SERVICE api
  640. def get_exposed_services_by_board_uuid(self, board_uuid):
  641. query = model_query(
  642. models.ExposedService).filter_by(
  643. board_uuid=board_uuid)
  644. try:
  645. return query.all()
  646. except NoResultFound:
  647. raise exception.NoExposedServices(uuid=board_uuid)
  648. def create_exposed_service(self, values):
  649. # ensure defaults are present for new services
  650. if 'uuid' not in values:
  651. values['uuid'] = uuidutils.generate_uuid()
  652. exp_serv = models.ExposedService()
  653. exp_serv.update(values)
  654. try:
  655. exp_serv.save()
  656. except db_exc.DBDuplicateEntry:
  657. raise exception.ServiceAlreadyExposed(uuid=values['uuid'])
  658. return exp_serv
  659. def update_exposed_service(self, service_exposed_id, values):
  660. if 'uuid' in values:
  661. msg = _("Cannot overwrite UUID for an existing Service.")
  662. raise exception.InvalidParameterValue(err=msg)
  663. try:
  664. return self._do_update_exposed_service(
  665. service_exposed_id, values)
  666. except db_exc.DBDuplicateEntry as e:
  667. if 'name' in e.columns:
  668. raise exception.DuplicateName(name=values['name'])
  669. elif 'uuid' in e.columns:
  670. raise exception.ServiceAlreadyExists(uuid=values['uuid'])
  671. else:
  672. raise e
  673. def get_exposed_service_by_uuids(self, board_uuid, service_uuid):
  674. query = model_query(
  675. models.ExposedService).filter_by(
  676. board_uuid=board_uuid).filter_by(
  677. service_uuid=service_uuid)
  678. try:
  679. return query.one()
  680. except NoResultFound:
  681. raise exception.ExposedServiceNotFound(uuid=service_uuid)
  682. def destroy_exposed_service(self, exposed_service_id):
  683. session = get_session()
  684. with session.begin():
  685. query = model_query(models.ExposedService, session=session)
  686. query = add_identity_filter(query, exposed_service_id)
  687. try:
  688. query.delete()
  689. except NoResultFound:
  690. raise exception.ExposedServiceNotFound()
  691. def get_exposed_service_list(self, board_uuid):
  692. query = model_query(
  693. models.ExposedService).filter_by(
  694. board_uuid=board_uuid)
  695. return query.all()
  696. def _do_update_exposed_service(self, service_id, values):
  697. session = get_session()
  698. with session.begin():
  699. query = model_query(models.ExposedService, session=session)
  700. query = add_identity_filter(query, service_id)
  701. try:
  702. ref = query.with_lockmode('update').one()
  703. except NoResultFound:
  704. raise exception.ServiceNotFoundNotFound(uuid=service_id)
  705. ref.update(values)
  706. return ref