# Copyright 2015 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 oslo_log import helpers as log_helpers from oslo_log import log as logging from oslo_utils import excutils from vmware_nsx._i18n import _LE from vmware_nsx.common import locking from vmware_nsx.db import nsxv_db from vmware_nsx.plugins.nsx_v.vshield.common import exceptions as nsxv_exc from vmware_nsx.services.lbaas.nsx_v import lbaas_common as lb_common from vmware_nsx.services.lbaas.nsx_v.v2 import base_mgr LOG = logging.getLogger(__name__) class EdgeMemberManager(base_mgr.EdgeLoadbalancerBaseManager): @log_helpers.log_method_call def __init__(self, vcns_driver): super(EdgeMemberManager, self).__init__(vcns_driver) self._fw_section_id = None def _get_pool_member_ips(self, pool, operation, address): member_ips = [member.address for member in pool.members] if operation == 'add' and address not in member_ips: member_ips.append(address) elif operation == 'del' and address in member_ips: member_ips.remove(address) return member_ips def _get_lbaas_fw_section_id(self): if not self._fw_section_id: self._fw_section_id = lb_common.get_lbaas_fw_section_id(self.vcns) return self._fw_section_id @log_helpers.log_method_call def create(self, context, member): listener = member.pool.listener lb_id = listener.loadbalancer_id lb_binding = nsxv_db.get_nsxv_lbaas_loadbalancer_binding( context.session, lb_id) pool_binding = nsxv_db.get_nsxv_lbaas_pool_binding( context.session, lb_id, listener.id, member.pool_id) edge_id = lb_binding['edge_id'] edge_pool_id = pool_binding['edge_pool_id'] with locking.LockManager.get_lock(edge_id, external=True): edge_pool = self.vcns.get_pool(edge_id, edge_pool_id)[1] edge_member = { 'ipAddress': member.address, 'weight': member.weight, 'port': member.protocol_port, 'monitorPort': member.protocol_port, 'name': lb_common.get_member_id(member.id), 'condition': 'enabled' if member.admin_state_up else 'disabled'} if edge_pool.get('member'): edge_pool['member'].append(edge_member) else: edge_pool['member'] = [edge_member] try: self.vcns.update_pool(edge_id, edge_pool_id, edge_pool) member_ips = self._get_pool_member_ips(member.pool, 'add', member.address) lb_common.update_pool_fw_rule(self.vcns, member.pool_id, edge_id, self._get_lbaas_fw_section_id(), member_ips) self.lbv2_driver.member.successful_completion(context, member) except nsxv_exc.VcnsApiException: with excutils.save_and_reraise_exception(): self.lbv2_driver.member.failed_completion(context, member) LOG.error(_LE('Failed to create member on edge: %s'), edge_id) @log_helpers.log_method_call def update(self, context, old_member, new_member): listener = new_member.pool.listener lb_id = listener.loadbalancer_id lb_binding = nsxv_db.get_nsxv_lbaas_loadbalancer_binding( context.session, lb_id) pool_binding = nsxv_db.get_nsxv_lbaas_pool_binding(context.session, lb_id, listener.id, new_member.pool_id) edge_id = lb_binding['edge_id'] edge_pool_id = pool_binding['edge_pool_id'] edge_member = { 'ipAddress': new_member.address, 'weight': new_member.weight, 'port': new_member.protocol_port, 'monitorPort': new_member.protocol_port, 'name': lb_common.get_member_id(new_member.id), 'condition': 'enabled' if new_member.admin_state_up else 'disabled'} with locking.LockManager.get_lock(edge_id, external=True): edge_pool = self.vcns.get_pool(edge_id, edge_pool_id)[1] if edge_pool.get('member'): for i, m in enumerate(edge_pool['member']): if m['name'] == lb_common.get_member_id(new_member.id): edge_pool['member'][i] = edge_member break try: self.vcns.update_pool(edge_id, edge_pool_id, edge_pool) self.lbv2_driver.member.successful_completion( context, new_member) except nsxv_exc.VcnsApiException: with excutils.save_and_reraise_exception(): self.lbv2_driver.member.failed_completion( context, new_member) LOG.error(_LE('Failed to update member on edge: %s'), edge_id) else: LOG.error(_LE('Pool %(pool_id)s on Edge %(edge_id)s has no ' 'members to update') % {'pool_id': new_member.pool.id, 'edge_id': edge_id}) @log_helpers.log_method_call def delete(self, context, member): listener = member.pool.listener lb_id = listener.loadbalancer_id lb_binding = nsxv_db.get_nsxv_lbaas_loadbalancer_binding( context.session, lb_id) pool_binding = nsxv_db.get_nsxv_lbaas_pool_binding( context.session, lb_id, listener.id, member.pool_id) edge_id = lb_binding['edge_id'] edge_pool_id = pool_binding['edge_pool_id'] with locking.LockManager.get_lock(edge_id, external=True): edge_pool = self.vcns.get_pool(edge_id, edge_pool_id)[1] for i, m in enumerate(edge_pool['member']): if m['name'] == lb_common.get_member_id(member.id): edge_pool['member'].pop(i) break try: self.vcns.update_pool(edge_id, edge_pool_id, edge_pool) self.lbv2_driver.member.successful_completion( context, member, delete=True) except nsxv_exc.VcnsApiException: with excutils.save_and_reraise_exception(): self.lbv2_driver.member.failed_completion(context, member) LOG.error(_LE('Failed to delete member on edge: %s'), edge_id)