Merge "[NSXv]: Add support for dns search domains in NSXv plugin"
This commit is contained in:
commit
e7012775a7
@ -1 +1 @@
|
|||||||
2af850eb3970
|
69fb78b33d41
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
# Copyright 2016 VMware, Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
"""NSXv add dns search domain to subnets
|
||||||
|
|
||||||
|
Revision ID: 69fb78b33d41
|
||||||
|
Revises: 2af850eb3970
|
||||||
|
Create Date: 2016-01-27 07:28:35.369938
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '69fb78b33d41'
|
||||||
|
down_revision = '2af850eb3970'
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
op.create_table(
|
||||||
|
'nsxv_subnet_ext_attributes',
|
||||||
|
sa.Column('subnet_id', sa.String(length=36), nullable=False),
|
||||||
|
sa.Column('dns_search_domain', sa.String(length=255), nullable=False),
|
||||||
|
sa.ForeignKeyConstraint(['subnet_id'],
|
||||||
|
['subnets.id'],
|
||||||
|
ondelete='CASCADE'),
|
||||||
|
sa.PrimaryKeyConstraint('subnet_id')
|
||||||
|
)
|
@ -27,6 +27,7 @@ from vmware_nsx._i18n import _, _LE
|
|||||||
from vmware_nsx.common import exceptions as nsx_exc
|
from vmware_nsx.common import exceptions as nsx_exc
|
||||||
from vmware_nsx.common import nsxv_constants
|
from vmware_nsx.common import nsxv_constants
|
||||||
from vmware_nsx.db import nsxv_models
|
from vmware_nsx.db import nsxv_models
|
||||||
|
from vmware_nsx.extensions import dns_search_domain as ext_dns_search_domain
|
||||||
from vmware_nsx.plugins.nsx_v.vshield.common import constants
|
from vmware_nsx.plugins.nsx_v.vshield.common import constants
|
||||||
|
|
||||||
NsxvEdgeDhcpStaticBinding = nsxv_models.NsxvEdgeDhcpStaticBinding
|
NsxvEdgeDhcpStaticBinding = nsxv_models.NsxvEdgeDhcpStaticBinding
|
||||||
@ -715,3 +716,29 @@ def del_nsxv_lbaas_certificate_binding(session, cert_id, edge_id):
|
|||||||
return (session.query(nsxv_models.NsxvLbaasCertificateBinding).
|
return (session.query(nsxv_models.NsxvLbaasCertificateBinding).
|
||||||
filter_by(cert_id=cert_id,
|
filter_by(cert_id=cert_id,
|
||||||
edge_id=edge_id).delete())
|
edge_id=edge_id).delete())
|
||||||
|
|
||||||
|
|
||||||
|
def add_nsxv_subnet_ext_attributes(session, subnet_id, dns_search_domain):
|
||||||
|
with session.begin(subtransactions=True):
|
||||||
|
binding = nsxv_models.NsxvSubnetExtAttributes(
|
||||||
|
subnet_id=subnet_id,
|
||||||
|
dns_search_domain=dns_search_domain)
|
||||||
|
session.add(binding)
|
||||||
|
return binding
|
||||||
|
|
||||||
|
|
||||||
|
def get_nsxv_subnet_ext_attributes(session, subnet_id):
|
||||||
|
try:
|
||||||
|
return session.query(
|
||||||
|
nsxv_models.NsxvSubnetExtAttributes).filter_by(
|
||||||
|
subnet_id=subnet_id).one()
|
||||||
|
except exc.NoResultFound:
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def update_nsxv_subnet_ext_attributes(session, subnet_id, dns_search_domain):
|
||||||
|
with session.begin(subtransactions=True):
|
||||||
|
binding = (session.query(nsxv_models.NsxvSubnetExtAttributes).
|
||||||
|
filter_by(subnet_id=subnet_id).one())
|
||||||
|
binding[ext_dns_search_domain.DNS_SEARCH_DOMAIN] = dns_search_domain
|
||||||
|
return binding
|
||||||
|
@ -310,3 +310,20 @@ class NsxvLbaasCertificateBinding(model_base.BASEV2):
|
|||||||
cert_id = sa.Column(sa.String(36), primary_key=True)
|
cert_id = sa.Column(sa.String(36), primary_key=True)
|
||||||
edge_id = sa.Column(sa.String(36), primary_key=True)
|
edge_id = sa.Column(sa.String(36), primary_key=True)
|
||||||
edge_cert_id = sa.Column(sa.String(36), nullable=False)
|
edge_cert_id = sa.Column(sa.String(36), nullable=False)
|
||||||
|
|
||||||
|
|
||||||
|
class NsxvSubnetExtAttributes(model_base.BASEV2):
|
||||||
|
"""Subnet attributes managed by NSX plugin extensions."""
|
||||||
|
|
||||||
|
__tablename__ = 'nsxv_subnet_ext_attributes'
|
||||||
|
|
||||||
|
subnet_id = sa.Column(sa.String(36),
|
||||||
|
sa.ForeignKey('subnets.id', ondelete="CASCADE"),
|
||||||
|
primary_key=True)
|
||||||
|
dns_search_domain = sa.Column(sa.String(255), nullable=False)
|
||||||
|
# Add a relationship to the Subnet model in order to instruct
|
||||||
|
# SQLAlchemy to eagerly load this association
|
||||||
|
subnet = orm.relationship(
|
||||||
|
models_v2.Subnet,
|
||||||
|
backref=orm.backref("nsxv_subnet_attributes", lazy='joined',
|
||||||
|
uselist=False, cascade='delete'))
|
||||||
|
52
vmware_nsx/extensions/dns_search_domain.py
Normal file
52
vmware_nsx/extensions/dns_search_domain.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# Copyright 2016 VMware, Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
from neutron.api import extensions
|
||||||
|
from neutron.api.v2 import attributes
|
||||||
|
|
||||||
|
|
||||||
|
DNS_SEARCH_DOMAIN = 'dns_search_domain'
|
||||||
|
EXTENDED_ATTRIBUTES_2_0 = {
|
||||||
|
'subnets': {
|
||||||
|
DNS_SEARCH_DOMAIN: {'allow_post': True, 'allow_put': True,
|
||||||
|
'default': attributes.ATTR_NOT_SPECIFIED,
|
||||||
|
'validate': {'type:string': None},
|
||||||
|
'is_visible': True},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Dns_search_domain(extensions.ExtensionDescriptor):
|
||||||
|
"""Extension class supporting dns search domains for subnets."""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_name(cls):
|
||||||
|
return "DNS search Domains"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_alias(cls):
|
||||||
|
return "dns-search-domain"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_description(cls):
|
||||||
|
return "Enable the ability to add DNS search domain name for Subnets"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_updated(cls):
|
||||||
|
return "2016-1-22T10:00:00-00:00"
|
||||||
|
|
||||||
|
def get_extended_resources(self, version):
|
||||||
|
if version == "2.0":
|
||||||
|
return EXTENDED_ATTRIBUTES_2_0
|
||||||
|
return {}
|
@ -69,6 +69,7 @@ from vmware_nsx.extensions import (
|
|||||||
advancedserviceproviders as as_providers)
|
advancedserviceproviders as as_providers)
|
||||||
from vmware_nsx.extensions import (
|
from vmware_nsx.extensions import (
|
||||||
vnicindex as ext_vnic_idx)
|
vnicindex as ext_vnic_idx)
|
||||||
|
from vmware_nsx.extensions import dns_search_domain as ext_dns_search_domain
|
||||||
from vmware_nsx.extensions import routersize
|
from vmware_nsx.extensions import routersize
|
||||||
from vmware_nsx.plugins.nsx_v import managers
|
from vmware_nsx.plugins.nsx_v import managers
|
||||||
from vmware_nsx.plugins.nsx_v import md_proxy as nsx_v_md_proxy
|
from vmware_nsx.plugins.nsx_v import md_proxy as nsx_v_md_proxy
|
||||||
@ -102,6 +103,7 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||||||
supported_extension_aliases = ["agent",
|
supported_extension_aliases = ["agent",
|
||||||
"allowed-address-pairs",
|
"allowed-address-pairs",
|
||||||
"binding",
|
"binding",
|
||||||
|
"dns-search-domain",
|
||||||
"dvr",
|
"dvr",
|
||||||
"ext-gw-mode",
|
"ext-gw-mode",
|
||||||
"multi-provider",
|
"multi-provider",
|
||||||
@ -1134,12 +1136,51 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||||||
s = super(NsxVPluginV2, self).create_subnet(context, subnet)
|
s = super(NsxVPluginV2, self).create_subnet(context, subnet)
|
||||||
if s['enable_dhcp']:
|
if s['enable_dhcp']:
|
||||||
try:
|
try:
|
||||||
|
self._process_subnet_ext_attr_create(
|
||||||
|
session=context.session,
|
||||||
|
subnet_db=s,
|
||||||
|
subnet_req=data)
|
||||||
self._update_dhcp_service_with_subnet(context, s)
|
self._update_dhcp_service_with_subnet(context, s)
|
||||||
except Exception:
|
except Exception:
|
||||||
with excutils.save_and_reraise_exception():
|
with excutils.save_and_reraise_exception():
|
||||||
self.delete_subnet(context, s['id'])
|
self.delete_subnet(context, s['id'])
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
def _process_subnet_ext_attr_create(self, session, subnet_db,
|
||||||
|
subnet_req):
|
||||||
|
# Verify if dns search domain for subnet is configured
|
||||||
|
dns_search_domain = subnet_req.get(
|
||||||
|
ext_dns_search_domain.DNS_SEARCH_DOMAIN)
|
||||||
|
if not attr.is_attr_set(dns_search_domain):
|
||||||
|
return
|
||||||
|
sub_binding = nsxv_db.get_nsxv_subnet_ext_attributes(
|
||||||
|
session=session,
|
||||||
|
subnet_id=subnet_db['id'])
|
||||||
|
# Create a DNS search domain entry for subnet if it does not exist
|
||||||
|
if not sub_binding:
|
||||||
|
nsxv_db.add_nsxv_subnet_ext_attributes(
|
||||||
|
session=session,
|
||||||
|
subnet_id=subnet_db['id'],
|
||||||
|
dns_search_domain=dns_search_domain)
|
||||||
|
# Else update only if a new value for dns search domain is provided
|
||||||
|
elif sub_binding.dns_search_domain != dns_search_domain:
|
||||||
|
nsxv_db.update_nsxv_subnet_ext_attributes(
|
||||||
|
session=session,
|
||||||
|
subnet_id=subnet_db['id'],
|
||||||
|
dns_search_domain=dns_search_domain)
|
||||||
|
subnet_db['dns_search_domain'] = dns_search_domain
|
||||||
|
|
||||||
|
def _process_subnet_ext_attr_update(self, session, subnet_db,
|
||||||
|
subnet_req):
|
||||||
|
update_dns_search_domain = False
|
||||||
|
# Update dns search domain attribute for subnet
|
||||||
|
if ext_dns_search_domain.DNS_SEARCH_DOMAIN in subnet_req:
|
||||||
|
self._process_subnet_ext_attr_create(session,
|
||||||
|
subnet_db,
|
||||||
|
subnet_req)
|
||||||
|
update_dns_search_domain = True
|
||||||
|
return update_dns_search_domain
|
||||||
|
|
||||||
def update_subnet(self, context, id, subnet):
|
def update_subnet(self, context, id, subnet):
|
||||||
s = subnet['subnet']
|
s = subnet['subnet']
|
||||||
if "host_routes" in s and s["host_routes"]:
|
if "host_routes" in s and s["host_routes"]:
|
||||||
@ -1149,7 +1190,9 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||||||
gateway_ip = orig['gateway_ip']
|
gateway_ip = orig['gateway_ip']
|
||||||
enable_dhcp = orig['enable_dhcp']
|
enable_dhcp = orig['enable_dhcp']
|
||||||
subnet = super(NsxVPluginV2, self).update_subnet(context, id, subnet)
|
subnet = super(NsxVPluginV2, self).update_subnet(context, id, subnet)
|
||||||
if (gateway_ip != subnet['gateway_ip'] or
|
update_dns_search_domain = self._process_subnet_ext_attr_update(
|
||||||
|
context.session, subnet, s)
|
||||||
|
if (gateway_ip != subnet['gateway_ip'] or update_dns_search_domain or
|
||||||
set(orig['dns_nameservers']) != set(subnet['dns_nameservers'])):
|
set(orig['dns_nameservers']) != set(subnet['dns_nameservers'])):
|
||||||
# Need to ensure that all of the subnet attributes will be reloaded
|
# Need to ensure that all of the subnet attributes will be reloaded
|
||||||
# when creating the edge bindings. Without adding this the original
|
# when creating the edge bindings. Without adding this the original
|
||||||
@ -1162,6 +1205,14 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
|
|||||||
self._update_subnet_dhcp_status(subnet, context)
|
self._update_subnet_dhcp_status(subnet, context)
|
||||||
return subnet
|
return subnet
|
||||||
|
|
||||||
|
db_base_plugin_v2.NeutronDbPluginV2.register_dict_extend_funcs(
|
||||||
|
attr.SUBNETS, ['_extend_subnet_dict_dns_search_domain'])
|
||||||
|
|
||||||
|
def _extend_subnet_dict_dns_search_domain(self, subnet_res, subnet_db):
|
||||||
|
subnet_attr = subnet_db.get('nsxv_subnet_attributes')
|
||||||
|
if subnet_attr:
|
||||||
|
subnet_res['dns_search_domain'] = subnet_attr.dns_search_domain
|
||||||
|
|
||||||
def _update_subnet_dhcp_status(self, subnet, context):
|
def _update_subnet_dhcp_status(self, subnet, context):
|
||||||
network_id = subnet['network_id']
|
network_id = subnet['network_id']
|
||||||
if subnet['enable_dhcp']:
|
if subnet['enable_dhcp']:
|
||||||
|
@ -681,6 +681,7 @@ class EdgeManager(object):
|
|||||||
<defaultGateway></defaultGateway> <!--optional.-->
|
<defaultGateway></defaultGateway> <!--optional.-->
|
||||||
<primaryNameServer></primaryNameServer> <!--optional-->
|
<primaryNameServer></primaryNameServer> <!--optional-->
|
||||||
<secondaryNameServer></secondaryNameServer> <!--optional-->
|
<secondaryNameServer></secondaryNameServer> <!--optional-->
|
||||||
|
<domainName></domainName> <!--optional-->
|
||||||
</staticBinding>
|
</staticBinding>
|
||||||
"""
|
"""
|
||||||
static_bindings = []
|
static_bindings = []
|
||||||
@ -711,6 +712,12 @@ class EdgeManager(object):
|
|||||||
elif len(name_servers) >= 2:
|
elif len(name_servers) >= 2:
|
||||||
static_config['primaryNameServer'] = name_servers[0]
|
static_config['primaryNameServer'] = name_servers[0]
|
||||||
static_config['secondaryNameServer'] = name_servers[1]
|
static_config['secondaryNameServer'] = name_servers[1]
|
||||||
|
# Set search domain for static binding
|
||||||
|
sub_binding = nsxv_db.get_nsxv_subnet_ext_attributes(
|
||||||
|
context.session,
|
||||||
|
subnet_id)
|
||||||
|
if sub_binding:
|
||||||
|
static_config['domainName'] = sub_binding.dns_search_domain
|
||||||
|
|
||||||
static_bindings.append(static_config)
|
static_bindings.append(static_config)
|
||||||
return static_bindings
|
return static_bindings
|
||||||
|
111
vmware_nsx/tests/unit/extensions/test_dns_search_domain.py
Normal file
111
vmware_nsx/tests/unit/extensions/test_dns_search_domain.py
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
# Copyright 2016 VMware, Inc.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
|
||||||
|
import neutron.db.api as db
|
||||||
|
from neutron.tests.unit.db import test_db_base_plugin_v2 as test_db
|
||||||
|
|
||||||
|
from vmware_nsx.db import nsxv_db
|
||||||
|
from vmware_nsx.extensions import dns_search_domain as ext_dns_search_domain
|
||||||
|
from vmware_nsx.plugins.nsx_v.vshield import edge_utils
|
||||||
|
from vmware_nsx.tests.unit.nsx_v import test_plugin
|
||||||
|
|
||||||
|
PLUGIN_NAME = 'vmware_nsx.plugin.NsxVPlugin'
|
||||||
|
|
||||||
|
|
||||||
|
class DnsSearchDomainExtensionManager(object):
|
||||||
|
|
||||||
|
def get_resources(self):
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_actions(self):
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_request_extensions(self):
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_extended_resources(self, version):
|
||||||
|
return ext_dns_search_domain.get_extended_resources(version)
|
||||||
|
|
||||||
|
|
||||||
|
class DnsSearchDomainExtensionTestCase(test_plugin.NsxVPluginV2TestCase):
|
||||||
|
"""Test API extension dns-search-domain attribute."""
|
||||||
|
|
||||||
|
@mock.patch.object(edge_utils.EdgeManager, '_deploy_edge')
|
||||||
|
def setUp(self, plugin=PLUGIN_NAME):
|
||||||
|
ext_mgr = DnsSearchDomainExtensionManager()
|
||||||
|
super(DnsSearchDomainExtensionTestCase, self).setUp(ext_mgr=ext_mgr)
|
||||||
|
|
||||||
|
def _create_subnet_with_dns_search_domain(self, dns_search_domain):
|
||||||
|
with self.network() as net:
|
||||||
|
tenant_id = net['network']['tenant_id']
|
||||||
|
net_id = net['network']['id']
|
||||||
|
data = {'subnet': {'network_id': net_id,
|
||||||
|
'cidr': '10.0.0.0/24',
|
||||||
|
'ip_version': 4,
|
||||||
|
'name': 'test-dns-search-domain-subnet',
|
||||||
|
'tenant_id': tenant_id,
|
||||||
|
'dns_search_domain': dns_search_domain}}
|
||||||
|
subnet_req = self.new_create_request('subnets', data)
|
||||||
|
res = subnet_req.get_response(self.api)
|
||||||
|
return self.deserialize(self.fmt, res)
|
||||||
|
|
||||||
|
def test_subnet_create_with_dns_search_domain(self):
|
||||||
|
sub = self._create_subnet_with_dns_search_domain('vmware.com')
|
||||||
|
self.assertEqual('vmware.com', sub['subnet']['dns_search_domain'])
|
||||||
|
|
||||||
|
def test_subnet_update_with_dns_search_domain(self):
|
||||||
|
sub = self._create_subnet_with_dns_search_domain('vmware.com')
|
||||||
|
data = {'subnet': {'dns_search_domain': 'eng.vmware.com'}}
|
||||||
|
req = self.new_update_request('subnets', data, sub['subnet']['id'])
|
||||||
|
updated_sub = self.deserialize(self.fmt, req.get_response(self.api))
|
||||||
|
self.assertEqual('eng.vmware.com',
|
||||||
|
updated_sub['subnet']['dns_search_domain'])
|
||||||
|
|
||||||
|
|
||||||
|
class DnsSearchDomainDBTestCase(test_db.NeutronDbPluginV2TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(DnsSearchDomainDBTestCase, self).setUp()
|
||||||
|
self.session = db.get_session()
|
||||||
|
|
||||||
|
def test_get_nsxv_subnet_ext_attributes_no_dns_search_domain(self):
|
||||||
|
with self.subnet() as sub:
|
||||||
|
sub_binding = nsxv_db.get_nsxv_subnet_ext_attributes(
|
||||||
|
session=self.session, subnet_id=sub['subnet']['id'])
|
||||||
|
self.assertIsNone(sub_binding)
|
||||||
|
|
||||||
|
def test_add_nsxv_subnet_ext_attributes_dns_search_domain(self):
|
||||||
|
with self.subnet() as sub:
|
||||||
|
nsxv_db.add_nsxv_subnet_ext_attributes(
|
||||||
|
session=self.session,
|
||||||
|
subnet_id=sub['subnet']['id'],
|
||||||
|
dns_search_domain='eng.vmware.com')
|
||||||
|
sub_binding = nsxv_db.get_nsxv_subnet_ext_attributes(
|
||||||
|
session=self.session, subnet_id=sub['subnet']['id'])
|
||||||
|
self.assertEqual('eng.vmware.com', sub_binding.dns_search_domain)
|
||||||
|
self.assertEqual(sub['subnet']['id'], sub_binding.subnet_id)
|
||||||
|
|
||||||
|
def test_update_nsxv_subnet_ext_attributes_dns_search_domain(self):
|
||||||
|
with self.subnet() as sub:
|
||||||
|
nsxv_db.add_nsxv_subnet_ext_attributes(
|
||||||
|
session=self.session,
|
||||||
|
subnet_id=sub['subnet']['id'],
|
||||||
|
dns_search_domain='eng.vmware.com')
|
||||||
|
sub_binding = nsxv_db.update_nsxv_subnet_ext_attributes(
|
||||||
|
session=self.session,
|
||||||
|
subnet_id=sub['subnet']['id'],
|
||||||
|
dns_search_domain='nsx.vmware.com')
|
||||||
|
self.assertEqual('nsx.vmware.com', sub_binding.dns_search_domain)
|
Loading…
Reference in New Issue
Block a user