Merge lp:~vishvananda/nova/fix-dhcpbridge into lp:~hudson-openstack/nova/trunk

Proposed by Vish Ishaya
Status: Merged
Approved by: Vish Ishaya
Approved revision: 237
Merged at revision: 241
Proposed branch: lp:~vishvananda/nova/fix-dhcpbridge
Merge into: lp:~hudson-openstack/nova/trunk
Prerequisite: lp:~vishvananda/nova/fix-hostname
Diff against target: 252 lines (+47/-36)
5 files modified
bin/nova-dhcpbridge (+1/-1)
nova/endpoint/cloud.py (+3/-3)
nova/network/linux_net.py (+2/-6)
nova/network/model.py (+37/-22)
nova/network/service.py (+4/-4)
To merge this branch: bzr merge lp:~vishvananda/nova/fix-dhcpbridge
Reviewer Review Type Date Requested Status
Devin Carlen (community) Approve
Jesse Andrews (community) Approve
Review via email: mp+32518@code.launchpad.net

Commit message

Fixes issues with allocation and deallocation of fixed and elastic addresses.

Description of the change

Fixes issues with allocation and deallocation of fixed and elastic addresses.

I ended up merging in fix-hostname while i was testing, so I'm resubmitting this branch with that one as a prereq.

To post a comment you must log in.
Revision history for this message
Jesse Andrews (anotherjesse) wrote :

lgtm

review: Approve
Revision history for this message
Devin Carlen (devcamcar) wrote :

lgtm

review: Approve
Revision history for this message
OpenStack Infra (hudson-openstack) wrote :
Download full text (10.6 KiB)

The attempt to merge lp:~vishvananda/nova/fix-dhcpbridge into lp:nova failed.Below is the output from the failed tests.

nova.tests.access_unittest
  AccessTestCase
    test_001_allow_all ... [OK]
    test_002_allow_none ... [OK]
    test_003_allow_project_manager ... [OK]
    test_004_allow_sys_and_net ... [OK]
    test_005_allow_sys_no_pm ... [OK]
nova.tests.api_unittest
  ApiEc2TestCase
    test_describe_instances ... [OK]
    test_get_all_key_pairs ... [OK]
nova.tests.auth_unittest
  AuthTestCase
    test_001_can_create_users ... [OK]
    test_002_can_get_user ... [OK]
    test_003_can_retreive_properties ... [OK]
    test_004_signature_is_valid ... [OK]
    test_005_can_get_credentials ... [OK]
    test_006_test_key_storage ... [OK]
    test_007_test_key_generation ... [OK]
    test_008_can_list_key_pairs ... [OK]
    test_009_can_delete_key_pair ... [OK]
    test_010_can_list_users ... [OK]
    test_101_can_add_user_role ... [OK]
    test_199_can_remove_user_role ... [OK]
    test_201_can_create_project ... [OK]
    test_202_user1_is_project_member ... [OK]
    test_203_user2_is_not_project_member ... [OK]
    test_204_user1_is_project_manager ... [OK]
    test_205_user2_is_not_project_manager ... [OK]
    test_206_can_add_user_to_project ... [OK]
    test_207_can_remove_user_from_project ... [OK]
    test_208_can_remove_add_user_with_role ... [OK]
    test_209_can_generate_x509 ... [OK]
    test_210_can_add_project_role ... [OK]
    test_211_can_list_project_roles ... [OK]
    test_212_can_remove_project_role ... [OK]
    test_214_can_retrieve_project_by_user ... [OK]
    test_299_can_delete_project ... [OK]
    test_999_can_delete_users ... [OK]
nova.tests.cloud_unittest
  CloudTestCase
    test_console_output ... [OK]
    test_instance_update_state ... [OK]
    test_run_instances ... ...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bin/nova-dhcpbridge'
