OpenStack Image Management (Glance)
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.

test_manage.py 33KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  1. # Copyright 2014 Rackspace Hosting
  2. # All Rights Reserved.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  5. # not use this file except in compliance with the License. You may obtain
  6. # a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. # License for the specific language governing permissions and limitations
  14. # under the License.
  15. from __future__ import absolute_import
  16. import fixtures
  17. import mock
  18. from six.moves import StringIO
  19. from glance.cmd import manage
  20. from glance.common import exception
  21. from glance.db.sqlalchemy import api as db_api
  22. from glance.db.sqlalchemy import metadata as db_metadata
  23. from glance.tests import utils as test_utils
  24. class TestManageBase(test_utils.BaseTestCase):
  25. def setUp(self):
  26. super(TestManageBase, self).setUp()
  27. def clear_conf():
  28. manage.CONF.reset()
  29. manage.CONF.unregister_opt(manage.command_opt)
  30. clear_conf()
  31. self.addCleanup(clear_conf)
  32. self.useFixture(fixtures.MonkeyPatch(
  33. 'oslo_log.log.setup', lambda product_name, version='test': None))
  34. patcher = mock.patch('glance.db.sqlalchemy.api.get_engine')
  35. patcher.start()
  36. self.addCleanup(patcher.stop)
  37. def _main_test_helper(self, argv, func_name=None, *exp_args, **exp_kwargs):
  38. self.useFixture(fixtures.MonkeyPatch('sys.argv', argv))
  39. manage.main()
  40. func_name.assert_called_once_with(*exp_args, **exp_kwargs)
  41. class TestLegacyManage(TestManageBase):
  42. @mock.patch.object(manage.DbCommands, 'version')
  43. def test_legacy_db_version(self, db_upgrade):
  44. self._main_test_helper(['glance.cmd.manage', 'db_version'],
  45. manage.DbCommands.version)
  46. @mock.patch.object(manage.DbCommands, 'sync')
  47. def test_legacy_db_sync(self, db_sync):
  48. self._main_test_helper(['glance.cmd.manage', 'db_sync'],
  49. manage.DbCommands.sync, None)
  50. @mock.patch.object(manage.DbCommands, 'upgrade')
  51. def test_legacy_db_upgrade(self, db_upgrade):
  52. self._main_test_helper(['glance.cmd.manage', 'db_upgrade'],
  53. manage.DbCommands.upgrade, None)
  54. @mock.patch.object(manage.DbCommands, 'version_control')
  55. def test_legacy_db_version_control(self, db_version_control):
  56. self._main_test_helper(['glance.cmd.manage', 'db_version_control'],
  57. manage.DbCommands.version_control, None)
  58. @mock.patch.object(manage.DbCommands, 'sync')
  59. def test_legacy_db_sync_version(self, db_sync):
  60. self._main_test_helper(['glance.cmd.manage', 'db_sync', 'liberty'],
  61. manage.DbCommands.sync, 'liberty')
  62. @mock.patch.object(manage.DbCommands, 'upgrade')
  63. def test_legacy_db_upgrade_version(self, db_upgrade):
  64. self._main_test_helper(['glance.cmd.manage', 'db_upgrade', 'liberty'],
  65. manage.DbCommands.upgrade, 'liberty')
  66. @mock.patch.object(manage.DbCommands, 'expand')
  67. def test_legacy_db_expand(self, db_expand):
  68. self._main_test_helper(['glance.cmd.manage', 'db_expand'],
  69. manage.DbCommands.expand)
  70. @mock.patch.object(manage.DbCommands, 'migrate')
  71. def test_legacy_db_migrate(self, db_migrate):
  72. self._main_test_helper(['glance.cmd.manage', 'db_migrate'],
  73. manage.DbCommands.migrate)
  74. @mock.patch.object(manage.DbCommands, 'contract')
  75. def test_legacy_db_contract(self, db_contract):
  76. self._main_test_helper(['glance.cmd.manage', 'db_contract'],
  77. manage.DbCommands.contract)
  78. def test_db_metadefs_unload(self):
  79. db_metadata.db_unload_metadefs = mock.Mock()
  80. self._main_test_helper(['glance.cmd.manage', 'db_unload_metadefs'],
  81. db_metadata.db_unload_metadefs,
  82. db_api.get_engine())
  83. def test_db_metadefs_load(self):
  84. db_metadata.db_load_metadefs = mock.Mock()
  85. self._main_test_helper(['glance.cmd.manage', 'db_load_metadefs'],
  86. db_metadata.db_load_metadefs,
  87. db_api.get_engine(),
  88. None, None, None, None)
  89. def test_db_metadefs_load_with_specified_path(self):
  90. db_metadata.db_load_metadefs = mock.Mock()
  91. self._main_test_helper(['glance.cmd.manage', 'db_load_metadefs',
  92. '/mock/'],
  93. db_metadata.db_load_metadefs,
  94. db_api.get_engine(),
  95. '/mock/', None, None, None)
  96. def test_db_metadefs_load_from_path_merge(self):
  97. db_metadata.db_load_metadefs = mock.Mock()
  98. self._main_test_helper(['glance.cmd.manage', 'db_load_metadefs',
  99. '/mock/', 'True'],
  100. db_metadata.db_load_metadefs,
  101. db_api.get_engine(),
  102. '/mock/', 'True', None, None)
  103. def test_db_metadefs_load_from_merge_and_prefer_new(self):
  104. db_metadata.db_load_metadefs = mock.Mock()
  105. self._main_test_helper(['glance.cmd.manage', 'db_load_metadefs',
  106. '/mock/', 'True', 'True'],
  107. db_metadata.db_load_metadefs,
  108. db_api.get_engine(),
  109. '/mock/', 'True', 'True', None)
  110. def test_db_metadefs_load_from_merge_and_prefer_new_and_overwrite(self):
  111. db_metadata.db_load_metadefs = mock.Mock()
  112. self._main_test_helper(['glance.cmd.manage', 'db_load_metadefs',
  113. '/mock/', 'True', 'True', 'True'],
  114. db_metadata.db_load_metadefs,
  115. db_api.get_engine(),
  116. '/mock/', 'True', 'True', 'True')
  117. def test_db_metadefs_export(self):
  118. db_metadata.db_export_metadefs = mock.Mock()
  119. self._main_test_helper(['glance.cmd.manage', 'db_export_metadefs'],
  120. db_metadata.db_export_metadefs,
  121. db_api.get_engine(),
  122. None)
  123. def test_db_metadefs_export_with_specified_path(self):
  124. db_metadata.db_export_metadefs = mock.Mock()
  125. self._main_test_helper(['glance.cmd.manage', 'db_export_metadefs',
  126. '/mock/'],
  127. db_metadata.db_export_metadefs,
  128. db_api.get_engine(),
  129. '/mock/')
  130. class TestManage(TestManageBase):
  131. def setUp(self):
  132. super(TestManage, self).setUp()
  133. self.db = manage.DbCommands()
  134. self.output = StringIO()
  135. self.useFixture(fixtures.MonkeyPatch('sys.stdout', self.output))
  136. @mock.patch('glance.db.sqlalchemy.api.get_engine')
  137. @mock.patch(
  138. 'glance.db.sqlalchemy.alembic_migrations.data_migrations.'
  139. 'has_pending_migrations')
  140. @mock.patch(
  141. 'glance.db.sqlalchemy.alembic_migrations.get_current_alembic_heads')
  142. @mock.patch(
  143. 'glance.db.sqlalchemy.alembic_migrations.get_alembic_branch_head')
  144. def test_db_check_result(self, mock_get_alembic_branch_head,
  145. mock_get_current_alembic_heads,
  146. mock_has_pending_migrations,
  147. get_mock_engine):
  148. get_mock_engine.return_value = mock.Mock()
  149. engine = get_mock_engine.return_value
  150. engine.engine.name = 'postgresql'
  151. exit = self.assertRaises(SystemExit, self.db.check)
  152. self.assertIn('Rolling upgrades are currently supported only for '
  153. 'MySQL and Sqlite', exit.code)
  154. engine = get_mock_engine.return_value
  155. engine.engine.name = 'mysql'
  156. mock_get_current_alembic_heads.return_value = ['ocata_contract01']
  157. mock_get_alembic_branch_head.return_value = 'pike_expand01'
  158. exit = self.assertRaises(SystemExit, self.db.check)
  159. self.assertEqual(3, exit.code)
  160. self.assertIn('Your database is not up to date. '
  161. 'Your first step is to run `glance-manage db expand`.',
  162. self.output.getvalue())
  163. mock_get_current_alembic_heads.return_value = ['pike_expand01']
  164. mock_get_alembic_branch_head.side_effect = ['pike_expand01', None]
  165. mock_has_pending_migrations.return_value = [mock.Mock()]
  166. exit = self.assertRaises(SystemExit, self.db.check)
  167. self.assertEqual(4, exit.code)
  168. self.assertIn('Your database is not up to date. '
  169. 'Your next step is to run `glance-manage db migrate`.',
  170. self.output.getvalue())
  171. mock_get_current_alembic_heads.return_value = ['pike_expand01']
  172. mock_get_alembic_branch_head.side_effect = ['pike_expand01',
  173. 'pike_contract01']
  174. mock_has_pending_migrations.return_value = None
  175. exit = self.assertRaises(SystemExit, self.db.check)
  176. self.assertEqual(5, exit.code)
  177. self.assertIn('Your database is not up to date. '
  178. 'Your next step is to run `glance-manage db contract`.',
  179. self.output.getvalue())
  180. mock_get_current_alembic_heads.return_value = ['pike_contract01']
  181. mock_get_alembic_branch_head.side_effect = ['pike_expand01',
  182. 'pike_contract01']
  183. mock_has_pending_migrations.return_value = None
  184. self.assertRaises(SystemExit, self.db.check)
  185. self.assertIn('Database is up to date. No upgrades needed.',
  186. self.output.getvalue())
  187. @mock.patch(
  188. 'glance.db.sqlalchemy.alembic_migrations.get_current_alembic_heads')
  189. @mock.patch(
  190. 'glance.db.sqlalchemy.alembic_migrations.get_alembic_branch_head')
  191. @mock.patch.object(manage.DbCommands, 'expand')
  192. @mock.patch.object(manage.DbCommands, 'migrate')
  193. @mock.patch.object(manage.DbCommands, 'contract')
  194. def test_sync(self, mock_contract, mock_migrate, mock_expand,
  195. mock_get_alembic_branch_head,
  196. mock_get_current_alembic_heads):
  197. mock_get_current_alembic_heads.return_value = ['ocata_contract01']
  198. mock_get_alembic_branch_head.return_value = ['pike_contract01']
  199. self.db.sync()
  200. mock_expand.assert_called_once_with(online_migration=False)
  201. mock_migrate.assert_called_once_with(online_migration=False)
  202. mock_contract.assert_called_once_with(online_migration=False)
  203. self.assertIn('Database is synced successfully.',
  204. self.output.getvalue())
  205. @mock.patch(
  206. 'glance.db.sqlalchemy.alembic_migrations.get_current_alembic_heads')
  207. @mock.patch(
  208. 'glance.db.sqlalchemy.alembic_migrations.get_alembic_branch_head')
  209. @mock.patch('glance.db.sqlalchemy.alembic_migrations.'
  210. 'place_database_under_alembic_control')
  211. @mock.patch('alembic.command.upgrade')
  212. def test_sync_db_is_already_sync(self, mock_upgrade,
  213. mock_db_under_alembic_control,
  214. mock_get_alembic_branch_head,
  215. mock_get_current_alembic_heads):
  216. mock_get_current_alembic_heads.return_value = ['pike_contract01']
  217. mock_get_alembic_branch_head.return_value = ['pike_contract01']
  218. self.assertRaises(SystemExit, self.db.sync)
  219. @mock.patch(
  220. 'glance.db.sqlalchemy.alembic_migrations.get_current_alembic_heads')
  221. @mock.patch(
  222. 'glance.db.sqlalchemy.alembic_migrations.get_alembic_branch_head')
  223. @mock.patch.object(manage.DbCommands, '_validate_engine')
  224. @mock.patch.object(manage.DbCommands, 'expand')
  225. def test_sync_failed_to_sync(self, mock_expand, mock_validate_engine,
  226. mock_get_alembic_branch_head,
  227. mock_get_current_alembic_heads):
  228. engine = mock_validate_engine.return_value
  229. engine.engine.name = 'mysql'
  230. mock_get_current_alembic_heads.return_value = ['ocata_contract01']
  231. mock_get_alembic_branch_head.side_effect = ['pike_contract01', '']
  232. mock_expand.side_effect = exception.GlanceException
  233. exit = self.assertRaises(SystemExit, self.db.sync)
  234. self.assertIn('Failed to sync database: ERROR:', exit.code)
  235. @mock.patch(
  236. 'glance.db.sqlalchemy.alembic_migrations.get_current_alembic_heads')
  237. @mock.patch(
  238. 'glance.db.sqlalchemy.alembic_migrations.get_alembic_branch_head')
  239. @mock.patch.object(manage.DbCommands, '_validate_engine')
  240. @mock.patch.object(manage.DbCommands, '_sync')
  241. def test_expand(self, mock_sync, mock_validate_engine,
  242. mock_get_alembic_branch_head,
  243. mock_get_current_alembic_heads):
  244. engine = mock_validate_engine.return_value
  245. engine.engine.name = 'mysql'
  246. mock_get_current_alembic_heads.side_effect = ['ocata_contract01',
  247. 'pike_expand01']
  248. mock_get_alembic_branch_head.side_effect = ['pike_expand01',
  249. 'pike_contract01']
  250. self.db.expand()
  251. mock_sync.assert_called_once_with(version='pike_expand01')
  252. @mock.patch(
  253. 'glance.db.sqlalchemy.alembic_migrations.get_current_alembic_heads')
  254. @mock.patch(
  255. 'glance.db.sqlalchemy.alembic_migrations.get_alembic_branch_head')
  256. @mock.patch.object(manage.DbCommands, '_validate_engine')
  257. def test_expand_if_not_expand_head(self, mock_validate_engine,
  258. mock_get_alembic_branch_head,
  259. mock_get_current_alembic_heads):
  260. engine = mock_validate_engine.return_value
  261. engine.engine.name = 'mysql'
  262. mock_get_current_alembic_heads.return_value = ['ocata_contract01']
  263. mock_get_alembic_branch_head.return_value = []
  264. exit = self.assertRaises(SystemExit, self.db.expand)
  265. self.assertIn('Database expansion failed. Couldn\'t find head '
  266. 'revision of expand branch.', exit.code)
  267. @mock.patch(
  268. 'glance.db.sqlalchemy.alembic_migrations.get_current_alembic_heads')
  269. @mock.patch(
  270. 'glance.db.sqlalchemy.alembic_migrations.get_alembic_branch_head')
  271. @mock.patch.object(manage.DbCommands, '_validate_engine')
  272. def test_expand_db_is_already_sync(self, mock_validate_engine,
  273. mock_get_alembic_branch_head,
  274. mock_get_current_alembic_heads):
  275. engine = mock_validate_engine.return_value
  276. engine.engine.name = 'mysql'
  277. mock_get_current_alembic_heads.return_value = ['pike_contract01']
  278. mock_get_alembic_branch_head.side_effect = ['pike_expand01',
  279. 'pike_contract01']
  280. self.assertRaises(SystemExit, self.db.expand)
  281. self.assertIn('Database is up to date. No migrations needed.',
  282. self.output.getvalue())
  283. @mock.patch(
  284. 'glance.db.sqlalchemy.alembic_migrations.get_current_alembic_heads')
  285. @mock.patch(
  286. 'glance.db.sqlalchemy.alembic_migrations.get_alembic_branch_head')
  287. @mock.patch.object(manage.DbCommands, '_validate_engine')
  288. def test_expand_already_sync(self, mock_validate_engine,
  289. mock_get_alembic_branch_head,
  290. mock_get_current_alembic_heads):
  291. engine = mock_validate_engine.return_value
  292. engine.engine.name = 'mysql'
  293. mock_get_current_alembic_heads.return_value = ['pike_expand01']
  294. mock_get_alembic_branch_head.side_effect = ['pike_expand01',
  295. 'pike_contract01']
  296. self.db.expand()
  297. self.assertIn('Database expansion is up to date. '
  298. 'No expansion needed.', self.output.getvalue())
  299. @mock.patch(
  300. 'glance.db.sqlalchemy.alembic_migrations.get_current_alembic_heads')
  301. @mock.patch(
  302. 'glance.db.sqlalchemy.alembic_migrations.get_alembic_branch_head')
  303. @mock.patch.object(manage.DbCommands, '_validate_engine')
  304. @mock.patch.object(manage.DbCommands, '_sync')
  305. def test_expand_failed(self, mock_sync, mock_validate_engine,
  306. mock_get_alembic_branch_head,
  307. mock_get_current_alembic_heads):
  308. engine = mock_validate_engine.return_value
  309. engine.engine.name = 'mysql'
  310. mock_get_current_alembic_heads.side_effect = ['ocata_contract01',
  311. 'test']
  312. mock_get_alembic_branch_head.side_effect = ['pike_expand01',
  313. 'pike_contract01']
  314. exit = self.assertRaises(SystemExit, self.db.expand)
  315. mock_sync.assert_called_once_with(version='pike_expand01')
  316. self.assertIn('Database expansion failed. Database expansion should '
  317. 'have brought the database version up to "pike_expand01"'
  318. ' revision. But, current revisions are: test ',
  319. exit.code)
  320. @mock.patch(
  321. 'glance.db.sqlalchemy.alembic_migrations.get_current_alembic_heads')
  322. @mock.patch(
  323. 'glance.db.sqlalchemy.alembic_migrations.get_alembic_branch_head')
  324. @mock.patch.object(manage.DbCommands, '_validate_engine')
  325. @mock.patch.object(manage.DbCommands, '_sync')
  326. def test_contract(self, mock_sync, mock_validate_engine,
  327. mock_get_alembic_branch_head,
  328. mock_get_current_alembic_heads):
  329. engine = mock_validate_engine.return_value
  330. engine.engine.name = 'mysql'
  331. mock_get_current_alembic_heads.side_effect = ['pike_expand01',
  332. 'pike_contract01']
  333. mock_get_alembic_branch_head.side_effect = ['pike_contract01',
  334. 'pike_expand01']
  335. self.db.contract()
  336. mock_sync.assert_called_once_with(version='pike_contract01')
  337. @mock.patch(
  338. 'glance.db.sqlalchemy.alembic_migrations.get_current_alembic_heads')
  339. @mock.patch(
  340. 'glance.db.sqlalchemy.alembic_migrations.get_alembic_branch_head')
  341. @mock.patch.object(manage.DbCommands, '_validate_engine')
  342. def test_contract_if_not_contract_head(self, mock_validate_engine,
  343. mock_get_alembic_branch_head,
  344. mock_get_current_alembic_heads):
  345. engine = mock_validate_engine.return_value
  346. engine.engine.name = 'mysql'
  347. mock_get_current_alembic_heads.return_value = ['ocata_contract01']
  348. mock_get_alembic_branch_head.return_value = []
  349. exit = self.assertRaises(SystemExit, self.db.contract)
  350. self.assertIn('Database contraction failed. Couldn\'t find head '
  351. 'revision of contract branch.', exit.code)
  352. @mock.patch(
  353. 'glance.db.sqlalchemy.alembic_migrations.get_current_alembic_heads')
  354. @mock.patch(
  355. 'glance.db.sqlalchemy.alembic_migrations.get_alembic_branch_head')
  356. @mock.patch.object(manage.DbCommands, '_validate_engine')
  357. def test_contract_db_is_already_sync(self, mock_validate_engine,
  358. mock_get_alembic_branch_head,
  359. mock_get_current_alembic_heads):
  360. engine = mock_validate_engine.return_value
  361. engine.engine.name = 'mysql'
  362. mock_get_current_alembic_heads.return_value = ['pike_contract01']
  363. mock_get_alembic_branch_head.side_effect = ['pike_contract01',
  364. 'pike_expand01']
  365. self.assertRaises(SystemExit, self.db.contract)
  366. self.assertIn('Database is up to date. No migrations needed.',
  367. self.output.getvalue())
  368. @mock.patch(
  369. 'glance.db.sqlalchemy.alembic_migrations.get_current_alembic_heads')
  370. @mock.patch(
  371. 'glance.db.sqlalchemy.alembic_migrations.get_alembic_branch_head')
  372. @mock.patch.object(manage.DbCommands, '_validate_engine')
  373. def test_contract_before_expand(self, mock_validate_engine,
  374. mock_get_alembic_branch_head,
  375. mock_get_current_alembic_heads):
  376. engine = mock_validate_engine.return_value
  377. engine.engine.name = 'mysql'
  378. mock_get_current_alembic_heads.return_value = ['ocata_contract01']
  379. mock_get_alembic_branch_head.side_effect = ['pike_expand01',
  380. 'pike_contract01']
  381. exit = self.assertRaises(SystemExit, self.db.contract)
  382. self.assertIn('Database contraction did not run. Database '
  383. 'contraction cannot be run before database expansion. '
  384. 'Run database expansion first using "glance-manage db '
  385. 'expand"', exit.code)
  386. @mock.patch(
  387. 'glance.db.sqlalchemy.alembic_migrations.data_migrations.'
  388. 'has_pending_migrations')
  389. @mock.patch(
  390. 'glance.db.sqlalchemy.alembic_migrations.get_current_alembic_heads')
  391. @mock.patch(
  392. 'glance.db.sqlalchemy.alembic_migrations.get_alembic_branch_head')
  393. @mock.patch.object(manage.DbCommands, '_validate_engine')
  394. def test_contract_before_migrate(self, mock_validate_engine,
  395. mock_get_alembic_branch_head,
  396. mock_get_curr_alembic_heads,
  397. mock_has_pending_migrations):
  398. engine = mock_validate_engine.return_value
  399. engine.engine.name = 'mysql'
  400. mock_get_curr_alembic_heads.side_effect = ['pike_expand01']
  401. mock_get_alembic_branch_head.side_effect = ['pike_contract01',
  402. 'pike_expand01']
  403. mock_has_pending_migrations.return_value = [mock.Mock()]
  404. exit = self.assertRaises(SystemExit, self.db.contract)
  405. self.assertIn('Database contraction did not run. Database '
  406. 'contraction cannot be run before data migration is '
  407. 'complete. Run data migration using "glance-manage db '
  408. 'migrate".', exit.code)
  409. @mock.patch(
  410. 'glance.db.sqlalchemy.alembic_migrations.data_migrations.'
  411. 'has_pending_migrations')
  412. @mock.patch(
  413. 'glance.db.sqlalchemy.alembic_migrations.get_current_alembic_heads')
  414. @mock.patch(
  415. 'glance.db.sqlalchemy.alembic_migrations.get_alembic_branch_head')
  416. @mock.patch.object(manage.DbCommands, '_validate_engine')
  417. def test_migrate(self, mock_validate_engine, mock_get_alembic_branch_head,
  418. mock_get_current_alembic_heads,
  419. mock_has_pending_migrations):
  420. engine = mock_validate_engine.return_value
  421. engine.engine.name = 'mysql'
  422. mock_get_current_alembic_heads.side_effect = ['pike_expand01',
  423. 'pike_contract01']
  424. mock_get_alembic_branch_head.side_effect = ['pike_contract01',
  425. 'pike_expand01']
  426. mock_has_pending_migrations.return_value = None
  427. self.db.migrate()
  428. self.assertIn('Database migration is up to date. '
  429. 'No migration needed.', self.output.getvalue())
  430. @mock.patch(
  431. 'glance.db.sqlalchemy.alembic_migrations.get_current_alembic_heads')
  432. @mock.patch(
  433. 'glance.db.sqlalchemy.alembic_migrations.get_alembic_branch_head')
  434. @mock.patch.object(manage.DbCommands, '_validate_engine')
  435. def test_migrate_db_is_already_sync(self, mock_validate_engine,
  436. mock_get_alembic_branch_head,
  437. mock_get_current_alembic_heads):
  438. engine = mock_validate_engine.return_value
  439. engine.engine.name = 'mysql'
  440. mock_get_current_alembic_heads.return_value = ['pike_contract01']
  441. mock_get_alembic_branch_head.side_effect = ['pike_contract01',
  442. 'pike_expand01']
  443. self.assertRaises(SystemExit, self.db.migrate)
  444. self.assertIn('Database is up to date. No migrations needed.',
  445. self.output.getvalue())
  446. @mock.patch(
  447. 'glance.db.sqlalchemy.alembic_migrations.get_current_alembic_heads')
  448. @mock.patch(
  449. 'glance.db.sqlalchemy.alembic_migrations.get_alembic_branch_head')
  450. @mock.patch.object(manage.DbCommands, '_validate_engine')
  451. def test_migrate_already_sync(self, mock_validate_engine,
  452. mock_get_alembic_branch_head,
  453. mock_get_current_alembic_heads):
  454. engine = mock_validate_engine.return_value
  455. engine.engine.name = 'mysql'
  456. mock_get_current_alembic_heads.return_value = ['ocata_contract01']
  457. mock_get_alembic_branch_head.side_effect = ['pike_contract01',
  458. 'pike_expand01']
  459. exit = self.assertRaises(SystemExit, self.db.migrate)
  460. self.assertIn('Data migration did not run. Data migration cannot be '
  461. 'run before database expansion. Run database expansion '
  462. 'first using "glance-manage db expand"', exit.code)
  463. @mock.patch(
  464. 'glance.db.sqlalchemy.alembic_migrations.data_migrations.'
  465. 'has_pending_migrations')
  466. @mock.patch(
  467. 'glance.db.sqlalchemy.alembic_migrations.get_current_alembic_heads')
  468. @mock.patch(
  469. 'glance.db.sqlalchemy.alembic_migrations.get_alembic_branch_head')
  470. @mock.patch.object(manage.DbCommands, '_validate_engine')
  471. def test_migrate_before_expand(self, mock_validate_engine,
  472. mock_get_alembic_branch_head,
  473. mock_get_current_alembic_heads,
  474. mock_has_pending_migrations):
  475. engine = mock_validate_engine.return_value
  476. engine.engine.name = 'mysql'
  477. mock_get_current_alembic_heads.return_value = ['pike_expand01']
  478. mock_get_alembic_branch_head.side_effect = ['pike_contract01',
  479. 'pike_expand01']
  480. mock_has_pending_migrations.return_value = None
  481. self.db.migrate()
  482. self.assertIn('Database migration is up to date. '
  483. 'No migration needed.', self.output.getvalue())
  484. @mock.patch.object(manage.DbCommands, 'version')
  485. def test_db_version(self, version):
  486. self._main_test_helper(['glance.cmd.manage', 'db', 'version'],
  487. manage.DbCommands.version)
  488. @mock.patch.object(manage.DbCommands, 'check')
  489. def test_db_check(self, check):
  490. self._main_test_helper(['glance.cmd.manage', 'db', 'check'],
  491. manage.DbCommands.check)
  492. @mock.patch.object(manage.DbCommands, 'sync')
  493. def test_db_sync(self, sync):
  494. self._main_test_helper(['glance.cmd.manage', 'db', 'sync'],
  495. manage.DbCommands.sync)
  496. @mock.patch.object(manage.DbCommands, 'upgrade')
  497. def test_db_upgrade(self, upgrade):
  498. self._main_test_helper(['glance.cmd.manage', 'db', 'upgrade'],
  499. manage.DbCommands.upgrade)
  500. @mock.patch.object(manage.DbCommands, 'version_control')
  501. def test_db_version_control(self, version_control):
  502. self._main_test_helper(['glance.cmd.manage', 'db', 'version_control'],
  503. manage.DbCommands.version_control)
  504. @mock.patch.object(manage.DbCommands, 'sync')
  505. def test_db_sync_version(self, sync):
  506. self._main_test_helper(['glance.cmd.manage', 'db', 'sync', 'liberty'],
  507. manage.DbCommands.sync, 'liberty')
  508. @mock.patch.object(manage.DbCommands, 'upgrade')
  509. def test_db_upgrade_version(self, upgrade):
  510. self._main_test_helper(['glance.cmd.manage', 'db',
  511. 'upgrade', 'liberty'],
  512. manage.DbCommands.upgrade, 'liberty')
  513. @mock.patch.object(manage.DbCommands, 'expand')
  514. def test_db_expand(self, expand):
  515. self._main_test_helper(['glance.cmd.manage', 'db', 'expand'],
  516. manage.DbCommands.expand)
  517. @mock.patch.object(manage.DbCommands, 'migrate')
  518. def test_db_migrate(self, migrate):
  519. self._main_test_helper(['glance.cmd.manage', 'db', 'migrate'],
  520. manage.DbCommands.migrate)
  521. @mock.patch.object(manage.DbCommands, 'contract')
  522. def test_db_contract(self, contract):
  523. self._main_test_helper(['glance.cmd.manage', 'db', 'contract'],
  524. manage.DbCommands.contract)
  525. def test_db_metadefs_unload(self):
  526. db_metadata.db_unload_metadefs = mock.Mock()
  527. self._main_test_helper(['glance.cmd.manage', 'db', 'unload_metadefs'],
  528. db_metadata.db_unload_metadefs,
  529. db_api.get_engine())
  530. def test_db_metadefs_load(self):
  531. db_metadata.db_load_metadefs = mock.Mock()
  532. self._main_test_helper(['glance.cmd.manage', 'db', 'load_metadefs'],
  533. db_metadata.db_load_metadefs,
  534. db_api.get_engine(),
  535. None, False, False, False)
  536. def test_db_metadefs_load_with_specified_path(self):
  537. db_metadata.db_load_metadefs = mock.Mock()
  538. self._main_test_helper(['glance.cmd.manage', 'db', 'load_metadefs',
  539. '--path', '/mock/'],
  540. db_metadata.db_load_metadefs,
  541. db_api.get_engine(),
  542. '/mock/', False, False, False)
  543. def test_db_metadefs_load_prefer_new_with_path(self):
  544. db_metadata.db_load_metadefs = mock.Mock()
  545. self._main_test_helper(['glance.cmd.manage', 'db', 'load_metadefs',
  546. '--path', '/mock/', '--merge', '--prefer_new'],
  547. db_metadata.db_load_metadefs,
  548. db_api.get_engine(),
  549. '/mock/', True, True, False)
  550. def test_db_metadefs_load_prefer_new(self):
  551. db_metadata.db_load_metadefs = mock.Mock()
  552. self._main_test_helper(['glance.cmd.manage', 'db', 'load_metadefs',
  553. '--merge', '--prefer_new'],
  554. db_metadata.db_load_metadefs,
  555. db_api.get_engine(),
  556. None, True, True, False)
  557. def test_db_metadefs_load_overwrite_existing(self):
  558. db_metadata.db_load_metadefs = mock.Mock()
  559. self._main_test_helper(['glance.cmd.manage', 'db', 'load_metadefs',
  560. '--merge', '--overwrite'],
  561. db_metadata.db_load_metadefs,
  562. db_api.get_engine(),
  563. None, True, False, True)
  564. def test_db_metadefs_load_prefer_new_and_overwrite_existing(self):
  565. db_metadata.db_load_metadefs = mock.Mock()
  566. self._main_test_helper(['glance.cmd.manage', 'db', 'load_metadefs',
  567. '--merge', '--prefer_new', '--overwrite'],
  568. db_metadata.db_load_metadefs,
  569. db_api.get_engine(),
  570. None, True, True, True)
  571. def test_db_metadefs_load_from_path_overwrite_existing(self):
  572. db_metadata.db_load_metadefs = mock.Mock()
  573. self._main_test_helper(['glance.cmd.manage', 'db', 'load_metadefs',
  574. '--path', '/mock/', '--merge', '--overwrite'],
  575. db_metadata.db_load_metadefs,
  576. db_api.get_engine(),
  577. '/mock/', True, False, True)
  578. def test_db_metadefs_export(self):
  579. db_metadata.db_export_metadefs = mock.Mock()
  580. self._main_test_helper(['glance.cmd.manage', 'db', 'export_metadefs'],
  581. db_metadata.db_export_metadefs,
  582. db_api.get_engine(),
  583. None)
  584. def test_db_metadefs_export_with_specified_path(self):
  585. db_metadata.db_export_metadefs = mock.Mock()
  586. self._main_test_helper(['glance.cmd.manage', 'db', 'export_metadefs',
  587. '--path', '/mock/'],
  588. db_metadata.db_export_metadefs,
  589. db_api.get_engine(),
  590. '/mock/')