Fuel UI
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_downgrade_fuel_9_2.py 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. # Copyright 2016 Mirantis, Inc.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the 'License'); you may
  4. # not use this file except in compliance with the License. You may obtain
  5. # a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT
  11. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  12. # License for the specific language governing permissions and limitations
  13. # under the License.
  14. from copy import deepcopy
  15. import datetime
  16. import alembic
  17. from oslo_serialization import jsonutils
  18. import sqlalchemy as sa
  19. from nailgun.db import db
  20. from nailgun.db import dropdb
  21. from nailgun.db.migration import ALEMBIC_CONFIG
  22. from nailgun.test import base
  23. _prepare_revision = '3763c404ca48'
  24. _test_revision = 'f2314e5d63c9'
  25. ATTRIBUTES_METADATA = {
  26. 'editable': {
  27. 'common': {}
  28. }
  29. }
  30. SECURITY_GROUPS = {
  31. 'value': 'iptables_hybrid',
  32. 'values': [
  33. {
  34. 'data': 'openvswitch',
  35. 'label': 'Open vSwitch Firewall Driver',
  36. 'description': 'Choose this driver for OVS based security groups '
  37. 'implementation. NOTE: Open vSwitch Firewall '
  38. 'Driver requires kernel version >= 4.3 '
  39. 'for non-dpdk case.'
  40. },
  41. {
  42. 'data': 'iptables_hybrid',
  43. 'label': 'Iptables-based Firewall Driver'
  44. ' (No firewall for DPDK case)',
  45. 'description': 'Choose this driver for iptables/linux bridge '
  46. 'based security groups implementation.'
  47. }
  48. ],
  49. 'group': 'security',
  50. 'weight': 20,
  51. 'type': 'radio',
  52. }
  53. ROLES_META = {
  54. 'controller': {
  55. 'tags': [
  56. 'controller',
  57. 'rabbitmq',
  58. 'database',
  59. 'keystone',
  60. 'neutron'
  61. ]
  62. }
  63. }
  64. PLUGIN_ROLE_META = {
  65. 'test_plugin_role': {
  66. 'tags': ['test_plugin_tag']
  67. }
  68. }
  69. PLUGIN_TAGS_META = {
  70. 'test_plugin_tag':
  71. {'has_primary': False}
  72. }
  73. TAGS_META = {
  74. 'controller': {
  75. 'has_primary': True,
  76. },
  77. 'rabbitmq': {
  78. 'has_primary': True
  79. },
  80. 'database': {
  81. 'has_primary': True
  82. },
  83. 'keystone': {
  84. 'has_primary': True
  85. },
  86. 'neutron': {
  87. 'has_primary': True
  88. }
  89. }
  90. def setup_module():
  91. dropdb()
  92. alembic.command.upgrade(ALEMBIC_CONFIG, _prepare_revision)
  93. prepare()
  94. alembic.command.downgrade(ALEMBIC_CONFIG, _test_revision)
  95. def prepare():
  96. meta = base.reflect_db_metadata()
  97. attrs_with_sec_group = deepcopy(ATTRIBUTES_METADATA)
  98. attrs_with_sec_group.setdefault('editable', {}).setdefault(
  99. 'common', {}).setdefault('security_groups', SECURITY_GROUPS)
  100. plugin = {
  101. 'name': 'Test_P',
  102. 'version': '3.0.0',
  103. 'title': 'Test Plugin',
  104. 'package_version': '5.0.0',
  105. 'roles_metadata': jsonutils.dumps(PLUGIN_ROLE_META),
  106. 'tags_metadata': jsonutils.dumps(PLUGIN_TAGS_META)
  107. }
  108. result = db.execute(meta.tables['plugins'].insert(), [plugin])
  109. for release_name, env_version, cluster_name, attrs in zip(
  110. ('release_1', 'release_2', 'release_3'),
  111. ('mitaka-9.0', 'liberty-8.0', 'mitaka-9.0'),
  112. ('cluster_1', 'cluster_2', 'cluster_3'),
  113. (ATTRIBUTES_METADATA, ATTRIBUTES_METADATA, attrs_with_sec_group)
  114. ):
  115. release = {
  116. 'name': release_name,
  117. 'version': env_version,
  118. 'operating_system': 'ubuntu',
  119. 'state': 'available',
  120. 'deployment_tasks': '[]',
  121. 'roles_metadata': jsonutils.dumps(ROLES_META),
  122. 'tags_matadata': jsonutils.dumps(TAGS_META),
  123. 'is_deployable': True,
  124. 'networks_metadata': '{}',
  125. 'attributes_metadata': jsonutils.dumps(attrs)
  126. }
  127. result = db.execute(meta.tables['releases'].insert(), [release])
  128. release_id = result.inserted_primary_key[0]
  129. result = db.execute(
  130. meta.tables['clusters'].insert(),
  131. [{
  132. 'name': cluster_name,
  133. 'release_id': release_id,
  134. 'mode': 'ha_compact',
  135. 'status': 'new',
  136. 'net_provider': 'neutron',
  137. 'grouping': 'roles',
  138. 'fuel_version': '9.0',
  139. 'deployment_tasks': '[]',
  140. 'roles_metadata': jsonutils.dumps(ROLES_META),
  141. 'tags_metadata': '{}',
  142. }])
  143. cluster_id = result.inserted_primary_key[0]
  144. editable = attrs.get('editable', {})
  145. db.execute(
  146. meta.tables['attributes'].insert(),
  147. [{
  148. 'cluster_id': cluster_id,
  149. 'editable': jsonutils.dumps(editable)
  150. }]
  151. )
  152. db.execute(
  153. meta.tables['nodes'].insert(),
  154. [{
  155. 'uuid': 'fcd49872-3917-4a18-98f9-3f5acfe3fdec',
  156. 'cluster_id': cluster_id,
  157. 'group_id': None,
  158. 'status': 'ready',
  159. 'roles': ['role_x', 'role_y'],
  160. 'primary_tags': ['role_y', 'test'],
  161. 'meta': '{}',
  162. 'mac': 'bb:aa:aa:aa:aa:aa',
  163. 'timestamp': datetime.datetime.utcnow(),
  164. }]
  165. )
  166. new_node = db.execute(
  167. meta.tables['nodes'].insert(),
  168. [{
  169. 'uuid': '26b508d0-0d76-4159-bce9-f67ec2765481',
  170. 'cluster_id': None,
  171. 'group_id': None,
  172. 'status': 'discover',
  173. 'mac': 'aa:aa:aa:aa:aa:aa',
  174. 'timestamp': datetime.datetime.utcnow()
  175. }]
  176. )
  177. node_id = new_node.inserted_primary_key[0]
  178. bond_interface = db.execute(
  179. meta.tables['node_bond_interfaces'].insert(),
  180. [{
  181. 'node_id': node_id,
  182. 'name': 'test_bond_interface',
  183. 'mode': 'balance-tlb',
  184. 'attributes': jsonutils.dumps({
  185. 'lacp_rate': {'value': {'value': ''}},
  186. 'xmit_hash_policy': {'value': {'value': 'layer2'}},
  187. 'offloading': {
  188. 'disable': {'value': True},
  189. 'modes': {'value': {'tx-checksumming': None,
  190. 'tx-checksum-sctp': None}}
  191. },
  192. 'mtu': {'value': {'value': 50}},
  193. 'lacp': {'value': {'value': ''}},
  194. 'mode': {'value': {'value': 'balance-tlb'}},
  195. 'type__': {'value': 'linux'},
  196. 'dpdk': {'enabled': {'value': False}}
  197. })
  198. }]
  199. )
  200. bond_id = bond_interface.inserted_primary_key[0]
  201. db.execute(
  202. meta.tables['node_nic_interfaces'].insert(),
  203. [{
  204. 'node_id': node_id,
  205. 'name': 'test_nic_empty_attributes',
  206. 'mac': '00:00:00:00:00:01',
  207. 'attributes': jsonutils.dumps({}),
  208. 'meta': jsonutils.dumps({})
  209. }]
  210. )
  211. db.execute(
  212. meta.tables['node_nic_interfaces'].insert(),
  213. [{
  214. 'node_id': node_id,
  215. 'name': 'test_nic_attributes',
  216. 'parent_id': bond_id,
  217. 'mac': '00:00:00:00:00:01',
  218. 'attributes': jsonutils.dumps({
  219. 'offloading': {
  220. 'disable': {'value': 'test_disable_offloading'},
  221. 'modes': {
  222. 'value': {
  223. 'tx-checksum-ipv4': 'IPV4_STATE',
  224. 'tx-checksumming': 'TX_STATE',
  225. 'rx-checksumming': 'RX_STATE',
  226. 'tx-checksum-ipv6': 'IPV6_STATE'
  227. }
  228. }
  229. },
  230. 'mtu': {
  231. 'value': {'value': 'test_mtu'}
  232. },
  233. 'sriov': {
  234. 'numvfs': {'value': 'test_sriov_numfs'},
  235. 'enabled': {'value': 'test_sriov_enabled'},
  236. 'physnet': {'value': 'test_sriov_physnet'}
  237. },
  238. 'dpdk': {
  239. 'enabled': {'value': 'test_dpdk_enabled'}
  240. }
  241. }),
  242. 'meta': jsonutils.dumps({
  243. 'offloading_modes': [{
  244. 'state': None,
  245. 'name': 'tx-checksumming',
  246. 'sub': [
  247. {'state': False, 'name': 'tx-checksum-sctp',
  248. 'sub': []},
  249. {'state': None, 'name': 'tx-checksum-ipv6',
  250. 'sub': []},
  251. {'state': None, 'name': 'tx-checksum-ipv4',
  252. 'sub': []}
  253. ]
  254. }, {
  255. 'state': None, 'name': 'rx-checksumming', 'sub': []
  256. }],
  257. 'numa_node': 12345,
  258. 'pci_id': 'test_pci_id',
  259. 'sriov': {
  260. 'available': 'test_sriov_available',
  261. 'totalvfs': 6789,
  262. 'pci_id': 'test_sriov_pci_id'
  263. },
  264. 'dpdk': {'available': True}
  265. })
  266. }]
  267. )
  268. db.commit()
  269. class TestAttributesDowngrade(base.BaseAlembicMigrationTest):
  270. def test_cluster_attributes_downgrade(self):
  271. clusters_attributes = self.meta.tables['attributes']
  272. results = db.execute(
  273. sa.select([clusters_attributes.c.editable]))
  274. for editable in results:
  275. editable = jsonutils.loads(editable[0])
  276. common = editable.setdefault('common', {})
  277. self.assertEqual(common.get('security_groups'), None)
  278. def test_release_attributes_downgrade(self):
  279. releases = self.meta.tables['releases']
  280. results = db.execute(
  281. sa.select([releases.c.attributes_metadata]))
  282. for attrs in results:
  283. attrs = jsonutils.loads(attrs[0])
  284. common = attrs.setdefault('editable', {}).setdefault('common', {})
  285. self.assertEqual(common.get('security_groups'), None)
  286. class TestTags(base.BaseAlembicMigrationTest):
  287. def test_primary_tags_downgrade(self):
  288. nodes = self.meta.tables['nodes']
  289. query = sa.select([nodes.c.primary_roles]).where(
  290. nodes.c.uuid == 'fcd49872-3917-4a18-98f9-3f5acfe3fdec')
  291. primary_roles = db.execute(query).fetchone()[0]
  292. self.assertItemsEqual(primary_roles, ['role_y'])
  293. def test_downgrade_tags_metadata(self):
  294. releases = self.meta.tables['releases']
  295. self.assertNotIn('tags_metadata', releases.c._all_columns)
  296. clusters = self.meta.tables['clusters']
  297. self.assertNotIn('tags_metadata', clusters.c._all_columns)
  298. self.assertNotIn('roles_metadata', clusters.c._all_columns)
  299. plugins = self.meta.tables['plugins']
  300. self.assertNotIn('tags_metadata', plugins.c._all_columns)
  301. def test_downgrade_field_tags_from_roles(self):
  302. releases = self.meta.tables['releases']
  303. query = sa.select([releases.c.roles_metadata])
  304. for role_meta in db.execute(query).fetchall():
  305. self.assertNotIn('tags', role_meta)
  306. plugins = self.meta.tables['plugins']
  307. query = sa.select([plugins.c.roles_metadata])
  308. for role_meta in db.execute(query):
  309. self.assertNotIn('tags', role_meta)
  310. class TestNodeNICAndBondAttributesMigration(base.BaseAlembicMigrationTest):
  311. def test_downgrade_release_with_nic_attributes(self):
  312. releases_table = self.meta.tables['releases']
  313. result = db.execute(
  314. sa.select([releases_table.c.nic_attributes,
  315. releases_table.c.bond_attributes])
  316. ).fetchall()[0]
  317. self.assertEqual(result['nic_attributes'], '{}')
  318. self.assertEqual(result['bond_attributes'], '{}')
  319. def test_downgrade_node_nic_attributes_with_empty_attributes(self):
  320. interfaces_table = self.meta.tables['node_nic_interfaces']
  321. result = db.execute(
  322. sa.select([interfaces_table.c.interface_properties,
  323. interfaces_table.c.offloading_modes]).
  324. where(interfaces_table.c.name == 'test_nic_empty_attributes')
  325. ).fetchone()
  326. self.assertEqual(
  327. jsonutils.loads(result['interface_properties']),
  328. {
  329. 'mtu': None,
  330. 'pci_id': '',
  331. 'disable_offloading': False,
  332. 'sriov': {
  333. 'enabled': False,
  334. 'available': False,
  335. 'sriov_numvfs': None,
  336. 'physnet': 'physnet2',
  337. 'pci_id': '',
  338. 'sriov_totalvfs': 0
  339. },
  340. 'dpdk': {
  341. 'enabled': False,
  342. 'available': False
  343. }
  344. }
  345. )
  346. self.assertEqual(jsonutils.loads(result['offloading_modes']), [])
  347. def test_downgrade_node_nic_attributes(self):
  348. interfaces_table = self.meta.tables['node_nic_interfaces']
  349. result = db.execute(
  350. sa.select([interfaces_table.c.interface_properties,
  351. interfaces_table.c.offloading_modes,
  352. interfaces_table.c.attributes,
  353. interfaces_table.c.meta]).
  354. where(interfaces_table.c.name == 'test_nic_attributes')
  355. ).fetchone()
  356. self.assertEqual(
  357. jsonutils.loads(result['interface_properties']),
  358. {
  359. 'mtu': 'test_mtu',
  360. 'pci_id': 'test_pci_id',
  361. 'disable_offloading': 'test_disable_offloading',
  362. 'sriov': {
  363. 'enabled': 'test_sriov_enabled',
  364. 'available': 'test_sriov_available',
  365. 'sriov_numvfs': 'test_sriov_numfs',
  366. 'physnet': 'test_sriov_physnet',
  367. 'pci_id': 'test_sriov_pci_id',
  368. 'sriov_totalvfs': 6789
  369. },
  370. 'dpdk': {
  371. 'enabled': 'test_dpdk_enabled',
  372. 'available': True
  373. }
  374. }
  375. )
  376. self.assertEqual(
  377. jsonutils.loads(result['offloading_modes']),
  378. [{
  379. 'state': 'TX_STATE',
  380. 'name': 'tx-checksumming',
  381. 'sub': [
  382. {'state': False, 'name': 'tx-checksum-sctp', 'sub': []},
  383. {'state': 'IPV6_STATE', 'name': 'tx-checksum-ipv6',
  384. 'sub': []},
  385. {'state': 'IPV4_STATE', 'name': 'tx-checksum-ipv4',
  386. 'sub': []}
  387. ]
  388. }, {
  389. 'state': 'RX_STATE', 'name': 'rx-checksumming', 'sub': []
  390. }]
  391. )
  392. self.assertEqual(result['meta'], '{}')
  393. self.assertEqual(result['attributes'], '{}')
  394. def test_downgrade_node_bond_attributes(self):
  395. node_bonds_table = self.meta.tables['node_bond_interfaces']
  396. result = db.execute(
  397. sa.select([node_bonds_table.c.interface_properties,
  398. node_bonds_table.c.bond_properties,
  399. node_bonds_table.c.offloading_modes,
  400. node_bonds_table.c.attributes]).
  401. where(node_bonds_table.c.name == 'test_bond_interface')
  402. ).fetchone()
  403. self.assertEqual(
  404. jsonutils.loads(result['bond_properties']),
  405. {'type__': 'linux', 'mode': 'balance-tlb',
  406. 'xmit_hash_policy': 'layer2'}
  407. )
  408. self.assertEqual(
  409. jsonutils.loads(result['interface_properties']),
  410. {'mtu': 50, 'disable_offloading': True,
  411. 'dpdk': {'available': True, 'enabled': False}}
  412. )
  413. self.assertEqual(result['offloading_modes'], "[]")
  414. self.assertEqual(result['attributes'], "{}")