--- bin/nova-dhcpbridge 2010-08-12 21:22:40 +0000
+++ bin/nova-dhcpbridge 2010-08-12 21:22:40 +0000
@@ -69,7 +69,7 @@
69 """Get the list of hosts for an interface."""69 """Get the list of hosts for an interface."""
70 net = model.get_network_by_interface(interface)70 net = model.get_network_by_interface(interface)
71 res = ""71 res = ""
72 for address in net.address_objs:72 for address in net.assigned_objs:
73 res += "%s\n" % linux_net.host_dhcp(address)73 res += "%s\n" % linux_net.host_dhcp(address)
74 return res74 return res
7575
7676
=== modified file 'nova/endpoint/cloud.py'
--- nova/endpoint/cloud.py 2010-08-12 21:22:40 +0000
+++ nova/endpoint/cloud.py 2010-08-12 21:22:40 +0000
@@ -126,7 +126,7 @@
126 else:126 else:
127 keys = ''127 keys = ''
128128
129 address_record = network_model.Address(i['private_dns_name'])129 address_record = network_model.FixedIp(i['private_dns_name'])
130 if address_record:130 if address_record:
131 hostname = address_record['hostname']131 hostname = address_record['hostname']
132 else:132 else:
@@ -311,7 +311,7 @@
311311
312 def _get_address(self, context, public_ip):312 def _get_address(self, context, public_ip):
313 # FIXME(vish) this should move into network.py313 # FIXME(vish) this should move into network.py
314 address = network_model.PublicAddress.lookup(public_ip)314 address = network_model.ElasticIp.lookup(public_ip)
315 if address and (context.user.is_admin() or address['project_id'] == context.project.id):315 if address and (context.user.is_admin() or address['project_id'] == context.project.id):
316 return address316 return address
317 raise exception.NotFound("Address at ip %s not found" % public_ip)317 raise exception.NotFound("Address at ip %s not found" % public_ip)
@@ -456,7 +456,7 @@
456456
457 def format_addresses(self, context):457 def format_addresses(self, context):
458 addresses = []458 addresses = []
459 for address in network_model.PublicAddress.all():459 for address in network_model.ElasticIp.all():
460 # TODO(vish): implement a by_project iterator for addresses460 # TODO(vish): implement a by_project iterator for addresses
461 if (context.user.is_admin() or461 if (context.user.is_admin() or
462 address['project_id'] == context.project.id):462 address['project_id'] == context.project.id):
463463
=== modified file 'nova/network/linux_net.py'
--- nova/network/linux_net.py 2010-08-12 21:22:40 +0000
+++ nova/network/linux_net.py 2010-08-12 21:22:40 +0000
@@ -116,7 +116,7 @@
116 ' --pid-file=%s' % dhcp_file(net['vlan'], 'pid'),116 ' --pid-file=%s' % dhcp_file(net['vlan'], 'pid'),
117 ' --listen-address=%s' % net.dhcp_listen_address,117 ' --listen-address=%s' % net.dhcp_listen_address,
118 ' --except-interface=lo',118 ' --except-interface=lo',
119 ' --dhcp-range=%s,static,600s' % net.dhcp_range_start,119 ' --dhcp-range=%s,static,120s' % net.dhcp_range_start,
120 ' --dhcp-hostsfile=%s' % dhcp_file(net['vlan'], 'conf'),120 ' --dhcp-hostsfile=%s' % dhcp_file(net['vlan'], 'conf'),
121 ' --dhcp-script=%s' % bin_file('nova-dhcpbridge'),121 ' --dhcp-script=%s' % bin_file('nova-dhcpbridge'),
122 ' --leasefile-ro']122 ' --leasefile-ro']
@@ -153,14 +153,10 @@
153 # correct dnsmasq process153 # correct dnsmasq process
154 try:154 try:
155 os.kill(pid, signal.SIGHUP)155 os.kill(pid, signal.SIGHUP)
156 return
156 except Exception as exc: # pylint: disable=W0703157 except Exception as exc: # pylint: disable=W0703
157 logging.debug("Hupping dnsmasq threw %s", exc)158 logging.debug("Hupping dnsmasq threw %s", exc)
158159
159 # otherwise delete the existing leases file and start dnsmasq
160 lease_file = dhcp_file(network['vlan'], 'leases')
161 if os.path.exists(lease_file):
162 os.unlink(lease_file)
163
164 # FLAGFILE and DNSMASQ_INTERFACE in env160 # FLAGFILE and DNSMASQ_INTERFACE in env
165 env = {'FLAGFILE': FLAGS.dhcpbridge_flagfile,161 env = {'FLAGFILE': FLAGS.dhcpbridge_flagfile,
166 'DNSMASQ_INTERFACE': network['bridge_name']}162 'DNSMASQ_INTERFACE': network['bridge_name']}
167163
=== modified file 'nova/network/model.py'
--- nova/network/model.py 2010-08-12 21:22:40 +0000
+++ nova/network/model.py 2010-08-12 21:22:40 +0000
@@ -143,25 +143,26 @@
143 network[start + FLAGS.network_size - 1])143 network[start + FLAGS.network_size - 1])
144144
145145
146class Address(datastore.BasicModel):146class FixedIp(datastore.BasicModel):
147 """Represents a fixed ip in the datastore"""147 """Represents a fixed ip in the datastore"""
148 override_type = "address"
149148
150 def __init__(self, address):149 def __init__(self, address):
151 self.address = address150 self.address = address
152 super(Address, self).__init__()151 super(FixedIp, self).__init__()
153152
154 @property153 @property
155 def identifier(self):154 def identifier(self):
156 return self.address155 return self.address
157156
157 # NOTE(vish): address states allocated, leased, deallocated
158 def default_state(self):158 def default_state(self):
159 return {'address': self.address}159 return {'address': self.address,
160 'state': 'none'}
160161
161 @classmethod162 @classmethod
162 # pylint: disable=R0913163 # pylint: disable=R0913
163 def create(cls, user_id, project_id, address, mac, hostname, network_id):164 def create(cls, user_id, project_id, address, mac, hostname, network_id):
164 """Creates an Address object"""165 """Creates an FixedIp object"""
165 addr = cls(address)166 addr = cls(address)
166 addr['user_id'] = user_id167 addr['user_id'] = user_id
167 addr['project_id'] = project_id168 addr['project_id'] = project_id
@@ -170,21 +171,22 @@
170 hostname = "ip-%s" % address.replace('.', '-')171 hostname = "ip-%s" % address.replace('.', '-')
171 addr['hostname'] = hostname172 addr['hostname'] = hostname
172 addr['network_id'] = network_id173 addr['network_id'] = network_id
174 addr['state'] = 'allocated'
173 addr.save()175 addr.save()
174 return addr176 return addr
175177
176 def save(self):178 def save(self):
177 is_new = self.is_new_record()179 is_new = self.is_new_record()
178 success = super(Address, self).save()180 success = super(FixedIp, self).save()
179 if success and is_new:181 if success and is_new:
180 self.associate_with("network", self['network_id'])182 self.associate_with("network", self['network_id'])
181183
182 def destroy(self):184 def destroy(self):
183 self.unassociate_with("network", self['network_id'])185 self.unassociate_with("network", self['network_id'])
184 super(Address, self).destroy()186 super(FixedIp, self).destroy()
185187
186188
187class PublicAddress(Address):189class ElasticIp(FixedIp):
188 """Represents an elastic ip in the datastore"""190 """Represents an elastic ip in the datastore"""
189 override_type = "address"191 override_type = "address"
190192
@@ -200,7 +202,7 @@
200class BaseNetwork(datastore.BasicModel):202class BaseNetwork(datastore.BasicModel):
201 """Implements basic logic for allocating ips in a network"""203 """Implements basic logic for allocating ips in a network"""
202 override_type = 'network'204 override_type = 'network'
203 address_class = Address205 address_class = FixedIp
204206
205 @property207 @property
206 def identifier(self):208 def identifier(self):
@@ -268,12 +270,12 @@
268 # pylint: disable=R0913270 # pylint: disable=R0913
269 def _add_host(self, user_id, project_id, ip_address, mac, hostname):271 def _add_host(self, user_id, project_id, ip_address, mac, hostname):
270 """Add a host to the datastore"""272 """Add a host to the datastore"""
271 Address.create(user_id, project_id, ip_address,273 self.address_class.create(user_id, project_id, ip_address,
272 mac, hostname, self.identifier)274 mac, hostname, self.identifier)
273275
274 def _rem_host(self, ip_address):276 def _rem_host(self, ip_address):
275 """Remove a host from the datastore"""277 """Remove a host from the datastore"""
276 Address(ip_address).destroy()278 self.address_class(ip_address).destroy()
277279
278 @property280 @property
279 def assigned(self):281 def assigned(self):
@@ -322,7 +324,13 @@
322324
323 def lease_ip(self, ip_str):325 def lease_ip(self, ip_str):
324 """Called when DHCP lease is activated"""326 """Called when DHCP lease is activated"""
325 logging.debug("Leasing allocated IP %s", ip_str)327 if not ip_str in self.assigned:
328 raise exception.AddressNotAllocated()
329 address = self.get_address(ip_str)
330 if address:
331 logging.debug("Leasing allocated IP %s", ip_str)
332 address['state'] = 'leased'
333 address.save()
326334
327 def release_ip(self, ip_str):335 def release_ip(self, ip_str):
328 """Called when DHCP lease expires336 """Called when DHCP lease expires
@@ -330,16 +338,23 @@
330 Removes the ip from the assigned list"""338 Removes the ip from the assigned list"""
331 if not ip_str in self.assigned:339 if not ip_str in self.assigned:
332 raise exception.AddressNotAllocated()340 raise exception.AddressNotAllocated()
341 logging.debug("Releasing IP %s", ip_str)
333 self._rem_host(ip_str)342 self._rem_host(ip_str)
334 self.deexpress(address=ip_str)343 self.deexpress(address=ip_str)
335 logging.debug("Releasing IP %s", ip_str)
336344
337 def deallocate_ip(self, ip_str):345 def deallocate_ip(self, ip_str):
338 """Deallocates an allocated ip"""346 """Deallocates an allocated ip"""
339 # NOTE(vish): Perhaps we should put the ip into an intermediate347 if not ip_str in self.assigned:
340 # state, so we know that we are pending waiting for348 raise exception.AddressNotAllocated()
341 # dnsmasq to confirm that it has been released.349 address = self.get_address(ip_str)
342 logging.debug("Deallocating allocated IP %s", ip_str)350 if address:
351 if address['state'] != 'leased':
352 # NOTE(vish): address hasn't been leased, so release it
353 self.release_ip(ip_str)
354 else:
355 logging.debug("Deallocating allocated IP %s", ip_str)
356 address['state'] == 'deallocated'
357 address.save()
343358
344 def express(self, address=None):359 def express(self, address=None):
345 """Set up network. Implemented in subclasses"""360 """Set up network. Implemented in subclasses"""
@@ -462,7 +477,7 @@
462class PublicNetworkController(BaseNetwork):477class PublicNetworkController(BaseNetwork):
463 """Handles elastic ips"""478 """Handles elastic ips"""
464 override_type = 'network'479 override_type = 'network'
465 address_class = PublicAddress480 address_class = ElasticIp
466481
467 def __init__(self, *args, **kwargs):482 def __init__(self, *args, **kwargs):
468 network_id = "public:default"483 network_id = "public:default"
@@ -597,7 +612,7 @@
597612
598def get_network_by_address(address):613def get_network_by_address(address):
599 """Gets the network for a given private ip"""614 """Gets the network for a given private ip"""
600 address_record = Address.lookup(address)615 address_record = FixedIp.lookup(address)
601 if not address_record:616 if not address_record:
602 raise exception.AddressNotAllocated()617 raise exception.AddressNotAllocated()
603 return get_project_network(address_record['project_id'])618 return get_project_network(address_record['project_id'])
@@ -613,6 +628,6 @@
613def get_public_ip_for_instance(instance_id):628def get_public_ip_for_instance(instance_id):
614 """Gets the public ip for a given instance"""629 """Gets the public ip for a given instance"""
615 # FIXME(josh): this should be a lookup - iteration won't scale630 # FIXME(josh): this should be a lookup - iteration won't scale
616 for address_record in PublicAddress.all():631 for address_record in ElasticIp.all():
617 if address_record.get('instance_id', 'available') == instance_id:632 if address_record.get('instance_id', 'available') == instance_id:
618 return address_record['address']633 return address_record['address']
619634
=== modified file 'nova/network/service.py'
--- nova/network/service.py 2010-08-12 21:22:40 +0000
+++ nova/network/service.py 2010-08-12 21:22:40 +0000
@@ -226,13 +226,13 @@
226 """Returns an ip to the pool"""226 """Returns an ip to the pool"""
227 return model.get_network_by_address(fixed_ip).deallocate_ip(fixed_ip)227 return model.get_network_by_address(fixed_ip).deallocate_ip(fixed_ip)
228228
229 def lease_ip(self, address):229 def lease_ip(self, fixed_ip):
230 """Called by bridge when ip is leased"""230 """Called by bridge when ip is leased"""
231 return model.get_network_by_address(address).lease_ip(address)231 return model.get_network_by_address(fixed_ip).lease_ip(fixed_ip)
232232
233 def release_ip(self, address):233 def release_ip(self, fixed_ip):
234 """Called by bridge when ip is released"""234 """Called by bridge when ip is released"""
235 return model.get_network_by_address(address).release_ip(address)235 return model.get_network_by_address(fixed_ip).release_ip(fixed_ip)
236236
237 def restart_nets(self):237 def restart_nets(self):
238 """Ensure the network for each user is enabled"""238 """Ensure the network for each user is enabled"""