def test_update_change_cluster(self): cluster_old = ClusterFactory(name='f5-1-fake-old') ethernet = EthernetFactory(base_object=cluster_old) vip = VIPFactory( ip=IPAddressFactory(ethernet=ethernet), parent=cluster_old, ) self.data['load_balancer'] = 'f5-1-fake-new' self.data['ip'] = vip.ip.address self.data['port'] = vip.port self.data['protocol'] = VIPProtocol.from_id(vip.protocol).name self.assertEqual(VIP.objects.count(), 1) self.assertEqual(Cluster.objects.count(), 1) self.assertEqual(Ethernet.objects.count(), 1) handle_update_vip_event(self.data) vips = VIP.objects.all() self.assertEqual(vips.count(), 1) self.assertEqual(Cluster.objects.count(), 2) self.assertEqual(Ethernet.objects.count(), 1) self.assertEqual(vips[0].ip.ethernet, ethernet) self.assertEqual( Ethernet.objects.get( id=ethernet.id).base_object.last_descendant.name, self.data['load_balancer'])
def test_delete_with_valid_event_data(self): vip = VIPFactory() self.data['ip'] = vip.ip.address self.data['port'] = vip.port self.data['protocol'] = VIPProtocol.from_id(vip.protocol).name self.assertEqual(VIP.objects.count(), 1) handle_delete_vip_event(self.data) self.assertEqual(VIP.objects.count(), 0)
def handle_create_vip_event(data): errors = validate_vip_event_data(data) if errors: msg = ('Error(s) detected in event data: %s. Ignoring received create ' 'event.') logger.error(msg, '; '.join(errors)) return # Check if VIP already exists. ip, ip_created = IPAddress.objects.get_or_create(address=data['ip']) protocol = VIPProtocol.from_name(data['protocol'].upper()) vip = get_vip(ip, data['port'], protocol) if vip: msg = ('VIP designated by IP address %s, port %s and protocol %s ' 'already exists. Ignoring received event.') logger.warning(msg, ip.address, data['port'], protocol.name) return # Create it. cluster_type, _ = ClusterType.objects.get_or_create( name=data['load_balancer_type']) cluster, _ = Cluster.objects.get_or_create( name=data['load_balancer'], type=cluster_type, ) if ip_created: eth = Ethernet.objects.create(base_object=cluster) ip.ethernet = eth ip.save() elif ip.dhcp_expose: logger.error( 'Trying to create VIP with IP %s, port %s and protocol %s ' 'failed because IP is exposed in dhcp', ip.address, data['port'], protocol.name) return try: service_env = ServiceEnvironment.objects.get( service__uid=data['service']['uid'], environment__name=data['environment'], ) except ServiceEnvironment.DoesNotExist: msg = ('ServiceEnvironment for service UID "%s" and environment "%s" ' 'does not exist. Ignoring received create event.') logger.error(msg, data['service']['uid'], data['environment']) return vip = VIP( name=data['name'], ip=ip, port=data['port'], protocol=protocol, parent=cluster, service_env=service_env, ) vip.save() logger.debug('VIP %s created successfully.', vip.name)
def handle_update_vip_event(data): errors = validate_vip_event_data(data) if errors: msg = ('Error(s) detected in event data: %s. Ignoring received update ' 'event.') logger.error(msg, '; '.join(errors)) return ip, _ = IPAddress.objects.get_or_create(address=data['ip']) protocol = VIPProtocol.from_name(data['protocol'].upper()) if ip.dhcp_expose: logger.error( 'Trying to update VIP with IP %s, port %s and protocol %s ' 'failed because IP is exposed in dhcp', ip.address, data['port'], protocol.name) return vip = get_vip(ip, data['port'], protocol) if vip is None: # VIP not found, should create new one. return handle_create_vip_event(data) # update cluster. cluster_type, _ = ClusterType.objects.get_or_create( name=data['load_balancer_type']) cluster, _ = Cluster.objects.get_or_create( name=data['load_balancer'], type=cluster_type, ) if (vip.parent != cluster or (ip.ethernet and ip.ethernet.base_object != cluster)): with transaction.atomic(): for migrated_vip in VIP.objects.select_for_update().filter(ip=ip): migrate_vip_to_cluster(migrated_vip, cluster, protocol) # update service/environment if changed. try: service_env = ServiceEnvironment.objects.get( service__uid=data['service']['uid'], environment__name=data['environment'], ) except ServiceEnvironment.DoesNotExist: msg = ('ServiceEnvironment for service UID "%s" and environment "%s" ' 'does not exist. Ignoring received update event.') logger.error(msg, data['service']['uid'], data['environment']) return if vip.service_env != service_env: vip.service_env = service_env vip.save() logger.debug('VIP %s changed service/env to %s.', vip.name, service_env) logger.debug('VIP %s update processed successfuly.', vip.name)
def test_delete_when_ip_does_not_exist(self): vip = VIPFactory() ip = IPAddressFactory() self.data['ip'] = ip.address ip.delete() self.data['port'] = vip.port self.data['protocol'] = VIPProtocol.from_id(vip.protocol).name self.assertEqual(VIP.objects.count(), 1) handle_delete_vip_event(self.data) self.assertEqual(VIP.objects.count(), 1)
def test_ip_with_eth_being_deleted_when_no_longer_used(self): vip = VIPFactory() self.data['ip'] = vip.ip.address self.data['port'] = vip.port self.data['protocol'] = VIPProtocol.from_id(vip.protocol).name self.assertEqual(VIP.objects.count(), 1) self.assertEqual(IPAddress.objects.count(), 1) self.assertEqual(Ethernet.objects.count(), 1) handle_delete_vip_event(self.data) self.assertEqual(VIP.objects.count(), 0) self.assertEqual(IPAddress.objects.count(), 0) self.assertEqual(Ethernet.objects.count(), 0)
def test_create_when_vip_already_exists(self): vip = VIPFactory() self.data['ip'] = vip.ip.address self.data['port'] = vip.port self.data['protocol'] = VIPProtocol.from_id(vip.protocol).name vips = VIP.objects.all() self.assertEqual(vips.count(), 1) modified_before = vips[0].modified handle_create_vip_event(self.data) vips = VIP.objects.all() self.assertEqual(vips.count(), 1) self.assertEqual(vips[0].modified, modified_before)
def test_update_change_service_env(self): vip = VIPFactory() self.data['ip'] = vip.ip.address self.data['port'] = vip.port self.data['protocol'] = VIPProtocol.from_id(vip.protocol).name service_env = ServiceEnvironmentFactory() self.data['service']['uid'] = service_env.service.uid self.data['environment'] = service_env.environment.name vips = VIP.objects.all() self.assertEqual(vips.count(), 1) handle_update_vip_event(self.data) vips = VIP.objects.all() self.assertEqual(vips.count(), 1) self.assertEqual(vips[0].service_env, service_env)
def test_ip_with_eth_not_being_deleted_when_still_used_by_some_vip(self): vip = VIPFactory() self.data['ip'] = vip.ip.address self.data['port'] = vip.port self.data['protocol'] = VIPProtocol.from_id(vip.protocol).name vip2 = VIPFactory() vip2.ip = vip.ip vip2.save() self.assertEqual(VIP.objects.count(), 2) self.assertEqual(IPAddress.objects.count(), 2) self.assertEqual(Ethernet.objects.count(), 2) handle_delete_vip_event(self.data) self.assertEqual(VIP.objects.count(), 1) self.assertEqual(IPAddress.objects.count(), 2) self.assertEqual(Ethernet.objects.count(), 2)
def handle_delete_vip_event(data): errors = validate_vip_event_data(data) if errors: msg = ('Error(s) detected in event data: %s. Ignoring received delete ' 'event.') logger.error(msg, '; '.join(errors)) return try: ip = IPAddress.objects.get(address=data['ip']) except IPAddress.DoesNotExist: msg = ( "IP address %s doesn't exist. Ignoring received delete VIP event.") logger.error(msg, data['ip']) return protocol = VIPProtocol.from_name(data['protocol'].upper()) vip = get_vip(ip, data['port'], protocol) if vip is None: msg = ("VIP designated by IP address %s, port %s and protocol %s " "doesn't exist. Ignoring received delete event.") logger.warning(msg, ip.address, data['port'], protocol.name) return vip.delete() logger.info('VIP %s deleted successfully.', vip.name) # Delete IP address associated with it (along with its Ethernet), but only # when this IP is not used anymore by other VIP(s). if not VIP.objects.filter(ip=ip).exists(): eth_deleted = False if ip.ethernet is not None: ip.ethernet.delete() eth_deleted = True ip.delete() if eth_deleted: msg = ( 'IP address %s has been deleted (along with Ethernet ' 'associated with it) since it is no longer being used by any ' 'VIP.') else: msg = ( 'IP address %s has been deleted since it is no longer being ' 'used by any VIP.') logger.info(msg, ip.address)
def handle_update_vip_event(data): # TODO(xor-xor): Since update event doesn't contain any changes yet, it # will be ignored for now. Remember to remove logger.info/return below when # this will get changed. logger.info( "Ignoring received update VIP event, since handling logic is not " "implemented yet.") return errors = validate_vip_event_data(data) if errors: msg = ('Error(s) detected in event data: %s. Ignoring received update ' 'event.') logger.error(msg, '; '.join(errors)) return ip, = IPAddress.objects.get_or_create(address=data['ip']) protocol = VIPProtocol.from_name(data['protocol'].upper()) vip = get_vip(ip.address, data['port'], protocol.name) if vip is None: msg = ("VIP designated by IP address %s, port %s and protocol %s " "doesn't exist. Ignoring received update event.") logger.warning(msg, ip.address, data['port'], protocol.name) return