move extra-dhcp-options from list to dictonary

This commit only change dhcp-options from list to dictonary that map between TAG to value  -
for enable usable search when answering to the dchp "Parmater Request List"

Change-Id: Id03fae3908fcd43c03ff18641694a2a218f4ea11
Related-bug: #1585170
This commit is contained in:
Eyal Leshem 2017-06-12 18:02:18 +03:00
parent 36185644c5
commit 976ce08a5a
6 changed files with 53 additions and 32 deletions

View File

@ -40,10 +40,6 @@ from dragonflow.db.models import l2
LOG = log.getLogger(__name__)
DHCP_DOMAIN_NAME_OPT = 15
DHCP_INTERFACE_MTU_OPT = 26
DHCP_CLASSLESS_ROUTE_OPT = 121
class DHCPApp(df_base_app.DFlowApp):
def __init__(self, *args, **kwargs):
@ -170,8 +166,8 @@ class DHCPApp(df_base_app.DFlowApp):
dhcp.option(dhcp.DHCP_SERVER_IDENTIFIER_OPT,
dhcp_server_address.packed),
dhcp.option(dhcp.DHCP_DNS_SERVER_ADDR_OPT, dns),
dhcp.option(DHCP_DOMAIN_NAME_OPT, domain_name_bin),
dhcp.option(DHCP_CLASSLESS_ROUTE_OPT, host_routes),
dhcp.option(dhcp.DHCP_DOMAIN_NAME_OPT, domain_name_bin),
dhcp.option(dhcp.DHCP_CLASSLESS_ROUTE_OPT, host_routes),
]
gw_ip = self._get_port_gateway_address(subnet, lport)
if gw_ip:
@ -181,7 +177,8 @@ class DHCPApp(df_base_app.DFlowApp):
if pkt_type == dhcp.DHCP_ACK:
intreface_mtu = self._get_port_mtu(lport)
mtu_bin = struct.pack('!H', intreface_mtu)
option_list.append(dhcp.option(DHCP_INTERFACE_MTU_OPT, mtu_bin))
option_list.append(dhcp.option(dhcp.DHCP_INTERFACE_MTU_OPT,
mtu_bin))
options = dhcp.options(option_list=option_list)
dhcp_pkt = ryu_packet.Packet()
dhcp_pkt.add_protocol(ethernet.ethernet(
@ -221,12 +218,12 @@ class DHCPApp(df_base_app.DFlowApp):
routes_bin = b''
dhcp_opts = lport.extra_dhcp_options
for opt in dhcp_opts:
if opt.tag == DHCP_CLASSLESS_ROUTE_OPT:
dest_cidr, _c, via = opt.value.partition(',')
host_routes.append(host_route.HostRoute(destination=dest_cidr,
nexthop=via))
opt = lport.extra_dhcp_options.get(dhcp.DHCP_CLASSLESS_ROUTE_OPT)
if opt:
dest_cidr, _c, via = opt.partition(',')
host_routes.append(
host_route.HostRoute(destination=dest_cidr,
nexthop=via))
for route in host_routes:
dest = route.destination.network
@ -258,10 +255,7 @@ class DHCPApp(df_base_app.DFlowApp):
if gateway_ip:
return gateway_ip
dhcp_opts = lport.extra_dhcp_options
for opt in dhcp_opts:
if opt.tag == dhcp.DHCP_GATEWAY_ADDR_OPT:
return opt.value
return lport.extra_dhcp_options.get(dhcp.DHCP_GATEWAY_ADDR_OPT)
def _is_dhcp_enabled_for_port(self, lport):
try:

View File

@ -232,3 +232,24 @@ class EnumListField(fields.ListField):
_('{value} is not one of: [{valid_values}]').format(
value=value,
valid_values=', '.join(self._valid_values)))
class IntStringDictField(fields.BaseField):
'''A field that stores a int -> string dictionary'''
types = (dict,)
def validate(self, value):
super(IntStringDictField, self).validate(value)
if not value:
return
for key, inner_val in value.items():
if not isinstance(key, six.integer_types):
raise errors.ValidationError(
_('Key {} is not a int').format(key))
if not isinstance(inner_val, six.string_types):
raise errors.ValidationError(
_('Value {value} to key {key} is not a string').format(
key=key, value=inner_val))
def get_default_value(self):
return {}

View File

@ -113,7 +113,7 @@ class LogicalPort(mf.ModelBase, mixins.Name, mixins.Version, mixins.Topic,
device_id = fields.StringField()
qos_policy = df_fields.ReferenceField(qos.QosPolicy)
remote_vtep = fields.BoolField()
extra_dhcp_options = fields.ListField(DHCPOption)
extra_dhcp_options = df_fields.IntStringDictField()
binding_vnic_type = df_fields.EnumField(portbindings.VNIC_TYPES)
def __init__(self, ofport=None, is_local=None,

View File

@ -70,9 +70,14 @@ def _validate_ip_prefix_allowed_address_pairs(allowed_address_pairs):
return supported_allowed_address_pairs
def _rename_extra_dhcp_opts_keys(neutron_extra_dhcp_opt):
return {'tag': int(neutron_extra_dhcp_opt['opt_name']),
'value': neutron_extra_dhcp_opt['opt_value']}
def _build_extra_dhcp_options(port):
dhcp_opt_dict = {}
opts = port.get(extra_dhcp_opt.EXTRADHCPOPTS, [])
for opt in opts:
dhcp_opt_dict[int(opt['opt_name'])] = opt['opt_value']
return dhcp_opt_dict
def logical_port_from_neutron_port(port):
@ -94,5 +99,4 @@ def logical_port_from_neutron_port(port):
port.get(addr_pair.ADDRESS_PAIRS, [])),
binding_vnic_type=port.get(portbindings.VNIC_TYPE),
qos_policy=port.get('qos_policy_id'),
extra_dhcp_options=[_rename_extra_dhcp_opts_keys(edo) for edo in
port.get(extra_dhcp_opt.EXTRADHCPOPTS, [])])
extra_dhcp_options=_build_extra_dhcp_options(port))

