Open Cedev opened 8 years ago
When the pool delete calls the member's delete the member's .pool
isn't populated
def delete(self, context, pool):
with a10.A10DeleteContext(self, context, pool) as c:
for member in pool.members:
self.a10_driver.member._delete(c, context, member)
The member tries to get the _pool_name
from the .pool
, which isn't populated:
def _delete(self, c, context, member):
server_ip = self.neutron.member_get_ip(
context, member, c.device_cfg['use_float'])
server_name = self._meta_name(member, server_ip)
try:
if self.neutron.member_count(context, member) > 1:
c.client.slb.service_group.member.delete(
self._pool_name(context, pool=member.pool),
server_name,
member.protocol_port)
else:
c.client.slb.server.delete(server_name)
except acos_errors.NotFound:
pass
_pool_name
also accepts a pool_id
and looks up the pool
when the pool
isn't specified.
There are two possible fixes. Set the .pool
on each member in the pool handler:
def delete(self, context, pool):
with a10.A10DeleteContext(self, context, pool) as c:
for member in pool.members:
member.pool = pool
self.a10_driver.member._delete(c, context, member)
Or pass the pool_id
to _pool_name
in the member handler delete:
c.client.slb.service_group.member.delete(
self._pool_name(context, pool_id = member.pool_id, pool=member.pool),
server_name,
member.protocol_port)
Wait, if the member is still associated to the pool, why isn't pool populated?
Because the neutron lbaas data_models don't populate the backreferences.
In liberty:
@classmethod
def from_sqlalchemy_model(cls, sa_model, calling_class=None):
...
for attr_name in vars(instance):
...
# Handles M:1 or 1:1 relationships
if isinstance(attr, model_base.BASEV2):
if hasattr(instance, attr_name):
data_class = SA_MODEL_TO_DATA_MODEL_MAP[attr.__class__]
if calling_class != data_class and data_class:
setattr(instance, attr_name,
data_class.from_sqlalchemy_model(
attr, calling_class=cls))
In master it keeps populating them until it's seen the same class twice, but doesn't reuse instances. Which means that pool.members[0].pool is not pool
. Warning, the linked code will make you physcially ill.
Seriously, why doesn't the code in master reuse the existing instances and tie them together?
@classmethod
def from_sqlalchemy_model(cls, sa_model, translated=None):
translated = translated or {}
# Reuse already translated instances
try:
return translated[id(sa_model)]
except KeyError as e:
pass
attr_mapping = vars(cls).get("attr_mapping")
instance = cls()
translated[id(sa_model)] = instance
...
See PR #316
Leaving this bug open until a fix gets merged into master.
Deleting a pool fails in lbaasv2 liberty when the pool still has members
Workaround: delete the members first