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_orchestrator_serializer_70.py 77KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951
  1. # -*- coding: utf-8 -*-
  2. # Copyright 2015 Mirantis, Inc.
  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. import collections
  16. import copy
  17. import mock
  18. import netaddr
  19. import six
  20. import yaml
  21. from oslo_serialization import jsonutils
  22. from nailgun import consts
  23. from nailgun.db import db
  24. from nailgun.db.sqlalchemy import models
  25. from nailgun import objects
  26. from nailgun.orchestrator import stages
  27. from nailgun.test import base
  28. from nailgun.test.base import DeploymentTasksTestMixin
  29. from nailgun.utils import reverse
  30. from nailgun.orchestrator.deployment_serializers import \
  31. deployment_info_to_legacy
  32. from nailgun.orchestrator.deployment_serializers import \
  33. get_serializer_for_cluster
  34. from nailgun.orchestrator.orchestrator_graph import AstuteGraph
  35. from nailgun.test.integration.test_orchestrator_serializer import \
  36. BaseDeploymentSerializer
  37. from nailgun.test.integration.test_orchestrator_serializer import \
  38. TestDeploymentHASerializer61
  39. from nailgun.test.integration.test_orchestrator_serializer import \
  40. TestNovaOrchestratorSerializer
  41. from nailgun.test.integration.test_orchestrator_serializer import \
  42. TestSerializeInterfaceDriversData
  43. from nailgun.extensions.network_manager.serializers.neutron_serializers \
  44. import NeutronNetworkDeploymentSerializer70
  45. from nailgun.extensions.network_manager.serializers.neutron_serializers \
  46. import NeutronNetworkTemplateSerializer70
  47. class PrepareDataMixin(object):
  48. def patch_net_roles_for_release(self):
  49. rel_id = self.env.create_release(version=self.env_version).id
  50. rel_db = self.db.query(models.Release).filter_by(id=rel_id).one()
  51. to_patch = yaml.safe_load("""
  52. -
  53. id: "keystone/api"
  54. default_mapping: "management"
  55. properties: &default_network_roles_metadata_properties
  56. subnet: true
  57. gateway: false
  58. vip: []
  59. -
  60. id: "admin/pxe"
  61. default_mapping: "fuelweb_admin"
  62. properties:
  63. subnet: true
  64. gateway: true
  65. vip: []
  66. -
  67. id: "swift/api"
  68. default_mapping: "management"
  69. properties: *default_network_roles_metadata_properties
  70. -
  71. id: "neutron/api"
  72. default_mapping: "management"
  73. properties: *default_network_roles_metadata_properties
  74. -
  75. id: "sahara/api"
  76. default_mapping: "management"
  77. properties: *default_network_roles_metadata_properties
  78. -
  79. id: "ceilometer/api"
  80. default_mapping: "management"
  81. properties: *default_network_roles_metadata_properties
  82. -
  83. id: "cinder/api"
  84. default_mapping: "management"
  85. properties: *default_network_roles_metadata_properties
  86. -
  87. id: "glance/api"
  88. default_mapping: "management"
  89. properties: *default_network_roles_metadata_properties
  90. -
  91. id: "heat/api"
  92. default_mapping: "management"
  93. properties: *default_network_roles_metadata_properties
  94. -
  95. id: "nova/api"
  96. default_mapping: "management"
  97. properties: *default_network_roles_metadata_properties
  98. -
  99. id: "murano/api"
  100. default_mapping: "management"
  101. properties: *default_network_roles_metadata_properties
  102. -
  103. id: "horizon"
  104. default_mapping: "management"
  105. properties: *default_network_roles_metadata_properties
  106. -
  107. id: "mgmt/memcache"
  108. default_mapping: "management"
  109. properties: *default_network_roles_metadata_properties
  110. -
  111. id: "mgmt/database"
  112. default_mapping: "management"
  113. properties: *default_network_roles_metadata_properties
  114. -
  115. id: "mgmt/messaging"
  116. default_mapping: "management"
  117. properties: *default_network_roles_metadata_properties
  118. -
  119. id: "mgmt/corosync"
  120. default_mapping: "management"
  121. properties: *default_network_roles_metadata_properties
  122. -
  123. id: "mgmt/vip"
  124. default_mapping: "management"
  125. properties:
  126. subnet: true
  127. gateway: false
  128. vip:
  129. -
  130. name: "vrouter"
  131. namespace: "vrouter"
  132. alias: "management_vrouter_vip"
  133. -
  134. name: "management"
  135. namespace: "haproxy"
  136. alias: "management_vip"
  137. -
  138. id: "public/vip"
  139. default_mapping: "public"
  140. properties:
  141. subnet: true
  142. gateway: true
  143. vip:
  144. -
  145. name: "vrouter_pub"
  146. namespace: "vrouter"
  147. alias: "public_vrouter_vip"
  148. -
  149. name: "public"
  150. namespace: "haproxy"
  151. alias: "public_vip"
  152. -
  153. id: "neutron/private"
  154. default_mapping: "private"
  155. properties:
  156. subnet: false
  157. gateway: false
  158. vip: []
  159. -
  160. id: "neutron/mesh"
  161. default_mapping: "private"
  162. properties: *default_network_roles_metadata_properties
  163. -
  164. id: "neutron/floating"
  165. default_mapping: "public"
  166. properties:
  167. subnet: false
  168. gateway: false
  169. vip: []
  170. -
  171. id: "swift/replication"
  172. default_mapping: "storage"
  173. properties: *default_network_roles_metadata_properties
  174. -
  175. id: "ceph/public"
  176. default_mapping: "management"
  177. properties: *default_network_roles_metadata_properties
  178. -
  179. id: "ceph/radosgw"
  180. default_mapping: "public"
  181. properties: *default_network_roles_metadata_properties
  182. -
  183. id: "ceph/replication"
  184. default_mapping: "storage"
  185. properties: *default_network_roles_metadata_properties
  186. -
  187. id: "cinder/iscsi"
  188. default_mapping: "storage"
  189. properties: *default_network_roles_metadata_properties
  190. -
  191. id: "mongo/db"
  192. default_mapping: "management"
  193. properties: *default_network_roles_metadata_properties
  194. -
  195. id: "fw-admin"
  196. default_mapping: "fuelweb_admin"
  197. properties:
  198. subnet: true
  199. gateway: true
  200. vip: []
  201. -
  202. id: "management"
  203. default_mapping: "management"
  204. properties: *default_network_roles_metadata_properties
  205. -
  206. id: "ex"
  207. default_mapping: "public"
  208. properties:
  209. subnet: true
  210. gateway: true
  211. vip: []
  212. -
  213. id: "storage"
  214. default_mapping: "storage"
  215. properties: *default_network_roles_metadata_properties
  216. -
  217. id: "nova/migration"
  218. default_mapping: "management"
  219. properties: *default_network_roles_metadata_properties
  220. """)
  221. rel_db.network_roles_metadata = to_patch
  222. self.db.flush()
  223. return rel_db
  224. class BaseTestDeploymentAttributesSerialization70(BaseDeploymentSerializer,
  225. PrepareDataMixin):
  226. management = ['keystone/api', 'neutron/api', 'swift/api', 'sahara/api',
  227. 'ceilometer/api', 'cinder/api', 'glance/api', 'heat/api',
  228. 'nova/api', 'murano/api', 'horizon', 'management',
  229. 'mgmt/database', 'mgmt/messaging', 'mgmt/corosync',
  230. 'mgmt/memcache', 'mgmt/vip', 'mongo/db',
  231. 'ceph/public', 'nova/migration']
  232. fuelweb_admin = ['admin/pxe', 'fw-admin']
  233. neutron = ['neutron/private', 'neutron/floating']
  234. storage = ['storage', 'ceph/replication', 'swift/replication',
  235. 'cinder/iscsi']
  236. public = ['ex', 'public/vip', 'ceph/radosgw']
  237. private = ['neutron/mesh']
  238. networks = ['fuelweb_admin', 'storage', 'management', 'public', 'private']
  239. # Must be set in subclasses
  240. segmentation_type = None
  241. env_version = '2015.1.0-7.0'
  242. def setUp(self):
  243. super(BaseTestDeploymentAttributesSerialization70, self).setUp()
  244. self.cluster = self.create_env(consts.CLUSTER_MODES.ha_compact)
  245. objects.Cluster.prepare_for_deployment(self.env.clusters[-1])
  246. self.cluster_db = self.db.query(models.Cluster).get(self.cluster['id'])
  247. serializer_type = get_serializer_for_cluster(self.cluster_db)
  248. self.serializer = serializer_type(AstuteGraph(self.cluster_db))
  249. self.serialized_for_astute = self.serializer.serialize(
  250. self.cluster_db, self.cluster_db.nodes)
  251. self.serialized_for_astute = deployment_info_to_legacy(
  252. self.serialized_for_astute)
  253. self.vm_data = self.env.read_fixtures(['vmware_attributes'])
  254. def create_env(self, mode):
  255. release = self.patch_net_roles_for_release()
  256. return self.env.create(
  257. cluster_kwargs={
  258. 'release_id': release.id,
  259. 'mode': mode,
  260. 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
  261. 'net_segment_type': self.segmentation_type},
  262. nodes_kwargs=[
  263. {'roles': ['controller'],
  264. 'pending_addition': True},
  265. {'roles': ['compute'],
  266. 'pending_addition': True}])
  267. def check_vips_serialized(self, node_data):
  268. vips_names = ['vrouter', 'management', 'vrouter_pub', 'public']
  269. # check that vip-related info is not in root
  270. self.assertTrue(all(vip_name not in node_data
  271. for vip_name in vips_names))
  272. vips_data = node_data['network_metadata']['vips']
  273. self.assertItemsEqual(vips_data,
  274. vips_names)
  275. for vip in vips_names:
  276. self.assertItemsEqual(
  277. vips_data[vip],
  278. ['network_role', 'namespace',
  279. 'ipaddr', 'node_roles', 'is_user_defined']
  280. )
  281. class TestDeploymentAttributesSerialization70(
  282. BaseTestDeploymentAttributesSerialization70
  283. ):
  284. segmentation_type = consts.NEUTRON_SEGMENT_TYPES.vlan
  285. custom_network = {
  286. 'name': 'custom',
  287. 'role': 'plugin/custom',
  288. 'cidr': '192.168.3.0/24',
  289. 'vlan_start': 50,
  290. 'bridge': 'br-custom',
  291. }
  292. plugin_network_roles = yaml.safe_load("""
  293. - id: "{role}"
  294. default_mapping: "{name}"
  295. properties:
  296. subnet: true
  297. gateway: false
  298. vip:
  299. - name: "{name}"
  300. namespace: "haproxy"
  301. """.format(**custom_network))
  302. def test_non_default_bridge_mapping(self):
  303. expected_mapping = {
  304. u'test': u'br-test',
  305. u'testnetwork1': u'br-testnetwork',
  306. u'testnetwork13': u'br-testnetwork',
  307. u'my-super-network': u'br-my-super-net',
  308. u'uplink-network-east': u'br-uplink-netw',
  309. u'uplink-network-west': u'br-uplink-netw',
  310. u'uplink-network-south': u'br-uplink-netw',
  311. u'12345uplink-network-south': u'br-12345uplink',
  312. u'fw-admin': u'br-fw-admi'
  313. }
  314. cluster = self.env.create(
  315. cluster_kwargs={
  316. 'release_id': self.env.releases[0].id,
  317. 'mode': consts.CLUSTER_MODES.ha_compact,
  318. 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
  319. 'net_segment_type': self.segmentation_type})
  320. self.cluster_db = objects.Cluster.get_by_uid(cluster['id'])
  321. for name in expected_mapping:
  322. self.env._create_network_group(cluster=self.cluster_db,
  323. name=name)
  324. self.env.create_node(
  325. api=True,
  326. cluster_id=cluster['id'],
  327. pending_roles=['controller'],
  328. pending_addition=True)
  329. net_serializer = self.serializer.get_net_provider_serializer(
  330. self.cluster_db)
  331. objects.Cluster.prepare_for_deployment(self.cluster_db)
  332. mapping = net_serializer.get_node_non_default_bridge_mapping(
  333. self.cluster_db.nodes[0])
  334. # since we have a suffix generation for bridges, they may have
  335. # different suffix based on PYTHONHASHSEED. hence, we can't
  336. # come up with a normal dictionary comparison. so let's
  337. # compare that all bridges are unique, and they are unique
  338. # for networks which may have bridge collision.
  339. br_collision = collections.defaultdict(list)
  340. self.assertEqual(len(mapping), len(expected_mapping))
  341. self.assertEqual(len(expected_mapping), len(set(mapping.values())))
  342. for netname in expected_mapping:
  343. # check that bridge name has been generated from the network
  344. self.assertTrue(
  345. mapping[netname].startswith(expected_mapping[netname]))
  346. br_collision[expected_mapping[netname]].append(netname)
  347. # check that there's no collision between networks
  348. for bridge, netnames in six.iteritems(br_collision):
  349. bridges = set((mapping[netname] for netname in netnames))
  350. self.assertEqual(len(bridges), len(netnames))
  351. def test_network_scheme_custom_networks(self):
  352. cluster = self.env.create(
  353. cluster_kwargs={
  354. 'release_id': self.env.releases[0].id,
  355. 'mode': consts.CLUSTER_MODES.ha_compact,
  356. 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
  357. 'net_segment_type': self.segmentation_type})
  358. self.cluster_db = objects.Cluster.get_by_uid(cluster['id'])
  359. self.env._create_network_group(cluster=self.cluster_db,
  360. name=self.custom_network['name'],
  361. cidr=self.custom_network['cidr'],
  362. vlan_start=self.custom_network[
  363. 'vlan_start'
  364. ])
  365. self.env.create_plugin(
  366. cluster=self.cluster_db,
  367. network_roles_metadata=self.plugin_network_roles,
  368. package_version='3.0.0')
  369. self.env.create_node(
  370. api=True,
  371. cluster_id=cluster['id'],
  372. pending_roles=['controller'],
  373. pending_addition=True)
  374. objects.Cluster.prepare_for_deployment(self.cluster_db)
  375. serializer = self.create_serializer(self.cluster_db)
  376. serialized_for_astute = serializer.serialize(
  377. self.cluster_db, self.cluster_db.nodes
  378. )
  379. serialized_for_astute = deployment_info_to_legacy(
  380. serialized_for_astute)
  381. for node in serialized_for_astute:
  382. vips = node['network_metadata']['vips']
  383. roles = node['network_scheme']['roles']
  384. transformations = node['network_scheme']['transformations']
  385. node_network_roles = (node['network_metadata']['nodes']
  386. ['node-' + node['uid']]['network_roles'])
  387. custom_ip = node_network_roles.get(self.custom_network['role'],
  388. '0.0.0.0')
  389. custom_brs = filter(lambda t: t.get('name') ==
  390. self.custom_network['bridge'],
  391. transformations)
  392. custom_ports = filter(lambda t: t.get('name') ==
  393. ("eth0.%s" %
  394. self.custom_network['vlan_start']),
  395. transformations)
  396. self.assertEqual(roles.get(self.custom_network['role']),
  397. self.custom_network['bridge'])
  398. self.assertEqual(vips.get(self.custom_network['name'],
  399. {}).get('network_role'),
  400. self.custom_network['role'])
  401. self.assertTrue(netaddr.IPAddress(custom_ip) in
  402. netaddr.IPNetwork(self.custom_network['cidr']))
  403. self.assertEqual(len(custom_brs), 1)
  404. self.assertEqual(len(custom_ports), 1)
  405. self.assertEqual(custom_ports[0]['bridge'],
  406. self.custom_network['bridge'])
  407. def test_network_scheme(self):
  408. for node in self.serialized_for_astute:
  409. roles = node['network_scheme']['roles']
  410. node = objects.Node.get_by_uid(node['uid'])
  411. expected_roles = zip(
  412. self.management, ['br-mgmt'] * len(self.management))
  413. expected_roles += zip(
  414. self.fuelweb_admin, ['br-fw-admin'] * len(self.fuelweb_admin))
  415. expected_roles += zip(
  416. self.storage, ['br-storage'] * len(self.storage))
  417. if objects.Node.should_have_public(node):
  418. expected_roles += zip(
  419. self.public, ['br-ex'] * len(self.public))
  420. expected_roles += [('neutron/floating', 'br-floating')]
  421. if node.cluster.network_config.segmentation_type == \
  422. consts.NEUTRON_SEGMENT_TYPES.vlan:
  423. expected_roles += [('neutron/private', 'br-prv')]
  424. if node.cluster.network_config.segmentation_type in \
  425. (consts.NEUTRON_SEGMENT_TYPES.gre,
  426. consts.NEUTRON_SEGMENT_TYPES.tun):
  427. expected_roles += [('neutron/mesh', 'br-mesh')]
  428. self.assertEqual(roles, dict(expected_roles))
  429. def test_network_metadata(self):
  430. neutron_serializer = self.serializer.get_net_provider_serializer(
  431. self.cluster_db)
  432. for node_data in self.serialized_for_astute:
  433. self.assertItemsEqual(
  434. node_data['network_metadata'], ['nodes', 'vips'])
  435. for k, v in six.iteritems(node_data['network_metadata']['nodes']):
  436. self.assertItemsEqual(
  437. v,
  438. ['uid', 'fqdn', 'name', 'user_node_name',
  439. 'swift_zone', 'node_roles', 'network_roles']
  440. )
  441. node = objects.Node.get_by_uid(v['uid'])
  442. ip_by_net = neutron_serializer.get_network_to_ip_mapping(node)
  443. self.assertEqual(objects.Node.get_slave_name(node), k)
  444. self.assertEqual(v['uid'], node.uid)
  445. self.assertEqual(v['fqdn'], objects.Node.get_node_fqdn(node))
  446. self.assertEqual(v['name'], k)
  447. self.assertEqual(v['user_node_name'], node.name)
  448. self.assertEqual(v['swift_zone'], node.uid)
  449. network_roles = zip(self.management,
  450. [ip_by_net['management']] * len(
  451. self.management))
  452. network_roles += zip(self.fuelweb_admin,
  453. [ip_by_net['fuelweb_admin']] * len(
  454. self.fuelweb_admin))
  455. network_roles += zip(
  456. self.storage, [ip_by_net['storage']] * len(self.storage))
  457. network_roles += zip(self.neutron, [None] * len(self.neutron))
  458. if objects.Node.should_have_public(node):
  459. network_roles += zip(
  460. self.public, [ip_by_net['public']] * len(self.public))
  461. if node.cluster.network_config.segmentation_type in \
  462. (consts.NEUTRON_SEGMENT_TYPES.gre,
  463. consts.NEUTRON_SEGMENT_TYPES.tun):
  464. network_roles += zip(
  465. self.private,
  466. [ip_by_net['private']] * len(self.private))
  467. self.assertEqual(v['network_roles'], dict(network_roles))
  468. self.check_vips_serialized(node_data)
  469. def test_generate_vmware_attributes_data(self):
  470. self.check_generate_vmware_attributes_data()
  471. result = self.serializer.serialize_node(
  472. self.env.nodes[0], 'compute-vmware'
  473. )
  474. self.assertEqual(
  475. result['vcenter']['computes'][0]['target_node'],
  476. "test_target_node")
  477. self.assertEqual(
  478. result['vcenter']['computes'][2]['target_node'],
  479. "controllers")
  480. class TestDeploymentAttributesSerializationSegmentationGre70(
  481. TestDeploymentAttributesSerialization70
  482. ):
  483. segmentation_type = consts.NEUTRON_SEGMENT_TYPES.gre
  484. class TestDeploymentAttributesSerializationSegmentationTun70(
  485. TestDeploymentAttributesSerialization70
  486. ):
  487. segmentation_type = consts.NEUTRON_SEGMENT_TYPES.tun
  488. class TestDeploymentSerializationForNovaNetwork70(
  489. BaseTestDeploymentAttributesSerialization70
  490. ):
  491. def create_env(self, mode):
  492. release = self.patch_net_roles_for_release()
  493. return self.env.create(
  494. cluster_kwargs={
  495. 'release_id': release.id,
  496. 'mode': mode,
  497. 'net_provider': consts.CLUSTER_NET_PROVIDERS.nova_network},
  498. nodes_kwargs=[
  499. {'roles': ['controller'],
  500. 'pending_addition': True,
  501. 'name': self.node_name,
  502. }
  503. ])
  504. def test_network_scheme(self):
  505. for node in self.serialized_for_astute:
  506. roles = node['network_scheme']['roles']
  507. expected_roles = {
  508. 'admin/pxe': 'br-fw-admin',
  509. 'keystone/api': 'br-mgmt',
  510. 'swift/api': 'br-mgmt',
  511. 'sahara/api': 'br-mgmt',
  512. 'ceilometer/api': 'br-mgmt',
  513. 'cinder/api': 'br-mgmt',
  514. 'glance/api': 'br-mgmt',
  515. 'heat/api': 'br-mgmt',
  516. 'nova/api': 'br-mgmt',
  517. 'murano/api': 'br-mgmt',
  518. 'horizon': 'br-mgmt',
  519. 'mgmt/database': 'br-mgmt',
  520. 'mgmt/messaging': 'br-mgmt',
  521. 'mgmt/corosync': 'br-mgmt',
  522. 'mgmt/memcache': 'br-mgmt',
  523. 'mgmt/vip': 'br-mgmt',
  524. 'public/vip': 'br-ex',
  525. 'swift/replication': 'br-storage',
  526. 'ceph/public': 'br-mgmt',
  527. 'ceph/radosgw': 'br-ex',
  528. 'ceph/replication': 'br-storage',
  529. 'cinder/iscsi': 'br-storage',
  530. 'mongo/db': 'br-mgmt',
  531. 'novanetwork/fixed': 'eth0.103',
  532. # deprecated
  533. 'fw-admin': 'br-fw-admin',
  534. 'management': 'br-mgmt',
  535. 'ex': 'br-ex',
  536. 'storage': 'br-storage',
  537. }
  538. self.assertEqual(roles, expected_roles)
  539. def test_network_metadata(self):
  540. nm = objects.Cluster.get_network_manager(self.cluster)
  541. ip_by_net = {
  542. 'fuelweb_admin': None,
  543. 'storage': None,
  544. 'management': None,
  545. 'public': None
  546. }
  547. node = self.env.nodes[0]
  548. networks = nm.get_node_networks(node)
  549. for net in ip_by_net:
  550. netgroup = nm.get_network_by_netname(net, networks)
  551. if netgroup.get('ip'):
  552. ip_by_net[net] = netgroup['ip'].split('/')[0]
  553. for node_data in self.serialized_for_astute:
  554. self.assertItemsEqual(
  555. node_data['network_metadata'], ['nodes', 'vips'])
  556. nodes = node_data['network_metadata']['nodes']
  557. for node_name, node_attrs in nodes.items():
  558. self.assertItemsEqual(
  559. node_attrs,
  560. ['uid', 'fqdn', 'name', 'user_node_name',
  561. 'swift_zone', 'node_roles', 'network_roles']
  562. )
  563. self.assertEqual(objects.Node.get_slave_name(node), node_name)
  564. self.assertEqual(node_attrs['uid'], node.uid)
  565. self.assertEqual(node_attrs['fqdn'],
  566. objects.Node.get_node_fqdn(node))
  567. self.assertEqual(node_attrs['name'], node_name)
  568. self.assertEqual(node_attrs['user_node_name'], node.name)
  569. self.assertEqual(node_attrs['swift_zone'], node.uid)
  570. network_roles = {
  571. 'admin/pxe': ip_by_net['fuelweb_admin'],
  572. 'fw-admin': ip_by_net['fuelweb_admin'],
  573. 'keystone/api': ip_by_net['management'],
  574. 'swift/api': ip_by_net['management'],
  575. 'sahara/api': ip_by_net['management'],
  576. 'ceilometer/api': ip_by_net['management'],
  577. 'cinder/api': ip_by_net['management'],
  578. 'glance/api': ip_by_net['management'],
  579. 'heat/api': ip_by_net['management'],
  580. 'nova/api': ip_by_net['management'],
  581. 'murano/api': ip_by_net['management'],
  582. 'horizon': ip_by_net['management'],
  583. 'management': ip_by_net['management'],
  584. 'mgmt/database': ip_by_net['management'],
  585. 'mgmt/messaging': ip_by_net['management'],
  586. 'mgmt/corosync': ip_by_net['management'],
  587. 'mgmt/memcache': ip_by_net['management'],
  588. 'mgmt/vip': ip_by_net['management'],
  589. 'mongo/db': ip_by_net['management'],
  590. 'ceph/public': ip_by_net['management'],
  591. 'storage': ip_by_net['storage'],
  592. 'ceph/replication': ip_by_net['storage'],
  593. 'swift/replication': ip_by_net['storage'],
  594. 'cinder/iscsi': ip_by_net['storage'],
  595. 'ex': ip_by_net['public'],
  596. 'public/vip': ip_by_net['public'],
  597. 'ceph/radosgw': ip_by_net['public'],
  598. }
  599. self.assertEqual(
  600. node_attrs['network_roles'],
  601. network_roles
  602. )
  603. self.check_vips_serialized(node_data)
  604. def test_generate_vmware_attributes_data(self):
  605. self.check_generate_vmware_attributes_data()
  606. result = self.serializer.serialize_node(
  607. self.env.nodes[0], 'compute-vmware'
  608. )
  609. self.assertEqual(
  610. result['vcenter']['computes'][0]['target_node'],
  611. "test_target_node")
  612. self.assertEqual(
  613. result['vcenter']['computes'][2]['target_node'],
  614. "controllers")
  615. class TestPluginDeploymentTasksInjection70(base.BaseIntegrationTest):
  616. env_version = '2015.1.0-7.0'
  617. release_deployment_tasks = [
  618. {'id': 'pre_deployment_start',
  619. 'type': 'stage'},
  620. {'id': 'pre_deployment_end',
  621. 'type': 'stage',
  622. 'requires': ['pre_deployment_start']},
  623. {'id': 'deploy_start',
  624. 'type': 'stage'},
  625. {'id': 'deploy_end',
  626. 'requires': ['deploy_start'],
  627. 'type': 'stage'},
  628. {'id': 'post_deployment_start',
  629. 'type': 'stage',
  630. 'requires': ['deploy_end']},
  631. {'id': 'post_deployment_end',
  632. 'type': 'stage',
  633. 'requires': ['post_deployment_start']},
  634. {'id': 'primary-controller',
  635. 'parameters': {'strategy': {'type': 'one_by_one'}},
  636. 'required_for': ['deploy_end'],
  637. 'requires': ['deploy_start'],
  638. 'role': ['primary-controller'],
  639. 'type': 'group'},
  640. {'id': 'first-fake-depl-task',
  641. 'required_for': ['deploy_end'],
  642. 'requires': ['deploy_start'],
  643. 'type': 'puppet',
  644. 'parameters': {'puppet_manifest': 'first-fake-depl-task',
  645. 'puppet_modules': 'test',
  646. 'timeout': 0},
  647. 'groups': ['primary-controller']},
  648. {'id': 'second-fake-depl-task',
  649. 'required_for': ['deploy_end'],
  650. 'requires': ['deploy_start'],
  651. 'type': 'puppet',
  652. 'parameters': {'puppet_manifest': 'second-fake-depl-task',
  653. 'puppet_modules': 'test',
  654. 'timeout': 0},
  655. 'groups': ['primary-controller']},
  656. ]
  657. def setUp(self):
  658. super(TestPluginDeploymentTasksInjection70, self).setUp()
  659. # Plugin task injection for Task based is checked in task based tests
  660. self.cluster = self.env.create(
  661. release_kwargs={
  662. 'deployment_tasks': self.release_deployment_tasks,
  663. 'version': self.env_version
  664. },
  665. cluster_kwargs={
  666. 'mode': consts.CLUSTER_MODES.ha_compact,
  667. 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
  668. 'net_segment_type': consts.NEUTRON_SEGMENT_TYPES.vlan,
  669. },
  670. nodes_kwargs=[
  671. {'roles': ['controller'], 'primary_tags': ['controller'],
  672. 'pending_addition': True}
  673. ]
  674. )
  675. objects.Cluster.set_primary_tags(self.cluster, self.cluster.nodes)
  676. self.plugin_data = {
  677. 'package_version': '3.0.0',
  678. 'releases': [
  679. {
  680. 'repository_path': 'plugin_test',
  681. 'version': self.cluster.release.version,
  682. 'os': self.cluster.release.operating_system.lower(),
  683. 'mode': ['ha', 'multinode'],
  684. 'deployment_scripts_path': 'plugin_test/'
  685. },
  686. ],
  687. }
  688. def prepare_plugins_for_cluster(self, cluster, plugins_kw_list):
  689. for kw in plugins_kw_list:
  690. kw.update(self.plugin_data)
  691. self.env.create_plugin(cluster=cluster, **kw)
  692. def _check_pre_deployment_tasks(self, serialized, task_type):
  693. self.assertTrue(serialized)
  694. needed_task = next(
  695. t for t in serialized
  696. if t['type'] == task_type)
  697. self.assertIsNotNone(needed_task)
  698. self.assertIsNotNone(needed_task.get('parameters'))
  699. self.assertItemsEqual(
  700. (n.uid for n in self.cluster.nodes),
  701. needed_task['uids']
  702. )
  703. def test_plugin_depl_tasks_proper_injections(self):
  704. self.prepare_plugins_for_cluster(
  705. self.cluster,
  706. [
  707. {
  708. 'name': 'between_rel_tasks',
  709. 'deployment_tasks': [
  710. {
  711. 'id': 'between-rel-tasks',
  712. 'type': 'puppet',
  713. 'groups': ['primary-controller'],
  714. 'requires': ['first-fake-depl-task'],
  715. 'required_for': ['second-fake-depl-task'],
  716. 'parameters': {
  717. 'puppet_manifest': 'between-rel-tasks',
  718. 'puppet_modules': 'test',
  719. 'timeout': 0,
  720. }
  721. },
  722. ],
  723. },
  724. ]
  725. )
  726. graph = AstuteGraph(self.cluster)
  727. objects.Cluster.prepare_for_deployment(self.cluster)
  728. serializer = \
  729. get_serializer_for_cluster(self.cluster)(graph)
  730. serialized = serializer.serialize(self.cluster, self.cluster.nodes)
  731. serialized = deployment_info_to_legacy(serialized)
  732. serialized_tasks = serialized[0]['tasks']
  733. expected_priority = {
  734. 100: 'first-fake-depl-task',
  735. 200: 'between-rel-tasks',
  736. 300: 'second-fake-depl-task',
  737. }
  738. for task in serialized_tasks:
  739. task_identificator = task['parameters']['puppet_manifest']
  740. self.assertEqual(
  741. task_identificator, expected_priority[task['priority']]
  742. )
  743. def test_plugin_depl_task_overwrite_from_rel(self):
  744. self.prepare_plugins_for_cluster(
  745. self.cluster,
  746. [
  747. {
  748. 'name': 'between_rel_tasks',
  749. 'deployment_tasks': [
  750. {
  751. 'id': 'first-fake-depl-task',
  752. 'type': 'puppet',
  753. 'groups': ['primary-controller'],
  754. 'requires': ['deploy_start'],
  755. 'required_for': ['second-fake-depl-task'],
  756. 'parameters': {
  757. 'puppet_manifest': 'plugin_task',
  758. 'puppet_modules': 'test',
  759. 'timeout': 0,
  760. }
  761. },
  762. ],
  763. },
  764. ]
  765. )
  766. graph = AstuteGraph(self.cluster)
  767. objects.Cluster.prepare_for_deployment(self.cluster)
  768. serializer = \
  769. get_serializer_for_cluster(self.cluster)(graph)
  770. serialized = serializer.serialize(self.cluster, self.cluster.nodes)
  771. serialized = deployment_info_to_legacy(serialized)
  772. serialized_tasks = serialized[0]['tasks']
  773. needed_task_priority = next(
  774. t['priority'] for t in serialized_tasks
  775. if t['parameters']['puppet_manifest'] == 'plugin_task'
  776. )
  777. # first task in graph has priority equal 100
  778. self.assertEqual(needed_task_priority, 100)
  779. def test_plugin_depl_task_in_pre_depl(self):
  780. self.prepare_plugins_for_cluster(
  781. self.cluster,
  782. [
  783. {
  784. 'name': 'pre_depl_plugin_task',
  785. 'deployment_tasks': [
  786. {
  787. 'id': 'pre-depl-plugin-task',
  788. 'type': 'puppet',
  789. 'role': ['primary-controller'],
  790. 'requires': ['pre_deployment_start'],
  791. 'required_for': ['pre_deployment_end'],
  792. 'parameters': {
  793. 'puppet_manifest': 'pre_depl_plugin_task',
  794. 'puppet_modules': 'test',
  795. 'timeout': 0,
  796. }
  797. },
  798. ],
  799. },
  800. ]
  801. )
  802. graph = AstuteGraph(self.cluster)
  803. objects.Cluster.prepare_for_deployment(self.cluster)
  804. with mock.patch('nailgun.plugins.adapters.glob.glob',
  805. mock.Mock(return_value='path/to/test/repos')):
  806. pre_deployment = stages.pre_deployment_serialize(
  807. graph, self.cluster, self.cluster.nodes)
  808. for task_type in (consts.ORCHESTRATOR_TASK_TYPES.sync,
  809. consts.ORCHESTRATOR_TASK_TYPES.upload_file):
  810. self._check_pre_deployment_tasks(pre_deployment, task_type)
  811. def test_plugin_depl_task_for_master_not_in_pre_depl(self):
  812. self.prepare_plugins_for_cluster(
  813. self.cluster,
  814. [
  815. {
  816. 'name': 'pre_depl_plugin_task',
  817. 'deployment_tasks': [
  818. {
  819. 'id': 'pre-depl-plugin-task',
  820. 'type': 'puppet',
  821. 'role': consts.MASTER_NODE_UID,
  822. 'requires': ['pre_deployment_start'],
  823. 'required_for': ['pre_deployment_end'],
  824. 'parameters': {
  825. 'puppet_manifest': 'pre_depl_plugin_task',
  826. 'puppet_modules': 'test',
  827. 'timeout': 0,
  828. }
  829. },
  830. ],
  831. },
  832. {
  833. 'name': 'pre_depl_plugin_task_for_master_and_contr',
  834. 'deployment_tasks': [
  835. {
  836. 'id': 'pre-depl-plugin-task-for-master-and-contr',
  837. 'type': 'puppet',
  838. 'groups': [consts.MASTER_NODE_UID,
  839. 'primary-controller'],
  840. 'requires': ['pre_deployment_start'],
  841. 'required_for': ['pre_deployment_end'],
  842. 'parameters': {
  843. 'puppet_manifest': 'pre_depl_plugin_task',
  844. 'puppet_modules': 'test',
  845. 'timeout': 0,
  846. }
  847. },
  848. ],
  849. },
  850. ]
  851. )
  852. graph = AstuteGraph(self.cluster)
  853. objects.Cluster.prepare_for_deployment(self.cluster)
  854. with mock.patch('nailgun.plugins.adapters.glob.glob',
  855. mock.Mock(return_value='path/to/test/repos')):
  856. pre_deployment = stages.pre_deployment_serialize(
  857. graph, self.cluster, self.cluster.nodes)
  858. for st in pre_deployment:
  859. self.assertNotIn(consts.MASTER_NODE_UID, st['uids'])
  860. def test_plugin_depl_task_in_post_depl(self):
  861. self.prepare_plugins_for_cluster(
  862. self.cluster,
  863. [
  864. {
  865. 'name': 'post-depl-plugin-task',
  866. 'deployment_tasks': [
  867. {
  868. 'id': 'post-depl-plugin-task',
  869. 'type': 'puppet',
  870. 'role': ['primary-controller'],
  871. 'requires': ['post_deployment_start'],
  872. 'required_for': ['post_deployment_end'],
  873. 'parameters': {
  874. 'puppet_manifest': 'post_depl_plugin_task',
  875. 'puppet_modules': 'test',
  876. 'timeout': 0,
  877. }
  878. },
  879. ],
  880. },
  881. ]
  882. )
  883. graph = AstuteGraph(self.cluster)
  884. objects.Cluster.prepare_for_deployment(self.cluster)
  885. post_deployment = stages.post_deployment_serialize(
  886. graph, self.cluster, self.cluster.nodes)
  887. self.assertEqual(
  888. post_deployment[0]['parameters']['puppet_manifest'],
  889. 'post_depl_plugin_task'
  890. )
  891. def test_process_skipped_task(self):
  892. self.prepare_plugins_for_cluster(
  893. self.cluster,
  894. [
  895. {
  896. 'name': 'task_with_skipped_plugin',
  897. 'deployment_tasks': [
  898. {
  899. 'id': 'skipped_task',
  900. 'type': 'skipped',
  901. },
  902. ],
  903. },
  904. ]
  905. )
  906. graph = AstuteGraph(self.cluster)
  907. objects.Cluster.prepare_for_deployment(self.cluster)
  908. serializer = \
  909. get_serializer_for_cluster(self.cluster)(graph)
  910. serialized = serializer.serialize(self.cluster, self.cluster.nodes)
  911. serialized = deployment_info_to_legacy(serialized)
  912. tasks = serialized[0]['tasks']
  913. release_depl_tasks_ids = ('first-fake-depl-task',
  914. 'second-fake-depl-task')
  915. serialized_tasks_ids = (t['parameters']['puppet_manifest']
  916. for t in tasks)
  917. self.assertItemsEqual(release_depl_tasks_ids, serialized_tasks_ids)
  918. class TestRolesSerializationWithPlugins(BaseDeploymentSerializer,
  919. PrepareDataMixin,
  920. DeploymentTasksTestMixin):
  921. env_version = '2015.1.0-7.0'
  922. ROLES = yaml.safe_load("""
  923. test_role:
  924. name: "Some plugin role"
  925. description: "Some description"
  926. conflicts:
  927. - some_not_compatible_role
  928. limits:
  929. min: 1
  930. restrictions:
  931. - condition: "some logic condition"
  932. message: "Some message for restriction warning"
  933. volumes_mapping:
  934. - {allocate_size: "min", id: "os"}
  935. - {allocate_size: "all", id: "role_volume_name"}
  936. """)
  937. DEPLOYMENT_TASKS = yaml.safe_load("""
  938. - id: test_role
  939. type: group
  940. role: [test_role]
  941. required_for: [deploy_end]
  942. requires: [deploy_start]
  943. parameters:
  944. strategy:
  945. type: one_by_one
  946. - id: deployment_task_id
  947. type: puppet
  948. groups: [test_role]
  949. required_for: [deploy_end]
  950. requires: [deploy_start]
  951. parameters:
  952. puppet_manifest: /path/to/manifests
  953. puppet_modules: /path/to/modules
  954. timeout: 3600
  955. """)
  956. def setUp(self):
  957. super(TestRolesSerializationWithPlugins, self).setUp()
  958. release = self.patch_net_roles_for_release()
  959. self.cluster = self.env.create(
  960. cluster_kwargs={
  961. 'release_id': release.id,
  962. 'mode': consts.CLUSTER_MODES.ha_compact,
  963. 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
  964. 'net_segment_type': consts.NEUTRON_SEGMENT_TYPES.vlan,
  965. })
  966. self.plugin_data = {
  967. 'package_version': '3.0.0',
  968. 'releases': [
  969. {
  970. 'repository_path': 'repositories/ubuntu',
  971. 'version': self.cluster.release.version,
  972. 'os': self.cluster.release.operating_system.lower(),
  973. 'mode': [self.cluster.mode],
  974. }
  975. ]
  976. }
  977. def test_tasks_were_serialized(self):
  978. plugin_data = {
  979. 'roles_metadata': self.ROLES,
  980. 'deployment_tasks': self.DEPLOYMENT_TASKS
  981. }
  982. plugin_data.update(self.plugin_data)
  983. self.env.create_plugin(cluster=self.cluster, **plugin_data)
  984. self.env.create_node(
  985. api=True,
  986. cluster_id=self.cluster.id,
  987. pending_roles=['test_role'],
  988. pending_addition=True)
  989. self.db.flush()
  990. objects.Cluster.prepare_for_deployment(self.cluster)
  991. serializer = self._get_serializer(self.cluster)
  992. with mock.patch('nailgun.objects.node.Node.all_tags',
  993. mock.Mock(return_value=['test_role'])):
  994. serialized_data = serializer.serialize(
  995. self.cluster, self.cluster.nodes)
  996. serialized_data = deployment_info_to_legacy(serialized_data)
  997. self.assertItemsEqual(serialized_data[0]['tasks'], [{
  998. 'parameters': {
  999. 'cwd': '/etc/fuel/plugins/testing_plugin-0.1/',
  1000. 'puppet_manifest': '/path/to/manifests',
  1001. 'puppet_modules': '/path/to/modules',
  1002. 'timeout': 3600,
  1003. 'retries': None,
  1004. },
  1005. 'priority': 100,
  1006. 'type': 'puppet',
  1007. 'uids': [self.cluster.nodes[0].uid],
  1008. 'id': 'deployment_task_id'
  1009. }])
  1010. def test_tasks_were_not_serialized(self):
  1011. plugin_data = {
  1012. 'roles_metadata': {},
  1013. 'deployment_tasks': self.DEPLOYMENT_TASKS
  1014. }
  1015. plugin_data.update(self.plugin_data)
  1016. self.env.create_plugin(cluster=self.cluster, **plugin_data)
  1017. self.env.create_node(
  1018. api=True,
  1019. cluster_id=self.cluster.id,
  1020. pending_roles=['controller'],
  1021. pending_addition=True)
  1022. self.db.flush()
  1023. objects.Cluster.prepare_for_deployment(self.cluster)
  1024. serializer = self._get_serializer(self.cluster)
  1025. serialized_data = serializer.serialize(
  1026. self.cluster, self.cluster.nodes)
  1027. serialized_data = deployment_info_to_legacy(serialized_data)
  1028. self.maxDiff = None
  1029. self._compare_tasks([
  1030. {
  1031. 'parameters': {
  1032. 'puppet_modules': '/etc/puppet/modules',
  1033. 'puppet_manifest': '/etc/puppet/modules/osnailyfacter/'
  1034. 'modular/netconfig/netconfig.pp',
  1035. 'timeout': 3600,
  1036. 'retries': None,
  1037. 'cwd': '/'},
  1038. 'priority': 100,
  1039. 'type': 'puppet',
  1040. 'id': 'netconfig',
  1041. 'uids': [self.cluster.nodes[0].uid],
  1042. }, {
  1043. 'parameters': {
  1044. 'cwd': '/',
  1045. 'puppet_manifest': '/etc/puppet/manifests/site.pp',
  1046. 'puppet_modules': '/etc/puppet/modules',
  1047. 'timeout': 3600,
  1048. 'retries': None},
  1049. 'priority': 200,
  1050. 'type': 'puppet',
  1051. 'id': 'deploy_legacy',
  1052. 'uids': [self.cluster.nodes[0].uid],
  1053. }, {
  1054. 'parameters': {
  1055. 'puppet_modules': '/etc/puppet/modules',
  1056. 'puppet_manifest': '/etc/puppet/modules/osnailyfacter/'
  1057. 'modular/globals/globals.pp',
  1058. 'timeout': 3600,
  1059. 'retries': None,
  1060. 'cwd': '/'},
  1061. 'priority': 300,
  1062. 'type': 'puppet',
  1063. 'id': 'globals',
  1064. 'uids': [self.cluster.nodes[0].uid],
  1065. }], serialized_data[0]['tasks'])
  1066. class TestNetworkTemplateSerializer70(BaseDeploymentSerializer,
  1067. PrepareDataMixin):
  1068. env_version = '2015.1.0-7.0'
  1069. general_serializer = NeutronNetworkDeploymentSerializer70
  1070. template_serializer = NeutronNetworkTemplateSerializer70
  1071. def setUp(self, *args):
  1072. super(TestNetworkTemplateSerializer70, self).setUp()
  1073. self.cluster = self.create_env(consts.NEUTRON_SEGMENT_TYPES.vlan)
  1074. self.net_template = self.env.read_fixtures(['network_template_70'])[0]
  1075. objects.Cluster.set_network_template(
  1076. self.cluster,
  1077. self.net_template
  1078. )
  1079. cluster_db = self.db.query(models.Cluster).get(self.cluster['id'])
  1080. objects.Cluster.prepare_for_deployment(cluster_db)
  1081. serializer = self._get_serializer(self.cluster)
  1082. self.serialized_for_astute = serializer.serialize(self.cluster,
  1083. cluster_db.nodes)
  1084. self.serialized_for_astute = deployment_info_to_legacy(
  1085. self.serialized_for_astute)
  1086. def create_env(self, segment_type):
  1087. release = self.patch_net_roles_for_release()
  1088. cluster = self.env.create(
  1089. cluster_kwargs={
  1090. 'api': False,
  1091. 'release_id': release.id,
  1092. 'mode': consts.CLUSTER_MODES.ha_compact,
  1093. 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
  1094. 'net_segment_type': segment_type},
  1095. )
  1096. nodes_kwargs = {
  1097. 'roles': ['controller'],
  1098. 'pending_addition': True,
  1099. 'name': self.node_name,
  1100. 'cluster_id': cluster['id']
  1101. }
  1102. self.env.create_nodes_w_interfaces_count(1, 6, **nodes_kwargs)
  1103. nodes_kwargs['roles'] = ['compute', 'cinder']
  1104. self.env.create_nodes_w_interfaces_count(1, 6, **nodes_kwargs)
  1105. return cluster
  1106. def create_more_nodes(self, iface_count=3):
  1107. self.env.create_nodes_w_interfaces_count(
  1108. 1, iface_count, roles=['cinder'], cluster_id=self.cluster.id)
  1109. self.env.create_nodes_w_interfaces_count(
  1110. 1, iface_count,
  1111. roles=['cinder', 'controller'], cluster_id=self.cluster.id)
  1112. self.env.create_nodes_w_interfaces_count(
  1113. 1, iface_count, roles=['compute'], cluster_id=self.cluster.id)
  1114. def check_node_ips_on_certain_networks(self, node, net_names):
  1115. ips = db().query(models.IPAddr).filter_by(node=node.id)
  1116. self.assertEqual(ips.count(), len(net_names))
  1117. for ip in ips:
  1118. self.assertIn(ip.network_data.name, net_names)
  1119. def test_get_net_provider_serializer(self):
  1120. serializer = get_serializer_for_cluster(self.cluster)
  1121. self.cluster.network_config.configuration_template = None
  1122. net_serializer = serializer.get_net_provider_serializer(self.cluster)
  1123. self.assertIs(net_serializer, self.general_serializer)
  1124. self.cluster.network_config.configuration_template = \
  1125. self.net_template
  1126. net_serializer = serializer.get_net_provider_serializer(self.cluster)
  1127. self.assertIs(net_serializer, self.template_serializer)
  1128. def test_ip_assignment_according_to_template(self):
  1129. self.create_more_nodes(iface_count=4)
  1130. # according to the template different node roles have different sets of
  1131. # networks
  1132. node_roles_vs_net_names = [
  1133. (['controller'], ['public', 'management', 'fuelweb_admin']),
  1134. (['compute'], ['management', 'fuelweb_admin']),
  1135. (['cinder'], ['storage', 'management', 'fuelweb_admin']),
  1136. (['compute', 'cinder'],
  1137. ['storage', 'management', 'fuelweb_admin']),
  1138. (['controller', 'cinder'],
  1139. ['public', 'storage', 'management', 'fuelweb_admin'])]
  1140. template_meta = self.net_template["adv_net_template"]["default"]
  1141. # wipe out 'storage' template for 'compute' node role to make
  1142. # node roles more distinct
  1143. for node_role, template_list in six.iteritems(
  1144. template_meta["templates_for_node_role"]):
  1145. if node_role == 'compute':
  1146. template_list.remove('storage')
  1147. objects.Cluster.set_network_template(
  1148. self.cluster,
  1149. self.net_template
  1150. )
  1151. cluster_db = objects.Cluster.get_by_uid(self.cluster['id'])
  1152. objects.Cluster.prepare_for_deployment(cluster_db)
  1153. serializer = self._get_serializer(self.cluster)
  1154. serialized_for_astute = serializer.serialize(self.cluster,
  1155. cluster_db.nodes)
  1156. serialized_for_astute = self._handle_facts(
  1157. deployment_info_to_legacy(serialized_for_astute)
  1158. )
  1159. nodes_count = self._get_nodes_count_in_astute_info(self.cluster.nodes)
  1160. self.assertEqual(len(serialized_for_astute), nodes_count)
  1161. for node_data in serialized_for_astute:
  1162. node = objects.Node.get_by_uid(node_data['uid'])
  1163. for node_roles, net_names in node_roles_vs_net_names:
  1164. if node.all_roles == set(node_roles):
  1165. self.check_node_ips_on_certain_networks(node, net_names)
  1166. break
  1167. else:
  1168. self.fail("Unexpected combination of node roles: {0}".format(
  1169. node.all_roles))
  1170. def test_gateway_not_set_for_none_ip(self):
  1171. attrs = copy.deepcopy(self.cluster.attributes.editable)
  1172. attrs['neutron_advanced_configuration']['neutron_dvr']['value'] = True
  1173. resp = self.app.patch(
  1174. reverse(
  1175. 'ClusterAttributesHandler',
  1176. kwargs={'cluster_id': self.cluster.id}),
  1177. params=jsonutils.dumps({'editable': attrs}),
  1178. headers=self.default_headers
  1179. )
  1180. self.assertEqual(200, resp.status_code)
  1181. self.assertTrue(objects.Cluster.neutron_dvr_enabled(self.cluster))
  1182. objects.Cluster.set_network_template(self.cluster, None)
  1183. computes = filter(lambda n: 'compute' in n.roles, self.cluster.nodes)
  1184. self.assertTrue(len(computes) > 0)
  1185. compute = computes[0]
  1186. serializer = get_serializer_for_cluster(self.cluster)
  1187. net_serializer = serializer.get_net_provider_serializer(self.cluster)
  1188. self.assertIs(net_serializer, self.general_serializer)
  1189. nm = objects.Cluster.get_network_manager(self.cluster)
  1190. networks = nm.get_node_networks(compute)
  1191. self.assertFalse(objects.Node.should_have_public_with_ip(compute))
  1192. network_scheme = net_serializer.generate_network_scheme(
  1193. compute, networks)
  1194. self.assertNotIn('gateway', network_scheme['endpoints']['br-ex'])
  1195. self.assertEqual('none', network_scheme['endpoints']['br-ex']['IP'])
  1196. def test_public_iface_added_to_br_ex_in_dvr(self):
  1197. attrs = copy.deepcopy(self.cluster.attributes.editable)
  1198. attrs['neutron_advanced_configuration']['neutron_dvr']['value'] = True
  1199. resp = self.app.patch(
  1200. reverse(
  1201. 'ClusterAttributesHandler',
  1202. kwargs={'cluster_id': self.cluster.id}),
  1203. params=jsonutils.dumps({'editable': attrs}),
  1204. headers=self.default_headers
  1205. )
  1206. self.assertEqual(200, resp.status_code)
  1207. self.assertTrue(objects.Cluster.neutron_dvr_enabled(self.cluster))
  1208. objects.Cluster.set_network_template(self.cluster, None)
  1209. computes = filter(lambda n: 'compute' in n.roles, self.cluster.nodes)
  1210. self.assertTrue(len(computes) > 0)
  1211. compute = computes[0]
  1212. serializer = get_serializer_for_cluster(self.cluster)
  1213. net_serializer = serializer.get_net_provider_serializer(self.cluster)
  1214. self.assertIs(net_serializer, self.general_serializer)
  1215. nm = objects.Cluster.get_network_manager(self.cluster)
  1216. networks = nm.get_node_networks(compute)
  1217. public_net = next((net for net in networks if net['name'] == 'public'),
  1218. None)
  1219. self.assertIsNotNone(public_net)
  1220. self.assertFalse(objects.Node.should_have_public_with_ip(compute))
  1221. network_scheme = net_serializer.generate_network_scheme(
  1222. compute, networks)
  1223. expected = {'action': 'add-port',
  1224. 'bridge': 'br-ex',
  1225. 'name': public_net['dev']}
  1226. self.assertIn(expected, network_scheme['transformations'])
  1227. def test_replacements_in_network_assignments(self):
  1228. node_roles_vs_net_names = [
  1229. (['controller'], ['public', 'management', 'fuelweb_admin']),
  1230. (['compute', 'cinder'],
  1231. ['storage', 'management', 'fuelweb_admin'])]
  1232. template_meta = self.net_template["adv_net_template"]["default"]
  1233. iface_var = template_meta['nic_mapping']['default'].keys()[0]
  1234. ep_with_var = "<% {0} %>.123".format(iface_var)
  1235. template_meta['network_assignments']['storage']['ep'] = ep_with_var
  1236. template_meta['network_scheme']['storage']['endpoints'] = \
  1237. [ep_with_var]
  1238. objects.Cluster.set_network_template(
  1239. self.cluster,
  1240. self.net_template
  1241. )
  1242. cluster_db = objects.Cluster.get_by_uid(self.cluster['id'])
  1243. objects.Cluster.prepare_for_deployment(cluster_db)
  1244. serializer = self._get_serializer(self.cluster)
  1245. serialized_for_astute = serializer.serialize(self.cluster,
  1246. cluster_db.nodes)
  1247. serialized_for_astute = self._handle_facts(
  1248. deployment_info_to_legacy(serialized_for_astute)
  1249. )
  1250. for node_data in serialized_for_astute:
  1251. node = objects.Node.get_by_uid(node_data['uid'])
  1252. for node_roles, net_names in node_roles_vs_net_names:
  1253. if node.all_roles == set(node_roles):
  1254. self.check_node_ips_on_certain_networks(node, net_names)
  1255. break
  1256. else:
  1257. self.fail("Unexpected combination of node roles: {0}".format(
  1258. node.all_roles))
  1259. def test_multiple_node_roles_network_roles(self):
  1260. expected_roles = {
  1261. # controller node
  1262. objects.Node.get_node_fqdn(self.cluster.nodes[0]): {
  1263. 'management': 'br-mgmt',
  1264. 'admin/pxe': 'br-fw-admin',
  1265. 'swift/api': 'br-mgmt',
  1266. 'neutron/api': 'br-mgmt',
  1267. 'sahara/api': 'br-mgmt',
  1268. 'ceilometer/api': 'br-mgmt',
  1269. 'cinder/api': 'br-mgmt',
  1270. 'keystone/api': 'br-mgmt',
  1271. 'glance/api': 'br-mgmt',
  1272. 'heat/api': 'br-mgmt',
  1273. 'nova/api': 'br-mgmt',
  1274. 'murano/api': 'br-mgmt',
  1275. 'horizon': 'br-mgmt',
  1276. 'mgmt/memcache': 'br-mgmt',
  1277. 'mgmt/database': 'br-mgmt',
  1278. 'ceph/public': 'br-mgmt',
  1279. 'public/vip': 'br-ex',
  1280. 'swift/public': 'br-ex',
  1281. 'neutron/floating': 'br-floating',
  1282. 'ceph/radosgw': 'br-ex',
  1283. 'mgmt/messaging': 'br-mgmt',
  1284. 'neutron/mesh': 'br-mgmt',
  1285. 'mgmt/vip': 'br-mgmt',
  1286. 'mgmt/corosync': 'br-mgmt',
  1287. 'mongo/db': 'br-mgmt',
  1288. 'nova/migration': 'br-mgmt',
  1289. 'fw-admin': 'br-fw-admin',
  1290. 'ex': 'br-ex'
  1291. },
  1292. # compute/cinder node
  1293. objects.Node.get_node_fqdn(self.cluster.nodes[1]): {
  1294. 'management': 'br-mgmt',
  1295. 'admin/pxe': 'br-fw-admin',
  1296. 'swift/api': 'br-mgmt',
  1297. 'neutron/api': 'br-mgmt',
  1298. 'sahara/api': 'br-mgmt',
  1299. 'ceilometer/api': 'br-mgmt',
  1300. 'cinder/api': 'br-mgmt',
  1301. 'keystone/api': 'br-mgmt',
  1302. 'glance/api': 'br-mgmt',
  1303. 'heat/api': 'br-mgmt',
  1304. 'nova/api': 'br-mgmt',
  1305. 'murano/api': 'br-mgmt',
  1306. 'horizon': 'br-mgmt',
  1307. 'mgmt/memcache': 'br-mgmt',
  1308. 'mgmt/database': 'br-mgmt',
  1309. 'ceph/public': 'br-mgmt',
  1310. 'cinder/iscsi': 'br-storage',
  1311. 'swift/replication': 'br-storage',
  1312. 'ceph/replication': 'br-storage',
  1313. 'neutron/private': 'br-prv',
  1314. 'mgmt/messaging': 'br-mgmt',
  1315. 'neutron/mesh': 'br-mgmt',
  1316. 'mgmt/vip': 'br-mgmt',
  1317. 'mgmt/corosync': 'br-mgmt',
  1318. 'mongo/db': 'br-mgmt',
  1319. 'nova/migration': 'br-mgmt',
  1320. 'fw-admin': 'br-fw-admin',
  1321. 'storage': 'br-storage'
  1322. }
  1323. }
  1324. for node in self._handle_facts(self.serialized_for_astute):
  1325. roles = node['network_scheme']['roles']
  1326. self.assertEqual(roles, expected_roles[node['fqdn']])
  1327. def test_routes_while_using_multiple_node_groups(self):
  1328. self.env.create_node_group()
  1329. objects.Cluster.prepare_for_deployment(self.cluster)
  1330. serializer = self._get_serializer(self.cluster)
  1331. facts = serializer.serialize(
  1332. self.cluster, self.cluster.nodes)
  1333. facts = self._handle_facts(
  1334. deployment_info_to_legacy(facts)
  1335. )
  1336. for node in facts:
  1337. node_db = objects.Node.get_by_uid(node['uid'])
  1338. is_public = objects.Node.should_have_public(node_db)
  1339. endpoints = node['network_scheme']['endpoints']
  1340. if 'compute' in node_db.roles:
  1341. # private network won't have routes
  1342. self.assertEqual(endpoints['br-prv'], {'IP': 'none'})
  1343. endpoints.pop('br-prv')
  1344. else:
  1345. self.assertNotIn('br-prv', endpoints)
  1346. if is_public:
  1347. # floating network won't have routes
  1348. self.assertEqual(endpoints['br-floating'], {'IP': 'none'})
  1349. endpoints.pop('br-floating')
  1350. for name, descr in six.iteritems(endpoints):
  1351. self.assertTrue({'IP', 'routes'}.issubset(descr))
  1352. # the only route in this case is for Admin network
  1353. # others are shared
  1354. self.assertIn(len(descr['routes']), [0, 1])
  1355. if descr['routes']:
  1356. self.assertEqual(name, 'br-fw-admin')
  1357. for route in descr['routes']:
  1358. self.assertItemsEqual(['net', 'via'], route)
  1359. def test_multiple_node_roles_transformations(self):
  1360. node = self.cluster.nodes[1]
  1361. serializer = get_serializer_for_cluster(self.cluster)
  1362. net_serializer = serializer.get_net_provider_serializer(self.cluster)
  1363. transformations = net_serializer.generate_transformations(node)
  1364. # Two node roles with the same template should only generate one
  1365. # transformation.
  1366. admin_brs = filter(lambda t: t.get('name') == 'br-fw-admin',
  1367. transformations)
  1368. self.assertEqual(1, len(admin_brs))
  1369. # Templates are applied in the order as defined in the template.
  1370. # storage network template is applied after the 4 transformations
  1371. # in common
  1372. self.assertEqual('br-storage', transformations[4]['name'])
  1373. # Ensure all ports connected to br-mgmt happen after the bridge
  1374. # has been created
  1375. port_seen = False
  1376. for tx in transformations:
  1377. if tx.get('name') == 'br-mgmt' and tx['action'] == 'add-br' \
  1378. and port_seen:
  1379. self.fail('Port was added to br-mgmt prior to the bridge '
  1380. 'being created')
  1381. if tx.get('bridge') == 'br-mgmt' and tx['action'] == 'add-port':
  1382. port_seen = True
  1383. def test_multiple_node_roles_network_metadata_attrs(self):
  1384. for node_data in self.serialized_for_astute:
  1385. self.assertItemsEqual(
  1386. node_data['network_metadata'], ['nodes', 'vips'])
  1387. nodes = node_data['network_metadata']['nodes']
  1388. for node_name, node_attrs in nodes.items():
  1389. self.assertItemsEqual(
  1390. node_attrs,
  1391. ['uid', 'fqdn', 'name', 'user_node_name',
  1392. 'swift_zone', 'node_roles', 'network_roles']
  1393. )
  1394. node = objects.Node.get_by_uid(node_attrs['uid'])
  1395. self.assertEqual(objects.Node.get_slave_name(node), node_name)
  1396. self.assertEqual(node_attrs['uid'], node.uid)
  1397. self.assertEqual(node_attrs['fqdn'],
  1398. objects.Node.get_node_fqdn(node))
  1399. self.assertEqual(node_attrs['name'], node_name)
  1400. self.assertEqual(node_attrs['user_node_name'], node.name)
  1401. self.assertEqual(node_attrs['swift_zone'], node.uid)
  1402. def test_multiple_node_roles_network_metadata_roles(self):
  1403. nm = objects.Cluster.get_network_manager(self.cluster)
  1404. ip_by_net = {}
  1405. for node_data in self.serialized_for_astute:
  1406. nodes = node_data['network_metadata']['nodes']
  1407. for node_name, node_attrs in nodes.items():
  1408. node = objects.Node.get_by_uid(node_attrs['uid'])
  1409. networks = nm.get_node_networks(node)
  1410. node_nets = [n['name'] for n in networks]
  1411. for net in node_nets:
  1412. netgroup = nm.get_network_by_netname(net, networks)
  1413. if netgroup.get('ip'):
  1414. ip_by_net[net] = netgroup['ip'].split('/')[0]
  1415. network_roles = {
  1416. 'management': ip_by_net['management'],
  1417. 'admin/pxe': ip_by_net['fuelweb_admin'],
  1418. 'swift/api': ip_by_net['management'],
  1419. 'neutron/api': ip_by_net['management'],
  1420. 'sahara/api': ip_by_net['management'],
  1421. 'ceilometer/api': ip_by_net['management'],
  1422. 'cinder/api': ip_by_net['management'],
  1423. 'keystone/api': ip_by_net['management'],
  1424. 'glance/api': ip_by_net['management'],
  1425. 'heat/api': ip_by_net['management'],
  1426. 'nova/api': ip_by_net['management'],
  1427. 'murano/api': ip_by_net['management'],
  1428. 'horizon': ip_by_net['management'],
  1429. 'mgmt/memcache': ip_by_net['management'],
  1430. 'mgmt/database': ip_by_net['management'],
  1431. 'mgmt/messaging': ip_by_net['management'],
  1432. 'neutron/mesh': ip_by_net['management'],
  1433. 'mgmt/vip': ip_by_net['management'],
  1434. 'mgmt/corosync': ip_by_net['management'],
  1435. 'mongo/db': ip_by_net['management'],
  1436. 'nova/migration': ip_by_net['management'],
  1437. 'ceph/public': ip_by_net['management'],
  1438. 'fw-admin': ip_by_net['fuelweb_admin']
  1439. }
  1440. if node.all_roles == set(['controller']):
  1441. network_roles.update({
  1442. 'public/vip': ip_by_net['public'],
  1443. 'swift/public': ip_by_net['public'],
  1444. 'neutron/floating': None,
  1445. 'ceph/radosgw': ip_by_net['public'],
  1446. 'ex': ip_by_net['public']
  1447. })
  1448. else:
  1449. network_roles.update({
  1450. 'cinder/iscsi': ip_by_net['storage'],
  1451. 'swift/replication': ip_by_net['storage'],
  1452. 'ceph/replication': ip_by_net['storage'],
  1453. 'storage': ip_by_net['storage'],
  1454. 'neutron/private': None
  1455. })
  1456. self.assertEqual(
  1457. node_attrs['network_roles'],
  1458. network_roles
  1459. )
  1460. def test_delete_default_network_group(self):
  1461. net_name = "storage"
  1462. node_group = objects.Cluster.get_default_group(self.cluster)
  1463. # delete one of default network group
  1464. storage_net = objects.NetworkGroup.get_from_node_group_by_name(
  1465. node_group.id, net_name)
  1466. objects.NetworkGroup.delete(storage_net)
  1467. # download default template and fix it
  1468. net_template = self.env.read_fixtures(['network_template_70'])[0]
  1469. template_meta = net_template["adv_net_template"]["default"]
  1470. # wipe out network from template
  1471. del(template_meta["network_assignments"][net_name])
  1472. for k, v in six.iteritems(template_meta["templates_for_node_role"]):
  1473. if net_name in v:
  1474. v.remove(net_name)
  1475. del(template_meta["network_scheme"][net_name])
  1476. # apply updated template to the cluster
  1477. objects.Cluster.set_network_template(
  1478. self.cluster,
  1479. net_template
  1480. )
  1481. serializer = get_serializer_for_cluster(self.cluster)
  1482. net_serializer = serializer.get_net_provider_serializer(self.cluster)
  1483. # serializer should not fail if we delete one of default network
  1484. # what is not used in template
  1485. net_serializer.generate_network_metadata(self.cluster)
  1486. def test_network_not_mapped_to_nics_w_template(self):
  1487. # delete and restore management network to break the default
  1488. # networks to interfaces mapping
  1489. resp = self.app.get(
  1490. reverse('NetworkGroupCollectionHandler',
  1491. kwargs=self.cluster),
  1492. headers=self.default_headers,
  1493. expect_errors=False
  1494. )
  1495. management = None
  1496. for ng in jsonutils.loads(resp.body):
  1497. if ng['name'] == 'management':
  1498. management = ng
  1499. break
  1500. self.app.delete(
  1501. reverse(
  1502. 'NetworkGroupHandler',
  1503. kwargs={'obj_id': management.pop('id')}
  1504. ),
  1505. headers=self.default_headers
  1506. )
  1507. self.app.post(
  1508. reverse('NetworkGroupCollectionHandler'),
  1509. jsonutils.dumps(management),
  1510. headers=self.default_headers,
  1511. expect_errors=False,
  1512. )
  1513. resp = self.app.get(
  1514. reverse('NetworkGroupCollectionHandler',
  1515. kwargs=self.cluster),
  1516. headers=self.default_headers,
  1517. expect_errors=False
  1518. )
  1519. # management network is not mapped to any interfaces in DB now
  1520. cluster_db = self.db.query(models.Cluster).get(self.cluster['id'])
  1521. objects.Cluster.prepare_for_deployment(cluster_db)
  1522. serializer = get_serializer_for_cluster(cluster_db)
  1523. self.serialized_for_astute = serializer(
  1524. AstuteGraph(cluster_db)).serialize(cluster_db, cluster_db.nodes)
  1525. self.serialized_for_astute = deployment_info_to_legacy(
  1526. self.serialized_for_astute)
  1527. network_roles = [
  1528. 'management',
  1529. 'swift/api',
  1530. 'neutron/api',
  1531. 'sahara/api',
  1532. 'ceilometer/api',
  1533. 'cinder/api',
  1534. 'keystone/api',
  1535. 'glance/api',
  1536. 'heat/api',
  1537. 'nova/api',
  1538. 'murano/api',
  1539. 'horizon',
  1540. 'mgmt/memcache',
  1541. 'mgmt/database',
  1542. 'mgmt/messaging',
  1543. 'neutron/mesh',
  1544. 'mgmt/vip',
  1545. 'mgmt/corosync',
  1546. 'mongo/db',
  1547. 'nova/migration'
  1548. ]
  1549. for node_data in self.serialized_for_astute:
  1550. for n in node_data['nodes']:
  1551. n_db = objects.Node.get_by_uid(n['uid'])
  1552. if 'controller' in n_db.roles:
  1553. self.assertIn('internal_address', n)
  1554. self.assertIn('internal_netmask', n)
  1555. self.assertIn('public_address', n)
  1556. self.assertIn('public_netmask', n)
  1557. self.assertNotIn('storage_address', n)
  1558. self.assertNotIn('storage_netmask', n)
  1559. else:
  1560. self.assertIn('internal_address', n)
  1561. self.assertIn('internal_netmask', n)
  1562. self.assertNotIn('public_address', n)
  1563. self.assertNotIn('public_netmask', n)
  1564. self.assertIn('storage_address', n)
  1565. self.assertIn('storage_netmask', n)
  1566. nodes = node_data['network_metadata']['nodes']
  1567. for node_name, node_attrs in nodes.items():
  1568. # IPs must be serialized for these roles which are tied to
  1569. # management network
  1570. for role in network_roles:
  1571. self.assertIsNotNone(node_attrs['network_roles'][role])
  1572. def test_floating_role_belongs_to_public_bridge(self):
  1573. # download default template and assign floating role to public bridge
  1574. net_template = self.env.read_fixtures(['network_template_70'])[0]
  1575. schemes = net_template["adv_net_template"]["default"]["network_scheme"]
  1576. schemes["public"]["roles"]["neutron/floating"] = "br-ex"
  1577. # apply updated template to the cluster
  1578. objects.Cluster.set_network_template(
  1579. self.cluster,
  1580. net_template
  1581. )
  1582. cluster_db = self.db.query(models.Cluster).get(self.cluster['id'])
  1583. nm = objects.Cluster.get_network_manager(self.cluster)
  1584. serializer = self._get_serializer(self.cluster)
  1585. self.serialized_for_astute = serializer.serialize(self.cluster,
  1586. cluster_db.nodes)
  1587. self.serialized_for_astute = self._handle_facts(
  1588. deployment_info_to_legacy(self.serialized_for_astute)
  1589. )
  1590. for node_data in self.serialized_for_astute:
  1591. node = objects.Node.get_by_uid(node_data['uid'])
  1592. # check nodes with assigned public ip
  1593. if objects.Node.should_have_public_with_ip(node):
  1594. nets = nm.get_node_networks(node)
  1595. ng = nm.get_network_by_netname('public', nets)
  1596. endpoints = node_data["network_scheme"]["endpoints"]
  1597. self.assertEqual(endpoints["br-ex"]["IP"], [ng.get('ip')])
  1598. def test_get_node_network_mapping(self):
  1599. self.create_more_nodes()
  1600. nm = objects.Cluster.get_network_manager(self.cluster)
  1601. # according to the template different node roles have different sets of
  1602. # networks (endpoints and network names here)
  1603. node_roles_vs_networks = [
  1604. (['controller'], [('public', 'br-ex'),
  1605. ('management', 'br-mgmt'),
  1606. ('fuelweb_admin', 'br-fw-admin')]),
  1607. (['compute'], [('private', 'br-prv'),
  1608. ('storage', 'br-storage'),
  1609. ('management', 'br-mgmt'),
  1610. ('fuelweb_admin', 'br-fw-admin')]),
  1611. (['cinder'], [('storage', 'br-storage'),
  1612. ('management', 'br-mgmt'),
  1613. ('fuelweb_admin', 'br-fw-admin')]),
  1614. (['compute', 'cinder'], [('private', 'br-prv'),
  1615. ('storage', 'br-storage'),
  1616. ('management', 'br-mgmt'),
  1617. ('fuelweb_admin', 'br-fw-admin')]),
  1618. (['controller', 'cinder'], [('public', 'br-ex'),
  1619. ('storage', 'br-storage'),
  1620. ('management', 'br-mgmt'),
  1621. ('fuelweb_admin', 'br-fw-admin')])]
  1622. for node in self.env.nodes:
  1623. net_names_and_eps = nm.get_node_network_mapping(node)
  1624. for node_roles, networks in node_roles_vs_networks:
  1625. if node.all_roles == set(node_roles):
  1626. self.assertItemsEqual(net_names_and_eps, networks)
  1627. def test_get_network_name_to_endpoint_mappings(self):
  1628. nm = objects.Cluster.get_network_manager(self.cluster)
  1629. group_id = objects.Cluster.get_default_group(self.cluster).id
  1630. self.assertEqual(
  1631. nm.get_network_name_to_endpoint_mappings(self.cluster),
  1632. {
  1633. group_id: {
  1634. 'br-ex': 'public',
  1635. 'br-mgmt': 'management',
  1636. 'br-fw-admin': 'fuelweb_admin',
  1637. 'br-prv': 'private',
  1638. 'br-storage': 'storage',
  1639. }
  1640. }
  1641. )
  1642. def test_assign_ips_in_node_group(self):
  1643. mgmt = self.db.query(models.NetworkGroup).\
  1644. filter_by(name='management').first()
  1645. ips_2_db = self.db.query(models.IPAddr.ip_addr).\
  1646. filter(models.IPAddr.network == mgmt.id,
  1647. models.IPAddr.node.isnot(None))
  1648. # two nodes now
  1649. self.assertEqual(ips_2_db.count(), 2)
  1650. ips_2_str = set(ips_2_db)
  1651. # add three nodes
  1652. self.create_more_nodes()
  1653. node_ids = set(n.id for n in self.env.nodes)
  1654. ip_ranges = [netaddr.IPRange(r.first, r.last)
  1655. for r in mgmt.ip_ranges]
  1656. nm = objects.Cluster.get_network_manager(self.cluster)
  1657. nm.assign_ips_in_node_group(
  1658. mgmt.id, mgmt.name, node_ids, ip_ranges)
  1659. ips_5_db = self.db.query(models.IPAddr.ip_addr). \
  1660. filter(models.IPAddr.network == mgmt.id,
  1661. models.IPAddr.node.isnot(None))
  1662. self.assertEqual(ips_5_db.count(), 5)
  1663. ips_5_str = set(ips_5_db)
  1664. # old IPs are the same
  1665. self.assertEqual(len(ips_5_str.difference(ips_2_str)), 3)
  1666. def check_vendor_specific_is_not_set(self, use_net_template=False):
  1667. node = self.env.create_node(
  1668. cluster_id=self.cluster.id,
  1669. roles=['controller'], primary_tags=['controller']
  1670. )
  1671. objects.Cluster.set_network_template(
  1672. self.cluster,
  1673. self.net_template if use_net_template else None)
  1674. objects.Cluster.prepare_for_deployment(self.cluster)
  1675. serializer = get_serializer_for_cluster(self.cluster)
  1676. net_serializer = serializer.get_net_provider_serializer(self.cluster)
  1677. nm = objects.Cluster.get_network_manager(self.cluster)
  1678. networks = nm.get_node_networks(node)
  1679. endpoints = net_serializer.generate_network_scheme(
  1680. node, networks)['endpoints']
  1681. for name in endpoints:
  1682. self.assertNotIn('vendor_specific', endpoints[name])
  1683. def test_vendor_specific_in_deployment_serializer(self):
  1684. self.check_vendor_specific_is_not_set()
  1685. def test_vendor_specific_in_template_serializer(self):
  1686. self.check_vendor_specific_is_not_set(use_net_template=True)
  1687. class TestCustomNetGroupIpAllocation(BaseDeploymentSerializer):
  1688. env_version = '2015.1.0-7.0'
  1689. def setUp(self):
  1690. super(TestCustomNetGroupIpAllocation, self).setUp()
  1691. self.cluster = self.create_env()
  1692. self.cluster_db = self.env.clusters[-1]
  1693. def create_env(self):
  1694. return self.env.create(
  1695. release_kwargs={'version': self.env_version},
  1696. cluster_kwargs={
  1697. 'api': False,
  1698. 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
  1699. 'net_segment_type': consts.NEUTRON_SEGMENT_TYPES.gre},
  1700. nodes_kwargs=[
  1701. {'roles': ['controller']},
  1702. {'roles': ['compute']},
  1703. ])
  1704. def test_ip_allocation(self):
  1705. self.env._create_network_group(
  1706. cluster=self.cluster, name='test', cidr='172.16.122.0/24',
  1707. meta={'notation': 'ip_ranges',
  1708. 'ip_range': ['172.16.122.2', '172.16.122.255']})
  1709. objects.Cluster.prepare_for_deployment(self.cluster_db)
  1710. ip_column_name = models.IPAddr.ip_addr.label('ip')
  1711. ip_addrs_count = db().query(models.IPAddr).filter(
  1712. "inet '172.16.122/24' >> {0}".format(ip_column_name)
  1713. ).count()
  1714. self.assertEqual(ip_addrs_count, 2)
  1715. class TestSerializer70Mixin(object):
  1716. env_version = "2015.1.0-7.0"
  1717. class TestNovaOrchestratorSerializer70(TestSerializer70Mixin,
  1718. TestNovaOrchestratorSerializer,
  1719. PrepareDataMixin):
  1720. def create_env(self, mode, network_manager='FlatDHCPManager'):
  1721. node_args = [
  1722. {'roles': ['controller', 'cinder'], 'pending_addition': True},
  1723. {'roles': ['compute', 'cinder'], 'pending_addition': True},
  1724. {'roles': ['compute'], 'pending_addition': True},
  1725. {'roles': ['mongo'], 'pending_addition': True},
  1726. {'roles': [], 'pending_roles': ['cinder'],
  1727. 'pending_addition': True}]
  1728. release = self.patch_net_roles_for_release()
  1729. cluster = self.env.create(
  1730. cluster_kwargs={
  1731. 'release_id': release.id,
  1732. 'mode': mode,
  1733. 'net_manager': network_manager,
  1734. 'net_provider': consts.CLUSTER_NET_PROVIDERS.nova_network},
  1735. nodes_kwargs=node_args)
  1736. cluster_db = self.db.query(models.Cluster).get(cluster['id'])
  1737. objects.Cluster.prepare_for_deployment(cluster_db)
  1738. self.db.flush()
  1739. return cluster_db
  1740. class TestSerializeInterfaceDriversData70(TestSerializer70Mixin,
  1741. TestSerializeInterfaceDriversData):
  1742. pass
  1743. class TestDeploymentHASerializer70(TestSerializer70Mixin,
  1744. TestDeploymentHASerializer61):
  1745. pass