View File

@ -162,6 +162,7 @@ def make_fake_port(id=None,
device_id='fake_device_id',
ofport=1,
extra_dhcp_opts=None):
fake_port = l2.LogicalPort(
id="%s_%s" % (name, ofport) if not id else id,
topic=topic,
@ -179,7 +180,7 @@ def make_fake_port(id=None,
device_owner=device_owner,
device_id=device_id,
# binding_vnic_type=binding_vnic_type,
extra_dhcp_options=extra_dhcp_opts,
extra_dhcp_options={} if not extra_dhcp_opts else extra_dhcp_opts,
)
fake_port.is_local = is_local
fake_port.ofport = ofport
@ -192,10 +193,10 @@ def make_fake_local_port(**kargs):
return make_fake_port(**kargs)
fake_local_port1_dhcp_opts = [
l2.DHCPOption(tag=3, value='10.0.0.1'),
l2.DHCPOption(tag=121, value='0.0.0.0/0,10.0.0.1'),
]
fake_local_port1_dhcp_opts = {
3: '10.0.0.1',
121: '0.0.0.0/0,10.0.0.1'
}
fake_local_port1 = make_fake_local_port(

View File

@ -484,9 +484,10 @@ class TestDFMechDriver(DFMechanismDriverTestCase):
'tag': 3},
{'value': "0.0.0.0/0,192.168.0.1",
'tag': 121}]
self.assertItemsEqual(expected_edo,
[edo.to_struct()
for edo in lport.extra_dhcp_options])
for edo in expected_edo:
self.assertEqual(edo['value'],
lport.extra_dhcp_options[edo['tag']])
self.nb_api.update.reset_mock()
data = {'port': {'extra_dhcp_opts': [{'opt_name': '3',
@ -500,7 +501,7 @@ class TestDFMechDriver(DFMechanismDriverTestCase):
self.nb_api.update.assert_called_once()
lport = self.nb_api.update.call_args_list[0][0][0]
self.assertIsInstance(lport, l2.LogicalPort)
self.assertEqual([], lport.extra_dhcp_options)
self.assertFalse(lport.extra_dhcp_options)
class TestDFMechansimDriverAllowedAddressPairs(