A set of Neutron drivers for the VMware NSX.
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_plugin.py 154KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271
  1. # Copyright (c) 2015 OpenStack Foundation.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  12. # implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. import mock
  16. import netaddr
  17. from neutron.db import l3_db
  18. from neutron.db import models_v2
  19. from neutron.db import securitygroups_db as sg_db
  20. from neutron.extensions import address_scope
  21. from neutron.extensions import l3
  22. from neutron.extensions import securitygroup as secgrp
  23. from neutron.tests.unit import _test_extension_portbindings as test_bindings
  24. from neutron.tests.unit.db import test_db_base_plugin_v2 as test_plugin
  25. from neutron.tests.unit.extensions import test_address_scope
  26. from neutron.tests.unit.extensions import test_extra_dhcp_opt as test_dhcpopts
  27. from neutron.tests.unit.extensions import test_extraroute as test_ext_route
  28. from neutron.tests.unit.extensions import test_l3 as test_l3_plugin
  29. from neutron.tests.unit.extensions \
  30. import test_l3_ext_gw_mode as test_ext_gw_mode
  31. from neutron.tests.unit.scheduler \
  32. import test_dhcp_agent_scheduler as test_dhcpagent
  33. from neutron.tests.unit import testlib_api
  34. from neutron_lib.api.definitions import external_net as extnet_apidef
  35. from neutron_lib.api.definitions import extraroute as xroute_apidef
  36. from neutron_lib.api.definitions import l3_ext_gw_mode as l3_egm_apidef
  37. from neutron_lib.api.definitions import port_security as psec
  38. from neutron_lib.api.definitions import portbindings
  39. from neutron_lib.api.definitions import provider_net as pnet
  40. from neutron_lib.api.definitions import vlantransparent as vlan_apidef
  41. from neutron_lib.callbacks import events
  42. from neutron_lib.callbacks import exceptions as nc_exc
  43. from neutron_lib.callbacks import registry
  44. from neutron_lib.callbacks import resources
  45. from neutron_lib import constants
  46. from neutron_lib import context
  47. from neutron_lib import exceptions as n_exc
  48. from neutron_lib.plugins import directory
  49. from neutron_lib.plugins import utils as plugin_utils
  50. from oslo_config import cfg
  51. from oslo_db import exception as db_exc
  52. from oslo_utils import uuidutils
  53. from webob import exc
  54. from vmware_nsx.api_client import exception as api_exc
  55. from vmware_nsx.common import utils
  56. from vmware_nsx.db import db as nsx_db
  57. from vmware_nsx.plugins.nsx_v3 import plugin as nsx_plugin
  58. from vmware_nsx.services.lbaas.nsx_v3.implementation import loadbalancer_mgr
  59. from vmware_nsx.services.lbaas.octavia import octavia_listener
  60. from vmware_nsx.tests import unit as vmware
  61. from vmware_nsx.tests.unit.common_plugin import common_v3
  62. from vmware_nsx.tests.unit.extensions import test_metadata
  63. from vmware_nsxlib.tests.unit.v3 import mocks as nsx_v3_mocks
  64. from vmware_nsxlib.tests.unit.v3 import nsxlib_testcase
  65. from vmware_nsxlib.v3 import exceptions as nsxlib_exc
  66. from vmware_nsxlib.v3 import nsx_constants
  67. PLUGIN_NAME = 'vmware_nsx.plugin.NsxV3Plugin'
  68. NSX_TZ_NAME = 'default transport zone'
  69. NSX_DHCP_PROFILE_ID = 'default dhcp profile'
  70. NSX_METADATA_PROXY_ID = 'default metadata proxy'
  71. NSX_SWITCH_PROFILE = 'dummy switch profile'
  72. NSX_DHCP_RELAY_SRV = 'dhcp relay srv'
  73. NSX_EDGE_CLUSTER_UUID = 'dummy edge cluster'
  74. def _mock_create_firewall_rules(*args):
  75. # NOTE(arosen): the code in the neutron plugin expects the
  76. # neutron rule id as the display_name.
  77. rules = args[4]
  78. return {
  79. 'rules': [
  80. {'display_name': rule['id'], 'id': uuidutils.generate_uuid()}
  81. for rule in rules
  82. ]}
  83. def _return_id_key(*args, **kwargs):
  84. return {'id': uuidutils.generate_uuid()}
  85. def _return_id_key_list(*args, **kwargs):
  86. return [{'id': uuidutils.generate_uuid()}]
  87. def _mock_nsx_backend_calls():
  88. mock.patch("vmware_nsxlib.v3.client.NSX3Client").start()
  89. fake_profile = {'key': 'FakeKey',
  90. 'resource_type': 'FakeResource',
  91. 'id': uuidutils.generate_uuid()}
  92. def _return_id(*args, **kwargs):
  93. return uuidutils.generate_uuid()
  94. def _return_same(key, *args, **kwargs):
  95. return key
  96. mock.patch(
  97. "vmware_nsxlib.v3.core_resources.NsxLibSwitchingProfile."
  98. "find_by_display_name",
  99. return_value=[fake_profile]
  100. ).start()
  101. mock.patch(
  102. "vmware_nsxlib.v3.router.RouterLib.validate_tier0").start()
  103. mock.patch(
  104. "vmware_nsxlib.v3.core_resources.NsxLibSwitchingProfile."
  105. "create_port_mirror_profile",
  106. side_effect=_return_id_key).start()
  107. mock.patch(
  108. "vmware_nsxlib.v3.core_resources.NsxLibBridgeEndpoint.create",
  109. side_effect=_return_id_key).start()
  110. mock.patch(
  111. "vmware_nsxlib.v3.security.NsxLibNsGroup.find_by_display_name",
  112. side_effect=_return_id_key_list).start()
  113. mock.patch(
  114. "vmware_nsxlib.v3.core_resources.NsxLibLogicalSwitch.create",
  115. side_effect=_return_id_key).start()
  116. mock.patch(
  117. "vmware_nsxlib.v3.core_resources.NsxLibDhcpProfile."
  118. "get_id_by_name_or_id",
  119. return_value=NSX_DHCP_PROFILE_ID).start()
  120. mock.patch(
  121. "vmware_nsxlib.v3.core_resources.NsxLibDhcpRelayService."
  122. "get_id_by_name_or_id",
  123. return_value=NSX_DHCP_RELAY_SRV).start()
  124. mock.patch(
  125. "vmware_nsxlib.v3.core_resources.NsxLibMetadataProxy."
  126. "get_id_by_name_or_id",
  127. side_effect=_return_same).start()
  128. mock.patch(
  129. "vmware_nsxlib.v3.resources.LogicalPort.create",
  130. side_effect=_return_id_key).start()
  131. mock.patch(
  132. "vmware_nsxlib.v3.core_resources.NsxLibLogicalRouter.create",
  133. side_effect=_return_id_key).start()
  134. mock.patch(
  135. "vmware_nsxlib.v3.resources.LogicalDhcpServer.create",
  136. side_effect=_return_id_key).start()
  137. mock.patch(
  138. "vmware_nsxlib.v3.resources.LogicalDhcpServer.create_binding",
  139. side_effect=_return_id_key).start()
  140. mock.patch(
  141. "vmware_nsxlib.v3.core_resources.NsxLibLogicalRouter."
  142. "get_firewall_section_id",
  143. side_effect=_return_id_key).start()
  144. mock.patch(
  145. "vmware_nsxlib.v3.NsxLib.get_version",
  146. return_value='2.4.0').start()
  147. mock.patch(
  148. "vmware_nsxlib.v3.load_balancer.Service.get_router_lb_service",
  149. return_value=None).start()
  150. mock.patch('vmware_nsxlib.v3.core_resources.NsxLibTransportZone.'
  151. 'get_transport_type', return_value='OVERLAY').start()
  152. class NsxV3PluginTestCaseMixin(test_plugin.NeutronDbPluginV2TestCase,
  153. nsxlib_testcase.NsxClientTestCase):
  154. def setup_conf_overrides(self):
  155. cfg.CONF.set_override('default_overlay_tz', NSX_TZ_NAME, 'nsx_v3')
  156. cfg.CONF.set_override('native_dhcp_metadata', False, 'nsx_v3')
  157. cfg.CONF.set_override('dhcp_profile',
  158. NSX_DHCP_PROFILE_ID, 'nsx_v3')
  159. cfg.CONF.set_override('metadata_proxy',
  160. NSX_METADATA_PROXY_ID, 'nsx_v3')
  161. cfg.CONF.set_override(
  162. 'network_scheduler_driver',
  163. 'neutron.scheduler.dhcp_agent_scheduler.AZAwareWeightScheduler')
  164. def mock_plugin_methods(self):
  165. # need to mock the global placeholder. This is due to the fact that
  166. # the generic security group tests assume that there is just one
  167. # security group.
  168. mock_ensure_global_sg_placeholder = mock.patch.object(
  169. nsx_plugin.NsxV3Plugin, '_ensure_global_sg_placeholder')
  170. mock_ensure_global_sg_placeholder.start()
  171. mock.patch(
  172. 'neutron_lib.rpc.Connection.consume_in_threads',
  173. return_value=[]).start()
  174. mock.patch.object(nsx_plugin.NsxV3Plugin,
  175. '_cleanup_duplicates').start()
  176. def setUp(self, plugin=PLUGIN_NAME,
  177. ext_mgr=None,
  178. service_plugins=None, **kwargs):
  179. self._patchers = []
  180. _mock_nsx_backend_calls()
  181. self.setup_conf_overrides()
  182. self.mock_get_edge_cluster = mock.patch.object(
  183. nsx_plugin.NsxV3Plugin, '_get_edge_cluster',
  184. return_value=NSX_EDGE_CLUSTER_UUID)
  185. self.mock_get_edge_cluster.start()
  186. self.mock_plugin_methods()
  187. # ignoring the given plugin and use the nsx-v3 one
  188. if not plugin.endswith('NsxTVDPlugin'):
  189. plugin = PLUGIN_NAME
  190. super(NsxV3PluginTestCaseMixin, self).setUp(plugin=plugin,
  191. ext_mgr=ext_mgr)
  192. self.maxDiff = None
  193. def tearDown(self):
  194. for patcher in self._patchers:
  195. patcher.stop()
  196. super(NsxV3PluginTestCaseMixin, self).tearDown()
  197. def _create_network(self, fmt, name, admin_state_up,
  198. arg_list=None, providernet_args=None,
  199. set_context=False, tenant_id=None,
  200. **kwargs):
  201. tenant_id = tenant_id or self._tenant_id
  202. data = {'network': {'name': name,
  203. 'admin_state_up': admin_state_up,
  204. 'tenant_id': tenant_id}}
  205. # Fix to allow the router:external attribute and any other
  206. # attributes containing a colon to be passed with
  207. # a double underscore instead
  208. kwargs = dict((k.replace('__', ':'), v) for k, v in kwargs.items())
  209. if extnet_apidef.EXTERNAL in kwargs:
  210. arg_list = (extnet_apidef.EXTERNAL, ) + (arg_list or ())
  211. if providernet_args:
  212. kwargs.update(providernet_args)
  213. for arg in (('admin_state_up', 'tenant_id', 'shared',
  214. 'availability_zone_hints') + (arg_list or ())):
  215. # Arg must be present
  216. if arg in kwargs:
  217. data['network'][arg] = kwargs[arg]
  218. network_req = self.new_create_request('networks', data, fmt)
  219. if set_context and tenant_id:
  220. # create a specific auth context for this request
  221. network_req.environ['neutron.context'] = context.Context(
  222. '', tenant_id)
  223. return network_req.get_response(self.api)
  224. def _create_l3_ext_network(
  225. self, physical_network=nsx_v3_mocks.DEFAULT_TIER0_ROUTER_UUID):
  226. name = 'l3_ext_net'
  227. net_type = utils.NetworkTypes.L3_EXT
  228. providernet_args = {pnet.NETWORK_TYPE: net_type,
  229. pnet.PHYSICAL_NETWORK: physical_network}
  230. return self.network(name=name,
  231. router__external=True,
  232. providernet_args=providernet_args,
  233. arg_list=(pnet.NETWORK_TYPE,
  234. pnet.PHYSICAL_NETWORK))
  235. def _save_networks(self, networks):
  236. ctx = context.get_admin_context()
  237. for network_id in networks:
  238. with ctx.session.begin(subtransactions=True):
  239. ctx.session.add(models_v2.Network(id=network_id))
  240. def _initialize_azs(self):
  241. self.plugin.init_availability_zones()
  242. self.plugin._translate_configured_names_to_uuids()
  243. def _enable_native_dhcp_md(self):
  244. cfg.CONF.set_override('native_dhcp_metadata', True, 'nsx_v3')
  245. cfg.CONF.set_override('dhcp_agent_notification', False)
  246. self.plugin._init_dhcp_metadata()
  247. def _enable_dhcp_relay(self):
  248. # Add the relay service to the config and availability zones
  249. cfg.CONF.set_override('dhcp_relay_service', NSX_DHCP_RELAY_SRV,
  250. 'nsx_v3')
  251. mock_nsx_version = mock.patch.object(
  252. self.plugin.nsxlib, 'feature_supported', return_value=True)
  253. mock_nsx_version.start()
  254. self._initialize_azs()
  255. self._enable_native_dhcp_md()
  256. class TestNetworksV2(test_plugin.TestNetworksV2, NsxV3PluginTestCaseMixin):
  257. def setUp(self, plugin=PLUGIN_NAME,
  258. ext_mgr=None,
  259. service_plugins=None):
  260. # add vlan transparent to the configuration
  261. cfg.CONF.set_override('vlan_transparent', True)
  262. super(TestNetworksV2, self).setUp(plugin=plugin,
  263. ext_mgr=ext_mgr)
  264. def tearDown(self):
  265. super(TestNetworksV2, self).tearDown()
  266. @mock.patch.object(nsx_plugin.NsxV3Plugin, 'validate_availability_zones')
  267. def test_create_network_with_availability_zone(self, mock_validate_az):
  268. name = 'net-with-zone'
  269. zone = ['zone1']
  270. mock_validate_az.return_value = None
  271. with self.network(name=name, availability_zone_hints=zone) as net:
  272. az_hints = net['network']['availability_zone_hints']
  273. self.assertListEqual(az_hints, zone)
  274. def test_network_failure_rollback(self):
  275. self._enable_native_dhcp_md()
  276. self.plugin = directory.get_plugin()
  277. with mock.patch.object(self.plugin.nsxlib.logical_port, 'create',
  278. side_effect=api_exc.NsxApiException):
  279. self.network()
  280. ctx = context.get_admin_context()
  281. networks = self.plugin.get_networks(ctx)
  282. self.assertListEqual([], networks)
  283. def test_create_provider_flat_network(self):
  284. providernet_args = {pnet.NETWORK_TYPE: 'flat'}
  285. with mock.patch('vmware_nsxlib.v3.core_resources.NsxLibLogicalSwitch.'
  286. 'create', side_effect=_return_id_key) as nsx_create, \
  287. mock.patch('vmware_nsxlib.v3.core_resources.NsxLibLogicalSwitch.'
  288. 'delete') as nsx_delete, \
  289. mock.patch('vmware_nsxlib.v3.core_resources.NsxLibTransportZone.'
  290. 'get_transport_type', return_value='VLAN'),\
  291. self.network(name='flat_net',
  292. providernet_args=providernet_args,
  293. arg_list=(pnet.NETWORK_TYPE, )) as net:
  294. self.assertEqual('flat', net['network'].get(pnet.NETWORK_TYPE))
  295. # make sure the network is created at the backend
  296. nsx_create.assert_called_once()
  297. # Delete the network and make sure it is deleted from the backend
  298. req = self.new_delete_request('networks', net['network']['id'])
  299. res = req.get_response(self.api)
  300. self.assertEqual(exc.HTTPNoContent.code, res.status_int)
  301. nsx_delete.assert_called_once()
  302. def test_create_provider_flat_network_with_physical_net(self):
  303. physical_network = nsx_v3_mocks.DEFAULT_TIER0_ROUTER_UUID
  304. providernet_args = {pnet.NETWORK_TYPE: 'flat',
  305. pnet.PHYSICAL_NETWORK: physical_network}
  306. with mock.patch(
  307. 'vmware_nsxlib.v3.core_resources.NsxLibTransportZone.'
  308. 'get_transport_type', return_value='VLAN'),\
  309. self.network(name='flat_net',
  310. providernet_args=providernet_args,
  311. arg_list=(pnet.NETWORK_TYPE,
  312. pnet.PHYSICAL_NETWORK)) as net:
  313. self.assertEqual('flat', net['network'].get(pnet.NETWORK_TYPE))
  314. def test_create_provider_flat_network_with_vlan(self):
  315. providernet_args = {pnet.NETWORK_TYPE: 'flat',
  316. pnet.SEGMENTATION_ID: 11}
  317. with mock.patch('vmware_nsxlib.v3.core_resources.NsxLibTransportZone.'
  318. 'get_transport_type', return_value='VLAN'):
  319. result = self._create_network(fmt='json', name='bad_flat_net',
  320. admin_state_up=True,
  321. providernet_args=providernet_args,
  322. arg_list=(pnet.NETWORK_TYPE,
  323. pnet.SEGMENTATION_ID))
  324. data = self.deserialize('json', result)
  325. # should fail
  326. self.assertEqual('InvalidInput', data['NeutronError']['type'])
  327. def test_create_provider_geneve_network(self):
  328. providernet_args = {pnet.NETWORK_TYPE: 'geneve'}
  329. with mock.patch('vmware_nsxlib.v3.core_resources.NsxLibLogicalSwitch.'
  330. 'create', side_effect=_return_id_key) as nsx_create, \
  331. mock.patch('vmware_nsxlib.v3.core_resources.NsxLibLogicalSwitch.'
  332. 'delete') as nsx_delete, \
  333. mock.patch('vmware_nsxlib.v3.core_resources.NsxLibTransportZone.'
  334. 'get_transport_type', return_value='OVERLAY'),\
  335. self.network(name='geneve_net',
  336. providernet_args=providernet_args,
  337. arg_list=(pnet.NETWORK_TYPE, )) as net:
  338. self.assertEqual('geneve', net['network'].get(pnet.NETWORK_TYPE))
  339. # make sure the network is created at the backend
  340. nsx_create.assert_called_once()
  341. # Delete the network and make sure it is deleted from the backend
  342. req = self.new_delete_request('networks', net['network']['id'])
  343. res = req.get_response(self.api)
  344. self.assertEqual(exc.HTTPNoContent.code, res.status_int)
  345. nsx_delete.assert_called_once()
  346. def test_create_provider_geneve_network_with_physical_net(self):
  347. physical_network = nsx_v3_mocks.DEFAULT_TIER0_ROUTER_UUID
  348. providernet_args = {pnet.NETWORK_TYPE: 'geneve',
  349. pnet.PHYSICAL_NETWORK: physical_network}
  350. with mock.patch(
  351. 'vmware_nsxlib.v3.core_resources.NsxLibTransportZone.'
  352. 'get_transport_type', return_value='OVERLAY'),\
  353. self.network(name='geneve_net',
  354. providernet_args=providernet_args,
  355. arg_list=(pnet.NETWORK_TYPE, )) as net:
  356. self.assertEqual('geneve', net['network'].get(pnet.NETWORK_TYPE))
  357. def test_create_provider_geneve_network_with_vlan(self):
  358. providernet_args = {pnet.NETWORK_TYPE: 'geneve',
  359. pnet.SEGMENTATION_ID: 11}
  360. with mock.patch(
  361. 'vmware_nsxlib.v3.core_resources.NsxLibTransportZone.'
  362. 'get_transport_type', return_value='OVERLAY'):
  363. result = self._create_network(fmt='json', name='bad_geneve_net',
  364. admin_state_up=True,
  365. providernet_args=providernet_args,
  366. arg_list=(pnet.NETWORK_TYPE,
  367. pnet.SEGMENTATION_ID))
  368. data = self.deserialize('json', result)
  369. # should fail
  370. self.assertEqual('InvalidInput', data['NeutronError']['type'])
  371. def test_create_provider_vlan_network(self):
  372. providernet_args = {pnet.NETWORK_TYPE: 'vlan',
  373. pnet.SEGMENTATION_ID: 11}
  374. with mock.patch('vmware_nsxlib.v3.core_resources.NsxLibLogicalSwitch.'
  375. 'create', side_effect=_return_id_key) as nsx_create, \
  376. mock.patch('vmware_nsxlib.v3.core_resources.NsxLibLogicalSwitch.'
  377. 'delete') as nsx_delete, \
  378. mock.patch('vmware_nsxlib.v3.core_resources.NsxLibTransportZone.'
  379. 'get_transport_type', return_value='VLAN'),\
  380. self.network(name='vlan_net',
  381. providernet_args=providernet_args,
  382. arg_list=(pnet.NETWORK_TYPE,
  383. pnet.SEGMENTATION_ID)) as net:
  384. self.assertEqual('vlan', net['network'].get(pnet.NETWORK_TYPE))
  385. # make sure the network is created at the backend
  386. nsx_create.assert_called_once()
  387. # Delete the network and make sure it is deleted from the backend
  388. req = self.new_delete_request('networks', net['network']['id'])
  389. res = req.get_response(self.api)
  390. self.assertEqual(exc.HTTPNoContent.code, res.status_int)
  391. nsx_delete.assert_called_once()
  392. def test_create_provider_nsx_network(self):
  393. physical_network = 'Fake logical switch'
  394. providernet_args = {pnet.NETWORK_TYPE: 'nsx-net',
  395. pnet.PHYSICAL_NETWORK: physical_network}
  396. with mock.patch(
  397. 'vmware_nsxlib.v3.core_resources.NsxLibLogicalSwitch.create',
  398. side_effect=nsxlib_exc.ResourceNotFound) as nsx_create, \
  399. mock.patch('vmware_nsxlib.v3.core_resources.NsxLibLogicalSwitch.'
  400. 'delete') as nsx_delete, \
  401. self.network(name='nsx_net',
  402. providernet_args=providernet_args,
  403. arg_list=(pnet.NETWORK_TYPE,
  404. pnet.PHYSICAL_NETWORK)) as net:
  405. self.assertEqual('nsx-net', net['network'].get(pnet.NETWORK_TYPE))
  406. self.assertEqual(physical_network,
  407. net['network'].get(pnet.PHYSICAL_NETWORK))
  408. # make sure the network is NOT created at the backend
  409. nsx_create.assert_not_called()
  410. # Delete the network. It should NOT deleted from the backend
  411. req = self.new_delete_request('networks', net['network']['id'])
  412. res = req.get_response(self.api)
  413. self.assertEqual(exc.HTTPNoContent.code, res.status_int)
  414. nsx_delete.assert_not_called()
  415. def test_create_provider_bad_nsx_network(self):
  416. physical_network = 'Bad logical switch'
  417. providernet_args = {pnet.NETWORK_TYPE: 'nsx-net',
  418. pnet.PHYSICAL_NETWORK: physical_network}
  419. with mock.patch(
  420. "vmware_nsxlib.v3.core_resources.NsxLibLogicalSwitch.get",
  421. side_effect=nsxlib_exc.ResourceNotFound):
  422. result = self._create_network(fmt='json', name='bad_nsx_net',
  423. admin_state_up=True,
  424. providernet_args=providernet_args,
  425. arg_list=(pnet.NETWORK_TYPE,
  426. pnet.PHYSICAL_NETWORK))
  427. data = self.deserialize('json', result)
  428. # should fail
  429. self.assertEqual('InvalidInput', data['NeutronError']['type'])
  430. def test_create_ens_network_with_no_port_sec(self):
  431. cfg.CONF.set_override('ens_support', True, 'nsx_v3')
  432. providernet_args = {psec.PORTSECURITY: False}
  433. with mock.patch("vmware_nsxlib.v3.core_resources.NsxLibTransportZone."
  434. "get_host_switch_mode", return_value="ENS"),\
  435. mock.patch(
  436. "vmware_nsxlib.v3.core_resources.NsxLibLogicalSwitch.get",
  437. return_value={'transport_zone_id': 'xxx'}):
  438. result = self._create_network(fmt='json', name='ens_net',
  439. admin_state_up=True,
  440. providernet_args=providernet_args,
  441. arg_list=(psec.PORTSECURITY,))
  442. res = self.deserialize('json', result)
  443. # should succeed, and net should have port security disabled
  444. self.assertFalse(res['network']['port_security_enabled'])
  445. def test_create_ens_network_with_port_sec(self):
  446. cfg.CONF.set_override('ens_support', True, 'nsx_v3')
  447. providernet_args = {psec.PORTSECURITY: True}
  448. with mock.patch("vmware_nsxlib.v3.NsxLib.get_version",
  449. return_value='2.3.0'),\
  450. mock.patch("vmware_nsxlib.v3.core_resources.NsxLibTransportZone."
  451. "get_host_switch_mode", return_value="ENS"),\
  452. mock.patch("vmware_nsxlib.v3.core_resources.NsxLibLogicalSwitch."
  453. "get", return_value={'transport_zone_id': 'xxx'}):
  454. result = self._create_network(fmt='json', name='ens_net',
  455. admin_state_up=True,
  456. providernet_args=providernet_args,
  457. arg_list=(psec.PORTSECURITY,))
  458. res = self.deserialize('json', result)
  459. # should fail
  460. self.assertEqual('NsxENSPortSecurity',
  461. res['NeutronError']['type'])
  462. def test_create_ens_network_with_port_sec_supported(self):
  463. cfg.CONF.set_override('ens_support', True, 'nsx_v3')
  464. providernet_args = {psec.PORTSECURITY: True}
  465. with mock.patch("vmware_nsxlib.v3.core_resources.NsxLibTransportZone."
  466. "get_host_switch_mode", return_value="ENS"),\
  467. mock.patch("vmware_nsxlib.v3.core_resources.NsxLibLogicalSwitch."
  468. "get", return_value={'transport_zone_id': 'xxx'}):
  469. result = self._create_network(fmt='json', name='ens_net',
  470. admin_state_up=True,
  471. providernet_args=providernet_args,
  472. arg_list=(psec.PORTSECURITY,))
  473. res = self.deserialize('json', result)
  474. # should succeed
  475. self.assertTrue(res['network'][psec.PORTSECURITY])
  476. def test_create_ens_network_disable_default_port_security(self):
  477. cfg.CONF.set_override('ens_support', True, 'nsx_v3')
  478. cfg.CONF.set_override('disable_port_security_for_ens', True, 'nsx_v3')
  479. mock_ens = mock.patch('vmware_nsxlib.v3'
  480. '.core_resources.NsxLibTransportZone'
  481. '.get_host_switch_mode', return_value='ENS')
  482. mock_tz = mock.patch('vmware_nsxlib.v3'
  483. '.core_resources.NsxLibLogicalSwitch.get',
  484. return_value={'transport_zone_id': 'xxx'})
  485. mock_tt = mock.patch('vmware_nsxlib.v3'
  486. '.core_resources.NsxLibTransportZone'
  487. '.get_transport_type', return_value='VLAN')
  488. data = {'network': {
  489. 'name': 'portsec_net',
  490. 'admin_state_up': True,
  491. 'shared': False,
  492. 'tenant_id': 'some_tenant',
  493. 'provider:network_type': 'flat',
  494. 'provider:physical_network': 'xxx',
  495. 'port_security_enabled': True}}
  496. with mock_ens, mock_tz, mock_tt:
  497. self.plugin.create_network(context.get_admin_context(), data)
  498. def test_create_ens_network_with_qos(self):
  499. cfg.CONF.set_override('ens_support', True, 'nsx_v3')
  500. mock_ens = mock.patch('vmware_nsxlib.v3'
  501. '.core_resources.NsxLibTransportZone'
  502. '.get_host_switch_mode', return_value='ENS')
  503. mock_tz = mock.patch('vmware_nsxlib.v3'
  504. '.core_resources.NsxLibLogicalSwitch.get',
  505. return_value={'transport_zone_id': 'xxx'})
  506. mock_tt = mock.patch('vmware_nsxlib.v3'
  507. '.core_resources.NsxLibTransportZone'
  508. '.get_transport_type', return_value='VLAN')
  509. mock_ver = mock.patch("vmware_nsxlib.v3.NsxLib.get_version",
  510. return_value='2.4.0')
  511. policy_id = uuidutils.generate_uuid()
  512. data = {'network': {
  513. 'name': 'qos_net',
  514. 'tenant_id': 'some_tenant',
  515. 'provider:network_type': 'flat',
  516. 'provider:physical_network': 'xxx',
  517. 'qos_policy_id': policy_id,
  518. 'port_security_enabled': False}}
  519. with mock_ens, mock_tz, mock_tt, mock_ver, mock.patch.object(
  520. self.plugin, '_validate_qos_policy_id'):
  521. self.assertRaises(n_exc.InvalidInput,
  522. self.plugin.create_network,
  523. context.get_admin_context(), data)
  524. def test_update_ens_network_with_qos(self):
  525. cfg.CONF.set_override('ens_support', True, 'nsx_v3')
  526. mock_ens = mock.patch('vmware_nsxlib.v3'
  527. '.core_resources.NsxLibTransportZone'
  528. '.get_host_switch_mode', return_value='ENS')
  529. mock_tz = mock.patch('vmware_nsxlib.v3'
  530. '.core_resources.NsxLibLogicalSwitch.get',
  531. return_value={'transport_zone_id': 'xxx'})
  532. mock_tt = mock.patch('vmware_nsxlib.v3'
  533. '.core_resources.NsxLibTransportZone'
  534. '.get_transport_type', return_value='VLAN')
  535. mock_ver = mock.patch("vmware_nsxlib.v3.NsxLib.get_version",
  536. return_value='2.4.0')
  537. data = {'network': {
  538. 'name': 'qos_net',
  539. 'tenant_id': 'some_tenant',
  540. 'provider:network_type': 'flat',
  541. 'provider:physical_network': 'xxx',
  542. 'admin_state_up': True,
  543. 'shared': False,
  544. 'port_security_enabled': False}}
  545. with mock_ens, mock_tz, mock_tt, mock_ver,\
  546. mock.patch.object(self.plugin, '_validate_qos_policy_id'):
  547. network = self.plugin.create_network(context.get_admin_context(),
  548. data)
  549. policy_id = uuidutils.generate_uuid()
  550. data = {'network': {
  551. 'id': network['id'],
  552. 'admin_state_up': True,
  553. 'shared': False,
  554. 'port_security_enabled': False,
  555. 'tenant_id': 'some_tenant',
  556. 'qos_policy_id': policy_id}}
  557. self.assertRaises(n_exc.InvalidInput,
  558. self.plugin.update_network,
  559. context.get_admin_context(),
  560. network['id'], data)
  561. def test_update_ens_network(self):
  562. cfg.CONF.set_override('ens_support', True, 'nsx_v3')
  563. providernet_args = {psec.PORTSECURITY: False}
  564. with mock.patch("vmware_nsxlib.v3.NsxLib.get_version",
  565. return_value='2.3.0'),\
  566. mock.patch("vmware_nsxlib.v3.core_resources.NsxLibTransportZone."
  567. "get_host_switch_mode", return_value="ENS"),\
  568. mock.patch("vmware_nsxlib.v3.core_resources.NsxLibLogicalSwitch."
  569. "get", return_value={'transport_zone_id': 'xxx'}):
  570. result = self._create_network(fmt='json', name='ens_net',
  571. admin_state_up=True,
  572. providernet_args=providernet_args,
  573. arg_list=(psec.PORTSECURITY,))
  574. net = self.deserialize('json', result)
  575. net_id = net['network']['id']
  576. args = {'network': {psec.PORTSECURITY: True}}
  577. req = self.new_update_request('networks', args,
  578. net_id, fmt='json')
  579. res = self.deserialize('json', req.get_response(self.api))
  580. # should fail
  581. self.assertEqual('NsxENSPortSecurity',
  582. res['NeutronError']['type'])
  583. def test_update_ens_network_psec_supported(self):
  584. cfg.CONF.set_override('ens_support', True, 'nsx_v3')
  585. providernet_args = {psec.PORTSECURITY: False}
  586. with mock.patch("vmware_nsxlib.v3.core_resources.NsxLibTransportZone."
  587. "get_host_switch_mode", return_value="ENS"),\
  588. mock.patch(
  589. "vmware_nsxlib.v3.core_resources.NsxLibLogicalSwitch.get",
  590. return_value={'transport_zone_id': 'xxx'}):
  591. result = self._create_network(fmt='json', name='ens_net',
  592. admin_state_up=True,
  593. providernet_args=providernet_args,
  594. arg_list=(psec.PORTSECURITY,))
  595. net = self.deserialize('json', result)
  596. net_id = net['network']['id']
  597. args = {'network': {psec.PORTSECURITY: True}}
  598. req = self.new_update_request('networks', args,
  599. net_id, fmt='json')
  600. res = self.deserialize('json', req.get_response(self.api))
  601. # should succeed
  602. self.assertTrue(res['network'][psec.PORTSECURITY])
  603. def test_create_transparent_vlan_network(self):
  604. providernet_args = {vlan_apidef.VLANTRANSPARENT: True}
  605. with mock.patch(
  606. 'vmware_nsxlib.v3.core_resources.NsxLibTransportZone.'
  607. 'get_transport_type', return_value='OVERLAY'),\
  608. self.network(name='vt_net',
  609. providernet_args=providernet_args,
  610. arg_list=(vlan_apidef.VLANTRANSPARENT, )) as net:
  611. self.assertTrue(net['network'].get(vlan_apidef.VLANTRANSPARENT))
  612. def test_create_provider_vlan_network_with_transparent(self):
  613. providernet_args = {pnet.NETWORK_TYPE: 'vlan',
  614. vlan_apidef.VLANTRANSPARENT: True}
  615. with mock.patch('vmware_nsxlib.v3.core_resources.NsxLibTransportZone.'
  616. 'get_transport_type', return_value='VLAN'):
  617. result = self._create_network(fmt='json', name='badvlan_net',
  618. admin_state_up=True,
  619. providernet_args=providernet_args,
  620. arg_list=(
  621. pnet.NETWORK_TYPE,
  622. pnet.SEGMENTATION_ID,
  623. vlan_apidef.VLANTRANSPARENT))
  624. data = self.deserialize('json', result)
  625. self.assertEqual('vlan', data['network'].get(pnet.NETWORK_TYPE))
  626. def _test_generate_tag(self, vlan_id):
  627. net_type = 'vlan'
  628. name = 'phys_net'
  629. plugin = directory.get_plugin()
  630. plugin._network_vlans = plugin_utils.parse_network_vlan_ranges(
  631. cfg.CONF.nsx_v3.network_vlan_ranges)
  632. expected = [('subnets', []), ('name', name),
  633. ('admin_state_up', True),
  634. ('status', 'ACTIVE'),
  635. ('shared', False),
  636. (pnet.NETWORK_TYPE, net_type),
  637. (pnet.PHYSICAL_NETWORK,
  638. 'fb69d878-958e-4f32-84e4-50286f26226b'),
  639. (pnet.SEGMENTATION_ID, vlan_id)]
  640. providernet_args = {pnet.NETWORK_TYPE: net_type,
  641. pnet.PHYSICAL_NETWORK:
  642. 'fb69d878-958e-4f32-84e4-50286f26226b'}
  643. gtt_path = "vmware_nsxlib.v3.core_resources." \
  644. "NsxLibTransportZone.get_transport_type"
  645. with mock.patch(gtt_path, return_value='VLAN'):
  646. with self.network(name=name, providernet_args=providernet_args,
  647. arg_list=(pnet.NETWORK_TYPE,
  648. pnet.PHYSICAL_NETWORK)) as net:
  649. for k, v in expected:
  650. self.assertEqual(net['network'][k], v)
  651. def test_create_phys_vlan_generate(self):
  652. cfg.CONF.set_override('network_vlan_ranges',
  653. 'fb69d878-958e-4f32-84e4-50286f26226b',
  654. 'nsx_v3')
  655. self._test_generate_tag(1)
  656. def test_create_phys_vlan_generate_range(self):
  657. cfg.CONF.set_override('network_vlan_ranges',
  658. 'fb69d878-958e-4f32-84e4-'
  659. '50286f26226b:100:110',
  660. 'nsx_v3')
  661. self._test_generate_tag(100)
  662. def test_create_phys_vlan_network_outofrange_returns_503(self):
  663. cfg.CONF.set_override('network_vlan_ranges',
  664. 'fb69d878-958e-4f32-84e4-'
  665. '50286f26226b:9:10',
  666. 'nsx_v3')
  667. self._test_generate_tag(9)
  668. self._test_generate_tag(10)
  669. with testlib_api.ExpectedException(exc.HTTPClientError) as ctx_manager:
  670. self._test_generate_tag(11)
  671. self.assertEqual(ctx_manager.exception.code, 503)
  672. def test_update_external_flag_on_net(self):
  673. with self.network() as net:
  674. # should fail to update the network to external
  675. args = {'network': {'router:external': 'True'}}
  676. req = self.new_update_request('networks', args,
  677. net['network']['id'], fmt='json')
  678. res = self.deserialize('json', req.get_response(self.api))
  679. self.assertEqual('InvalidInput',
  680. res['NeutronError']['type'])
  681. def test_network_update_external(self):
  682. # This plugin does not support updating the external flag of a network
  683. self.skipTest("UnSupported")
  684. def test_network_update_external_failure(self):
  685. data = {'network': {'name': 'net1',
  686. 'router:external': 'True',
  687. 'tenant_id': 'tenant_one',
  688. 'provider:physical_network': 'stam'}}
  689. network_req = self.new_create_request('networks', data)
  690. network = self.deserialize(self.fmt,
  691. network_req.get_response(self.api))
  692. ext_net_id = network['network']['id']
  693. # should fail to update the network to non-external
  694. args = {'network': {'router:external': 'False'}}
  695. req = self.new_update_request('networks', args,
  696. ext_net_id, fmt='json')
  697. res = self.deserialize('json', req.get_response(self.api))
  698. self.assertEqual('InvalidInput',
  699. res['NeutronError']['type'])
  700. def test_update_network_rollback(self):
  701. with self.network() as net:
  702. # Fail the backend update
  703. with mock.patch("vmware_nsxlib.v3.core_resources."
  704. "NsxLibLogicalSwitch.update",
  705. side_effect=nsxlib_exc.InvalidInput):
  706. args = {'network': {'description': 'test rollback'}}
  707. req = self.new_update_request('networks', args,
  708. net['network']['id'], fmt='json')
  709. res = self.deserialize('json', req.get_response(self.api))
  710. # should fail with the nsxlib error (meaning that the rollback
  711. # did not fail)
  712. self.assertEqual('InvalidInput',
  713. res['NeutronError']['type'])
  714. class TestSubnetsV2(common_v3.NsxV3TestSubnets, NsxV3PluginTestCaseMixin):
  715. def setUp(self, plugin=PLUGIN_NAME, ext_mgr=None):
  716. super(TestSubnetsV2, self).setUp(plugin=plugin, ext_mgr=ext_mgr)
  717. def test_create_subnet_with_shared_address_space(self):
  718. with self.network() as network:
  719. data = {'subnet': {'network_id': network['network']['id'],
  720. 'cidr': '100.64.0.0/16',
  721. 'name': 'sub1',
  722. 'enable_dhcp': False,
  723. 'dns_nameservers': None,
  724. 'allocation_pools': None,
  725. 'tenant_id': 'tenant_one',
  726. 'host_routes': None,
  727. 'ip_version': 4}}
  728. self.assertRaises(n_exc.InvalidInput,
  729. self.plugin.create_subnet,
  730. context.get_admin_context(), data)
  731. def _create_external_network(self):
  732. data = {'network': {'name': 'net1',
  733. 'router:external': 'True',
  734. 'tenant_id': 'tenant_one',
  735. 'provider:physical_network': 'stam'}}
  736. network_req = self.new_create_request('networks', data)
  737. network = self.deserialize(self.fmt,
  738. network_req.get_response(self.api))
  739. return network
  740. def test_create_subnet_with_conflicting_t0_address(self):
  741. network = self._create_external_network()
  742. data = {'subnet': {'network_id': network['network']['id'],
  743. 'cidr': '172.20.1.0/24',
  744. 'name': 'sub1',
  745. 'enable_dhcp': False,
  746. 'dns_nameservers': None,
  747. 'allocation_pools': None,
  748. 'tenant_id': 'tenant_one',
  749. 'host_routes': None,
  750. 'ip_version': 4}}
  751. ports = [{'subnets': [{'ip_addresses': [u'172.20.1.60'],
  752. 'prefix_length': 24}],
  753. 'resource_type': 'LogicalRouterUpLinkPort'}]
  754. with mock.patch.object(self.plugin.nsxlib.logical_router_port,
  755. 'get_by_router_id',
  756. return_value=ports):
  757. self.assertRaises(n_exc.InvalidInput,
  758. self.plugin.create_subnet,
  759. context.get_admin_context(), data)
  760. def test_subnet_native_dhcp_subnet_enabled(self):
  761. self._enable_native_dhcp_md()
  762. with self.network() as network:
  763. with mock.patch.object(self.plugin,
  764. '_enable_native_dhcp') as enable_dhcp,\
  765. self.subnet(network=network, enable_dhcp=True):
  766. # Native dhcp should be set for this subnet
  767. self.assertTrue(enable_dhcp.called)
  768. def test_subnet_native_dhcp_subnet_disabled(self):
  769. self._enable_native_dhcp_md()
  770. with self.network() as network:
  771. with mock.patch.object(self.plugin,
  772. '_enable_native_dhcp') as enable_dhcp,\
  773. self.subnet(network=network, enable_dhcp=False):
  774. # Native dhcp should not be set for this subnet
  775. self.assertFalse(enable_dhcp.called)
  776. def test_subnet_native_dhcp_with_relay(self):
  777. """Verify that the relay service is added to the router interface"""
  778. self._enable_dhcp_relay()
  779. with self.network() as network:
  780. with mock.patch.object(self.plugin,
  781. '_enable_native_dhcp') as enable_dhcp,\
  782. self.subnet(network=network, enable_dhcp=True):
  783. # Native dhcp should not be set for this subnet
  784. self.assertFalse(enable_dhcp.called)
  785. def test_subnet_native_dhcp_flat_subnet_disabled(self):
  786. self._enable_native_dhcp_md()
  787. providernet_args = {pnet.NETWORK_TYPE: 'flat'}
  788. with mock.patch('vmware_nsxlib.v3.core_resources.NsxLibTransportZone.'
  789. 'get_transport_type', return_value='VLAN'):
  790. with self.network(name='flat_net',
  791. providernet_args=providernet_args,
  792. arg_list=(pnet.NETWORK_TYPE, )) as network:
  793. data = {'subnet': {'network_id': network['network']['id'],
  794. 'cidr': '172.20.1.0/24',
  795. 'name': 'sub1',
  796. 'enable_dhcp': False,
  797. 'dns_nameservers': None,
  798. 'allocation_pools': None,
  799. 'tenant_id': 'tenant_one',
  800. 'host_routes': None,
  801. 'ip_version': 4}}
  802. self.plugin.create_subnet(
  803. context.get_admin_context(), data)
  804. def test_subnet_native_dhcp_flat_subnet_enabled(self):
  805. self._enable_native_dhcp_md()
  806. providernet_args = {pnet.NETWORK_TYPE: 'flat'}
  807. with mock.patch('vmware_nsxlib.v3.core_resources.NsxLibTransportZone.'
  808. 'get_transport_type', return_value='VLAN'):
  809. with self.network(name='flat_net',
  810. providernet_args=providernet_args,
  811. arg_list=(pnet.NETWORK_TYPE, )) as network:
  812. data = {'subnet': {'network_id': network['network']['id'],
  813. 'cidr': '172.20.1.0/24',
  814. 'name': 'sub1',
  815. 'enable_dhcp': True,
  816. 'dns_nameservers': None,
  817. 'allocation_pools': None,
  818. 'tenant_id': 'tenant_one',
  819. 'host_routes': None,
  820. 'ip_version': 4}}
  821. self.assertRaises(n_exc.InvalidInput,
  822. self.plugin.create_subnet,
  823. context.get_admin_context(), data)
  824. def test_fail_create_static_routes_per_subnet_over_limit(self):
  825. with self.network() as network:
  826. data = {'subnet': {'network_id': network['network']['id'],
  827. 'cidr': '10.0.0.0/16',
  828. 'name': 'sub1',
  829. 'dns_nameservers': None,
  830. 'allocation_pools': None,
  831. 'tenant_id': 'tenant_one',
  832. 'enable_dhcp': False,
  833. 'ip_version': 4}}
  834. count = 1
  835. host_routes = []
  836. while count < nsx_constants.MAX_STATIC_ROUTES:
  837. host_routes.append("'host_routes': [{'destination': "
  838. "'135.207.0.0/%s', 'nexthop': "
  839. "'1.2.3.%s'}]" % (count, count))
  840. count += 1
  841. data['subnet']['host_routes'] = host_routes
  842. self.assertRaises(n_exc.InvalidInput,
  843. self.plugin.create_subnet,
  844. context.get_admin_context(), data)
  845. def test_create_subnet_disable_dhcp_with_host_route_fails(self):
  846. with self.network() as network:
  847. data = {'subnet': {'network_id': network['network']['id'],
  848. 'cidr': '172.20.1.0/24',
  849. 'name': 'sub1',
  850. 'dns_nameservers': None,
  851. 'allocation_pools': None,
  852. 'tenant_id': 'tenant_one',
  853. 'enable_dhcp': False,
  854. 'host_routes': [{
  855. 'destination': '135.207.0.0/16',
  856. 'nexthop': '1.2.3.4'}],
  857. 'ip_version': 4}}
  858. self.assertRaises(n_exc.InvalidInput,
  859. self.plugin.create_subnet,
  860. context.get_admin_context(), data)
  861. def test_update_subnet_disable_dhcp_with_host_route_fails(self):
  862. with self.network() as network:
  863. data = {'subnet': {'network_id': network['network']['id'],
  864. 'cidr': '172.20.1.0/24',
  865. 'name': 'sub1',
  866. 'dns_nameservers': None,
  867. 'allocation_pools': None,
  868. 'tenant_id': 'tenant_one',
  869. 'enable_dhcp': True,
  870. 'host_routes': [{
  871. 'destination': '135.207.0.0/16',
  872. 'nexthop': '1.2.3.4'}],
  873. 'ip_version': 4}}
  874. subnet = self.plugin.create_subnet(
  875. context.get_admin_context(), data)
  876. data['subnet']['enable_dhcp'] = False
  877. self.assertRaises(n_exc.InvalidInput,
  878. self.plugin.update_subnet,
  879. context.get_admin_context(), subnet['id'], data)
  880. class TestPortsV2(common_v3.NsxV3SubnetMixin,
  881. common_v3.NsxV3TestPorts, NsxV3PluginTestCaseMixin,
  882. test_bindings.PortBindingsTestCase,
  883. test_bindings.PortBindingsHostTestCaseMixin,
  884. test_bindings.PortBindingsVnicTestCaseMixin):
  885. VIF_TYPE = portbindings.VIF_TYPE_OVS
  886. HAS_PORT_FILTER = True
  887. def setUp(self):
  888. cfg.CONF.set_override('switching_profiles', [NSX_SWITCH_PROFILE],
  889. 'nsx_v3')
  890. # add vlan transparent to the configuration
  891. cfg.CONF.set_override('vlan_transparent', True)
  892. super(TestPortsV2, self).setUp()
  893. self.plugin = directory.get_plugin()
  894. self.ctx = context.get_admin_context()
  895. def test_update_port_delete_ip(self):
  896. # This test case overrides the default because the nsx plugin
  897. # implements port_security/security groups and it is not allowed
  898. # to remove an ip address from a port unless the security group
  899. # is first removed.
  900. with self.subnet() as subnet:
  901. with self.port(subnet=subnet) as port:
  902. data = {'port': {'admin_state_up': False,
  903. 'fixed_ips': [],
  904. secgrp.SECURITYGROUPS: []}}
  905. req = self.new_update_request('ports',
  906. data, port['port']['id'])
  907. res = self.deserialize('json', req.get_response(self.api))
  908. self.assertEqual(res['port']['admin_state_up'],
  909. data['port']['admin_state_up'])
  910. self.assertEqual(res['port']['fixed_ips'],
  911. data['port']['fixed_ips'])
  912. def test_delete_dhcp_port(self):
  913. self._enable_native_dhcp_md()
  914. with self.subnet():
  915. pl = directory.get_plugin()
  916. ctx = context.Context(user_id=None, tenant_id=self._tenant_id,
  917. is_admin=False)
  918. ports = pl.get_ports(
  919. ctx, filters={'device_owner': [constants.DEVICE_OWNER_DHCP]})
  920. req = self.new_delete_request('ports', ports[0]['id'])
  921. res = req.get_response(self.api)
  922. self.assertEqual(exc.HTTPBadRequest.code, res.status_int)
  923. def test_fail_create_port_with_ext_net(self):
  924. expected_error = 'InvalidInput'
  925. with self._create_l3_ext_network() as network:
  926. with self.subnet(network=network, cidr='10.0.0.0/24'):
  927. device_owner = constants.DEVICE_OWNER_COMPUTE_PREFIX + 'X'
  928. res = self._create_port(self.fmt,
  929. network['network']['id'],
  930. exc.HTTPBadRequest.code,
  931. device_owner=device_owner)
  932. data = self.deserialize(self.fmt, res)
  933. self.assertEqual(expected_error, data['NeutronError']['type'])
  934. def test_fail_update_port_with_ext_net(self):
  935. with self._create_l3_ext_network() as network:
  936. with self.subnet(network=network, cidr='10.0.0.0/24') as subnet:
  937. with self.port(subnet=subnet) as port:
  938. device_owner = constants.DEVICE_OWNER_COMPUTE_PREFIX + 'X'
  939. data = {'port': {'device_owner': device_owner}}
  940. req = self.new_update_request('ports',
  941. data, port['port']['id'])
  942. res = req.get_response(self.api)
  943. self.assertEqual(exc.HTTPBadRequest.code,
  944. res.status_int)
  945. def test_fail_update_lb_port_with_allowed_address_pairs(self):
  946. with self.network() as network:
  947. data = {'port': {
  948. 'network_id': network['network']['id'],
  949. 'tenant_id': self._tenant_id,
  950. 'name': 'pair_port',
  951. 'admin_state_up': True,
  952. 'device_id': 'fake_device',
  953. 'device_owner': constants.DEVICE_OWNER_LOADBALANCERV2,
  954. 'fixed_ips': []}
  955. }
  956. port = self.plugin.create_port(self.ctx, data)
  957. data['port']['allowed_address_pairs'] = '10.0.0.1'
  958. self.assertRaises(
  959. n_exc.InvalidInput,
  960. self.plugin.update_port, self.ctx, port['id'], data)
  961. def test_fail_create_allowed_address_pairs_over_limit(self):
  962. with self.network() as network, self.subnet(
  963. network=network, enable_dhcp=True) as s1:
  964. data = {
  965. 'port': {
  966. 'network_id': network['network']['id'],
  967. 'tenant_id': self._tenant_id,
  968. 'name': 'pair_port',
  969. 'admin_state_up': True,
  970. 'device_id': 'fake_device',
  971. 'device_owner': 'fake_owner',
  972. 'fixed_ips': [{'subnet_id': s1['subnet']['id']}]
  973. }
  974. }
  975. count = 1
  976. address_pairs = []
  977. while count < 129:
  978. address_pairs.append({'ip_address': '10.0.0.%s' % count})
  979. count += 1
  980. data['port']['allowed_address_pairs'] = address_pairs
  981. self.assertRaises(n_exc.InvalidInput,
  982. self.plugin.create_port, self.ctx, data)
  983. def test_fail_update_lb_port_with_fixed_ip(self):
  984. with self.network() as network:
  985. data = {'port': {
  986. 'network_id': network['network']['id'],
  987. 'tenant_id': self._tenant_id,
  988. 'name': 'pair_port',
  989. 'admin_state_up': True,
  990. 'device_id': 'fake_device',
  991. 'device_owner': constants.DEVICE_OWNER_LOADBALANCERV2,
  992. 'fixed_ips': []}
  993. }
  994. port = self.plugin.create_port(self.ctx, data)
  995. data['port']['fixed_ips'] = '10.0.0.1'
  996. self.assertRaises(
  997. n_exc.InvalidInput,
  998. self.plugin.update_port, self.ctx, port['id'], data)
  999. def test_create_port_with_qos(self):
  1000. with self.network() as network:
  1001. policy_id = uuidutils.generate_uuid()
  1002. data = {'port': {
  1003. 'network_id': network['network']['id'],
  1004. 'tenant_id': self._tenant_id,
  1005. 'qos_policy_id': policy_id,
  1006. 'name': 'qos_port',
  1007. 'admin_state_up': True,
  1008. 'device_id': 'fake_device',
  1009. 'device_owner': 'fake_owner',
  1010. 'fixed_ips': [],
  1011. 'mac_address': '00:00:00:00:00:01'}
  1012. }
  1013. with mock.patch.object(self.plugin, '_get_qos_profile_id'),\
  1014. mock.patch.object(self.plugin, '_validate_qos_policy_id'):
  1015. port = self.plugin.create_port(self.ctx, data)
  1016. self.assertEqual(policy_id, port['qos_policy_id'])
  1017. # Get port should also return the qos policy id
  1018. with mock.patch('vmware_nsx.services.qos.common.utils.'
  1019. 'get_port_policy_id',
  1020. return_value=policy_id):
  1021. port = self.plugin.get_port(self.ctx, port['id'])
  1022. self.assertEqual(policy_id, port['qos_policy_id'])
  1023. def test_update_port_with_qos(self):
  1024. with self.network() as network:
  1025. data = {'port': {
  1026. 'network_id': network['network']['id'],
  1027. 'tenant_id': self._tenant_id,
  1028. 'name': 'qos_port',
  1029. 'admin_state_up': True,
  1030. 'device_id': 'fake_device',
  1031. 'device_owner': 'fake_owner',
  1032. 'fixed_ips': [],
  1033. 'mac_address': '00:00:00:00:00:01'}
  1034. }
  1035. port = self.plugin.create_port(self.ctx, data)
  1036. policy_id = uuidutils.generate_uuid()
  1037. data['port']['qos_policy_id'] = policy_id
  1038. with mock.patch.object(self.plugin, '_get_qos_profile_id'),\
  1039. mock.patch.object(self.plugin, '_validate_qos_policy_id'):
  1040. res = self.plugin.update_port(self.ctx, port['id'], data)
  1041. self.assertEqual(policy_id, res['qos_policy_id'])
  1042. # Get port should also return the qos policy id
  1043. with mock.patch('vmware_nsx.services.qos.common.utils.'
  1044. 'get_port_policy_id',
  1045. return_value=policy_id):
  1046. res = self.plugin.get_port(self.ctx, port['id'])
  1047. self.assertEqual(policy_id, res['qos_policy_id'])
  1048. # now remove the qos from the port
  1049. data['port']['qos_policy_id'] = None
  1050. res = self.plugin.update_port(self.ctx, port['id'], data)
  1051. self.assertIsNone(res['qos_policy_id'])
  1052. def test_create_ext_port_with_qos_fail(self):
  1053. with self._create_l3_ext_network() as network:
  1054. with self.subnet(network=network, cidr='10.0.0.0/24'),\
  1055. mock.patch.object(self.plugin, '_validate_qos_policy_id'):
  1056. policy_id = uuidutils.generate_uuid()
  1057. data = {'port': {'network_id': network['network']['id'],
  1058. 'tenant_id': self._tenant_id,
  1059. 'qos_policy_id': policy_id}}
  1060. # Cannot add qos policy to a router port
  1061. self.assertRaises(n_exc.InvalidInput,
  1062. self.plugin.create_port, self.ctx, data)
  1063. def _test_create_illegal_port_with_qos_fail(self, device_owner):
  1064. with self.network() as network:
  1065. with self.subnet(network=network, cidr='10.0.0.0/24'),\
  1066. mock.patch.object(self.plugin, '_validate_qos_policy_id'):
  1067. policy_id = uuidutils.generate_uuid()
  1068. data = {'port': {'network_id': network['network']['id'],
  1069. 'tenant_id': self._tenant_id,
  1070. 'device_owner': device_owner,
  1071. 'qos_policy_id': policy_id}}
  1072. # Cannot add qos policy to this type of port
  1073. self.assertRaises(n_exc.InvalidInput,
  1074. self.plugin.create_port, self.ctx, data)
  1075. def test_create_port_ens_with_qos_fail(self):
  1076. with self.network() as network:
  1077. with self.subnet(network=network, cidr='10.0.0.0/24'):
  1078. policy_id = uuidutils.generate_uuid()
  1079. mock_ens = mock.patch('vmware_nsxlib.v3'
  1080. '.core_resources.NsxLibTransportZone'
  1081. '.get_host_switch_mode',
  1082. return_value='ENS')
  1083. mock_tz = mock.patch('vmware_nsxlib.v3'
  1084. '.core_resources'
  1085. '.NsxLibLogicalSwitch.get',
  1086. return_value={
  1087. 'transport_zone_id': 'xxx'})
  1088. mock_tt = mock.patch('vmware_nsxlib.v3'
  1089. '.core_resources.NsxLibTransportZone'
  1090. '.get_transport_type',
  1091. return_value='VLAN')
  1092. mock_ver = mock.patch("vmware_nsxlib.v3.NsxLib.get_version",
  1093. return_value='2.4.0')
  1094. data = {'port': {
  1095. 'network_id': network['network']['id'],
  1096. 'tenant_id': self._tenant_id,
  1097. 'name': 'qos_port',
  1098. 'admin_state_up': True,
  1099. 'device_id': 'fake_device',
  1100. 'device_owner': 'fake_owner',
  1101. 'fixed_ips': [],
  1102. 'port_security_enabled': False,
  1103. 'mac_address': '00:00:00:00:00:01',
  1104. 'qos_policy_id': policy_id}
  1105. }
  1106. # Cannot add qos policy to this type of port
  1107. with mock_ens, mock_tz, mock_tt, mock_ver,\
  1108. mock.patch.object(self.plugin, '_validate_qos_policy_id'):
  1109. self.assertRaises(n_exc.InvalidInput,
  1110. self.plugin.create_port, self.ctx, data)
  1111. def test_create_port_ens_with_sg(self):
  1112. cfg.CONF.set_override('disable_port_security_for_ens', True, 'nsx_v3')
  1113. with self.network() as network:
  1114. with self.subnet(network=network, cidr='10.0.0.0/24'):
  1115. mock_ens = mock.patch('vmware_nsxlib.v3'
  1116. '.core_resources.NsxLibTransportZone'
  1117. '.get_host_switch_mode',
  1118. return_value='ENS')
  1119. mock_tz = mock.patch('vmware_nsxlib.v3'
  1120. '.core_resources'
  1121. '.NsxLibLogicalSwitch.get',
  1122. return_value={
  1123. 'transport_zone_id': 'xxx'})
  1124. mock_tt = mock.patch('vmware_nsxlib.v3'
  1125. '.core_resources.NsxLibTransportZone'
  1126. '.get_transport_type',
  1127. return_value='VLAN')
  1128. data = {'port': {
  1129. 'network_id': network['network']['id'],
  1130. 'tenant_id': self._tenant_id,
  1131. 'name': 'sg_port',
  1132. 'admin_state_up': True,
  1133. 'device_id': 'fake_device',
  1134. 'device_owner': 'fake_owner',
  1135. 'fixed_ips': [],
  1136. 'mac_address': '00:00:00:00:00:01',
  1137. 'port_security_enabled': True}
  1138. }
  1139. with mock_ens, mock_tz, mock_tt:
  1140. self.plugin.create_port(self.ctx, data)
  1141. def test_update_port_ens_with_qos_fail(self):
  1142. with self.network() as network:
  1143. with self.subnet(network=network, cidr='10.0.0.0/24'):
  1144. policy_id = uuidutils.generate_uuid()
  1145. mock_ens = mock.patch('vmware_nsxlib.v3'
  1146. '.core_resources.NsxLibTransportZone'
  1147. '.get_host_switch_mode',
  1148. return_value='ENS')
  1149. mock_tz = mock.patch('vmware_nsxlib.v3'
  1150. '.core_resources'
  1151. '.NsxLibLogicalSwitch.get',
  1152. return_value={
  1153. 'transport_zone_id': 'xxx'})
  1154. mock_tt = mock.patch('vmware_nsxlib.v3'
  1155. '.core_resources.NsxLibTransportZone'
  1156. '.get_transport_type',
  1157. return_value='VLAN')
  1158. mock_ver = mock.patch("vmware_nsxlib.v3.NsxLib.get_version",
  1159. return_value='2.4.0')
  1160. data = {'port': {
  1161. 'network_id': network['network']['id'],
  1162. 'tenant_id': self._tenant_id,
  1163. 'name': 'qos_port',
  1164. 'admin_state_up': True,
  1165. 'device_id': 'fake_device',
  1166. 'device_owner': 'fake_owner',
  1167. 'fixed_ips': [],
  1168. 'port_security_enabled': False,
  1169. 'mac_address': '00:00:00:00:00:01'}
  1170. }
  1171. with mock_ens, mock_tz, mock_tt, mock_ver,\
  1172. mock.patch.object(self.plugin, '_validate_qos_policy_id'):
  1173. port = self.plugin.create_port(self.ctx, data)
  1174. data['port'] = {'qos_policy_id': policy_id}
  1175. self.assertRaises(n_exc.InvalidInput,
  1176. self.plugin.update_port,
  1177. self.ctx, port['id'], data)
  1178. def test_create_port_with_mac_learning_true(self):
  1179. with self.network() as network:
  1180. data = {'port': {
  1181. 'network_id': network['network']['id'],
  1182. 'tenant_id': self._tenant_id,
  1183. 'name': 'qos_port',
  1184. 'admin_state_up': True,
  1185. 'device_id': 'fake_device',
  1186. 'device_owner': 'fake_owner',
  1187. 'fixed_ips': [],
  1188. 'port_security_enabled': False,
  1189. 'mac_address': '00:00:00:00:00:01',
  1190. 'mac_learning_enabled': True}
  1191. }
  1192. port = self.plugin.create_port(self.ctx, data)
  1193. self.assertTrue(port['mac_learning_enabled'])
  1194. def test_create_port_with_mac_learning_false(self):
  1195. with self.network() as network:
  1196. data = {'port': {
  1197. 'network_id': network['network']['id'],
  1198. 'tenant_id': self._tenant_id,
  1199. 'name': 'qos_port',
  1200. 'admin_state_up': True,
  1201. 'device_id': 'fake_device',
  1202. 'device_owner': 'fake_owner',
  1203. 'fixed_ips': [],
  1204. 'port_security_enabled': False,
  1205. 'mac_address': '00:00:00:00:00:01',
  1206. 'mac_learning_enabled': False}
  1207. }
  1208. port = self.plugin.create_port(self.ctx, data)
  1209. self.assertFalse(port['mac_learning_enabled'])
  1210. def test_update_port_with_mac_learning_true(self):
  1211. with self.network() as network:
  1212. data = {'port': {
  1213. 'network_id': network['network']['id'],
  1214. 'tenant_id': self._tenant_id,
  1215. 'name': 'qos_port',
  1216. 'admin_state_up': True,
  1217. 'device_id': 'fake_device',
  1218. 'device_owner': 'fake_owner',
  1219. 'fixed_ips': [],
  1220. 'port_security_enabled': False,
  1221. 'mac_address': '00:00:00:00:00:01'}
  1222. }
  1223. port = self.plugin.create_port(self.ctx, data)
  1224. data['port']['mac_learning_enabled'] = True
  1225. update_res = self.plugin.update_port(self.ctx, port['id'], data)
  1226. self.assertTrue(update_res['mac_learning_enabled'])
  1227. def test_update_port_with_mac_learning_false(self):
  1228. with self.network() as network:
  1229. data = {'port': {
  1230. 'network_id': network['network']['id'],
  1231. 'tenant_id': self._tenant_id,
  1232. 'name': 'qos_port',
  1233. 'admin_state_up': True,
  1234. 'device_id': 'fake_device',
  1235. 'device_owner': 'fake_owner',
  1236. 'fixed_ips': [],
  1237. 'port_security_enabled': False,
  1238. 'mac_address': '00:00:00:00:00:01'}
  1239. }
  1240. port = self.plugin.create_port(self.ctx, data)
  1241. data['port']['mac_learning_enabled'] = False
  1242. update_res = self.plugin.update_port(self.ctx, port['id'], data)
  1243. self.assertFalse(update_res['mac_learning_enabled'])
  1244. def test_update_port_with_mac_learning_failes(self):
  1245. with self.network() as network:
  1246. data = {'port': {
  1247. 'network_id': network['network']['id'],
  1248. 'tenant_id': self._tenant_id,
  1249. 'name': 'qos_port',
  1250. 'admin_state_up': True,
  1251. 'device_id': 'fake_device',
  1252. 'device_owner': constants.DEVICE_OWNER_FLOATINGIP,
  1253. 'fixed_ips': [],
  1254. 'port_security_enabled': False,
  1255. 'mac_address': '00:00:00:00:00:01'}
  1256. }
  1257. port = self.plugin.create_port(self.ctx, data)
  1258. data['port']['mac_learning_enabled'] = True
  1259. self.assertRaises(
  1260. n_exc.InvalidInput,
  1261. self.plugin.update_port, self.ctx, port['id'], data)
  1262. def test_create_router_port_with_qos_fail(self):
  1263. self._test_create_illegal_port_with_qos_fail(
  1264. 'network:router_interface')
  1265. def test_create_dhcp_port_with_qos_fail(self):
  1266. self._test_create_illegal_port_with_qos_fail('network:dhcp')
  1267. def _test_update_illegal_port_with_qos_fail(self, device_owner):
  1268. with self.network() as network:
  1269. with self.subnet(network=network, cidr='10.0.0.0/24'),\
  1270. mock.patch.object(self.plugin, '_validate_qos_policy_id'):
  1271. policy_id = uuidutils.generate_uuid()
  1272. data = {'port': {'network_id': network['network']['id'],
  1273. 'tenant_id': self._tenant_id,
  1274. 'name': 'qos_port',
  1275. 'admin_state_up': True,
  1276. 'fixed_ips': [],
  1277. 'mac_address': '00:00:00:00:00:01',
  1278. 'device_id': 'dummy',
  1279. 'device_owner': ''}}
  1280. port = self.plugin.create_port(self.ctx, data)
  1281. policy_id = uuidutils.generate_uuid()
  1282. data['port'] = {'qos_policy_id': policy_id,
  1283. 'device_owner': device_owner}
  1284. # Cannot add qos policy to a router interface port
  1285. self.assertRaises(n_exc.InvalidInput,
  1286. self.plugin.update_port, self.ctx, port['id'], data)
  1287. def test_update_router_port_with_qos_fail(self):
  1288. self._test_update_illegal_port_with_qos_fail(
  1289. 'network:router_interface')
  1290. def test_update_dhcp_port_with_qos_fail(self):
  1291. self._test_update_illegal_port_with_qos_fail('network:dhcp')
  1292. def test_create_port_with_qos_on_net(self):
  1293. with self.network() as network:
  1294. policy_id = uuidutils.generate_uuid()
  1295. device_owner = constants.DEVICE_OWNER_COMPUTE_PREFIX + 'X'
  1296. data = {'port': {
  1297. 'network_id': network['network']['id'],
  1298. 'tenant_id': self._tenant_id,
  1299. 'name': 'qos_port',
  1300. 'admin_state_up': True,
  1301. 'device_id': 'fake_device',
  1302. 'device_owner': device_owner,
  1303. 'fixed_ips': [],
  1304. 'mac_address': '00:00:00:00:00:01'}
  1305. }
  1306. with mock.patch.object(self.plugin,
  1307. '_get_qos_profile_id') as get_profile,\
  1308. mock.patch('vmware_nsx.services.qos.common.utils.'
  1309. 'get_network_policy_id', return_value=policy_id),\
  1310. mock.patch.object(self.plugin, '_validate_qos_policy_id'):
  1311. self.plugin.create_port(self.ctx, data)
  1312. get_profile.assert_called_once_with(self.ctx, policy_id)
  1313. def test_update_port_with_qos_on_net(self):
  1314. with self.network() as network:
  1315. data = {'port': {
  1316. 'network_id': network['network']['id'],
  1317. 'tenant_id': self._tenant_id,
  1318. 'name': 'qos_port',
  1319. 'admin_state_up': True,
  1320. 'device_id': 'fake_device',
  1321. 'device_owner': 'fake_owner',
  1322. 'fixed_ips': [],
  1323. 'mac_address': '00:00:00:00:00:01'}
  1324. }
  1325. port = self.plugin.create_port(self.ctx, data)
  1326. policy_id = uuidutils.generate_uuid()
  1327. device_owner = constants.DEVICE_OWNER_COMPUTE_PREFIX + 'X'
  1328. data['port']['device_owner'] = device_owner
  1329. with mock.patch.object(self.plugin,
  1330. '_get_qos_profile_id') as get_profile,\
  1331. mock.patch('vmware_nsx.services.qos.common.utils.'
  1332. 'get_network_policy_id', return_value=policy_id),\
  1333. mock.patch.object(self.plugin, '_validate_qos_policy_id'):
  1334. self.plugin.update_port(self.ctx, port['id'], data)
  1335. get_profile.assert_called_once_with(self.ctx, policy_id)
  1336. def _get_ports_with_fields(self, tenid, fields, expected_count):
  1337. pl = directory.get_plugin()
  1338. ctx = context.Context(user_id=None, tenant_id=tenid,
  1339. is_admin=False)
  1340. ports = pl.get_ports(ctx, filters={'tenant_id': [tenid]},
  1341. fields=fields)
  1342. self.assertEqual(expected_count, len(ports))
  1343. def test_get_ports_with_fields(self):
  1344. with self.port(), self.port(), self.port(), self.port() as p:
  1345. tenid = p['port']['tenant_id']
  1346. # get all fields:
  1347. self._get_ports_with_fields(tenid, None, 4)
  1348. # get specific fields:
  1349. self._get_ports_with_fields(tenid, 'mac_address', 4)
  1350. self._get_ports_with_fields(tenid, 'network_id', 4)
  1351. def test_list_ports_filtered_by_security_groups(self):
  1352. ctx = context.get_admin_context()
  1353. with self.port() as port1, self.port() as port2:
  1354. query_params = "security_groups=%s" % (
  1355. port1['port']['security_groups'][0])
  1356. ports_data = self._list('ports', query_params=query_params)
  1357. self.assertEqual(set([port1['port']['id'], port2['port']['id']]),
  1358. set([port['id'] for port in ports_data['ports']]))
  1359. query_params = "security_groups=%s&id=%s" % (
  1360. port1['port']['security_groups'][0],
  1361. port1['port']['id'])
  1362. ports_data = self._list('ports', query_params=query_params)
  1363. self.assertEqual(port1['port']['id'], ports_data['ports'][0]['id'])
  1364. self.assertEqual(1, len(ports_data['ports']))
  1365. temp_sg = {'security_group': {'tenant_id': 'some_tenant',
  1366. 'name': '', 'description': 's'}}
  1367. sg_dbMixin = sg_db.SecurityGroupDbMixin()
  1368. sg = sg_dbMixin.create_security_group(ctx, temp_sg)
  1369. sg_dbMixin._delete_port_security_group_bindings(
  1370. ctx, port2['port']['id'])
  1371. sg_dbMixin._create_port_security_group_binding(
  1372. ctx, port2['port']['id'], sg['id'])
  1373. port2['port']['security_groups'][0] = sg['id']
  1374. query_params = "security_groups=%s" % (
  1375. port1['port']['security_groups'][0])
  1376. ports_data = self._list('ports', query_params=query_params)
  1377. self.assertEqual(port1['port']['id'], ports_data['ports'][0]['id'])
  1378. self.assertEqual(1, len(ports_data['ports']))
  1379. query_params = "security_groups=%s" % (
  1380. (port2['port']['security_groups'][0]))
  1381. ports_data = self._list('ports', query_params=query_params)
  1382. self.assertEqual(port2['port']['id'], ports_data['ports'][0]['id'])
  1383. def test_port_failure_rollback_dhcp_exception(self):
  1384. self._enable_native_dhcp_md()
  1385. self.plugin = directory.get_plugin()
  1386. with mock.patch.object(self.plugin, '_add_dhcp_binding',
  1387. side_effect=nsxlib_exc.ManagerError):
  1388. self.port()
  1389. ctx = context.get_admin_context()
  1390. networks = self.plugin.get_ports(ctx)
  1391. self.assertListEqual([], networks)
  1392. def test_port_DB_failure_rollback_dhcp_exception(self):
  1393. self._enable_native_dhcp_md()
  1394. self.plugin = directory.get_plugin()
  1395. with mock.patch('vmware_nsx.db.db.add_neutron_nsx_dhcp_binding',
  1396. side_effect=db_exc.DBError),\
  1397. mock.patch.object(self.plugin, '_enable_native_dhcp'),\
  1398. mock.patch('vmware_nsx.db.db.get_nsx_service_binding'),\
  1399. self.network() as network,\
  1400. self.subnet(network, cidr='10.0.1.0/24') as subnet:
  1401. data = {'port': {
  1402. 'network_id': network['network']['id'],
  1403. 'tenant_id': self._tenant_id,
  1404. 'name': 'p1',
  1405. 'admin_state_up': True,
  1406. 'device_id': 'fake_device',
  1407. 'device_owner': 'fake_owner',
  1408. 'fixed_ips': [{'subnet_id':
  1409. subnet['subnet']['id'],
  1410. 'ip_address': '10.0.1.2'}],
  1411. 'mac_address': '00:00:00:00:00:01'}
  1412. }
  1413. # making sure the port creation succeeded anyway
  1414. created_port = self.plugin.create_port(self.ctx, data)
  1415. self.assertEqual('fake_device', created_port['device_id'])
  1416. def test_update_port_add_additional_ip(self):
  1417. """Test update of port with additional IP fails."""
  1418. with self.subnet() as subnet:
  1419. with self.port(subnet=subnet) as port:
  1420. data = {'port': {'admin_state_up': False,
  1421. 'fixed_ips': [{'subnet_id':
  1422. subnet['subnet']['id']},
  1423. {'subnet_id':
  1424. subnet['subnet']['id']}]}}
  1425. req = self.new_update_request('ports', data,
  1426. port['port']['id'])
  1427. res = req.get_response(self.api)
  1428. self.assertEqual(exc.HTTPBadRequest.code,
  1429. res.status_int)
  1430. def test_create_port_additional_ip(self):
  1431. """Test that creation of port with additional IP fails."""
  1432. with self.subnet() as subnet:
  1433. data = {'port': {'network_id': subnet['subnet']['network_id'],
  1434. 'tenant_id': subnet['subnet']['tenant_id'],
  1435. 'fixed_ips': [{'subnet_id':
  1436. subnet['subnet']['id']},
  1437. {'subnet_id':
  1438. subnet['subnet']['id']}]}}
  1439. port_req = self.new_create_request('ports', data)
  1440. res = port_req.get_response(self.api)
  1441. self.assertEqual(exc.HTTPBadRequest.code,
  1442. res.status_int)
  1443. def test_create_port_with_switching_profiles(self):
  1444. """Tests that nsx ports get the configures switching profiles"""
  1445. self.plugin = directory.get_plugin()
  1446. with self.network() as network:
  1447. data = {'port': {
  1448. 'network_id': network['network']['id'],
  1449. 'tenant_id': self._tenant_id,
  1450. 'name': 'p1',
  1451. 'admin_state_up': True,
  1452. 'device_id': 'fake_device',
  1453. 'device_owner': 'fake_owner',
  1454. 'fixed_ips': [],
  1455. 'mac_address': '00:00:00:00:00:01'}
  1456. }
  1457. with mock.patch.object(self.plugin.nsxlib.logical_port, 'create',
  1458. return_value={'id': 'fake'}) as nsx_create:
  1459. self.plugin.create_port(self.ctx, data)
  1460. expected_prof = self.plugin.get_default_az().\
  1461. switching_profiles_objs[0]
  1462. actual_profs = nsx_create.call_args[1]['switch_profile_ids']
  1463. # the ports switching profiles should start with the
  1464. # configured one
  1465. self.assertEqual(expected_prof, actual_profs[0])
  1466. def test_create_ens_port_with_no_port_sec(self):
  1467. with self.subnet() as subnet,\
  1468. mock.patch("vmware_nsxlib.v3.core_resources.NsxLibTransportZone."
  1469. "get_host_switch_mode", return_value="ENS"),\
  1470. mock.patch(
  1471. "vmware_nsxlib.v3.core_resources.NsxLibLogicalSwitch.get",
  1472. return_value={'transport_zone_id': 'xxx'}):
  1473. args = {'port': {'network_id': subnet['subnet']['network_id'],
  1474. 'tenant_id': subnet['subnet']['tenant_id'],
  1475. 'fixed_ips': [{'subnet_id':
  1476. subnet['subnet']['id']}],
  1477. psec.PORTSECURITY: False}}
  1478. port_req = self.new_create_request('ports', args)
  1479. port = self.deserialize(self.fmt, port_req.get_response(self.api))
  1480. self.assertFalse(port['port']['port_security_enabled'])
  1481. def test_create_ens_port_with_port_sec(self):
  1482. with self.subnet() as subnet,\
  1483. mock.patch("vmware_nsxlib.v3.NsxLib.get_version",
  1484. return_value='2.3.0'),\
  1485. mock.patch("vmware_nsxlib.v3.core_resources.NsxLibTransportZone."
  1486. "get_host_switch_mode", return_value="ENS"),\
  1487. mock.patch("vmware_nsxlib.v3.core_resources.NsxLibLogicalSwitch."
  1488. "get", return_value={'transport_zone_id': 'xxx'}):
  1489. args = {'port': {'network_id': subnet['subnet']['network_id'],
  1490. 'tenant_id': subnet['subnet']['tenant_id'],
  1491. 'fixed_ips': [{'subnet_id':
  1492. subnet['subnet']['id']}],
  1493. psec.PORTSECURITY: True}}
  1494. port_req = self.new_create_request('ports', args)
  1495. res = self.deserialize('json', port_req.get_response(self.api))
  1496. # should fail
  1497. self.assertEqual('NsxENSPortSecurity',
  1498. res['NeutronError']['type'])
  1499. def test_create_ens_port_with_port_sec_supported(self):
  1500. with self.subnet() as subnet,\
  1501. mock.patch("vmware_nsxlib.v3.core_resources.NsxLibTransportZone."
  1502. "get_host_switch_mode", return_value="ENS"),\
  1503. mock.patch(
  1504. "vmware_nsxlib.v3.core_resources.NsxLibLogicalSwitch.get",
  1505. return_value={'transport_zone_id': 'xxx'}):
  1506. args = {'port': {'network_id': subnet['subnet']['network_id'],
  1507. 'tenant_id': subnet['subnet']['tenant_id'],
  1508. 'fixed_ips': [{'subnet_id':
  1509. subnet['subnet']['id']}],
  1510. psec.PORTSECURITY: True}}
  1511. port_req = self.new_create_request('ports', args)
  1512. res = self.deserialize('json', port_req.get_response(self.api))
  1513. # should succeed
  1514. self.assertTrue(res['port'][psec.PORTSECURITY])
  1515. def test_update_ens_port(self):
  1516. with self.subnet() as subnet,\
  1517. mock.patch("vmware_nsxlib.v3.NsxLib.get_version",
  1518. return_value='2.3.0'),\
  1519. mock.patch("vmware_nsxlib.v3.core_resources.NsxLibTransportZone."
  1520. "get_host_switch_mode", return_value="ENS"),\
  1521. mock.patch("vmware_nsxlib.v3.core_resources.NsxLibLogicalSwitch."
  1522. "get", return_value={'transport_zone_id': 'xxx'}):
  1523. args = {'port': {'network_id': subnet['subnet']['network_id'],
  1524. 'tenant_id': subnet['subnet']['tenant_id'],
  1525. 'fixed_ips': [{'subnet_id':
  1526. subnet['subnet']['id']}],
  1527. psec.PORTSECURITY: False}}
  1528. port_req = self.new_create_request('ports', args)
  1529. port = self.deserialize(self.fmt, port_req.get_response(self.api))
  1530. port_id = port['port']['id']
  1531. args = {'port': {psec.PORTSECURITY: True}}
  1532. req = self.new_update_request('ports', args, port_id)
  1533. res = self.deserialize('json', req.get_response(self.api))
  1534. # should fail
  1535. self.assertEqual('NsxENSPortSecurity',
  1536. res['NeutronError']['type'])
  1537. def test_update_ens_port_psec_supported(self):
  1538. with self.subnet() as subnet,\
  1539. mock.patch("vmware_nsxlib.v3.core_resources.NsxLibTransportZone."
  1540. "get_host_switch_mode", return_value="ENS"),\
  1541. mock.patch("vmware_nsxlib.v3.core_resources.NsxLibLogicalSwitch."
  1542. "get", return_value={'transport_zone_id': 'xxx'}):
  1543. args = {'port': {'network_id': subnet['subnet']['network_id'],
  1544. 'tenant_id': subnet['subnet']['tenant_id'],
  1545. 'fixed_ips': [{'subnet_id':
  1546. subnet['subnet']['id']}],
  1547. psec.PORTSECURITY: False}}
  1548. port_req = self.new_create_request('ports', args)
  1549. port = self.deserialize(self.fmt, port_req.get_response(self.api))
  1550. port_id = port['port']['id']
  1551. args = {'port': {psec.PORTSECURITY: True}}
  1552. req = self.new_update_request('ports', args, port_id)
  1553. res = self.deserialize('json', req.get_response(self.api))
  1554. # should succeed
  1555. self.assertTrue(res['port'][psec.PORTSECURITY])
  1556. def test_update_dhcp_port_device_owner(self):
  1557. self._enable_native_dhcp_md()
  1558. with self.subnet():
  1559. pl = directory.get_plugin()
  1560. ctx = context.Context(user_id=None, tenant_id=self._tenant_id,
  1561. is_admin=False)
  1562. ports = pl.get_ports(
  1563. ctx, filters={'device_owner': [constants.DEVICE_OWNER_DHCP]})
  1564. port_id = ports[0]['id']
  1565. args = {'port': {'admin_state_up': False,
  1566. 'fixed_ips': [],
  1567. 'device_owner': 'abcd'}}
  1568. req = self.new_update_request('ports', args, port_id)
  1569. res = self.deserialize('json', req.get_response(self.api))
  1570. # should fail
  1571. self.assertEqual('InvalidInput',
  1572. res['NeutronError']['type'])
  1573. def test_create_compute_port_with_relay_no_router(self):
  1574. """Compute port creation should fail
  1575. if a network with dhcp relay is not connected to a router
  1576. """
  1577. self._enable_dhcp_relay()
  1578. with self.network() as network, \
  1579. self.subnet(network=network, enable_dhcp=True) as s1:
  1580. device_owner = constants.DEVICE_OWNER_COMPUTE_PREFIX + 'X'
  1581. data = {'port': {
  1582. 'network_id': network['network']['id'],
  1583. 'tenant_id': self._tenant_id,
  1584. 'name': 'port',
  1585. 'admin_state_up': True,
  1586. 'device_id': 'fake_device',
  1587. 'device_owner': device_owner,
  1588. 'fixed_ips': [{'subnet_id': s1['subnet']['id']}],
  1589. 'mac_address': '00:00:00:00:00:01'}
  1590. }
  1591. self.assertRaises(n_exc.InvalidInput,
  1592. self.plugin.create_port,
  1593. self.ctx, data)
  1594. def test_create_compute_port_with_relay_and_router(self):
  1595. self._enable_dhcp_relay()
  1596. with self.network() as network, \
  1597. self.subnet(network=network, enable_dhcp=True) as s1,\
  1598. mock.patch.object(self.plugin, '_get_router',
  1599. return_value={'name': 'dummy'}):
  1600. # first create a router interface to simulate a router
  1601. data = {'port': {
  1602. 'network_id': network['network']['id'],
  1603. 'tenant_id': self._tenant_id,
  1604. 'name': 'port',
  1605. 'admin_state_up': True,
  1606. 'device_id': 'dummy',
  1607. 'device_owner': l3_db.DEVICE_OWNER_ROUTER_INTF,
  1608. 'fixed_ips': [{'subnet_id': s1['subnet']['id']}],
  1609. 'mac_address': '00:00:00:00:00:02'}
  1610. }
  1611. port1 = self.plugin.create_port(self.ctx, data)
  1612. self.assertIn('id', port1)
  1613. # Now create a compute port
  1614. device_owner = constants.DEVICE_OWNER_COMPUTE_PREFIX + 'X'
  1615. data = {'port': {
  1616. 'network_id': network['network']['id'],
  1617. 'tenant_id': self._tenant_id,
  1618. 'name': 'port',
  1619. 'admin_state_up': True,
  1620. 'device_id': 'fake_device',
  1621. 'device_owner': device_owner,
  1622. 'fixed_ips': [{'subnet_id': s1['subnet']['id']}],
  1623. 'mac_address': '00:00:00:00:00:01'}
  1624. }
  1625. port2 = self.plugin.create_port(self.ctx, data)
  1626. self.assertIn('id', port2)
  1627. def _test_create_direct_network(self, vlan_id=0):
  1628. net_type = vlan_id and 'vlan' or 'flat'
  1629. name = 'direct_net'
  1630. providernet_args = {pnet.NETWORK_TYPE: net_type,
  1631. pnet.PHYSICAL_NETWORK: 'tzuuid'}
  1632. if vlan_id:
  1633. providernet_args[pnet.SEGMENTATION_ID] = vlan_id
  1634. mock_tt = mock.patch('vmware_nsxlib.v3'
  1635. '.core_resources.NsxLibTransportZone'
  1636. '.get_transport_type',
  1637. return_value='VLAN')
  1638. mock_tt.start()
  1639. return self.network(name=name,
  1640. providernet_args=providernet_args,
  1641. arg_list=(pnet.NETWORK_TYPE,
  1642. pnet.PHYSICAL_NETWORK,
  1643. pnet.SEGMENTATION_ID))
  1644. def _test_create_port_vnic_direct(self, vlan_id):
  1645. with self._test_create_direct_network(vlan_id=vlan_id) as network:
  1646. # Check that port security conflicts
  1647. kwargs = {portbindings.VNIC_TYPE: portbindings.VNIC_DIRECT,
  1648. psec.PORTSECURITY: True}
  1649. net_id = network['network']['id']
  1650. res = self._create_port(self.fmt, net_id=net_id,
  1651. arg_list=(portbindings.VNIC_TYPE,
  1652. psec.PORTSECURITY),
  1653. **kwargs)
  1654. self.assertEqual(res.status_int, exc.HTTPBadRequest.code)
  1655. # Check that security group conflicts
  1656. kwargs = {portbindings.VNIC_TYPE: portbindings.VNIC_DIRECT,
  1657. 'security_groups': [
  1658. '4cd70774-cc67-4a87-9b39-7d1db38eb087'],
  1659. psec.PORTSECURITY: False}
  1660. net_id = network['network']['id']
  1661. res = self._create_port(self.fmt, net_id=net_id,
  1662. arg_list=(portbindings.VNIC_TYPE,
  1663. psec.PORTSECURITY),
  1664. **kwargs)
  1665. self.assertEqual(res.status_int, exc.HTTPBadRequest.code)
  1666. # All is kosher so we can create the port
  1667. kwargs = {portbindings.VNIC_TYPE: portbindings.VNIC_DIRECT}
  1668. net_id = network['network']['id']
  1669. res = self._create_port(self.fmt, net_id=net_id,
  1670. arg_list=(portbindings.VNIC_TYPE,),
  1671. **kwargs)
  1672. port = self.deserialize('json', res)
  1673. self.assertEqual("direct", port['port'][portbindings.VNIC_TYPE])
  1674. self.assertEqual("dvs", port['port'][portbindings.VIF_TYPE])
  1675. self.assertEqual(
  1676. vlan_id,
  1677. port['port'][portbindings.VIF_DETAILS]['segmentation-id'])
  1678. # try to get the same port
  1679. req = self.new_show_request('ports', port['port']['id'], self.fmt)
  1680. sport = self.deserialize(self.fmt, req.get_response(self.api))
  1681. self.assertEqual("dvs", sport['port'][portbindings.VIF_TYPE])
  1682. self.assertEqual("direct", sport['port'][portbindings.VNIC_TYPE])
  1683. self.assertEqual(
  1684. vlan_id,
  1685. sport['port'][portbindings.VIF_DETAILS]['segmentation-id'])
  1686. self.assertFalse(
  1687. sport['port'][portbindings.VIF_DETAILS]['vlan-transparent'])
  1688. def test_create_port_vnic_direct_flat(self):
  1689. self._test_create_port_vnic_direct(0)
  1690. def test_create_port_vnic_direct_vlan(self):
  1691. self._test_create_port_vnic_direct(10)
  1692. def test_create_port_vnic_direct_invalid_network(self):
  1693. with self.network(name='not vlan/flat') as net:
  1694. kwargs = {portbindings.VNIC_TYPE: portbindings.VNIC_DIRECT,
  1695. psec.PORTSECURITY: False}
  1696. net_id = net['network']['id']
  1697. res = self._create_port(self.fmt, net_id=net_id,
  1698. arg_list=(portbindings.VNIC_TYPE,
  1699. psec.PORTSECURITY),
  1700. **kwargs)
  1701. self.assertEqual(exc.HTTPBadRequest.code, res.status_int)
  1702. def test_update_vnic_direct(self):
  1703. with self._test_create_direct_network(vlan_id=7) as network:
  1704. with self.subnet(network=network) as subnet:
  1705. with self.port(subnet=subnet) as port:
  1706. # need to do two updates as the update for port security
  1707. # disabled requires that it can only change 2 items
  1708. data = {'port': {psec.PORTSECURITY: False,
  1709. 'security_groups': []}}
  1710. req = self.new_update_request('ports',
  1711. data, port['port']['id'])
  1712. res = self.deserialize('json', req.get_response(self.api))
  1713. self.assertEqual(portbindings.VNIC_NORMAL,
  1714. res['port'][portbindings.VNIC_TYPE])
  1715. data = {'port': {portbindings.VNIC_TYPE:
  1716. portbindings.VNIC_DIRECT}}
  1717. req = self.new_update_request('ports',
  1718. data, port['port']['id'])
  1719. res = self.deserialize('json', req.get_response(self.api))
  1720. self.assertEqual(portbindings.VNIC_DIRECT,
  1721. res['port'][portbindings.VNIC_TYPE])
  1722. def test_port_invalid_vnic_type(self):
  1723. with self._test_create_direct_network(vlan_id=7) as network:
  1724. kwargs = {portbindings.VNIC_TYPE: 'invalid',
  1725. psec.PORTSECURITY: False}
  1726. net_id = network['network']['id']
  1727. res = self._create_port(self.fmt, net_id=net_id,
  1728. arg_list=(portbindings.VNIC_TYPE,
  1729. psec.PORTSECURITY),
  1730. **kwargs)
  1731. self.assertEqual(res.status_int, exc.HTTPBadRequest.code)
  1732. def test_create_transparent_vlan_port(self):
  1733. providernet_args = {pnet.NETWORK_TYPE: 'vlan',
  1734. vlan_apidef.VLANTRANSPARENT: True}
  1735. with mock.patch('vmware_nsxlib.v3.core_resources.NsxLibTransportZone.'
  1736. 'get_transport_type', return_value='VLAN'):
  1737. result = self._create_network(fmt='json', name='vlan_net',
  1738. admin_state_up=True,
  1739. providernet_args=providernet_args,
  1740. arg_list=(
  1741. pnet.NETWORK_TYPE,
  1742. pnet.SEGMENTATION_ID,
  1743. vlan_apidef.VLANTRANSPARENT))
  1744. network = self.deserialize('json', result)
  1745. net_id = network['network']['id']
  1746. with self.subnet(network=network):
  1747. kwargs = {portbindings.VNIC_TYPE: portbindings.VNIC_DIRECT}
  1748. net_id = network['network']['id']
  1749. res = self._create_port(self.fmt, net_id=net_id,
  1750. arg_list=(portbindings.VNIC_TYPE,),
  1751. **kwargs)
  1752. port = self.deserialize('json', res)
  1753. self.assertTrue(
  1754. port['port'][portbindings.VIF_DETAILS]['vlan-transparent'])
  1755. @common_v3.with_disable_dhcp
  1756. def test_requested_subnet_id_v4_and_v6(self):
  1757. return super(TestPortsV2, self).test_requested_subnet_id_v4_and_v6()
  1758. class DHCPOptsTestCase(test_dhcpopts.TestExtraDhcpOpt,
  1759. NsxV3PluginTestCaseMixin):
  1760. def setUp(self, plugin=None):
  1761. super(test_dhcpopts.ExtraDhcpOptDBTestCase, self).setUp(
  1762. plugin=PLUGIN_NAME)
  1763. class NSXv3DHCPAgentAZAwareWeightSchedulerTestCase(
  1764. test_dhcpagent.DHCPAgentAZAwareWeightSchedulerTestCase,
  1765. NsxV3PluginTestCaseMixin):
  1766. def setUp(self):
  1767. super(NSXv3DHCPAgentAZAwareWeightSchedulerTestCase, self).setUp()
  1768. self.plugin = directory.get_plugin()
  1769. self.ctx = context.get_admin_context()
  1770. def setup_coreplugin(self, core_plugin=None, load_plugins=True):
  1771. super(NSXv3DHCPAgentAZAwareWeightSchedulerTestCase,
  1772. self).setup_coreplugin(core_plugin=PLUGIN_NAME,
  1773. load_plugins=load_plugins)
  1774. class TestL3ExtensionManager(object):
  1775. def get_resources(self):
  1776. # Simulate extension of L3 attribute map
  1777. l3.L3().update_attributes_map(
  1778. l3_egm_apidef.RESOURCE_ATTRIBUTE_MAP)
  1779. l3.L3().update_attributes_map(
  1780. xroute_apidef.RESOURCE_ATTRIBUTE_MAP)
  1781. return (l3.L3.get_resources() +
  1782. address_scope.Address_scope.get_resources())
  1783. def get_actions(self):
  1784. return []
  1785. def get_request_extensions(self):
  1786. return []
  1787. class L3NatTest(test_l3_plugin.L3BaseForIntTests,
  1788. NsxV3PluginTestCaseMixin,
  1789. common_v3.FixExternalNetBaseTest,
  1790. common_v3.NsxV3SubnetMixin,
  1791. test_address_scope.AddressScopeTestCase):
  1792. def setUp(self, plugin=PLUGIN_NAME, ext_mgr=None,
  1793. service_plugins=None):
  1794. cfg.CONF.set_override('api_extensions_path', vmware.NSXEXT_PATH)
  1795. cfg.CONF.set_default('max_routes', 3)
  1796. ext_mgr = ext_mgr or TestL3ExtensionManager()
  1797. mock_nsx_version = mock.patch.object(nsx_plugin.utils,
  1798. 'is_nsx_version_2_0_0',
  1799. new=lambda v: True)
  1800. mock_nsx_version.start()
  1801. # Make sure the LB callback is not called on router deletion
  1802. self.lb_mock1 = mock.patch(
  1803. "vmware_nsx.services.lbaas.octavia.octavia_listener."
  1804. "NSXOctaviaListenerEndpoint._check_lb_service_on_router")
  1805. self.lb_mock1.start()
  1806. self.lb_mock2 = mock.patch(
  1807. "vmware_nsx.services.lbaas.octavia.octavia_listener."
  1808. "NSXOctaviaListenerEndpoint._check_lb_service_on_router_interface")
  1809. self.lb_mock2.start()
  1810. super(L3NatTest, self).setUp(
  1811. plugin=plugin, ext_mgr=ext_mgr, service_plugins=service_plugins)
  1812. self.plugin_instance = directory.get_plugin()
  1813. self._plugin_name = "%s.%s" % (
  1814. self.plugin_instance.__module__,
  1815. self.plugin_instance.__class__.__name__)
  1816. self._plugin_class = self.plugin_instance.__class__
  1817. self.plugin_instance.fwaas_callbacks = None
  1818. self.original_subnet = self.subnet
  1819. self.original_network = self.network
  1820. def _set_net_external(self, net_id):
  1821. # This action is not supported by the V3 plugin
  1822. pass
  1823. def external_network(self, name='net1',
  1824. admin_state_up=True,
  1825. fmt=None, **kwargs):
  1826. if not name:
  1827. name = 'l3_ext_net'
  1828. physical_network = nsx_v3_mocks.DEFAULT_TIER0_ROUTER_UUID
  1829. net_type = utils.NetworkTypes.L3_EXT
  1830. providernet_args = {pnet.NETWORK_TYPE: net_type,
  1831. pnet.PHYSICAL_NETWORK: physical_network}
  1832. return self.original_network(name=name,
  1833. admin_state_up=admin_state_up,
  1834. fmt=fmt,
  1835. router__external=True,
  1836. providernet_args=providernet_args,
  1837. arg_list=(pnet.NETWORK_TYPE,
  1838. pnet.PHYSICAL_NETWORK))
  1839. def test_floatingip_create_different_fixed_ip_same_port(self):
  1840. self.skipTest('Multiple fixed ips on a port are not supported')
  1841. def test_router_add_interface_multiple_ipv4_subnet_port_returns_400(self):
  1842. self.skipTest('Multiple fixed ips on a port are not supported')
  1843. def test_router_add_interface_multiple_ipv6_subnet_port(self):
  1844. self.skipTest('Multiple fixed ips on a port are not supported')
  1845. def test_floatingip_update_different_fixed_ip_same_port(self):
  1846. self.skipTest('Multiple fixed ips on a port are not supported')
  1847. def test_create_multiple_floatingips_same_fixed_ip_same_port(self):
  1848. self.skipTest('Multiple fixed ips on a port are not supported')
  1849. class TestL3NatTestCase(L3NatTest,
  1850. test_l3_plugin.L3NatDBIntTestCase,
  1851. test_ext_route.ExtraRouteDBTestCaseBase,
  1852. test_metadata.MetaDataTestCase):
  1853. block_dhcp_notifier = False
  1854. def setUp(self, plugin=PLUGIN_NAME,
  1855. ext_mgr=None,
  1856. service_plugins=None):
  1857. super(TestL3NatTestCase, self).setUp(plugin=plugin, ext_mgr=ext_mgr)
  1858. cfg.CONF.set_override('metadata_mode', None, 'nsx_v3')
  1859. cfg.CONF.set_override('metadata_on_demand', False, 'nsx_v3')
  1860. self.subnet_calls = []
  1861. def _test_create_l3_ext_network(
  1862. self, physical_network=nsx_v3_mocks.DEFAULT_TIER0_ROUTER_UUID):
  1863. name = 'l3_ext_net'
  1864. net_type = utils.NetworkTypes.L3_EXT
  1865. expected = [('subnets', []), ('name', name), ('admin_state_up', True),
  1866. ('status', 'ACTIVE'), ('shared', False),
  1867. (extnet_apidef.EXTERNAL, True),
  1868. (pnet.NETWORK_TYPE, net_type),
  1869. (pnet.PHYSICAL_NETWORK, physical_network)]
  1870. with self._create_l3_ext_network(physical_network) as net:
  1871. for k, v in expected:
  1872. self.assertEqual(net['network'][k], v)
  1873. @common_v3.with_external_subnet
  1874. def test_router_update_gateway_with_external_ip_used_by_gw(self):
  1875. super(TestL3NatTestCase,
  1876. self).test_router_update_gateway_with_external_ip_used_by_gw()
  1877. @common_v3.with_external_subnet
  1878. def test_router_update_gateway_with_invalid_external_ip(self):
  1879. super(TestL3NatTestCase,
  1880. self).test_router_update_gateway_with_invalid_external_ip()
  1881. @common_v3.with_external_subnet
  1882. def test_router_update_gateway_with_invalid_external_subnet(self):
  1883. super(TestL3NatTestCase,
  1884. self).test_router_update_gateway_with_invalid_external_subnet()
  1885. @common_v3.with_external_network
  1886. def test_router_update_gateway_with_different_external_subnet(self):
  1887. super(TestL3NatTestCase,
  1888. self).test_router_update_gateway_with_different_external_subnet()
  1889. @common_v3.with_disable_dhcp
  1890. def test_create_floatingip_ipv6_only_network_returns_400(self):
  1891. super(TestL3NatTestCase,
  1892. self).test_create_floatingip_ipv6_only_network_returns_400()
  1893. @common_v3.with_disable_dhcp
  1894. def test_create_floatingip_with_assoc_to_ipv4_and_ipv6_port(self):
  1895. super(L3NatTest,
  1896. self).test_create_floatingip_with_assoc_to_ipv4_and_ipv6_port()
  1897. @common_v3.with_external_subnet_once
  1898. def test_router_update_gateway_with_existed_floatingip(self):
  1899. with self.subnet(cidr='20.0.0.0/24') as subnet:
  1900. self._set_net_external(subnet['subnet']['network_id'])
  1901. with self.floatingip_with_assoc() as fip:
  1902. self._add_external_gateway_to_router(
  1903. fip['floatingip']['router_id'],
  1904. subnet['subnet']['network_id'],
  1905. expected_code=exc.HTTPConflict.code)
  1906. @common_v3.with_external_network
  1907. def test_router_update_gateway_add_multiple_prefixes_ipv6(self):
  1908. super(TestL3NatTestCase,
  1909. self).test_router_update_gateway_add_multiple_prefixes_ipv6()
  1910. @common_v3.with_external_network
  1911. def test_router_concurrent_delete_upon_subnet_create(self):
  1912. super(TestL3NatTestCase,
  1913. self).test_router_concurrent_delete_upon_subnet_create()
  1914. @common_v3.with_external_network
  1915. def test_router_update_gateway_upon_subnet_create_ipv6(self):
  1916. super(TestL3NatTestCase,
  1917. self).test_router_update_gateway_upon_subnet_create_ipv6()
  1918. @common_v3.with_external_subnet
  1919. def test_router_add_gateway_dup_subnet2_returns_400(self):
  1920. super(TestL3NatTestCase,
  1921. self).test_router_add_gateway_dup_subnet2_returns_400()
  1922. @common_v3.with_external_subnet
  1923. def test_router_update_gateway(self):
  1924. super(TestL3NatTestCase,
  1925. self).test_router_update_gateway()
  1926. @common_v3.with_external_subnet
  1927. def test_router_create_with_gwinfo(self):
  1928. super(TestL3NatTestCase,
  1929. self).test_router_create_with_gwinfo()
  1930. @common_v3.with_external_subnet
  1931. def test_router_clear_gateway_callback_failure_returns_409(self):
  1932. super(TestL3NatTestCase,
  1933. self).test_router_clear_gateway_callback_failure_returns_409()
  1934. @common_v3.with_external_subnet
  1935. def test_router_create_with_gwinfo_ext_ip(self):
  1936. super(TestL3NatTestCase,
  1937. self).test_router_create_with_gwinfo_ext_ip()
  1938. @common_v3.with_external_network
  1939. def test_router_create_with_gwinfo_ext_ip_subnet(self):
  1940. super(TestL3NatTestCase,
  1941. self).test_router_create_with_gwinfo_ext_ip_subnet()
  1942. @common_v3.with_external_subnet_second_time
  1943. def test_router_delete_with_floatingip_existed_returns_409(self):
  1944. super(TestL3NatTestCase,
  1945. self).test_router_delete_with_floatingip_existed_returns_409()
  1946. @common_v3.with_external_subnet
  1947. def test_router_add_and_remove_gateway_tenant_ctx(self):
  1948. super(TestL3NatTestCase,
  1949. self).test_router_add_and_remove_gateway_tenant_ctx()
  1950. @common_v3.with_external_subnet
  1951. def test_router_add_and_remove_gateway(self):
  1952. super(TestL3NatTestCase,
  1953. self).test_router_add_and_remove_gateway()
  1954. def test_router_update_gateway_upon_subnet_create_max_ips_ipv6(self):
  1955. self.skipTest('not supported')
  1956. def test_router_add_gateway_multiple_subnets_ipv6(self):
  1957. self.skipTest('multiple ipv6 subnets not supported')
  1958. def test__notify_gateway_port_ip_changed(self):
  1959. self.skipTest('not supported')
  1960. def test__notify_gateway_port_ip_not_changed(self):
  1961. self.skipTest('not supported')
  1962. def test_floatingip_via_router_interface_returns_201(self):
  1963. self.skipTest('not supported')
  1964. def test_floatingip_via_router_interface_returns_404(self):
  1965. self.skipTest('not supported')
  1966. def test_router_delete_dhcpv6_stateless_subnet_inuse_returns_409(self):
  1967. self.skipTest('DHCPv6 not supported')
  1968. @common_v3.with_disable_dhcp
  1969. def test_router_add_interface_ipv6_subnet(self):
  1970. self.skipTest('DHCPv6 not supported')
  1971. @common_v3.with_disable_dhcp
  1972. def test_router_add_interface_ipv6_subnet_without_gateway_ip(self):
  1973. super(TestL3NatTestCase,
  1974. self).test_router_add_interface_ipv6_subnet_without_gateway_ip()
  1975. @common_v3.with_disable_dhcp
  1976. def test_router_add_interface_multiple_ipv6_subnets_different_net(self):
  1977. super(TestL3NatTestCase, self).\
  1978. test_router_add_interface_multiple_ipv6_subnets_different_net()
  1979. @common_v3.with_disable_dhcp
  1980. def test_create_floatingip_with_assoc_to_ipv6_subnet(self):
  1981. super(TestL3NatTestCase,
  1982. self).test_create_floatingip_with_assoc_to_ipv6_subnet()
  1983. def test_router_add_iface_ipv6_ext_ra_subnet_returns_400(self):
  1984. self.skipTest('DHCPv6 not supported')
  1985. @common_v3.with_external_subnet
  1986. def test_floatingip_list_with_sort(self):
  1987. super(TestL3NatTestCase,
  1988. self).test_floatingip_list_with_sort()
  1989. @common_v3.with_external_subnet_once
  1990. def test_floatingip_with_assoc_fails(self):
  1991. super(TestL3NatTestCase,
  1992. self).test_floatingip_with_assoc_fails()
  1993. @common_v3.with_external_subnet_second_time
  1994. def test_floatingip_update_same_fixed_ip_same_port(self):
  1995. super(TestL3NatTestCase,
  1996. self).test_floatingip_update_same_fixed_ip_same_port()
  1997. @common_v3.with_external_subnet
  1998. def test_floatingip_list_with_pagination_reverse(self):
  1999. super(TestL3NatTestCase,
  2000. self).test_floatingip_list_with_pagination_reverse()
  2001. @common_v3.with_external_subnet_once
  2002. def test_floatingip_association_on_unowned_router(self):
  2003. super(TestL3NatTestCase,
  2004. self).test_floatingip_association_on_unowned_router()
  2005. @common_v3.with_external_network
  2006. def test_delete_ext_net_with_disassociated_floating_ips(self):
  2007. super(TestL3NatTestCase,
  2008. self).test_delete_ext_net_with_disassociated_floating_ips()
  2009. @common_v3.with_external_network
  2010. def test_create_floatingip_with_subnet_and_invalid_fip_address(self):
  2011. super(
  2012. TestL3NatTestCase,
  2013. self).test_create_floatingip_with_subnet_and_invalid_fip_address()
  2014. @common_v3.with_external_subnet
  2015. def test_create_floatingip_with_duplicated_specific_ip(self):
  2016. super(TestL3NatTestCase,
  2017. self).test_create_floatingip_with_duplicated_specific_ip()
  2018. @common_v3.with_external_subnet
  2019. def test_create_floatingip_with_subnet_id_non_admin(self):
  2020. super(TestL3NatTestCase,
  2021. self).test_create_floatingip_with_subnet_id_non_admin()
  2022. @common_v3.with_external_subnet
  2023. def test_floatingip_list_with_pagination(self):
  2024. super(TestL3NatTestCase,
  2025. self).test_floatingip_list_with_pagination()
  2026. @common_v3.with_external_subnet
  2027. def test_create_floatingips_native_quotas(self):
  2028. super(TestL3NatTestCase,
  2029. self).test_create_floatingips_native_quotas()
  2030. @common_v3.with_external_network
  2031. def test_create_floatingip_with_multisubnet_id(self):
  2032. super(TestL3NatTestCase,
  2033. self).test_create_floatingip_with_multisubnet_id()
  2034. @common_v3.with_external_network
  2035. def test_create_floatingip_with_subnet_id_and_fip_address(self):
  2036. super(TestL3NatTestCase,
  2037. self).test_create_floatingip_with_subnet_id_and_fip_address()
  2038. @common_v3.with_external_subnet
  2039. def test_create_floatingip_with_specific_ip(self):
  2040. super(TestL3NatTestCase,
  2041. self).test_create_floatingip_with_specific_ip()
  2042. @common_v3.with_external_network
  2043. def test_create_floatingip_ipv6_and_ipv4_network_creates_ipv4(self):
  2044. super(TestL3NatTestCase,
  2045. self).test_create_floatingip_ipv6_and_ipv4_network_creates_ipv4()
  2046. @common_v3.with_external_subnet_once
  2047. def test_create_floatingip_non_admin_context_agent_notification(self):
  2048. super(
  2049. TestL3NatTestCase,
  2050. self).test_create_floatingip_non_admin_context_agent_notification()
  2051. @common_v3.with_external_subnet
  2052. def test_create_floatingip_no_ext_gateway_return_404(self):
  2053. super(TestL3NatTestCase,
  2054. self).test_create_floatingip_no_ext_gateway_return_404()
  2055. @common_v3.with_external_subnet
  2056. def test_create_floatingip_with_specific_ip_out_of_allocation(self):
  2057. super(TestL3NatTestCase,
  2058. self).test_create_floatingip_with_specific_ip_out_of_allocation()
  2059. @common_v3.with_external_subnet_third_time
  2060. def test_floatingip_update_different_router(self):
  2061. super(TestL3NatTestCase,
  2062. self).test_floatingip_update_different_router()
  2063. def test_router_add_gateway_notifications(self):
  2064. with self.router() as r,\
  2065. self._create_l3_ext_network() as ext_net,\
  2066. self.subnet(network=ext_net):
  2067. with mock.patch.object(registry, 'publish') as publish:
  2068. self._add_external_gateway_to_router(
  2069. r['router']['id'], ext_net['network']['id'])
  2070. expected = [mock.call(
  2071. resources.ROUTER_GATEWAY,
  2072. events.AFTER_CREATE, mock.ANY,
  2073. payload=mock.ANY)]
  2074. publish.assert_has_calls(expected)
  2075. def test_create_l3_ext_network_with_default_tier0(self):
  2076. self._test_create_l3_ext_network()
  2077. def test_floatingip_update(self):
  2078. super(TestL3NatTestCase, self).test_floatingip_update(
  2079. expected_status=constants.FLOATINGIP_STATUS_DOWN)
  2080. @common_v3.with_external_subnet_second_time
  2081. def test_floatingip_with_invalid_create_port(self):
  2082. self._test_floatingip_with_invalid_create_port(self._plugin_name)
  2083. def test_network_update_external(self):
  2084. # This plugin does not support updating the external flag of a network
  2085. self.skipTest('not supported')
  2086. def test_network_update_external_failure(self):
  2087. # This plugin does not support updating the external flag of a network
  2088. # This is tested with a different test
  2089. self.skipTest('not supported')
  2090. def test_router_add_gateway_dup_subnet1_returns_400(self):
  2091. self.skipTest('not supported')
  2092. def test_router_add_interface_dup_subnet2_returns_400(self):
  2093. self.skipTest('not supported')
  2094. def test_router_add_interface_ipv6_port_existing_network_returns_400(self):
  2095. self.skipTest('multiple ipv6 subnets not supported')
  2096. def test_routes_update_for_multiple_routers(self):
  2097. self.skipTest('not supported')
  2098. def test_floatingip_multi_external_one_internal(self):
  2099. self.skipTest('not supported')
  2100. def test_floatingip_same_external_and_internal(self):
  2101. self.skipTest('not supported')
  2102. def test_route_update_with_external_route(self):
  2103. self.skipTest('not supported')
  2104. def test_floatingip_update_subnet_gateway_disabled(self):
  2105. self.skipTest('not supported')
  2106. def test_router_add_interface_by_port_other_tenant_address_out_of_pool(
  2107. self):
  2108. # multiple fixed ips per port are not supported
  2109. self.skipTest('not supported')
  2110. def test_router_add_interface_by_port_other_tenant_address_in_pool(self):
  2111. # multiple fixed ips per port are not supported
  2112. self.skipTest('not supported')
  2113. def test_router_add_interface_by_port_admin_address_out_of_pool(self):
  2114. # multiple fixed ips per port are not supported
  2115. self.skipTest('not supported')
  2116. def test_router_delete_with_lb_service(self):
  2117. self.lb_mock1.stop()
  2118. self.lb_mock2.stop()
  2119. # Create the LB object - here the delete callback is registered
  2120. loadbalancer = loadbalancer_mgr.EdgeLoadBalancerManagerFromDict()
  2121. oct_listener = octavia_listener.NSXOctaviaListenerEndpoint(
  2122. loadbalancer=loadbalancer)
  2123. with self.router() as router:
  2124. with mock.patch('vmware_nsxlib.v3.load_balancer.Service.'
  2125. 'get_router_lb_service'),\
  2126. mock.patch('vmware_nsx.db.db.get_nsx_router_id',
  2127. return_value='1'),\
  2128. mock.patch.object(
  2129. nsx_db,
  2130. 'has_nsx_lbaas_loadbalancer_binding_by_router',
  2131. return_value=True):
  2132. self.assertRaises(nc_exc.CallbackFailure,
  2133. self.plugin_instance.delete_router,
  2134. context.get_admin_context(),
  2135. router['router']['id'])
  2136. # Unregister callback
  2137. oct_listener._unsubscribe_router_delete_callback()
  2138. self.lb_mock1.start()
  2139. self.lb_mock2.start()
  2140. def test_multiple_subnets_on_different_routers(self):
  2141. with self.network() as network:
  2142. with self.subnet(network=network) as s1,\
  2143. self.subnet(network=network,
  2144. cidr='11.0.0.0/24') as s2,\
  2145. self.router() as r1,\
  2146. self.router() as r2:
  2147. self._router_interface_action('add', r1['router']['id'],
  2148. s1['subnet']['id'], None)
  2149. self.assertRaises(n_exc.Conflict,
  2150. self.plugin_instance.add_router_interface,
  2151. context.get_admin_context(),
  2152. r2['router']['id'],
  2153. {'subnet_id': s2['subnet']['id']})
  2154. self._router_interface_action('remove', r1['router']['id'],
  2155. s1['subnet']['id'], None)
  2156. self._router_interface_action('add', r2['router']['id'],
  2157. s2['subnet']['id'], None)
  2158. self._router_interface_action('remove', r2['router']['id'],
  2159. s2['subnet']['id'], None)
  2160. def test_multiple_subnets_on_same_router(self):
  2161. with self.network() as network:
  2162. with self.subnet(network=network) as s1,\
  2163. self.subnet(network=network,
  2164. cidr='11.0.0.0/24') as s2,\
  2165. self.router() as r1:
  2166. self._router_interface_action('add', r1['router']['id'],
  2167. s1['subnet']['id'], None)
  2168. self.assertRaises(n_exc.InvalidInput,
  2169. self.plugin_instance.add_router_interface,
  2170. context.get_admin_context(),
  2171. r1['router']['id'],
  2172. {'subnet_id': s2['subnet']['id']})
  2173. self._router_interface_action('remove', r1['router']['id'],
  2174. s1['subnet']['id'], None)
  2175. def test_router_remove_interface_inuse_return_409(self):
  2176. with self.router() as r1,\
  2177. self._create_l3_ext_network() as ext_net,\
  2178. self.subnet(network=ext_net) as ext_subnet,\
  2179. self.subnet(cidr='11.0.0.0/24') as s1:
  2180. self._router_interface_action(
  2181. 'add', r1['router']['id'],
  2182. s1['subnet']['id'], None)
  2183. self._add_external_gateway_to_router(
  2184. r1['router']['id'],
  2185. ext_subnet['subnet']['network_id'])
  2186. with self.port(subnet=s1,) as p:
  2187. fip_res = self._create_floatingip(
  2188. self.fmt,
  2189. ext_subnet['subnet']['network_id'],
  2190. subnet_id=ext_subnet['subnet']['id'],
  2191. port_id=p['port']['id'])
  2192. fip = self.deserialize(self.fmt, fip_res)
  2193. self._router_interface_action(
  2194. 'remove',
  2195. r1['router']['id'],
  2196. s1['subnet']['id'],
  2197. None,
  2198. expected_code=exc.HTTPConflict.code)
  2199. self._delete('floatingips', fip['floatingip']['id'])
  2200. self._remove_external_gateway_from_router(
  2201. r1['router']['id'],
  2202. ext_subnet['subnet']['network_id'])
  2203. self._router_interface_action('remove',
  2204. r1['router']['id'],
  2205. s1['subnet']['id'],
  2206. None)
  2207. def test_router_update_on_external_port(self):
  2208. with self.router() as r:
  2209. with self._create_l3_ext_network() as ext_net,\
  2210. self.subnet(network=ext_net, cidr='10.0.1.0/24') as s:
  2211. self._add_external_gateway_to_router(
  2212. r['router']['id'],
  2213. s['subnet']['network_id'])
  2214. body = self._show('routers', r['router']['id'])
  2215. net_id = body['router']['external_gateway_info']['network_id']
  2216. self.assertEqual(net_id, s['subnet']['network_id'])
  2217. port_res = self._list_ports(
  2218. 'json',
  2219. 200,
  2220. s['subnet']['network_id'],
  2221. tenant_id=r['router']['tenant_id'],
  2222. device_owner=constants.DEVICE_OWNER_ROUTER_GW)
  2223. port_list = self.deserialize('json', port_res)
  2224. self.assertEqual(len(port_list['ports']), 1)
  2225. routes = [{'destination': '135.207.0.0/16',
  2226. 'nexthop': '10.0.1.3'}]
  2227. self.assertRaises(n_exc.InvalidInput,
  2228. self.plugin_instance.update_router,
  2229. context.get_admin_context(),
  2230. r['router']['id'],
  2231. {'router': {'routes':
  2232. routes}})
  2233. updates = {'admin_state_up': False}
  2234. self.assertRaises(n_exc.InvalidInput,
  2235. self.plugin_instance.update_router,
  2236. context.get_admin_context(),
  2237. r['router']['id'],
  2238. {'router': updates})
  2239. self._remove_external_gateway_from_router(
  2240. r['router']['id'],
  2241. s['subnet']['network_id'])
  2242. body = self._show('routers', r['router']['id'])
  2243. gw_info = body['router']['external_gateway_info']
  2244. self.assertIsNone(gw_info)
  2245. def test_router_on_vlan_net(self):
  2246. providernet_args = {pnet.NETWORK_TYPE: 'vlan',
  2247. pnet.SEGMENTATION_ID: 10}
  2248. with mock.patch('vmware_nsxlib.v3.core_resources.NsxLibTransportZone.'
  2249. 'get_transport_type', return_value='VLAN'):
  2250. result = self._create_network(fmt='json', name='badvlan_net',
  2251. admin_state_up=True,
  2252. providernet_args=providernet_args,
  2253. arg_list=(
  2254. pnet.NETWORK_TYPE,
  2255. pnet.SEGMENTATION_ID))
  2256. vlan_network = self.deserialize('json', result)
  2257. with self.router() as r1,\
  2258. self._create_l3_ext_network() as ext_net,\
  2259. self.subnet(network=ext_net) as ext_subnet,\
  2260. self.subnet(cidr='11.0.0.0/24', network=vlan_network) as s1:
  2261. # adding a vlan interface with no GW should fail
  2262. self._router_interface_action(
  2263. 'add', r1['router']['id'],
  2264. s1['subnet']['id'], None,
  2265. expected_code=400)
  2266. # adding GW
  2267. self._add_external_gateway_to_router(
  2268. r1['router']['id'],
  2269. ext_subnet['subnet']['network_id'])
  2270. # adding the vlan interface
  2271. self._router_interface_action(
  2272. 'add', r1['router']['id'],
  2273. s1['subnet']['id'], None)
  2274. # adding a floating ip
  2275. with self.port(subnet=s1) as p:
  2276. fip_res = self._create_floatingip(
  2277. self.fmt,
  2278. ext_subnet['subnet']['network_id'],
  2279. subnet_id=ext_subnet['subnet']['id'],
  2280. port_id=p['port']['id'])
  2281. fip = self.deserialize(self.fmt, fip_res)
  2282. self.assertEqual(p['port']['id'],
  2283. fip['floatingip']['port_id'])
  2284. def test_create_router_gateway_fails(self):
  2285. self.skipTest('not supported')
  2286. def test_router_remove_ipv6_subnet_from_interface(self):
  2287. self.skipTest('not supported')
  2288. def test_router_add_interface_multiple_ipv6_subnets_same_net(self):
  2289. self.skipTest('not supported')
  2290. def test_router_add_interface_multiple_ipv4_subnets(self):
  2291. self.skipTest('not supported')
  2292. def test_floatingip_update_to_same_port_id_twice(self):
  2293. self.skipTest('Plugin changes floating port status')
  2294. def _test_create_subnetpool(self, prefixes, expected=None,
  2295. admin=False, **kwargs):
  2296. keys = kwargs.copy()
  2297. keys.setdefault('tenant_id', self._tenant_id)
  2298. with self.subnetpool(prefixes, admin, **keys) as subnetpool:
  2299. self._validate_resource(subnetpool, keys, 'subnetpool')
  2300. if expected:
  2301. self._compare_resource(subnetpool, expected, 'subnetpool')
  2302. return subnetpool
  2303. def _update_router_enable_snat(self, router_id, network_id, enable_snat):
  2304. return self._update('routers', router_id,
  2305. {'router': {'external_gateway_info':
  2306. {'network_id': network_id,
  2307. 'enable_snat': enable_snat}}})
  2308. def test_router_no_snat_with_different_address_scope(self):
  2309. """Test that if the router has no snat, you cannot add an interface
  2310. from a different address scope than the gateway.
  2311. """
  2312. # create an external network on one address scope
  2313. with self.address_scope(name='as1') as addr_scope, \
  2314. self._create_l3_ext_network() as ext_net:
  2315. as_id = addr_scope['address_scope']['id']
  2316. subnet = netaddr.IPNetwork('10.10.10.0/24')
  2317. subnetpool = self._test_create_subnetpool(
  2318. [subnet.cidr], name='sp1',
  2319. min_prefixlen='24', address_scope_id=as_id)
  2320. subnetpool_id = subnetpool['subnetpool']['id']
  2321. data = {'subnet': {
  2322. 'network_id': ext_net['network']['id'],
  2323. 'subnetpool_id': subnetpool_id,
  2324. 'ip_version': 4,
  2325. 'enable_dhcp': False,
  2326. 'tenant_id': ext_net['network']['tenant_id']}}
  2327. req = self.new_create_request('subnets', data)
  2328. ext_subnet = self.deserialize(self.fmt, req.get_response(self.api))
  2329. # create a regular network on another address scope
  2330. with self.address_scope(name='as2') as addr_scope2, \
  2331. self.network() as net:
  2332. as_id2 = addr_scope2['address_scope']['id']
  2333. subnet2 = netaddr.IPNetwork('20.10.10.0/24')
  2334. subnetpool2 = self._test_create_subnetpool(
  2335. [subnet2.cidr], name='sp2',
  2336. min_prefixlen='24', address_scope_id=as_id2)
  2337. subnetpool_id2 = subnetpool2['subnetpool']['id']
  2338. data = {'subnet': {
  2339. 'network_id': net['network']['id'],
  2340. 'subnetpool_id': subnetpool_id2,
  2341. 'ip_version': 4,
  2342. 'tenant_id': net['network']['tenant_id']}}
  2343. req = self.new_create_request('subnets', data)
  2344. int_subnet = self.deserialize(
  2345. self.fmt, req.get_response(self.api))
  2346. # create a no snat router with this gateway
  2347. with self.router() as r:
  2348. self._add_external_gateway_to_router(
  2349. r['router']['id'],
  2350. ext_subnet['subnet']['network_id'])
  2351. self._update_router_enable_snat(
  2352. r['router']['id'],
  2353. ext_subnet['subnet']['network_id'],
  2354. False)
  2355. # should fail adding the interface to the router
  2356. err_code = exc.HTTPBadRequest.code
  2357. self._router_interface_action('add',
  2358. r['router']['id'],
  2359. int_subnet['subnet']['id'],
  2360. None,
  2361. err_code)
  2362. def test_router_no_snat_with_same_address_scope(self):
  2363. """Test that if the router has no snat, you can add an interface
  2364. from the same address scope as the gateway.
  2365. """
  2366. # create an external network on one address scope
  2367. with self.address_scope(name='as1') as addr_scope, \
  2368. self._create_l3_ext_network() as ext_net:
  2369. as_id = addr_scope['address_scope']['id']
  2370. subnet = netaddr.IPNetwork('10.10.10.0/21')
  2371. subnetpool = self._test_create_subnetpool(
  2372. [subnet.cidr], name='sp1',
  2373. min_prefixlen='24', address_scope_id=as_id)
  2374. subnetpool_id = subnetpool['subnetpool']['id']
  2375. data = {'subnet': {
  2376. 'network_id': ext_net['network']['id'],
  2377. 'subnetpool_id': subnetpool_id,
  2378. 'ip_version': 4,
  2379. 'enable_dhcp': False,
  2380. 'tenant_id': ext_net['network']['tenant_id']}}
  2381. req = self.new_create_request('subnets', data)
  2382. ext_subnet = self.deserialize(self.fmt, req.get_response(self.api))
  2383. # create a regular network on the same address scope
  2384. with self.network() as net:
  2385. data = {'subnet': {
  2386. 'network_id': net['network']['id'],
  2387. 'subnetpool_id': subnetpool_id,
  2388. 'ip_version': 4,
  2389. 'tenant_id': net['network']['tenant_id']}}
  2390. req = self.new_create_request('subnets', data)
  2391. int_subnet = self.deserialize(
  2392. self.fmt, req.get_response(self.api))
  2393. # create a no snat router with this gateway
  2394. with self.router() as r:
  2395. self._add_external_gateway_to_router(
  2396. r['router']['id'],
  2397. ext_subnet['subnet']['network_id'])
  2398. self._update_router_enable_snat(
  2399. r['router']['id'],
  2400. ext_subnet['subnet']['network_id'],
  2401. False)
  2402. # should succeed adding the interface to the router
  2403. self._router_interface_action('add',
  2404. r['router']['id'],
  2405. int_subnet['subnet']['id'],
  2406. None)
  2407. def _mock_add_snat_rule(self):
  2408. return mock.patch("vmware_nsxlib.v3.router.RouterLib."
  2409. "add_gw_snat_rule")
  2410. def _mock_add_remove_service_router(self):
  2411. return mock.patch("vmware_nsxlib.v3.core_resources."
  2412. "NsxLibLogicalRouter.update")
  2413. def _mock_del_snat_rule(self):
  2414. return mock.patch("vmware_nsxlib.v3.router.RouterLib."
  2415. "delete_gw_snat_rule_by_source")
  2416. def _prepare_external_subnet_on_address_scope(self,
  2417. ext_net,
  2418. address_scope):
  2419. as_id = address_scope['address_scope']['id']
  2420. subnet = netaddr.IPNetwork('10.10.10.0/21')
  2421. subnetpool = self._test_create_subnetpool(
  2422. [subnet.cidr], name='sp1',
  2423. min_prefixlen='24', address_scope_id=as_id)
  2424. subnetpool_id = subnetpool['subnetpool']['id']
  2425. data = {'subnet': {
  2426. 'network_id': ext_net['network']['id'],
  2427. 'subnetpool_id': subnetpool_id,
  2428. 'ip_version': 4,
  2429. 'enable_dhcp': False,
  2430. 'tenant_id': ext_net['network']['tenant_id']}}
  2431. req = self.new_create_request('subnets', data)
  2432. ext_subnet = self.deserialize(self.fmt, req.get_response(self.api))
  2433. return ext_subnet['subnet']
  2434. def _create_subnet_and_assert_snat_rules(self, subnetpool_id,
  2435. router_id,
  2436. assert_snat_deleted=False,
  2437. assert_snat_added=False):
  2438. # create a regular network on the given subnet pool
  2439. with self.network() as net:
  2440. data = {'subnet': {
  2441. 'network_id': net['network']['id'],
  2442. 'subnetpool_id': subnetpool_id,
  2443. 'ip_version': 4,
  2444. 'tenant_id': net['network']['tenant_id']}}
  2445. req = self.new_create_request('subnets', data)
  2446. int_subnet = self.deserialize(
  2447. self.fmt, req.get_response(self.api))
  2448. with self._mock_add_snat_rule() as add_nat,\
  2449. self._mock_del_snat_rule() as delete_nat:
  2450. # Add the interface
  2451. self._router_interface_action(
  2452. 'add',
  2453. router_id,
  2454. int_subnet['subnet']['id'],
  2455. None)
  2456. if assert_snat_deleted:
  2457. delete_nat.assert_called()
  2458. else:
  2459. delete_nat.assert_not_called()
  2460. if assert_snat_added:
  2461. add_nat.assert_called()
  2462. else:
  2463. add_nat.assert_not_called()
  2464. def test_add_service_router_enable_snat(self):
  2465. with self.address_scope(name='as1') as addr_scope, \
  2466. self._create_l3_ext_network() as ext_net:
  2467. ext_subnet = self._prepare_external_subnet_on_address_scope(
  2468. ext_net, addr_scope)
  2469. # create a router with this gateway
  2470. with self.router() as r, \
  2471. mock.patch("vmware_nsxlib.v3.router.RouterLib."
  2472. "has_service_router", return_value=False),\
  2473. self._mock_add_remove_service_router() as change_sr:
  2474. router_id = r['router']['id']
  2475. self._add_external_gateway_to_router(
  2476. router_id, ext_subnet['network_id'])
  2477. # Checking that router update is being called with
  2478. # edge_cluster_uuid, for creating a service router
  2479. change_sr.assert_called_once_with(
  2480. mock.ANY, edge_cluster_id=NSX_EDGE_CLUSTER_UUID,
  2481. enable_standby_relocation=True)
  2482. def test_remove_service_router_disable_snat(self):
  2483. with self.address_scope(name='as1') as addr_scope, \
  2484. self._create_l3_ext_network() as ext_net:
  2485. ext_subnet = self._prepare_external_subnet_on_address_scope(
  2486. ext_net, addr_scope)
  2487. # create a router with this gateway, disable snat
  2488. with self.router() as r:
  2489. self._add_external_gateway_to_router(
  2490. r['router']['id'],
  2491. ext_subnet['network_id'])
  2492. with mock.patch("vmware_nsxlib.v3.router.RouterLib."
  2493. "has_service_router", return_value=True),\
  2494. self._mock_add_remove_service_router() as change_sr:
  2495. self._update_router_enable_snat(
  2496. r['router']['id'],
  2497. ext_subnet['network_id'],
  2498. False)
  2499. # Checking that router update is being called
  2500. # and setting edge_cluster_uuid to None, for service
  2501. # router removal.
  2502. change_sr.assert_called_once_with(
  2503. mock.ANY, edge_cluster_id=None,
  2504. enable_standby_relocation=False)
  2505. def test_router_address_scope_snat_rules(self):
  2506. """Test that if the router interface had the same address scope
  2507. as the gateway - snat rule is not added.
  2508. """
  2509. # create an external network on one address scope
  2510. with self.address_scope(name='as1') as addr_scope, \
  2511. self._create_l3_ext_network() as ext_net:
  2512. ext_subnet = self._prepare_external_subnet_on_address_scope(
  2513. ext_net, addr_scope)
  2514. # create a router with this gateway
  2515. with self.router() as r:
  2516. self._add_external_gateway_to_router(
  2517. r['router']['id'],
  2518. ext_subnet['network_id'])
  2519. # create a regular network on same address scope
  2520. # and verify no snat change
  2521. as_id = addr_scope['address_scope']['id']
  2522. subnet = netaddr.IPNetwork('30.10.10.0/24')
  2523. subnetpool = self._test_create_subnetpool(
  2524. [subnet.cidr], name='sp2',
  2525. min_prefixlen='24', address_scope_id=as_id)
  2526. as_id = addr_scope['address_scope']['id']
  2527. subnetpool_id = subnetpool['subnetpool']['id']
  2528. self._create_subnet_and_assert_snat_rules(
  2529. subnetpool_id, r['router']['id'])
  2530. # create a regular network on a different address scope
  2531. # and verify snat rules are added
  2532. with self.address_scope(name='as2') as addr_scope2:
  2533. as2_id = addr_scope2['address_scope']['id']
  2534. subnet2 = netaddr.IPNetwork('20.10.10.0/24')
  2535. subnetpool2 = self._test_create_subnetpool(
  2536. [subnet2.cidr], name='sp2',
  2537. min_prefixlen='24', address_scope_id=as2_id)
  2538. subnetpool2_id = subnetpool2['subnetpool']['id']
  2539. self._create_subnet_and_assert_snat_rules(
  2540. subnetpool2_id, r['router']['id'],
  2541. assert_snat_added=True)
  2542. def _test_router_address_scope_change(self, change_gw=False):
  2543. """When subnetpool address scope changes, and router that was
  2544. originally under same address scope, results having different
  2545. address scopes, relevant snat rules are added.
  2546. """
  2547. # create an external network on one address scope
  2548. with self.address_scope(name='as1') as addr_scope, \
  2549. self._create_l3_ext_network() as ext_net:
  2550. ext_subnet = self._prepare_external_subnet_on_address_scope(
  2551. ext_net, addr_scope)
  2552. # create a router with this gateway
  2553. with self.router() as r:
  2554. self._add_external_gateway_to_router(
  2555. r['router']['id'],
  2556. ext_subnet['network_id'])
  2557. # create a regular network on same address scope
  2558. # and verify no snat change
  2559. as_id = addr_scope['address_scope']['id']
  2560. subnet2 = netaddr.IPNetwork('40.10.10.0/24')
  2561. subnetpool2 = self._test_create_subnetpool(
  2562. [subnet2.cidr], name='sp2',
  2563. min_prefixlen='24', address_scope_id=as_id)
  2564. subnetpool2_id = subnetpool2['subnetpool']['id']
  2565. self._create_subnet_and_assert_snat_rules(
  2566. subnetpool2_id, r['router']['id'])
  2567. # change address scope of the first subnetpool
  2568. with self.address_scope(name='as2') as addr_scope2,\
  2569. self._mock_add_snat_rule() as add_nat:
  2570. as2_id = addr_scope2['address_scope']['id']
  2571. data = {'subnetpool': {
  2572. 'address_scope_id': as2_id}}
  2573. if change_gw:
  2574. subnetpool_to_update = ext_subnet['subnetpool_id']
  2575. else:
  2576. subnetpool_to_update = subnetpool2_id
  2577. req = self.new_update_request('subnetpools', data,
  2578. subnetpool_to_update)
  2579. req.get_response(self.api)
  2580. add_nat.assert_called_once()
  2581. def test_router_address_scope_change(self):
  2582. self._test_router_address_scope_change()
  2583. def test_router_address_scope_gw_change(self):
  2584. self._test_router_address_scope_change(change_gw=True)
  2585. def _test_3leg_router_address_scope_change(self, change_gw=False,
  2586. change_2gw=False):
  2587. """Test address scope change scenarios with router that covers
  2588. 3 address scopes
  2589. """
  2590. # create an external network on one address scope
  2591. with self.address_scope(name='as1') as as1, \
  2592. self.address_scope(name='as2') as as2, \
  2593. self.address_scope(name='as3') as as3, \
  2594. self._create_l3_ext_network() as ext_net:
  2595. ext_subnet = self._prepare_external_subnet_on_address_scope(
  2596. ext_net, as1)
  2597. as1_id = as1['address_scope']['id']
  2598. # create a router with this gateway
  2599. with self.router() as r:
  2600. self._add_external_gateway_to_router(
  2601. r['router']['id'],
  2602. ext_subnet['network_id'])
  2603. # create a regular network on address scope 2
  2604. # and verify snat change
  2605. as2_id = as2['address_scope']['id']
  2606. subnet2 = netaddr.IPNetwork('20.10.10.0/24')
  2607. subnetpool2 = self._test_create_subnetpool(
  2608. [subnet2.cidr], name='sp2',
  2609. min_prefixlen='24', address_scope_id=as2_id)
  2610. subnetpool2_id = subnetpool2['subnetpool']['id']
  2611. self._create_subnet_and_assert_snat_rules(
  2612. subnetpool2_id, r['router']['id'], assert_snat_added=True)
  2613. # create a regular network on address scope 3
  2614. # verify no snat change
  2615. as3_id = as3['address_scope']['id']
  2616. subnet3 = netaddr.IPNetwork('30.10.10.0/24')
  2617. subnetpool3 = self._test_create_subnetpool(
  2618. [subnet3.cidr], name='sp2',
  2619. min_prefixlen='24', address_scope_id=as3_id)
  2620. subnetpool3_id = subnetpool3['subnetpool']['id']
  2621. self._create_subnet_and_assert_snat_rules(
  2622. subnetpool3_id, r['router']['id'], assert_snat_added=True)
  2623. with self._mock_add_snat_rule() as add_nat, \
  2624. self._mock_del_snat_rule() as del_nat:
  2625. if change_gw:
  2626. # change address scope of GW subnet
  2627. subnetpool_to_update = ext_subnet['subnetpool_id']
  2628. else:
  2629. subnetpool_to_update = subnetpool2_id
  2630. if change_2gw:
  2631. # change subnet2 to be in GW address scope
  2632. target_as = as1_id
  2633. else:
  2634. target_as = as3_id
  2635. data = {'subnetpool': {
  2636. 'address_scope_id': target_as}}
  2637. req = self.new_update_request('subnetpools', data,
  2638. subnetpool_to_update)
  2639. req.get_response(self.api)
  2640. if change_gw:
  2641. # The test changed address scope of gw subnet.
  2642. # Both previous rules should be deleted,
  2643. # and one new rule for subnet2 should be added
  2644. del_nat.assert_called()
  2645. self.assertEqual(2, del_nat.call_count)
  2646. add_nat.assert_called_once()
  2647. else:
  2648. if change_2gw:
  2649. # The test changed address scope of subnet2 to be
  2650. # same as GW address scope.
  2651. # Snat rule for as2 will be deleted. No effect on as3
  2652. # rule.
  2653. del_nat.assert_called_once()
  2654. else:
  2655. # The test changed address scope of subnet2 to
  2656. # as3. Affected snat rule should be re-created.
  2657. del_nat.assert_called_once()
  2658. add_nat.assert_called_once()
  2659. def test_3leg_router_address_scope_change(self):
  2660. self._test_3leg_router_address_scope_change()
  2661. def test_3leg_router_address_scope_change_to_gw(self):
  2662. self._test_3leg_router_address_scope_change(change_2gw=True)
  2663. def test_3leg_router_gw_address_scope_change(self):
  2664. self._test_3leg_router_address_scope_change(change_gw=True)
  2665. def test_subnetpool_router_address_scope_change_no_effect(self):
  2666. """When all router interfaces are allocated from same subnetpool,
  2667. changing address scope on this subnetpool should not affect snat rules.
  2668. """
  2669. # create an external network on one address scope
  2670. with self.address_scope(name='as1') as addr_scope, \
  2671. self._create_l3_ext_network() as ext_net:
  2672. ext_subnet = self._prepare_external_subnet_on_address_scope(
  2673. ext_net, addr_scope)
  2674. # create a router with this gateway
  2675. with self.router() as r:
  2676. self._add_external_gateway_to_router(
  2677. r['router']['id'],
  2678. ext_subnet['network_id'])
  2679. # create a regular network on same address scope
  2680. # and verify no snat change
  2681. self._create_subnet_and_assert_snat_rules(
  2682. ext_subnet['subnetpool_id'], r['router']['id'])
  2683. with self.address_scope(name='as2') as addr_scope2,\
  2684. self._mock_add_snat_rule() as add_nat,\
  2685. self._mock_del_snat_rule() as delete_nat:
  2686. as2_id = addr_scope2['address_scope']['id']
  2687. # change address scope of the subnetpool
  2688. data = {'subnetpool': {
  2689. 'address_scope_id': as2_id}}
  2690. req = self.new_update_request('subnetpools', data,
  2691. ext_subnet['subnetpool_id'])
  2692. req.get_response(self.api)
  2693. add_nat.assert_not_called()
  2694. delete_nat.assert_not_called()
  2695. def test_router_admin_state(self):
  2696. """It is not allowed to set the router admin-state to down"""
  2697. with self.router() as r:
  2698. self._update('routers', r['router']['id'],
  2699. {'router': {'admin_state_up': False}},
  2700. expected_code=exc.HTTPBadRequest.code)
  2701. def test_router_dhcp_relay_dhcp_enabled(self):
  2702. """Verify that the relay service is added to the router interface"""
  2703. self._enable_dhcp_relay()
  2704. with self.network() as network:
  2705. with mock.patch.object(self.plugin,
  2706. 'validate_router_dhcp_relay'),\
  2707. self.subnet(network=network, enable_dhcp=True) as s1,\
  2708. self.router() as r1,\
  2709. mock.patch.object(self.plugin.nsxlib.logical_router_port,
  2710. 'update') as mock_update_port:
  2711. self._router_interface_action('add', r1['router']['id'],
  2712. s1['subnet']['id'], None)
  2713. mock_update_port.assert_called_once_with(
  2714. mock.ANY,
  2715. relay_service_uuid=NSX_DHCP_RELAY_SRV,
  2716. subnets=mock.ANY)
  2717. def test_router_dhcp_relay_dhcp_disabled(self):
  2718. """Verify that the relay service is not added to the router interface
  2719. If the subnet do not have enabled dhcp
  2720. """
  2721. self._enable_dhcp_relay()
  2722. with self.network() as network:
  2723. with mock.patch.object(self.plugin,
  2724. 'validate_router_dhcp_relay'),\
  2725. self.subnet(network=network, enable_dhcp=False) as s1,\
  2726. self.router() as r1,\
  2727. mock.patch.object(self.plugin.nsxlib.logical_router_port,
  2728. 'update') as mock_update_port:
  2729. self._router_interface_action('add', r1['router']['id'],
  2730. s1['subnet']['id'], None)
  2731. mock_update_port.assert_called_once_with(
  2732. mock.ANY,
  2733. relay_service_uuid=None,
  2734. subnets=mock.ANY)
  2735. def test_router_dhcp_relay_no_ipam(self):
  2736. """Verify that a router cannot be created with relay and no ipam"""
  2737. # Add the relay service to the config and availability zones
  2738. self._enable_dhcp_relay()
  2739. self.assertRaises(n_exc.InvalidInput,
  2740. self.plugin_instance.create_router,
  2741. context.get_admin_context(),
  2742. {'router': {'name': 'rtr'}})
  2743. def test_router_add_gateway_no_subnet_forbidden(self):
  2744. with self.router() as r:
  2745. with self._create_l3_ext_network() as n:
  2746. self._add_external_gateway_to_router(
  2747. r['router']['id'], n['network']['id'],
  2748. expected_code=exc.HTTPBadRequest.code)
  2749. def test_router_add_gateway_no_subnet(self):
  2750. self.skipTest('No support for no subnet gateway set')
  2751. @mock.patch.object(nsx_plugin.NsxV3Plugin, 'validate_availability_zones')
  2752. def test_create_router_with_availability_zone(self, mock_validate_az):
  2753. name = 'rtr-with-zone'
  2754. zone = ['zone1']
  2755. mock_validate_az.return_value = None
  2756. with self.router(name=name, availability_zone_hints=zone) as rtr:
  2757. az_hints = rtr['router']['availability_zone_hints']
  2758. self.assertListEqual(zone, az_hints)
  2759. def _test_route_update_illegal(self, destination):
  2760. routes = [{'destination': destination, 'nexthop': '10.0.1.3'}]
  2761. with self.router() as r:
  2762. with self.subnet(cidr='10.0.1.0/24') as s:
  2763. fixed_ip_data = [{'ip_address': '10.0.1.2'}]
  2764. with self.port(subnet=s, fixed_ips=fixed_ip_data) as p:
  2765. self._router_interface_action(
  2766. 'add', r['router']['id'], None, p['port']['id'])
  2767. self._update('routers', r['router']['id'],
  2768. {'router': {'routes': routes}},
  2769. expected_code=400)
  2770. def test_route_update_illegal(self):
  2771. self._test_route_update_illegal('0.0.0.0/0')
  2772. self._test_route_update_illegal('0.0.0.0/16')
  2773. def test_update_router_distinct_edge_cluster(self):
  2774. self.mock_get_edge_cluster.stop()
  2775. edge_cluster = uuidutils.generate_uuid()
  2776. mock.patch(
  2777. "vmware_nsxlib.v3.core_resources.NsxLibEdgeCluster."
  2778. "get_id_by_name_or_id",
  2779. return_value=edge_cluster).start()
  2780. cfg.CONF.set_override('edge_cluster', edge_cluster, 'nsx_v3')
  2781. self._initialize_azs()
  2782. with self.address_scope(name='as1') as addr_scope, \
  2783. self._create_l3_ext_network() as ext_net:
  2784. ext_subnet = self._prepare_external_subnet_on_address_scope(
  2785. ext_net, addr_scope)
  2786. # create a router with this gateway
  2787. with self.router() as r, \
  2788. mock.patch("vmware_nsxlib.v3.router.RouterLib."
  2789. "has_service_router", return_value=False),\
  2790. self._mock_add_remove_service_router() as change_sr:
  2791. router_id = r['router']['id']
  2792. self._add_external_gateway_to_router(
  2793. router_id, ext_subnet['network_id'])
  2794. change_sr.assert_called_once_with(
  2795. mock.ANY, edge_cluster_id=edge_cluster,
  2796. enable_standby_relocation=True)
  2797. self.mock_get_edge_cluster.start()
  2798. def test_router_add_interface_cidr_overlapped_with_gateway(self):
  2799. with self.router() as r,\
  2800. self._create_l3_ext_network() as ext_net,\
  2801. self.subnet(cidr='10.0.1.0/24') as s1,\
  2802. self.subnet(network=ext_net, cidr='10.0.0.0/16',
  2803. enable_dhcp=False) as s2:
  2804. self._add_external_gateway_to_router(
  2805. r['router']['id'],
  2806. s2['subnet']['network_id'])
  2807. res = self._router_interface_action(
  2808. 'add', r['router']['id'],
  2809. s1['subnet']['id'], None,
  2810. expected_code=exc.HTTPBadRequest.code)
  2811. self.assertIn('NeutronError', res)
  2812. def test_router_add_gateway_overlapped_with_interface_cidr(self):
  2813. with self.router() as r,\
  2814. self._create_l3_ext_network() as ext_net,\
  2815. self.subnet(cidr='10.0.1.0/24') as s1,\
  2816. self.subnet(network=ext_net, cidr='10.0.0.0/16',
  2817. enable_dhcp=False) as s2:
  2818. self._router_interface_action(
  2819. 'add', r['router']['id'],
  2820. s1['subnet']['id'], None)
  2821. res = self._add_external_gateway_to_router(
  2822. r['router']['id'],
  2823. s2['subnet']['network_id'],
  2824. expected_code=exc.HTTPBadRequest.code)
  2825. self.assertIn('NeutronError', res)
  2826. def test_router_add_interface_by_port_cidr_overlapped_with_gateway(self):
  2827. with self.router() as r,\
  2828. self._create_l3_ext_network() as ext_net,\
  2829. self.subnet(cidr='10.0.1.0/24') as s1,\
  2830. self.subnet(network=ext_net, cidr='10.0.0.0/16',
  2831. enable_dhcp=False) as s2,\
  2832. self.port(subnet=s1) as p:
  2833. self._add_external_gateway_to_router(
  2834. r['router']['id'],
  2835. s2['subnet']['network_id'])
  2836. res = self._router_interface_action(
  2837. 'add', r['router']['id'],
  2838. None,
  2839. p['port']['id'],
  2840. expected_code=exc.HTTPBadRequest.code)
  2841. self.assertIn('NeutronError', res)
  2842. def test_create_floatingip_invalid_fixed_ipv6_address_returns_400(self):
  2843. self.skipTest('Failed because of illegal port id')
  2844. def test_create_floatingip_with_router_interface_device_owner_fail(self):
  2845. # This tests that an error is raised when trying to assign a router
  2846. # interface port with floatingip.
  2847. with self.subnet(cidr='30.0.0.0/24', gateway_ip=None) as private_sub:
  2848. with self.port(
  2849. subnet=private_sub,
  2850. device_owner=constants.DEVICE_OWNER_ROUTER_INTF) as p:
  2851. port_id = p['port']['id']
  2852. with self.router() as r:
  2853. self._router_interface_action('add', r['router']['id'],
  2854. None, port_id)
  2855. with self.external_network() as public_net, self.subnet(
  2856. network=public_net, cidr='12.0.0.0/24') as public_sub:
  2857. self._add_external_gateway_to_router(
  2858. r['router']['id'],
  2859. public_sub['subnet']['network_id'])
  2860. self._make_floatingip(
  2861. self.fmt, public_sub['subnet']['network_id'],
  2862. port_id=port_id,
  2863. http_status=exc.HTTPBadRequest.code)
  2864. def test_assign_floatingip_to_router_interface_device_owner_fail(self):
  2865. # This tests that an error is raised when trying to assign a router
  2866. # interface port with floatingip.
  2867. with self.subnet(cidr='30.0.0.0/24', gateway_ip=None) as private_sub:
  2868. with self.port(
  2869. subnet=private_sub,
  2870. device_owner=constants.DEVICE_OWNER_ROUTER_INTF) as p:
  2871. port_id = p['port']['id']
  2872. with self.router() as r:
  2873. self._router_interface_action('add', r['router']['id'],
  2874. None, port_id)
  2875. with self.external_network() as public_net, self.subnet(
  2876. network=public_net, cidr='12.0.0.0/24') as public_sub:
  2877. self._add_external_gateway_to_router(
  2878. r['router']['id'],
  2879. public_sub['subnet']['network_id'])
  2880. fip = self._make_floatingip(self.fmt, public_sub[
  2881. 'subnet']['network_id'])
  2882. self._update('floatingips', fip['floatingip'][
  2883. 'id'], {'floatingip': {'port_id': port_id}},
  2884. expected_code=exc.HTTPBadRequest.code)
  2885. class ExtGwModeTestCase(test_ext_gw_mode.ExtGwModeIntTestCase,
  2886. L3NatTest):
  2887. def test_router_gateway_set_fail_after_port_create(self):
  2888. self.skipTest("TBD")
  2889. @common_v3.with_external_subnet
  2890. def _test_router_update_ext_gwinfo(self, snat_input_value,
  2891. snat_expected_value=False,
  2892. expected_http_code=exc.HTTPOk.code):
  2893. return super(ExtGwModeTestCase, self)._test_router_update_ext_gwinfo(
  2894. snat_input_value,
  2895. snat_expected_value=snat_expected_value,
  2896. expected_http_code=expected_http_code)
  2897. @common_v3.with_external_subnet
  2898. def test_router_gateway_set_retry(self):
  2899. super(ExtGwModeTestCase, self).test_router_gateway_set_retry()
  2900. @common_v3.with_external_subnet
  2901. def _test_router_create_show_ext_gwinfo(self, *args, **kwargs):
  2902. return super(ExtGwModeTestCase,
  2903. self)._test_router_create_show_ext_gwinfo(*args, **kwargs)