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_network_manager.py 70KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949
  1. # -*- coding: utf-8 -*-
  2. # Copyright 2013 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. from copy import deepcopy
  16. import mock
  17. from mock import Mock
  18. from mock import patch
  19. from netaddr import IPAddress
  20. from netaddr import IPNetwork
  21. from netaddr import IPRange
  22. import six
  23. from sqlalchemy import not_
  24. import yaml
  25. import nailgun
  26. from nailgun import consts
  27. from nailgun import errors
  28. from nailgun.extensions.network_manager.objects.serializers \
  29. import network_configuration
  30. from nailgun import objects
  31. from nailgun.db.sqlalchemy.models import IPAddr
  32. from nailgun.db.sqlalchemy.models import IPAddrRange
  33. from nailgun.db.sqlalchemy.models import NetworkGroup
  34. from nailgun.db.sqlalchemy.models import Node
  35. from nailgun.db.sqlalchemy.models import NodeNICInterface
  36. from nailgun.db.sqlalchemy.models import Release
  37. from nailgun.extensions.network_manager.managers.neutron import NeutronManager
  38. from nailgun.extensions.network_manager.managers.neutron import \
  39. NeutronManager70
  40. from nailgun.extensions.network_manager.managers.neutron import \
  41. NeutronManager80
  42. from nailgun.extensions.network_manager.managers.nova_network import \
  43. NovaNetworkManager
  44. from nailgun.extensions.network_manager.managers.nova_network import \
  45. NovaNetworkManager70
  46. from nailgun.logger import logger
  47. from nailgun.test.base import BaseIntegrationTest
  48. from nailgun.test.base import mock_rpc
  49. def _convert_vips(vips):
  50. """Returns VIPs in a form that is easy to compare on equality.
  51. This function is used in tests that are related to getting and
  52. assigning VIPs.
  53. :param vips: A of dicts that represents VIPs.
  54. :returns: A two level dict with the next keys mapping
  55. network_name:vip_name = ip_addr.
  56. """
  57. vips = deepcopy(vips)
  58. for net in vips:
  59. for vip_name, vip in vips[net].items():
  60. vips[net][vip_name] = vip['ip_addr']
  61. return vips
  62. def _set_name(vips):
  63. """Return VIPs mapped to names of network groups.
  64. :param vips: A dict of VIPs mapped to IDs of network groups.
  65. :returns: A dict of VIPs mapped to names of network groups.
  66. """
  67. return {objects.NetworkGroup.get_by_uid(id).name: vip
  68. for id, vip in six.iteritems(vips)}
  69. def _set_id(vips, cluster):
  70. """Return VIPs mapped to IDs of network groups.
  71. :param vips: A dict of VIPs mapped to names of network groups.
  72. :param cluster: Is an instance of :class:`models.Cluster`.
  73. :returns: A dict of VIPs mapped to IDs of network groups.
  74. """
  75. return {ng.id: vips[ng.name]
  76. for ng in cluster.network_groups if ng.name in vips}
  77. def _make_vip(**kwargs):
  78. """Represents a VIP as a dict with some default values."""
  79. data = {
  80. 'id': 1,
  81. 'ip_addr': '0.0.0.0',
  82. 'network': None,
  83. 'vip_name': 'test',
  84. 'vip_namespace': consts.NETWORK_VIP_NAMES_V6_1.vrouter,
  85. 'is_user_defined': False,
  86. 'network_data': None,
  87. 'node_data': None,
  88. }
  89. data.update(kwargs)
  90. return data
  91. class TestNetworkManager(BaseIntegrationTest):
  92. @mock_rpc()
  93. def test_assign_ips(self):
  94. cluster = self.env.create(
  95. cluster_kwargs={},
  96. nodes_kwargs=[
  97. {"pending_addition": True, "api": True},
  98. {"pending_addition": True, "api": True}
  99. ]
  100. )
  101. nailgun.task.task.Cobbler = Mock()
  102. self.env.network_manager.assign_ips(
  103. self.env.clusters[-1],
  104. self.env.nodes,
  105. consts.NETWORKS.management
  106. )
  107. management_net = self.db.query(NetworkGroup).filter(
  108. NetworkGroup.group_id ==
  109. objects.Cluster.get_default_group(cluster).id
  110. ).filter_by(
  111. name=consts.NETWORKS.management
  112. ).first()
  113. assigned_ips = []
  114. for node in self.env.nodes:
  115. ips = self.db.query(IPAddr).\
  116. filter_by(node=node.id).\
  117. filter_by(network=management_net.id).all()
  118. self.assertEqual(1, len(ips))
  119. self.assertEqual(
  120. True,
  121. self.env.network_manager.check_ip_belongs_to_net(
  122. ips[0].ip_addr,
  123. management_net
  124. )
  125. )
  126. assigned_ips.append(ips[0].ip_addr)
  127. # check for uniqueness of IPs:
  128. self.assertEqual(len(assigned_ips), len(list(set(assigned_ips))))
  129. # check it doesn't contain broadcast and other special IPs
  130. net_ip = IPNetwork(management_net.cidr)[0]
  131. gateway = management_net.gateway
  132. broadcast = IPNetwork(management_net.cidr)[-1]
  133. self.assertEqual(False, net_ip in assigned_ips)
  134. self.assertEqual(False, gateway in assigned_ips)
  135. self.assertEqual(False, broadcast in assigned_ips)
  136. def test_get_free_ips_from_ranges(self):
  137. ranges = [IPRange("192.168.33.2", "192.168.33.222")]
  138. ips = self.env.network_manager.get_free_ips_from_ranges(
  139. consts.NETWORKS.management, ranges, set(), 3
  140. )
  141. self.assertItemsEqual(["192.168.33.2", "192.168.33.3", "192.168.33.4"],
  142. ips)
  143. self.db.add(IPAddr(ip_addr="192.168.33.3"))
  144. self.db.flush()
  145. ips = self.env.network_manager.get_free_ips_from_ranges(
  146. consts.NETWORKS.management, ranges, set(), 3
  147. )
  148. self.assertItemsEqual(["192.168.33.2", "192.168.33.4", "192.168.33.5"],
  149. ips)
  150. ips = self.env.network_manager.get_free_ips_from_ranges(
  151. consts.NETWORKS.management, ranges,
  152. set(["192.168.33.5", "192.168.33.8"]), 7
  153. )
  154. self.assertItemsEqual(
  155. ["192.168.33.2", "192.168.33.4", "192.168.33.6", "192.168.33.7",
  156. "192.168.33.9", "192.168.33.10", "192.168.33.11"],
  157. ips)
  158. @mock_rpc()
  159. def test_assign_ips_idempotent(self):
  160. self.env.create(
  161. cluster_kwargs={},
  162. nodes_kwargs=[
  163. {
  164. "pending_addition": True,
  165. "api": True,
  166. "status": consts.NODE_STATUSES.discover,
  167. }
  168. ]
  169. )
  170. node_db = self.env.nodes[0]
  171. self.env.network_manager.assign_ips(
  172. self.env.clusters[-1],
  173. [node_db],
  174. consts.NETWORKS.management
  175. )
  176. self.env.network_manager.assign_ips(
  177. self.env.clusters[-1],
  178. [node_db],
  179. consts.NETWORKS.management
  180. )
  181. self.db.refresh(node_db)
  182. self.assertEqual(
  183. len(
  184. filter(
  185. lambda n: n['name'] == consts.NETWORKS.management,
  186. self.env.network_manager.get_node_networks(
  187. node_db
  188. )
  189. )
  190. ),
  191. 1
  192. )
  193. def create_env_w_controller(self):
  194. # environment must be created with nodes in order
  195. # to VIP be assigned (without nodes there will be no
  196. # node group which network VIP must be allocated in)
  197. return self.env.create(
  198. cluster_kwargs={'api': False},
  199. nodes_kwargs=[{'roles': ['controller']}]
  200. )
  201. def test_assign_vip_is_idempotent(self):
  202. cluster = self.create_env_w_controller()
  203. nodegroup = objects.Cluster.get_controllers_node_group(cluster)
  204. vip = self.env.network_manager.assign_vip(
  205. nodegroup,
  206. consts.NETWORKS.management,
  207. consts.NETWORK_VIP_NAMES_V6_1.haproxy
  208. )
  209. vip2 = self.env.network_manager.assign_vip(
  210. nodegroup,
  211. consts.NETWORKS.management,
  212. consts.NETWORK_VIP_NAMES_V6_1.haproxy
  213. )
  214. self.assertEqual(vip, vip2)
  215. def test_assign_vip_for_admin_network(self):
  216. cluster = self.create_env_w_controller()
  217. nodegroup = objects.Cluster.get_controllers_node_group(cluster)
  218. self.env.network_manager.assign_vip(
  219. nodegroup,
  220. consts.NETWORKS.fuelweb_admin,
  221. consts.NETWORK_VIP_NAMES_V6_1.haproxy)
  222. def test_assign_vip_throws_not_found_exception(self):
  223. cluster = self.create_env_w_controller()
  224. nodegroup = objects.Cluster.get_controllers_node_group(cluster)
  225. self.assertRaisesRegexp(
  226. errors.CanNotFindNetworkForNodeGroup,
  227. "Network 'non-existing-network' for nodegroup='[\w-]+' not found.",
  228. self.env.network_manager.assign_vip,
  229. nodegroup,
  230. 'non-existing-network',
  231. consts.NETWORK_VIP_NAMES_V6_1.haproxy
  232. )
  233. def change_ranges_and_update_vip(self, vip):
  234. ip_range = vip.network_data.ip_ranges[0]
  235. new_first = '172.16.0.10'
  236. new_last = '172.16.0.20'
  237. # VIP address is outside of the new range
  238. new_vip_addr = '172.16.0.21'
  239. update_data = {
  240. 'first': new_first,
  241. 'last': new_last
  242. }
  243. objects.NailgunObject.update(ip_range, update_data)
  244. update_data = {
  245. 'ip_addr': new_vip_addr,
  246. 'is_user_defined': True
  247. }
  248. objects.IPAddr.update(vip, update_data)
  249. def get_cluster_and_vip(self):
  250. cluster = self.create_env_w_controller()
  251. self.env.network_manager.assign_vips_for_net_groups(cluster)
  252. vip = objects.IPAddrCollection.get_by_cluster_id(cluster.id).first()
  253. return cluster, vip
  254. def test_assign_vip_return_user_defined_wo_namespace_outside_net(self):
  255. cluster, vip = self.get_cluster_and_vip()
  256. self.change_ranges_and_update_vip(vip)
  257. ip_before = vip.ip_addr
  258. self.env.network_manager.assign_vips_for_net_groups(cluster)
  259. vips_after = self.env.network_manager.get_assigned_vips(cluster)
  260. needed_vip_ip = [
  261. vip_info for network, vip_info in six.iteritems(vips_after)
  262. if vip.network_data.id == network and vip.vip_name in vip_info
  263. ][0][vip.vip_name]['ip_addr']
  264. self.assertEqual(needed_vip_ip, ip_before)
  265. def test_assign_vip_throws_out_of_ips_error(self):
  266. cluster = self.create_env_w_controller()
  267. pub_net = objects.NetworkGroup.get_by_cluster(cluster.id).filter(
  268. objects.NetworkGroup.model.name == consts.NETWORKS.public
  269. ).first()
  270. self.db.query(IPAddrRange).filter_by(
  271. network_group_id=pub_net.id
  272. ).delete()
  273. full_range = IPAddrRange(
  274. first='172.16.10.2',
  275. last='172.16.10.2',
  276. network_group_id=pub_net.id
  277. )
  278. self.db.add(full_range)
  279. self.db.flush()
  280. self.assertRaises(
  281. errors.OutOfIPs,
  282. self.env.network_manager.assign_vips_for_net_groups,
  283. cluster
  284. )
  285. def test_vip_for_admin_network_is_free(self):
  286. admin_net_id = objects.NetworkGroup.get_admin_network_group().id
  287. self.db.query(IPAddrRange).filter_by(
  288. network_group_id=admin_net_id
  289. ).delete()
  290. admin_range = IPAddrRange(
  291. first='10.20.0.3',
  292. last='10.20.0.254',
  293. network_group_id=admin_net_id
  294. )
  295. self.db.add(admin_range)
  296. self.db.flush()
  297. cluster = self.env.create(
  298. cluster_kwargs={"api": False},
  299. nodes_kwargs=[
  300. {"pending_addition": True, "api": True, "ip": "10.20.0.3"},
  301. {"pending_addition": True, "api": True, "ip": "10.20.0.4"},
  302. {"pending_addition": True, "api": True, "ip": "10.20.0.5"},
  303. ]
  304. )
  305. # These nodes are "bootstrapped". They have an IP but don't yet
  306. # belong to a cluster. Because fuelweb_admin is a shared network
  307. # these IPs should not be used for a VIP in any cluster.
  308. self.env.create_node(ip="10.20.0.6")
  309. self.env.create_node(ip="10.20.0.7")
  310. self.env.create_node(ip="10.20.0.8")
  311. self.env.network_manager.assign_admin_ips(cluster.nodes)
  312. admin_vip = self.env.network_manager.assign_vip(
  313. objects.Cluster.get_controllers_node_group(cluster),
  314. consts.NETWORKS.fuelweb_admin,
  315. consts.NETWORK_VIP_NAMES_V6_1.haproxy
  316. )
  317. node_ips = [n.ip for n in self.env.nodes]
  318. self.assertNotIn(admin_vip, node_ips)
  319. def test_get_node_networks_for_vlan_manager(self):
  320. cluster = self.env.create(
  321. cluster_kwargs={
  322. 'net_provider': consts.CLUSTER_NET_PROVIDERS.nova_network},
  323. nodes_kwargs=[
  324. {"pending_addition": True},
  325. ]
  326. )
  327. networks_data = {
  328. 'networking_parameters': {
  329. 'net_manager': consts.NOVA_NET_MANAGERS.VlanManager,
  330. },
  331. }
  332. resp = self.env.nova_networks_put(cluster['id'], networks_data)
  333. self.assertEqual(resp.status_code, 200)
  334. network_data = self.env.network_manager.get_node_networks(
  335. self.env.nodes[0]
  336. )
  337. self.assertEqual(len(network_data), 5)
  338. fixed_nets = filter(lambda net: net['name'] == consts.NETWORKS.fixed,
  339. network_data)
  340. self.assertEqual(len(fixed_nets), 1)
  341. def test_assign_admin_ip_multiple_groups(self):
  342. self.env.create(
  343. cluster_kwargs={
  344. 'api': False,
  345. 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
  346. 'net_segment_type': consts.NEUTRON_SEGMENT_TYPES.gre,
  347. },
  348. nodes_kwargs=[{}, {}]
  349. )
  350. node_group = self.env.create_node_group()
  351. self.env.nodes[1].group_id = node_group.json_body['id']
  352. self.db().flush()
  353. admin_net =\
  354. objects.NetworkGroup.get_admin_network_group(
  355. self.env.nodes[1]
  356. )
  357. mock_range = IPAddrRange(
  358. first='9.9.9.1',
  359. last='9.9.9.254',
  360. network_group_id=admin_net.id
  361. )
  362. self.db.add(mock_range)
  363. self.db.flush()
  364. self.env.network_manager.assign_admin_ips(self.env.nodes)
  365. for n in self.env.nodes:
  366. admin_net = objects.NetworkGroup.get_admin_network_group(n)
  367. ip = self.db.query(IPAddr).\
  368. filter_by(network=admin_net.id).\
  369. filter_by(node=n.id).first()
  370. self.assertIn(
  371. IPAddress(ip.ip_addr),
  372. IPNetwork(admin_net.cidr)
  373. )
  374. def test_get_admin_network_group(self):
  375. self.env.create(
  376. cluster_kwargs={
  377. 'api': False,
  378. 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
  379. 'net_segment_type': consts.NEUTRON_SEGMENT_TYPES.gre,
  380. },
  381. nodes_kwargs=[{}, {}]
  382. )
  383. node0 = self.env.nodes[0]
  384. node1 = self.env.nodes[1]
  385. node_group = self.env.create_node_group()
  386. node1.group_id = node_group.json_body['id']
  387. self.db().flush()
  388. admin_net1 = objects.NetworkGroup.get_admin_network_group(node=node0)
  389. admin_net2 = objects.NetworkGroup.get_admin_network_group(node=node1)
  390. self.assertEqual(admin_net1.group_id, None)
  391. self.assertEqual(admin_net2.group_id, node_group.json_body['id'])
  392. def test_get_admin_network_group_with_admin_net(self):
  393. """Test for default_admin_net parameter.
  394. Check if this parameter is provided,
  395. get_default_admin_network is not called and
  396. get_admin_network_group returns the same values if
  397. this parameter specified or not.
  398. """
  399. self.env.create(
  400. cluster_kwargs={
  401. 'api': False,
  402. 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
  403. 'net_segment_type': consts.NEUTRON_SEGMENT_TYPES.gre,
  404. },
  405. nodes_kwargs=[{}, {}]
  406. )
  407. node0 = self.env.nodes[0]
  408. node1 = self.env.nodes[1]
  409. node_group = self.env.create_node_group()
  410. node1.group_id = node_group.json_body['id']
  411. self.db().flush()
  412. default_admin_net = objects.NetworkGroup.get_default_admin_network()
  413. self.assertIsNotNone(default_admin_net)
  414. with patch.object(objects.NetworkGroup,
  415. 'get_default_admin_network') as get_mock:
  416. get_mock.return_value = default_admin_net
  417. admin_net1 = objects.NetworkGroup.get_admin_network_group(node0)
  418. self.assertEqual(int(get_mock.call_count), 1)
  419. admin_net2 = objects.NetworkGroup.get_admin_network_group(node1)
  420. self.assertEqual(admin_net1, default_admin_net)
  421. self.assertNotEqual(admin_net2, default_admin_net)
  422. self.assertEqual(int(get_mock.call_count), 1)
  423. with patch.object(objects.NetworkGroup,
  424. 'get_default_admin_network') as get_mock:
  425. admin_net1 = objects.NetworkGroup.get_admin_network_group(
  426. node0, default_admin_net)
  427. self.assertEqual(admin_net1, default_admin_net)
  428. self.assertEqual(get_mock.call_count, 0)
  429. def test_assign_ip_multiple_groups(self):
  430. self.env.create(
  431. cluster_kwargs={
  432. 'api': False,
  433. 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
  434. 'net_segment_type': consts.NEUTRON_SEGMENT_TYPES.gre
  435. },
  436. nodes_kwargs=[{}, {}]
  437. )
  438. node_group = self.env.create_node_group()
  439. self.env.nodes[1].group_id = node_group.json_body['id']
  440. mgmt_net = self.db.query(NetworkGroup).filter_by(
  441. group_id=node_group.json_body['id'],
  442. name=consts.NETWORKS.management
  443. ).first()
  444. # set new range for management network of non-default node group
  445. mgmt_net.cidr = '7.7.7.0/24'
  446. mgmt_net.ip_ranges = [IPAddrRange(first='7.7.7.1', last='7.7.7.254')]
  447. self.db().flush()
  448. self.env.network_manager.assign_ips(
  449. self.env.clusters[-1],
  450. self.env.nodes,
  451. consts.NETWORKS.management
  452. )
  453. for node in self.env.nodes:
  454. mgmt_net = self.db.query(NetworkGroup).\
  455. filter_by(
  456. group_id=node.group_id,
  457. name=consts.NETWORKS.management).first()
  458. ip = self.db.query(IPAddr).\
  459. filter_by(network=mgmt_net.id, node=node.id).first()
  460. self.assertIn(IPAddress(ip.ip_addr), IPNetwork(mgmt_net.cidr))
  461. def test_ipaddr_joinedload_relations(self):
  462. self.env.create(
  463. cluster_kwargs={},
  464. nodes_kwargs=[
  465. {"pending_addition": True, "api": True},
  466. {"pending_addition": True, "api": True}
  467. ]
  468. )
  469. self.env.network_manager.assign_ips(
  470. self.env.clusters[-1],
  471. self.env.nodes,
  472. consts.NETWORKS.management
  473. )
  474. ips = []
  475. for node in self.env.nodes:
  476. # if node_id is not passed to the method vips also will be
  477. # returned as they are assigned at the cretion of a cluster
  478. ip = objects.IPAddr.get_ips_except_admin(
  479. node=node, include_network_data=True
  480. )[0]
  481. ips.append(ip)
  482. self.assertEqual(len(ips), 2)
  483. self.assertIsInstance(ips[0].node_data, Node)
  484. self.assertIsInstance(ips[0].network_data, NetworkGroup)
  485. def test_nets_empty_list_if_node_does_not_belong_to_cluster(self):
  486. node = self.env.create_node(api=False)
  487. network_data = self.env.network_manager.get_node_networks(node)
  488. self.assertEqual(network_data, [])
  489. def test_assign_admin_ips(self):
  490. node = self.env.create_node()
  491. self.env.network_manager.assign_admin_ips([node])
  492. admin_ng_id = objects.NetworkGroup.get_admin_network_group().id
  493. admin_network_range = self.db.query(IPAddrRange).\
  494. filter_by(network_group_id=admin_ng_id).all()[0]
  495. admin_ip = self.db.query(IPAddr).\
  496. filter_by(node=node.id).\
  497. filter_by(network=admin_ng_id).all()
  498. self.assertEqual(len(admin_ip), 1)
  499. self.assertIn(
  500. IPAddress(admin_ip[0].ip_addr),
  501. IPRange(admin_network_range.first, admin_network_range.last))
  502. def test_assign_admin_ips_idempotent(self):
  503. node = self.env.create_node()
  504. self.env.network_manager.assign_admin_ips([node])
  505. admin_net_id = objects.NetworkGroup.get_admin_network_group().id
  506. admin_ips = set([i.ip_addr for i in self.db.query(IPAddr).
  507. filter_by(node=node.id).
  508. filter_by(network=admin_net_id).all()])
  509. self.env.network_manager.assign_admin_ips([node])
  510. admin_ips2 = set([i.ip_addr for i in self.db.query(IPAddr).
  511. filter_by(node=node.id).
  512. filter_by(network=admin_net_id).all()])
  513. self.assertEqual(admin_ips, admin_ips2)
  514. def test_assign_admin_ips_only_one(self):
  515. for ipaddr in self.db.query(IPAddrRange).all():
  516. self.db.delete(ipaddr)
  517. admin_net_id = objects.NetworkGroup.get_admin_network_group().id
  518. mock_range = IPAddrRange(
  519. first='10.0.0.1',
  520. last='10.0.0.1',
  521. network_group_id=admin_net_id
  522. )
  523. self.db.add(mock_range)
  524. self.db.flush()
  525. node = self.env.create_node()
  526. self.env.network_manager.assign_admin_ips([node])
  527. admin_net_id = objects.NetworkGroup.get_admin_network_group().id
  528. admin_ips = self.db.query(IPAddr).\
  529. filter_by(node=node.id).\
  530. filter_by(network=admin_net_id).all()
  531. self.assertEqual(len(admin_ips), 1)
  532. self.assertEqual(admin_ips[0].ip_addr, '10.0.0.1')
  533. def test_assign_admin_ips_for_many_nodes(self):
  534. for ipaddr in self.db.query(IPAddrRange).all():
  535. self.db.delete(ipaddr)
  536. admin_net_id = objects.NetworkGroup.get_admin_network_group().id
  537. mock_range = IPAddrRange(
  538. first='10.0.0.1',
  539. last='10.0.0.2',
  540. network_group_id=admin_net_id
  541. )
  542. self.db.add(mock_range)
  543. self.db.flush()
  544. n1 = self.env.create_node()
  545. n2 = self.env.create_node()
  546. nc = [n1, n2]
  547. self.env.network_manager.assign_admin_ips(nc)
  548. admin_net_id = objects.NetworkGroup.get_admin_network_group().id
  549. for node, ip in zip(nc, ['10.0.0.1', '10.0.0.2']):
  550. admin_ips = self.db.query(IPAddr).\
  551. filter_by(node=node.id).\
  552. filter_by(network=admin_net_id).all()
  553. self.assertEqual(len(admin_ips), 1)
  554. self.assertEqual(admin_ips[0].ip_addr, ip)
  555. def test_get_node_networks_ips(self):
  556. cluster = self.env.create_cluster(api=False)
  557. node = self.env.create_node(cluster_id=cluster.id)
  558. self.env.network_manager.assign_ips(
  559. cluster, [node], consts.NETWORKS.management
  560. )
  561. node_net_ips = dict(
  562. (ip.network_data.name, ip.ip_addr) for ip in node.ip_addrs
  563. )
  564. self.assertEquals(node_net_ips,
  565. objects.IPAddr.get_networks_ips_dict(node))
  566. def test_get_admin_ip_for_node(self):
  567. cluster = self.env.create(api=False)
  568. node_data = self.env.create_node(cluster_id=cluster.id)
  569. node = self.env.nodes[-1]
  570. # No admin ip assigned
  571. self.env.network_manager.assign_ips(
  572. cluster, [node_data], consts.NETWORKS.management
  573. )
  574. self.assertIsNone(
  575. self.env.network_manager.get_admin_ip_for_node(node))
  576. # Admin ip assigned
  577. self.env.network_manager.assign_ips(
  578. cluster, [node_data], consts.NETWORKS.fuelweb_admin
  579. )
  580. self.env.db.refresh(node)
  581. self.assertIsNotNone(
  582. self.env.network_manager.get_admin_ip_for_node(node))
  583. def test_set_node_networks_ips(self):
  584. cluster = self.env.create_cluster(api=False)
  585. node = self.env.create_node(cluster_id=cluster.id)
  586. self.env.network_manager.assign_ips(
  587. cluster, [node], consts.NETWORKS.management
  588. )
  589. node_net_ips = \
  590. dict((net.name, self.env.network_manager.get_free_ips(net)[0])
  591. for net in node.networks)
  592. objects.IPAddr.set_networks_ips(node, node_net_ips)
  593. self.assertEquals(node_net_ips,
  594. objects.IPAddr.get_networks_ips_dict(node))
  595. def test_set_netgroups_ids(self):
  596. cluster = self.env.create_cluster(api=False)
  597. node = self.env.create_node(cluster_id=cluster.id)
  598. self.env.network_manager.assign_ips(
  599. cluster, [node], consts.NETWORKS.management
  600. )
  601. admin_ng_id = objects.NetworkGroup.get_admin_network_group(node).id
  602. node_ng_ids = dict((ip.network, admin_ng_id) for ip in node.ip_addrs)
  603. objects.Node.set_netgroups_ids(node, node_ng_ids)
  604. for ip in node.ip_addrs:
  605. self.assertEquals(admin_ng_id, ip.network)
  606. def test_set_nic_assignment_netgroups_ids(self):
  607. cluster = self.env.create_cluster(api=False)
  608. node = self.env.create_node(cluster_id=cluster.id)
  609. self.env.network_manager.assign_ips(
  610. cluster, [node], consts.NETWORKS.management
  611. )
  612. admin_ng_id = \
  613. objects.NetworkGroup.get_admin_network_group(node).id
  614. nic_ng_ids = \
  615. dict((net.id, admin_ng_id) for iface in node.nic_interfaces
  616. for net in iface.assigned_networks_list)
  617. objects.Node.set_nic_assignment_netgroups_ids(node, nic_ng_ids)
  618. self.db.refresh(node)
  619. for iface in node.nic_interfaces:
  620. for net in iface.assigned_networks_list:
  621. self.assertEquals(admin_ng_id, net.id)
  622. def test_set_bond_assignment_netgroups_ids(self):
  623. cluster = self.env.create_cluster(api=False)
  624. node = self.env.create_node(cluster_id=cluster.id)
  625. self.env.network_manager.assign_ips(
  626. cluster, [node], consts.NETWORKS.management
  627. )
  628. assigned_networks = [net for iface in node.interfaces
  629. for net in iface.assigned_networks]
  630. self.env.network_manager._update_attrs({
  631. 'id': node.id,
  632. 'interfaces': [{
  633. 'name': 'ovs-bond0',
  634. 'type': consts.NETWORK_INTERFACE_TYPES.bond,
  635. 'mode': consts.BOND_MODES.balance_slb,
  636. 'slaves': [{'name': 'eth0'}],
  637. 'assigned_networks': assigned_networks
  638. }]
  639. })
  640. admin_ng_id = \
  641. objects.NetworkGroup.get_admin_network_group(node).id
  642. bond_ng_ids = \
  643. dict((net.id, admin_ng_id) for iface in node.bond_interfaces
  644. for net in iface.assigned_networks_list)
  645. objects.Node.set_bond_assignment_netgroups_ids(node, bond_ng_ids)
  646. self.db.refresh(node)
  647. for iface in node.bond_interfaces:
  648. for net in iface.assigned_networks_list:
  649. self.assertEquals(admin_ng_id, net.id)
  650. def test_get_assigned_vips(self):
  651. vips_to_create = {
  652. consts.NETWORKS.management: {
  653. consts.NETWORK_VIP_NAMES_V6_1.haproxy: '192.168.0.1',
  654. consts.NETWORK_VIP_NAMES_V6_1.vrouter: '192.168.0.2',
  655. },
  656. consts.NETWORKS.public: {
  657. consts.NETWORK_VIP_NAMES_V6_1.haproxy: '172.16.0.2',
  658. consts.NETWORK_VIP_NAMES_V6_1.vrouter: '172.16.0.3',
  659. },
  660. }
  661. cluster = self.create_env_w_controller()
  662. self.env.create_ip_addrs_by_rules(cluster, vips_to_create)
  663. vips = self.env.network_manager.get_assigned_vips(cluster)
  664. self.assertEqual(vips_to_create, _set_name(_convert_vips(vips)))
  665. def test_assign_given_vips_for_net_groups(self):
  666. haproxy = consts.NETWORK_VIP_NAMES_V6_1.haproxy
  667. vrouter = consts.NETWORK_VIP_NAMES_V6_1.vrouter
  668. vips_to_assign = {
  669. consts.NETWORKS.management: {
  670. haproxy: _make_vip(ip_addr='192.168.0.1'),
  671. vrouter: _make_vip(ip_addr='192.168.0.2'),
  672. },
  673. consts.NETWORKS.public: {
  674. haproxy: _make_vip(ip_addr='172.16.0.4'),
  675. vrouter: _make_vip(ip_addr='172.16.0.5'),
  676. },
  677. }
  678. cluster = self.env.create_cluster(api=False)
  679. vips_to_assign = _set_id(vips_to_assign, cluster)
  680. self.env.network_manager.assign_given_vips_for_net_groups(
  681. cluster, vips_to_assign)
  682. vips = self.env.network_manager.get_assigned_vips(cluster)
  683. self.assertEqual(_convert_vips(vips_to_assign), _convert_vips(vips))
  684. def test_assign_given_vips_for_net_groups_idempotent(self):
  685. cluster = self.env.create_cluster(api=False)
  686. self.env.network_manager.assign_vips_for_net_groups(cluster)
  687. expected_vips = self.env.network_manager.get_assigned_vips(cluster)
  688. self.env.network_manager.assign_given_vips_for_net_groups(
  689. cluster, expected_vips)
  690. self.env.network_manager.assign_vips_for_net_groups(cluster)
  691. vips = self.env.network_manager.get_assigned_vips(cluster)
  692. self.assertEqual(expected_vips, vips)
  693. def test_assign_given_vips_for_net_groups_assign_error(self):
  694. vips_to_assign = {
  695. consts.NETWORKS.management: {
  696. consts.NETWORK_VIP_NAMES_V6_1.haproxy:
  697. _make_vip(ip_addr='10.10.0.1'),
  698. },
  699. }
  700. expected_msg_regexp = "^Cannot assign VIP with the address '10.10.0.1'"
  701. cluster = self.env.create_cluster(api=False)
  702. vips_to_assign = _set_id(vips_to_assign, cluster)
  703. with self.assertRaisesRegexp(errors.AssignIPError,
  704. expected_msg_regexp):
  705. self.env.network_manager.assign_given_vips_for_net_groups(
  706. cluster, vips_to_assign)
  707. def test_update_networks_idempotent(self):
  708. cluster = self.env.create_cluster(
  709. api=False,
  710. net_provider=consts.CLUSTER_NET_PROVIDERS.neutron,
  711. net_l23_provider=consts.NEUTRON_L23_PROVIDERS.ovs,
  712. )
  713. get_network_config = network_configuration.\
  714. NeutronNetworkConfigurationSerializer.serialize_for_cluster
  715. nets = get_network_config(cluster)
  716. self.env.network_manager.update_networks(nets)
  717. updated_nets = get_network_config(cluster)
  718. self.assertEqual(nets, updated_nets)
  719. def get_net_by_name(self, networks, name):
  720. for net in networks:
  721. if net["meta"]["name"] == name:
  722. return net
  723. raise Exception("Network with name {0} not found".format(name))
  724. def test_update_networks(self):
  725. updates = {
  726. consts.NETWORKS.public: {
  727. "cidr": "172.16.42.0/24",
  728. "gateway": "172.16.42.1",
  729. "ip_ranges": [["172.16.42.2", "172.16.42.126"]],
  730. },
  731. consts.NETWORKS.management: {
  732. 'cidr': "192.10.2.0/24",
  733. 'ip_ranges': [["192.10.2.1", "192.10.2.254"]],
  734. },
  735. }
  736. cluster = self.env.create_cluster(
  737. api=False,
  738. net_provider=consts.CLUSTER_NET_PROVIDERS.neutron,
  739. net_l23_provider=consts.NEUTRON_L23_PROVIDERS.ovs,
  740. )
  741. get_network_config = network_configuration.\
  742. NeutronNetworkConfigurationSerializer.serialize_for_cluster
  743. nets = get_network_config(cluster)
  744. for net_name, net_changes in six.iteritems(updates):
  745. ng = self.get_net_by_name(nets["networks"], net_name)
  746. ng.update(net_changes)
  747. self.env.network_manager.update_networks(nets)
  748. updated_nets = get_network_config(cluster)
  749. for net_name in updates.keys():
  750. expected_ng = self.get_net_by_name(nets["networks"], net_name)
  751. updated_ng = self.get_net_by_name(updated_nets["networks"],
  752. net_name)
  753. self.assertEqual(expected_ng, updated_ng)
  754. def test_update_networks_meta(self):
  755. updates = {
  756. consts.NETWORKS.public: {
  757. "meta": {"notation": consts.NETWORK_NOTATION.cidr},
  758. },
  759. consts.NETWORKS.management: {
  760. "meta": {"use_gateway": True}
  761. }
  762. }
  763. cluster = self.env.create_cluster(
  764. api=False,
  765. net_provider=consts.CLUSTER_NET_PROVIDERS.neutron,
  766. net_l23_provider=consts.NEUTRON_L23_PROVIDERS.ovs,
  767. )
  768. get_network_config = network_configuration.\
  769. NeutronNetworkConfigurationSerializer.serialize_for_cluster
  770. nets = get_network_config(cluster)
  771. # Lower value of range is "192.168.0.1".
  772. mgmt_ng = self.get_net_by_name(
  773. nets["networks"],
  774. consts.NETWORKS.management)
  775. self.assertEqual(mgmt_ng['ip_ranges'][0][0], "192.168.0.1")
  776. for net_name, net_changes in six.iteritems(updates):
  777. ng = self.get_net_by_name(nets["networks"], net_name)
  778. ng['meta'].update(net_changes['meta'])
  779. self.env.network_manager.update_networks(nets)
  780. nets_updated = get_network_config(cluster)
  781. public_ng = self.get_net_by_name(
  782. nets_updated["networks"],
  783. consts.NETWORKS.public)
  784. self.assertEqual(public_ng["meta"]["notation"],
  785. consts.NETWORK_NOTATION.cidr)
  786. mgmt_ng_updated = self.get_net_by_name(
  787. nets_updated["networks"],
  788. consts.NETWORKS.management)
  789. self.assertTrue(mgmt_ng_updated["meta"]["use_gateway"])
  790. # Check whether ranges are changed after 'use_gateway=True' was set.
  791. # Lower value of range is changed from "192.168.0.1" to "192.168.0.2".
  792. self.assertEqual(mgmt_ng_updated['ip_ranges'][0][0], "192.168.0.2")
  793. @mock_rpc()
  794. def test_admin_ip_cobbler(self):
  795. node_1_meta = {}
  796. self.env.set_interfaces_in_meta(node_1_meta, [{
  797. "name": "eth0",
  798. "mac": "00:00:00:00:00:00",
  799. }, {
  800. "name": "eth1",
  801. "mac": "00:00:00:00:00:01"}])
  802. node_2_meta = {}
  803. self.env.set_interfaces_in_meta(node_2_meta, [{
  804. "name": "eth0",
  805. "mac": "00:00:00:00:00:02",
  806. }, {
  807. "name": "eth1",
  808. "mac": "00:00:00:00:00:03"}])
  809. self.env.create(
  810. cluster_kwargs={
  811. 'editable_attributes': {'public_network_assignment': {
  812. 'assign_to_all_nodes': {'value': True}}}
  813. },
  814. nodes_kwargs=[
  815. {
  816. "api": True,
  817. "pending_addition": True,
  818. "mac": "00:00:00:00:00:00",
  819. "meta": node_1_meta
  820. },
  821. {
  822. "api": True,
  823. "pending_addition": True,
  824. "mac": "00:00:00:00:00:02",
  825. "meta": node_2_meta
  826. }
  827. ]
  828. )
  829. self.env.launch_deployment()
  830. rpc_nodes_provision = nailgun.task.manager.rpc.cast. \
  831. call_args_list[0][0][1][0]['args']['provisioning_info']['nodes']
  832. admin_ng_id = objects.NetworkGroup.get_admin_network_group().id
  833. admin_network_range = self.db.query(IPAddrRange).\
  834. filter_by(network_group_id=admin_ng_id).all()[0]
  835. for x in range(2):
  836. self.assertIn(
  837. IPAddress(
  838. rpc_nodes_provision[x]['interfaces']['eth0']['ip_address']
  839. ),
  840. IPRange(
  841. admin_network_range.first,
  842. admin_network_range.last
  843. )
  844. )
  845. def test_restricted_networks(self):
  846. rel = self.env.create_release()
  847. enabled_net = {'name': 'always_enabled',
  848. 'notation': None,
  849. 'restrictions': ['false']}
  850. disabled_net = {'name': 'always_disabled',
  851. 'notation': None,
  852. 'restrictions': ['true']}
  853. netw_meta = deepcopy(rel.networks_metadata)
  854. netw_meta['neutron']['networks'].extend([enabled_net, disabled_net])
  855. rel.networks_metadata = netw_meta
  856. cluster = self.env.create_cluster(
  857. release_id=rel.id,
  858. api=False
  859. )
  860. self.assertEqual(len(filter(lambda ng: ng.name == 'always_enabled',
  861. cluster.network_groups)), 1)
  862. self.assertEqual(len(filter(lambda ng: ng.name == 'always_disabled',
  863. cluster.network_groups)), 0)
  864. def test_update_restricted_networks(self):
  865. restricted_net = {
  866. 'name': 'restricted_net',
  867. 'map_priority': 5,
  868. 'restrictions': [
  869. 'settings:additional_components.ironic.value == false'
  870. ]
  871. }
  872. attributes_metadata = """
  873. editable:
  874. additional_components:
  875. ironic:
  876. value: %r
  877. type: "checkbox"
  878. """
  879. rel = self.env.create_release()
  880. netw_meta = deepcopy(rel.networks_metadata)
  881. netw_meta['neutron']['networks'].append(restricted_net)
  882. rel.networks_metadata = netw_meta
  883. cluster = self.env.create_cluster(
  884. release_id=rel.id,
  885. api=False,
  886. editable_attributes={'public_network_assignment': {
  887. 'assign_to_all_nodes': {'value': True}}})
  888. self.env.create_node(cluster_id=cluster.id)
  889. self.assertEqual(len(filter(lambda ng: ng.name == 'restricted_net',
  890. cluster.network_groups)), 0)
  891. with patch.object(logger, 'warning') as mock_warn:
  892. objects.Cluster.patch_attributes(
  893. cluster, yaml.load(attributes_metadata % True))
  894. mock_warn.assert_called_once_with(
  895. "Cannot assign network %r appropriately for "
  896. "node %r. Set unassigned network to the "
  897. "interface %r",
  898. "restricted_net", mock.ANY, mock.ANY
  899. )
  900. assigned_nets_count = 0
  901. for iface in cluster.nodes[0].interfaces:
  902. assigned_nets_count += len(filter(lambda n: n['name'] ==
  903. 'restricted_net',
  904. iface.assigned_networks))
  905. self.assertEqual(assigned_nets_count, 1)
  906. self.assertEqual(len(filter(lambda ng: ng.name == 'restricted_net',
  907. cluster.network_groups)), 1)
  908. objects.Cluster.patch_attributes(
  909. cluster, yaml.load(attributes_metadata % False))
  910. self.assertEqual(len(filter(lambda ng: ng.name == 'restricted_net',
  911. cluster.network_groups)), 0)
  912. def test_clear_assigned_networks(self):
  913. self.env.create(
  914. cluster_kwargs={},
  915. nodes_kwargs=[
  916. {"pending_addition": True, "api": True},
  917. ]
  918. )
  919. node = self.env.nodes[0]
  920. self.env.network_manager.clear_assigned_networks(node)
  921. for iface in node.interfaces:
  922. self.assertEqual([], iface.assigned_networks_list)
  923. class TestNovaNetworkManager(BaseIntegrationTest):
  924. def setUp(self):
  925. super(TestNovaNetworkManager, self).setUp()
  926. self.env.create(
  927. cluster_kwargs={
  928. 'net_provider': consts.CLUSTER_NET_PROVIDERS.nova_network,
  929. },
  930. nodes_kwargs=[
  931. {'api': True,
  932. 'pending_addition': True}
  933. ])
  934. self.node_db = self.env.nodes[0]
  935. def test_get_default_nic_assignment(self):
  936. admin_nic_id = self.env.network_manager.get_admin_interface(
  937. self.node_db
  938. ).id
  939. admin_nets = [n.name for n in self.db.query(
  940. NodeNICInterface).get(admin_nic_id).assigned_networks_list]
  941. other_nic = self.db.query(NodeNICInterface).filter_by(
  942. node_id=self.node_db.id
  943. ).filter(
  944. not_(NodeNICInterface.id == admin_nic_id)
  945. ).first()
  946. other_nets = [n.name for n in other_nic.assigned_networks_list]
  947. nics = NovaNetworkManager.get_default_interfaces_configuration(
  948. self.node_db)
  949. def_admin_nic = [n for n in nics if n['id'] == admin_nic_id]
  950. def_other_nic = [n for n in nics if n['id'] == other_nic.id]
  951. self.assertEqual(len(def_admin_nic), 1)
  952. self.assertEqual(len(def_other_nic), 1)
  953. self.assertEqual(
  954. set(admin_nets),
  955. set([n['name'] for n in def_admin_nic[0]['assigned_networks']]))
  956. self.assertEqual(
  957. set(other_nets),
  958. set([n['name'] for n in def_other_nic[0]['assigned_networks']]))
  959. class TestNeutronManager(BaseIntegrationTest):
  960. def check_networks_assignment(self, node_db):
  961. node_nics = self.db.query(NodeNICInterface).filter_by(
  962. node_id=node_db.id
  963. ).all()
  964. def_nics = NeutronManager.get_default_interfaces_configuration(node_db)
  965. self.assertEqual(len(node_nics), len(def_nics))
  966. for n_nic in node_nics:
  967. n_assigned = set(n['name'] for n in n_nic.assigned_networks)
  968. for d_nic in def_nics:
  969. if d_nic['id'] == n_nic.id:
  970. d_assigned = set(n['name']
  971. for n in d_nic['assigned_networks']) \
  972. if d_nic.get('assigned_networks') else set()
  973. self.assertEqual(n_assigned, d_assigned)
  974. break
  975. else:
  976. self.fail("NIC is not found")
  977. def test_gre_get_default_nic_assignment(self):
  978. self.env.create(
  979. cluster_kwargs={
  980. 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
  981. 'net_segment_type': consts.NEUTRON_SEGMENT_TYPES.gre},
  982. nodes_kwargs=[
  983. {'api': True,
  984. 'pending_addition': True}
  985. ])
  986. self.check_networks_assignment(self.env.nodes[0])
  987. def test_tun_get_default_nic_assignment(self):
  988. self.env.create(
  989. cluster_kwargs={
  990. 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
  991. 'net_segment_type': consts.NEUTRON_SEGMENT_TYPES.tun},
  992. nodes_kwargs=[
  993. {'api': True,
  994. 'pending_addition': True}
  995. ])
  996. self.check_networks_assignment(self.env.nodes[0])
  997. def test_vlan_get_default_nic_assignment(self):
  998. meta = self.env.default_metadata()
  999. self.env.set_interfaces_in_meta(
  1000. meta,
  1001. [{'name': 'eth0', 'mac': '00:00:00:00:00:11'},
  1002. {'name': 'eth1', 'mac': '00:00:00:00:00:22'},
  1003. {'name': 'eth2', 'mac': '00:00:00:00:00:33'}])
  1004. self.env.create(
  1005. cluster_kwargs={
  1006. 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
  1007. 'net_segment_type': consts.NEUTRON_SEGMENT_TYPES.vlan},
  1008. nodes_kwargs=[
  1009. {'api': True,
  1010. 'meta': meta,
  1011. 'pending_addition': True}
  1012. ])
  1013. self.check_networks_assignment(self.env.nodes[0])
  1014. def test_admin_networks_serialization(self):
  1015. cluster = self.env.create(
  1016. cluster_kwargs={
  1017. 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
  1018. 'net_segment_type': consts.NEUTRON_SEGMENT_TYPES.gre}
  1019. )
  1020. ng = self.env.create_node_group().json_body
  1021. admin_nets = self.db.query(NetworkGroup).filter_by(
  1022. name='fuelweb_admin'
  1023. )
  1024. admin_def = admin_nets.filter_by(group_id=None).first()
  1025. admin_ng = admin_nets.filter_by(group_id=ng['id']).first()
  1026. expected = [
  1027. {
  1028. 'id': admin_def.id,
  1029. 'cidr': '10.20.0.0/24',
  1030. 'gateway': '10.20.0.1',
  1031. 'ip_ranges': [['10.20.0.129', '10.20.0.254']]
  1032. },
  1033. {
  1034. 'id': admin_ng.id,
  1035. 'cidr': '9.9.9.0/24',
  1036. 'gateway': '9.9.9.1',
  1037. 'ip_ranges': [['9.9.9.2', '9.9.9.254']]
  1038. }
  1039. ]
  1040. nm = objects.Cluster.get_network_manager()
  1041. admin_nets = nm.get_admin_networks()
  1042. self.assertItemsEqual(admin_nets, expected)
  1043. expected[0].update({
  1044. 'node_group_id': None,
  1045. 'node_group_name': None,
  1046. 'cluster_id': None,
  1047. 'cluster_name': None
  1048. })
  1049. expected[1].update({
  1050. 'node_group_id': ng['id'],
  1051. 'node_group_name': ng['name'],
  1052. 'cluster_id': cluster['id'],
  1053. 'cluster_name': cluster['name']
  1054. })
  1055. admin_nets = nm.get_admin_networks(True)
  1056. self.assertItemsEqual(admin_nets, expected)
  1057. def test_check_admin_network_mapping(self):
  1058. self.env.create(
  1059. cluster_kwargs={
  1060. 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
  1061. 'net_segment_type': consts.NEUTRON_SEGMENT_TYPES.tun},
  1062. nodes_kwargs=[
  1063. {'api': True,
  1064. 'pending_addition': True}
  1065. ])
  1066. node = self.env.nodes[0]
  1067. admin_nic = self.env.network_manager.get_admin_interface(node)
  1068. # move 'pxe' flag to another interface
  1069. for nic in node.nic_interfaces:
  1070. if nic != admin_nic:
  1071. admin_nic.pxe = False
  1072. nic.pxe = True
  1073. self.env.db.flush()
  1074. admin_nic = nic
  1075. break
  1076. # networks mapping in DB is not changed
  1077. self.assertNotEqual(
  1078. admin_nic,
  1079. self.env.network_manager.get_admin_interface(node))
  1080. self.env.network_manager._remap_admin_network(node)
  1081. # networks mapping in DB is changed
  1082. self.assertEqual(
  1083. admin_nic,
  1084. self.env.network_manager.get_admin_interface(node))
  1085. class TestNeutronManager70(BaseIntegrationTest):
  1086. def setUp(self):
  1087. super(TestNeutronManager70, self).setUp()
  1088. self.cluster = self._create_env()
  1089. self.net_manager = objects.Cluster.get_network_manager(self.cluster)
  1090. def _create_env(self):
  1091. release = self._prepare_release()
  1092. # environment must be created with nodes in order
  1093. # to VIP be assigned (without nodes there will be no
  1094. # node group which network VIP must be allocated in)
  1095. return self.env.create(
  1096. cluster_kwargs={
  1097. 'api': False,
  1098. 'release_id': release.id,
  1099. 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron
  1100. },
  1101. nodes_kwargs=[{'roles': ['controller']}]
  1102. )
  1103. def _prepare_release(self):
  1104. rel_id = self.env.create_release(version='1111-7.0').id
  1105. rel_db = self.db.query(Release).filter_by(id=rel_id).one()
  1106. to_patch = [
  1107. {
  1108. 'id': "mgmt/vip",
  1109. 'default_mapping': "management",
  1110. 'properties': {
  1111. 'subnet': True,
  1112. 'gateway': False,
  1113. 'vip': [
  1114. {
  1115. 'name': "vrouter",
  1116. 'namespace': "vrouter",
  1117. 'alias': "management_vrouter_vip",
  1118. },
  1119. {
  1120. 'name': "management",
  1121. 'namespace': "haproxy",
  1122. 'alias': "management_vip",
  1123. },
  1124. ]
  1125. }
  1126. },
  1127. {
  1128. 'id': "public/vip",
  1129. 'default_mapping': "public",
  1130. 'properties': {
  1131. 'subnet': True,
  1132. 'gateway': True,
  1133. 'vip': [
  1134. {
  1135. 'name': "vrouter_pub",
  1136. 'namespace': "vrouter",
  1137. 'alias': "public_vrouter_vip",
  1138. },
  1139. {
  1140. 'name': "public",
  1141. 'namespace': "haproxy",
  1142. 'alias': "public_vip",
  1143. }
  1144. ]
  1145. }
  1146. }
  1147. ]
  1148. rel_db.network_roles_metadata = to_patch
  1149. self.db.flush()
  1150. return rel_db
  1151. def _check_vip_configuration(self, expected_vips, real_vips):
  1152. for vip in expected_vips:
  1153. name = vip['name']
  1154. self.assertIn(name, real_vips)
  1155. self.assertEqual(real_vips[name]['namespace'],
  1156. vip['namespace'])
  1157. self.assertEqual(real_vips[name]['node_roles'],
  1158. ['controller',
  1159. 'primary-controller'])
  1160. def _get_network_role_metadata(self, **kwargs):
  1161. network_role = {
  1162. 'id': 'test_network_role',
  1163. 'default_mapping': 'public',
  1164. 'properties': {
  1165. 'subnet': True,
  1166. 'gateway': False,
  1167. 'vip': [
  1168. {'name': 'test_vip_a'}
  1169. ]
  1170. }
  1171. }
  1172. network_role.update(kwargs)
  1173. return network_role
  1174. def test_get_network_manager(self):
  1175. self.assertIs(self.net_manager, NeutronManager70)
  1176. def test_purge_stalled_vips(self):
  1177. self.net_manager.assign_vips_for_net_groups(self.cluster)
  1178. vips_before = self.net_manager.get_assigned_vips(self.cluster)
  1179. net_name = next(six.iterkeys(vips_before))
  1180. vips_to_remove = vips_before[net_name]
  1181. # remove network role information from release metadata in order
  1182. # to omit processing of VIPs for this role
  1183. new_nroles_meta = []
  1184. for net_role in self.cluster.release.network_roles_metadata:
  1185. if net_role.get('properties', {}).get('vip', []):
  1186. vip_info = net_role['properties']['vip']
  1187. if set(ip['name'] for ip in vip_info) == set(vips_to_remove):
  1188. continue
  1189. new_nroles_meta.append(net_role)
  1190. self.cluster.release.network_roles_metadata = new_nroles_meta
  1191. self.net_manager.assign_vips_for_net_groups(self.cluster)
  1192. vips_after = self.net_manager.get_assigned_vips(self.cluster)
  1193. self.assertNotIn(net_name, vips_after)
  1194. # check that information about VIPs for other networks is not affected
  1195. # after purging
  1196. del vips_before[net_name]
  1197. self.assertEqual(vips_before, vips_after)
  1198. def test_get_network_group_for_role(self):
  1199. net_template = self.env.read_fixtures(['network_template_70'])[0]
  1200. objects.Cluster.set_network_template(self.cluster, net_template)
  1201. node_group = objects.Cluster.get_controllers_node_group(self.cluster)
  1202. net_group_mapping = \
  1203. self.net_manager.build_role_to_network_group_mapping(
  1204. self.cluster, node_group.name)
  1205. self.assertEqual(
  1206. self.net_manager.get_network_group_for_role(
  1207. self._get_network_role_metadata(id='public/vip'),
  1208. net_group_mapping),
  1209. 'public')
  1210. self.assertEqual(
  1211. self.net_manager.get_network_group_for_role(
  1212. self._get_network_role_metadata(id='keystone/api'),
  1213. net_group_mapping),
  1214. 'management')
  1215. self.assertEqual(
  1216. self.net_manager.get_network_group_for_role(
  1217. self._get_network_role_metadata(id='management'),
  1218. net_group_mapping),
  1219. 'management')
  1220. self.assertEqual(
  1221. self.net_manager.get_network_group_for_role(
  1222. self._get_network_role_metadata(
  1223. id='role_not_in_template',
  1224. default_mapping='default_net_group'), net_group_mapping),
  1225. 'default_net_group')
  1226. def assign_vips_for_api_and_check_configuration(self, allocate):
  1227. expected_aliases = [
  1228. 'management_vip', 'management_vrouter_vip',
  1229. 'public_vip', 'public_vrouter_vip'
  1230. ]
  1231. expected_vips = [
  1232. {'name': 'vrouter', 'namespace': 'vrouter'},
  1233. {'name': 'vrouter_pub', 'namespace': 'vrouter'},
  1234. {'name': 'management', 'namespace': 'haproxy'},
  1235. {'name': 'public', 'namespace': 'haproxy'},
  1236. ]
  1237. assigned_vips = self.net_manager.assign_vips_for_net_groups_for_api(
  1238. self.cluster, allocate=allocate)
  1239. self._check_vip_configuration(expected_vips, assigned_vips['vips'])
  1240. # Also check that the configuration in the old format is included
  1241. for a in expected_aliases:
  1242. self.assertIn(a, assigned_vips)
  1243. return assigned_vips
  1244. def check_assigned_vips_against_db_data(self, assigned_vips):
  1245. vips_db = objects.IPAddrCollection.get_by_cluster_id(
  1246. self.cluster.id
  1247. )
  1248. vip_info = assigned_vips['vips']
  1249. for vip in vips_db:
  1250. self.assertIn(vip.vip_name, vip_info)
  1251. info = vip_info[vip.vip_name]
  1252. self.assertEqual(info['ipaddr'], vip.ip_addr)
  1253. self.assertEqual(info['is_user_defined'], vip.is_user_defined)
  1254. def test_assign_vips_for_net_groups_for_api_w_allocation(self):
  1255. assigned_vips = self.assign_vips_for_api_and_check_configuration(
  1256. allocate=True)
  1257. self.check_assigned_vips_against_db_data(assigned_vips)
  1258. def test_assign_vips_for_net_groups_for_api_wo_allocation(self):
  1259. # if anything, delete already assigned VIPs
  1260. objects.IPAddrCollection.all().delete(synchronize_session='fetch')
  1261. assigned_vips = self.assign_vips_for_api_and_check_configuration(
  1262. allocate=False)
  1263. # check that the action didn't triggered VIP allocation
  1264. cluster_vips_db = objects.IPAddrCollection.get_by_cluster_id(
  1265. self.cluster.id).all()
  1266. self.assertFalse(cluster_vips_db)
  1267. vip_info = assigned_vips['vips']
  1268. for vip_name, info in six.iteritems(vip_info):
  1269. self.assertIsNone(info['ipaddr'])
  1270. self.assertFalse(info['is_user_defined'])
  1271. def test_assign_vips_for_net_groups_for_api_contains_removed_vip(self):
  1272. # allocate VIPs, if anything
  1273. self.net_manager.assign_vips_for_net_groups(self.cluster)
  1274. # remember details of removed VIP to check against them later
  1275. removed_vip = objects.IPAddrCollection.get_by_cluster_id(
  1276. self.cluster.id
  1277. ).first()
  1278. vip_name = removed_vip.vip_name
  1279. self.db.delete(removed_vip)
  1280. self.db.flush()
  1281. assigned_vips = self.assign_vips_for_api_and_check_configuration(
  1282. allocate=False)
  1283. self.check_assigned_vips_against_db_data(assigned_vips)
  1284. # check that removed VIP is serialized and it is done properly
  1285. self.assertIn(vip_name, assigned_vips['vips'])
  1286. self.assertIsNone(assigned_vips['vips'][vip_name]['ipaddr'])
  1287. self.assertFalse(assigned_vips['vips'][vip_name]['is_user_defined'])
  1288. # check that removed VIP is restored (as its info is present in
  1289. # network roles metadata for the cluster) after auto allocation
  1290. # executed
  1291. assigned_vips = self.assign_vips_for_api_and_check_configuration(
  1292. allocate=True)
  1293. self.check_assigned_vips_against_db_data(assigned_vips)
  1294. def test_assign_vips_for_net_groups(self):
  1295. expected_vips = [
  1296. {'name': 'vrouter', 'namespace': 'vrouter'},
  1297. {'name': 'vrouter_pub', 'namespace': 'vrouter'},
  1298. {'name': 'management', 'namespace': 'haproxy'},
  1299. {'name': 'public', 'namespace': 'haproxy'},
  1300. ]
  1301. assigned_vips = self.net_manager.assign_vips_for_net_groups(
  1302. self.cluster)
  1303. self._check_vip_configuration(expected_vips, assigned_vips)
  1304. @mock.patch('nailgun.objects.Cluster.get_network_roles')
  1305. def test_check_unique_vip_names_for_cluster(self, get_nr_mock):
  1306. fake_role_erroneous_data = [
  1307. {
  1308. 'properties': {
  1309. 'vip': [
  1310. {
  1311. 'name': 'duplicate_name'
  1312. }
  1313. ]
  1314. }
  1315. },
  1316. {
  1317. 'properties': {
  1318. 'vip': [
  1319. {
  1320. 'name': 'duplicate_name'
  1321. }
  1322. ]
  1323. }
  1324. },
  1325. ]
  1326. get_nr_mock.return_value = fake_role_erroneous_data
  1327. self.assertRaises(
  1328. errors.DuplicatedVIPNames,
  1329. self.net_manager.check_unique_vip_names_for_cluster,
  1330. self.cluster
  1331. )
  1332. fake_role_proper_data = [
  1333. {
  1334. 'properties': {
  1335. 'vip': [
  1336. {
  1337. 'name': 'test_name_one'
  1338. }
  1339. ]
  1340. }
  1341. },
  1342. {
  1343. 'properties': {
  1344. 'vip': [
  1345. {
  1346. 'name': 'test_name_two'
  1347. }
  1348. ]
  1349. }
  1350. },
  1351. ]
  1352. get_nr_mock.return_value = fake_role_proper_data
  1353. self.assertNotRaises(
  1354. errors.DuplicatedVIPNames,
  1355. self.net_manager.check_unique_vip_names_for_cluster,
  1356. self.cluster
  1357. )
  1358. def test_get_assigned_vips(self):
  1359. self.net_manager.assign_vips_for_net_groups(self.cluster)
  1360. vips = self.net_manager.get_assigned_vips(self.cluster)
  1361. expected_vips = {
  1362. 'management': {
  1363. 'vrouter': '192.168.0.1',
  1364. 'management': '192.168.0.2',
  1365. },
  1366. 'public': {
  1367. 'vrouter_pub': '172.16.0.2',
  1368. 'public': '172.16.0.3',
  1369. },
  1370. }
  1371. self.assertEqual(expected_vips, _set_name(_convert_vips(vips)))
  1372. def test_assign_given_vips_for_net_groups(self):
  1373. # rewrite VIPs allocated on creation of cluster
  1374. vips_to_assign = {
  1375. 'management': {
  1376. 'vrouter': _make_vip(ip_addr='192.168.0.4'),
  1377. 'management': _make_vip(ip_addr='192.168.0.5'),
  1378. },
  1379. 'public': {
  1380. 'vrouter_pub': _make_vip(ip_addr='172.16.0.4'),
  1381. 'public': _make_vip(ip_addr='172.16.0.5'),
  1382. },
  1383. }
  1384. vips_to_assign = _set_id(vips_to_assign, self.cluster)
  1385. self.net_manager.assign_given_vips_for_net_groups(
  1386. self.cluster, vips_to_assign)
  1387. vips = self.net_manager.get_assigned_vips(self.cluster)
  1388. self.assertEqual(_convert_vips(vips_to_assign), _convert_vips(vips))
  1389. class TestNovaNetworkManager70(TestNeutronManager70):
  1390. def _create_env(self):
  1391. release = self._prepare_release()
  1392. # environment must be created with nodes in order
  1393. # to VIP be assigned (without nodes there will be no
  1394. # node group which network VIP must be allocated in)
  1395. return self.env.create(
  1396. cluster_kwargs={
  1397. 'release_id': release.id,
  1398. 'api': False,
  1399. 'net_provider': consts.CLUSTER_NET_PROVIDERS.nova_network
  1400. },
  1401. nodes_kwargs=[{'roles': ['controller']}]
  1402. )
  1403. def test_get_network_manager(self):
  1404. self.assertIs(self.net_manager, NovaNetworkManager70)
  1405. def test_get_network_group_for_role(self):
  1406. node_group = objects.Cluster.get_controllers_node_group(self.cluster)
  1407. net_group_mapping = \
  1408. self.net_manager.build_role_to_network_group_mapping(
  1409. self.cluster, node_group.name)
  1410. self.assertEqual(
  1411. self.net_manager.get_network_group_for_role(
  1412. self._get_network_role_metadata(id='public/vip'),
  1413. net_group_mapping),
  1414. 'public')
  1415. self.assertEqual(
  1416. self.net_manager.get_network_group_for_role(
  1417. self._get_network_role_metadata(
  1418. id='role_not_in_template',
  1419. default_mapping='default_net_group'), net_group_mapping),
  1420. 'default_net_group')
  1421. class TestTemplateManager70(BaseIntegrationTest):
  1422. def setUp(self):
  1423. super(TestTemplateManager70, self).setUp()
  1424. self.cluster = self.env.create(
  1425. release_kwargs={'version': '1111-7.0'},
  1426. cluster_kwargs={
  1427. 'api': True,
  1428. 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron,
  1429. }
  1430. )
  1431. self.cluster = objects.Cluster.get_by_uid(self.cluster['id'])
  1432. self.nm = objects.Cluster.get_network_manager(self.cluster)
  1433. self.net_template = self.env.read_fixtures(['network_template_70'])[1]
  1434. self.env.create_nodes_w_interfaces_count(
  1435. 1, 5,
  1436. roles=['controller'],
  1437. cluster_id=self.cluster['id']
  1438. )
  1439. self.env._create_network_group(name='mongo', vlan_start=None)
  1440. self.env._create_network_group(name='keystone', vlan_start=None)
  1441. self.env._create_network_group(name='murano', vlan_start=None)
  1442. objects.Cluster.set_network_template(
  1443. self.cluster,
  1444. self.net_template
  1445. )
  1446. def _get_network_by_name(self, name, cluster=None):
  1447. cluster = cluster or self.env.clusters[0]
  1448. return [n for n in cluster.network_groups if n.name == name][0]
  1449. def _check_nic_mapping(self, node, expected_mapping):
  1450. for nic in node.interfaces:
  1451. assigned_nets = [net['name'] for net in nic.assigned_networks]
  1452. self.assertItemsEqual(assigned_nets, expected_mapping[nic.name])
  1453. def test_assign_networks_based_on_template(self):
  1454. expected_mapping = {
  1455. 'eth0': ['fuelweb_admin'],
  1456. 'eth1': ['public', 'storage'],
  1457. 'eth2': ['murano'],
  1458. 'eth3': [],
  1459. 'eth4': ['mongo', 'keystone'],
  1460. 'eth5': [],
  1461. 'lnxbond0': ['management']
  1462. }
  1463. node = self.env.nodes[0]
  1464. self._check_nic_mapping(node, expected_mapping)
  1465. # Network groups should have their vlan updated to match what
  1466. # is defined in the template.
  1467. keystone_ng = self._get_network_by_name('keystone')
  1468. self.assertEqual(keystone_ng.vlan_start, 202)
  1469. def test_get_interfaces_from_template(self):
  1470. expected_interfaces = {
  1471. 'br-aux': {
  1472. 'interface_properties': {},
  1473. 'name': 'eth3.103',
  1474. 'offloading_modes': [],
  1475. 'type': 'ether'
  1476. },
  1477. 'br-ex': {
  1478. 'interface_properties': {},
  1479. 'name': 'eth1',
  1480. 'offloading_modes': [],
  1481. 'type': 'ether'
  1482. },
  1483. 'br-fw-admin': {
  1484. 'interface_properties': {},
  1485. 'name': 'eth0',
  1486. 'offloading_modes': [],
  1487. 'type': 'ether'
  1488. },
  1489. 'br-keystone': {
  1490. 'interface_properties': {},
  1491. 'name': 'eth4.202',
  1492. 'offloading_modes': [],
  1493. 'type': 'ether'
  1494. },
  1495. 'br-mgmt': {
  1496. 'bond_properties': {'mode': u'active-backup'},
  1497. 'name': u'lnxbond0',
  1498. 'offloading_modes': [],
  1499. 'slaves': [{'name': u'eth3'}, {'name': u'eth4'}],
  1500. 'type': 'bond'
  1501. },
  1502. 'br-mongo': {
  1503. 'interface_properties': {},
  1504. 'name': u'eth4.201',
  1505. 'offloading_modes': [],
  1506. 'type': 'ether'
  1507. },
  1508. 'br-storage': {
  1509. 'interface_properties': {},
  1510. 'name': 'eth1.102',
  1511. 'offloading_modes': [],
  1512. 'type': 'ether'
  1513. },
  1514. 'eth2': {
  1515. 'interface_properties': {},
  1516. 'name': 'eth2',
  1517. 'offloading_modes': [],
  1518. 'type': 'ether'
  1519. },
  1520. 'eth3.101': {
  1521. 'interface_properties': {},
  1522. 'name': u'eth3.101',
  1523. 'offloading_modes': [],
  1524. 'type': 'ether'
  1525. },
  1526. 'eth4.101': {
  1527. 'interface_properties': {},
  1528. 'name': u'eth4.101',
  1529. 'offloading_modes': [],
  1530. 'type': 'ether'
  1531. }
  1532. }
  1533. interfaces = self.nm.get_interfaces_from_template(self.env.nodes[0])
  1534. self.assertItemsEqual(interfaces, expected_interfaces)
  1535. def test_reassign_networks_based_on_template(self):
  1536. expected_mapping = {
  1537. 'eth0': ['fuelweb_admin'],
  1538. 'eth1': ['public', 'storage'],
  1539. 'eth2': ['murano'],
  1540. 'eth3': [],
  1541. 'eth4': ['mongo', 'keystone'],
  1542. 'eth5': [],
  1543. 'lnxbond0': ['management']
  1544. }
  1545. node = self.env.nodes[0]
  1546. # All networks should be mapped as expected
  1547. self._check_nic_mapping(node, expected_mapping)
  1548. # When a network group is deleted it should be skipped
  1549. # when the template is applied.
  1550. keystone_ng = self._get_network_by_name('keystone')
  1551. self.env._delete_network_group(keystone_ng.id)
  1552. missing_net_mapping = expected_mapping.copy()
  1553. missing_net_mapping['eth4'] = ['mongo']
  1554. self._check_nic_mapping(node, missing_net_mapping)
  1555. # Adding a new network group should reassign all networks on all
  1556. # nodes based on the current template
  1557. self.env._create_network_group(name='keystone', vlan_start=None)
  1558. self._check_nic_mapping(node, expected_mapping)
  1559. class TestNeutronManager80(BaseIntegrationTest):
  1560. def setUp(self):
  1561. super(TestNeutronManager80, self).setUp()
  1562. self.cluster = self._create_env()
  1563. self.net_manager = objects.Cluster.get_network_manager(self.cluster)
  1564. def _create_env(self):
  1565. # environment must be created with nodes in order
  1566. # to VIP be assigned (without nodes there will be no
  1567. # node group which network VIP must be allocated in)
  1568. return self.env.create(
  1569. release_kwargs={'version': '1111-8.0'},
  1570. cluster_kwargs={
  1571. 'api': False,
  1572. 'net_provider': consts.CLUSTER_NET_PROVIDERS.neutron
  1573. },
  1574. nodes_kwargs=[{'roles': ['controller']}]
  1575. )
  1576. def _check_nic_mapping(self, node, expected_mapping):
  1577. for nic in node.interfaces:
  1578. assigned_nets = [net['name'] for net in nic.assigned_networks]
  1579. self.assertItemsEqual(assigned_nets, expected_mapping[nic.name])
  1580. def _check_vip_configuration(self, expected_vips, real_vips):
  1581. for vip in expected_vips:
  1582. name = vip['name']
  1583. self.assertIn(name, real_vips)
  1584. self.assertEqual(real_vips[name]['namespace'],
  1585. vip['namespace'])
  1586. self.assertEqual(real_vips[name]['node_roles'],
  1587. ['controller',
  1588. 'primary-controller'])
  1589. self.assertIn('vendor_specific', real_vips[name].keys())
  1590. expected_vips_names = sorted([vip['name'] for vip in expected_vips])
  1591. self.assertListEqual(expected_vips_names, sorted(real_vips.keys()))
  1592. def test_get_network_manager(self):
  1593. self.assertIs(self.net_manager, NeutronManager80)
  1594. def test_assign_vips_with_unmapped_net_groups(self):
  1595. expected_vips = [
  1596. {'name': 'vrouter', 'namespace': 'vrouter'},
  1597. {'name': 'vrouter_pub', 'namespace': 'vrouter'},
  1598. {'name': 'management', 'namespace': 'haproxy'},
  1599. {'name': 'public', 'namespace': 'haproxy'},
  1600. ]
  1601. unmapped_roles = yaml.safe_load("""
  1602. - id: "unmapped_role"
  1603. default_mapping: "non_existing_net"
  1604. properties:
  1605. subnet: true
  1606. gateway: false
  1607. vip:
  1608. - name: "unmapped_vip"
  1609. namespace: "haproxy"
  1610. """)
  1611. self.env.create_plugin(
  1612. cluster=self.cluster,
  1613. network_roles_metadata=unmapped_roles,
  1614. package_version='3.0.0')
  1615. assigned_vips = self.net_manager.assign_vips_for_net_groups(
  1616. self.cluster)
  1617. self.assertNotIn('unmapped_vip', assigned_vips)
  1618. self._check_vip_configuration(expected_vips, assigned_vips)
  1619. def test_network_template_vlan_bonds(self):
  1620. expected_mapping = {
  1621. 'eth0': ['fuelweb_admin'],
  1622. 'eth1': [],
  1623. 'eth2': [],
  1624. 'bond0': ['storage', 'public', 'management', 'private'],
  1625. }
  1626. cluster = self.env.create(
  1627. release_kwargs={'version': 'liberty-8.0'},
  1628. cluster_kwargs={'api': False}
  1629. )
  1630. self.env.create_nodes_w_interfaces_count(
  1631. 1, 3,
  1632. roles=['controller'],
  1633. cluster_id=cluster.id
  1634. )
  1635. node = cluster.nodes[0]
  1636. net_template = self.env.read_fixtures(['network_template_80'])[2]
  1637. objects.Cluster.set_network_template(
  1638. cluster,
  1639. net_template
  1640. )
  1641. self._check_nic_mapping(node, expected_mapping)
  1642. def test_node_dpdk_enabled_w_template(self):
  1643. template = {
  1644. "templates_for_node_role": {
  1645. "cinder": [],
  1646. "controller": [],
  1647. "test_role": [
  1648. "storage",
  1649. "private"
  1650. ]
  1651. },
  1652. "templates": {
  1653. "storage": {
  1654. "transformations": [
  1655. {
  1656. "action": "add-br",
  1657. "name": "br-storage"
  1658. },
  1659. {
  1660. "action": "add-port",
  1661. "bridge": "br-storage",
  1662. "name": "<% if3 %>"
  1663. }
  1664. ],
  1665. "roles": {
  1666. "storage": "br-storage"
  1667. }
  1668. },
  1669. "private": {
  1670. "transformations": [
  1671. {
  1672. "action": "add-br",
  1673. "name": "br-prv",
  1674. "provider": "ovs",
  1675. "vendor_specific": {
  1676. "datapath_type": "netdev"
  1677. }
  1678. },
  1679. {
  1680. "action": "add-port",
  1681. "bridge": "br-prv",
  1682. "name": "<% if4 %>.101",
  1683. "provider": "dpdkovs"
  1684. }
  1685. ],
  1686. "roles": {
  1687. "neutron/private": "br-prv"
  1688. }
  1689. },
  1690. }
  1691. }
  1692. node = mock.Mock(network_template=template,
  1693. all_roles=['test_role'])
  1694. self.assertTrue(self.net_manager.dpdk_enabled_for_node(node))
  1695. template['templates_for_node_role']['test_role'].remove('private')
  1696. self.assertFalse(self.net_manager.dpdk_enabled_for_node(node))