def __init__(self, domain, ip_type, ip_val, port): ''' Constructor: This routine assumes that the IP address of the DPS Client uniquely identifies the DPS Client. @param domain: The Domain object @type domain: Domain @param ip_type: socket.AF_INET6 or socket.AF_INET @type ip_type: Integer @param ip_val: The Value of the IP Address @type ip_val: String (IPv6) or Integer @param port: The DPS Client Port (for UDP communication) @type port: Integer ''' self.domain = domain #DPS Client Location i.e. the UDP Port and Location self.location = IPAddressLocation(ip_type, ip_val, port) #List of Tunnel Endpoints #This is to store the Tunnel Endpoint IP Address self.Tunnel_Endpoints_Hash_IPv4 = {} self.Tunnel_Endpoints_Hash_IPv6 = {} ##Failure count self.failure_count = self.failure_count_max self.version = 0 self.valid = True #Add to Domain collection Domain.dps_client_add(self.domain, self)
def __init__(self, domain, ip_type, ip_val, port, client_type): ''' Constructor: This routine assumes that the IP address of the DPS Client uniquely identifies the DPS Client. @param domain: The Domain object for which this DPSHostClient was first created @type domain: Domain @param ip_type: socket.AF_INET6 or socket.AF_INET @type ip_type: Integer @param ip_val: The Value of the IP Address @type ip_val: String (IPv6) or Integer @param port: The DPS Client Port (for UDP communication) @type port: Integer @param client_type: What kind of Client is it @type client_type: Should be one of DpsClientType ''' self.frequency = self.heartbeat_frequency[client_type] self.domains = {} self.domains[domain.unique_id] = domain #DPS Client Location i.e. the UDP Port and Location self.location = IPAddressLocation(ip_type, ip_val, port) self.client_type = client_type self.client_types = {} self.client_types[client_type] = True self.last_contact = time.time() #print '%s added client_type %s\r'%(self.location.show_ip(), DpsClientType.types[client_type]) #Add self to global collection try: DPSClientHost.Collection[ip_val] = self except Exception: pass self.valid = True
def primary_ip(self): ''' This routine shows any one IP Address to represent the Tunnel ''' try: ip = self.ip_listv4.get_primary() return IPAddressLocation(socket.AF_INET, ip, 0) except Exception: pass try: ip = self.ip_listv6.get_primary() return IPAddressLocation(socket.AF_INET6, ip, 0) except Exception: pass return IPAddressLocation(socket.AF_INET, 0, 0)
def __init__(self, vIP_type, vIP_value): ''' Constructor: @param vIP_type: socket.AF_INET or socket.AF_INET6 @type vIP_type: Integer @param vIP_value: The Virtual IP Address @type vIP_value: String (IPv6), Integer (IPv4) ''' self.vIP = IPAddressLocation(vIP_type, vIP_value, 0) #List of Waiters which are waiting for answer on this Resolution #Key (DPS Client) self.dps_clients = {} #Total number of waiters self.total = 0 #Retry is decremented in every cycle self.retry = 2
def __init__(self, domain_id, vIP_type, vIP_value): ''' Constructor: @param domain_id: The Domain ID @type domain_id: Integer @param vIP_type: socket.AF_INET or socket.AF_INET6 @type vIP_type: Integer @param vIP_value: The Virtual IP Address @type vIP_value: String (IPv6), Integer (IPv4) ''' self.domain_id = domain_id self.vIP = IPAddressLocation(vIP_type, vIP_value, 0) #Set of Endpoints that claim to have this vIP self.endpoints_claim = {} #Set of Endpoint which actually have this vIP self.endpoints_registered = {} #Retry is decremented in every cycle self.retry = 2 #Who owns the endpoint at this time self.endpoint_owner = None
class DPSClient: ''' This represents the DPS Client which is communicating via the DPS Client Server Protocol. Each DPS Client is associated with one or more Tunnel Endpoints. NOTE: Each DPSClient will have multiple instances every every Domain it hosts TunnelEndpoint on. In other words if a DPSClient hosts TunnelEndpoint on Domain A and Domain B, then there will be 2 independent instances of that DPSClient, 1 in Domain A and 1 in Domain B. ''' #A maximum of "max_failure" failures is tolerated from a DPS Client. After #that the DPS Client will have been deemed to be down and will be removed #from the collection failure_count_max = 4 def __init__(self, domain, ip_type, ip_val, port): ''' Constructor: This routine assumes that the IP address of the DPS Client uniquely identifies the DPS Client. @param domain: The Domain object @type domain: Domain @param ip_type: socket.AF_INET6 or socket.AF_INET @type ip_type: Integer @param ip_val: The Value of the IP Address @type ip_val: String (IPv6) or Integer @param port: The DPS Client Port (for UDP communication) @type port: Integer ''' self.domain = domain #DPS Client Location i.e. the UDP Port and Location self.location = IPAddressLocation(ip_type, ip_val, port) #List of Tunnel Endpoints #This is to store the Tunnel Endpoint IP Address self.Tunnel_Endpoints_Hash_IPv4 = {} self.Tunnel_Endpoints_Hash_IPv6 = {} ##Failure count self.failure_count = self.failure_count_max self.version = 0 self.valid = True #Add to Domain collection Domain.dps_client_add(self.domain, self) #self.show(None) def tunnel_endpoint_add(self, tunnel_endpoint): ''' Add a Tunnel Endpoint to the collection @param tunnel_endpoint: The Tunnel Endpoint @type tunnel_endpoint: TunnelEndpoint Object ''' ip_list = tunnel_endpoint.ip_listv4.ip_list for ip_value in ip_list: self.Tunnel_Endpoints_Hash_IPv4[ip_value] = tunnel_endpoint ip_list = tunnel_endpoint.ip_listv6.ip_list for ip_value in ip_list: self.Tunnel_Endpoints_Hash_IPv6[ip_value] = tunnel_endpoint return def tunnel_endpoint_delete(self, tunnel_endpoint): ''' Removes a Tunnel Endpoint from the collection @param tunnel_endpoint: The Tunnel Endpoint @type tunnel_endpoint: TunnelEndpoint Object ''' #log.info('DPSClient.tunnel_endpoint_delete %s', tunnel_endpoint.primary_ip().show()) ip_list = tunnel_endpoint.ip_listv4.ip_list for ip_value in ip_list: try: del self.Tunnel_Endpoints_Hash_IPv4[ip_value] except Exception: pass ip_list = tunnel_endpoint.ip_listv6.ip_list for ip_value in ip_list: try: del self.Tunnel_Endpoints_Hash_IPv6[ip_value] except Exception: pass if ((len(self.Tunnel_Endpoints_Hash_IPv4) == 0) and (len(self.Tunnel_Endpoints_Hash_IPv6) == 0)): #log.info('DPSClient.tunnel_endpoint_delete: No tunnel endpoints') #No other tunnels attached Domain.dps_client_delete(self.domain, self) #self.show(None) def tunnel_endpoint_add_IP(self, tunnel_endpoint, inet_type, ip_value): ''' Adds a Tunnel Endpoint Physical IP Address to the Domain Collection @param tunnel_endpoint: The Tunnel Endpoint @type tunnel_endpoint: TunnelEndpoint Object @param inet_type: AF_INET or AF_INET6 @type inet_type: Integer @param ip_value: The IP address value @type ip_value: Integer or String ''' #TODO: Should we add all IPs to this hash or only the primary IP if inet_type == socket.AF_INET: ip_hash = self.Tunnel_Endpoints_Hash_IPv4 else: ip_hash = self.Tunnel_Endpoints_Hash_IPv6 ip_hash[ip_value] = tunnel_endpoint return def tunnel_endpoint_delete_IP(self, inet_type, ip_value): ''' Deletes a Tunnel Endpoint Physical IP Address to the Domain Collection @param tunnel_endpoint: The Tunnel Endpoint @type tunnel_endpoint: TunnelEndpoint Object @param inet_type: AF_INET or AF_INET6 @type inet_type: Integer @param ip_value: The IP address value @type ip_value: Integer or String ''' if inet_type == socket.AF_INET: ip_hash = self.Tunnel_Endpoints_Hash_IPv4 else: ip_hash = self.Tunnel_Endpoints_Hash_IPv6 try: del ip_hash[ip_value] except Exception: pass if ((len(self.Tunnel_Endpoints_Hash_IPv4) == 0) and (len(self.Tunnel_Endpoints_Hash_IPv6) == 0)): #log.info('DPSClient.tunnel_endpoint_delete: No tunnel endpoints') #No other tunnels attached Domain.dps_client_delete(self.domain, self) return def delete(self): ''' Destructor: ''' if not self.valid: return self.valid = False #Remove from GlobalCollection DPSClientHost.Host_Delete_All(self.domain, self.location.ip_value) #Remove self from VNID_Broadcast_Updates_To for key in DpsCollection.VNID_Broadcast_Updates_To.keys(): try: tuple_value = DpsCollection.VNID_Broadcast_Updates_To[key] dps_client = tuple_value[1] if dps_client == self: del DpsCollection.VNID_Broadcast_Updates_To[key] except Exception: pass #Remove self from DPS Client Updates for key in DpsCollection.Policy_Updates_To.keys(): try: tuple_value = DpsCollection.Policy_Updates_To[key] dps_client = tuple_value[1] if dps_client == self: del DpsCollection.Policy_Updates_To[key] except Exception: pass #Remove from Gateway_Updates_To for key in DpsCollection.Gateway_Updates_To.keys(): try: tuple_value = DpsCollection.Gateway_Updates_To[key] dps_client = tuple_value[1] if dps_client == self: del DpsCollection.Gateway_Updates_To[key] except Exception: pass #Remove from VNID_Multicast_Updates_To for key in DpsCollection.VNID_Multicast_Updates_To.keys(): try: tuple_value = DpsCollection.VNID_Multicast_Updates_To[key] dps_client = tuple_value[1] if dps_client == self: del DpsCollection.VNID_Multicast_Updates_To[key] except Exception: pass #Remove from Address_Resolution_Requests_To for key in DpsCollection.Address_Resolution_Requests_To.keys(): try: tuple_value = DpsCollection.Address_Resolution_Requests_To[key] dps_client = tuple_value[1] if dps_client == self: del DpsCollection.Address_Resolution_Requests_To[key] except Exception: continue for tunnel in self.Tunnel_Endpoints_Hash_IPv4.values(): tunnel.delete() for tunnel in self.Tunnel_Endpoints_Hash_IPv6.values(): tunnel.delete() Domain.dps_client_delete(self.domain, self) def show(self): ''' Display Details ''' print 'DPS Client: %s\r'%(self.location.show()) print '---------------------- Tunnel Endpoints --------------------------\r' ############################################################# #Show list of tunnels. ############################################################# #First create a unique tunnel list tunnel_set = {} for tunnel in self.Tunnel_Endpoints_Hash_IPv4.values(): tunnel_set[tunnel] = True for tunnel in self.Tunnel_Endpoints_Hash_IPv6.values(): tunnel_set[tunnel] = True for tunnel in tunnel_set.keys(): tunnel.show() tunnel_set.clear() print '------------------------------------------------------------------\r' return
class DPSClientHost: ''' This represents the DPS Client which is communicating via the DPS Client Server Protocol. @attention: A DCSHostClient is not associated with any specific domain (unlike the DPSClient object). This object is maintained to keep in contact with that Host via heartbeat messages ''' Collection = {} #The frequency (seconds) at which to send heartbeat to DPS Clients heartbeat_frequency = { DpsClientType.dove_switch: 60, DpsClientType.external_gateway: 3, DpsClientType.vlan_gateway: 20 } #A maximum of no contact time before DPS Client is marked as down heartbeat_no_contact = { DpsClientType.dove_switch: 3600, DpsClientType.external_gateway: 20, DpsClientType.vlan_gateway: 600 } def __init__(self, domain, ip_type, ip_val, port, client_type): ''' Constructor: This routine assumes that the IP address of the DPS Client uniquely identifies the DPS Client. @param domain: The Domain object for which this DPSHostClient was first created @type domain: Domain @param ip_type: socket.AF_INET6 or socket.AF_INET @type ip_type: Integer @param ip_val: The Value of the IP Address @type ip_val: String (IPv6) or Integer @param port: The DPS Client Port (for UDP communication) @type port: Integer @param client_type: What kind of Client is it @type client_type: Should be one of DpsClientType ''' self.frequency = self.heartbeat_frequency[client_type] self.domains = {} self.domains[domain.unique_id] = domain #DPS Client Location i.e. the UDP Port and Location self.location = IPAddressLocation(ip_type, ip_val, port) self.client_type = client_type self.client_types = {} self.client_types[client_type] = True self.last_contact = time.time() #print '%s added client_type %s\r'%(self.location.show_ip(), DpsClientType.types[client_type]) #Add self to global collection try: DPSClientHost.Collection[ip_val] = self except Exception: pass self.valid = True def update_add(self, domain, port, client_type): ''' This routine updates the dps client with the parameters @param domain: The Domain object for which this DPSHostClient was first created @type domain: Domain @param port: The DPS Client Port (for UDP communication) @type port: Integer @param client_type: What kind of Client is it @type client_type: Should be one of DpsClientType ''' if not self.valid: return self.domains[domain.unique_id] = domain self.location.port = port self.client_types[client_type] = True #Get the client type with the highest (lowest in time difference) frequency heartbeat requirement try: if DPSClientHost.heartbeat_frequency[ client_type] < DPSClientHost.heartbeat_frequency[ self.client_type]: self.client_type = client_type print '%s changing client_type to %s\r' % ( self.location.show_ip(), DpsClientType.types[client_type]) except Exception: self.client_type = client_type return def update_delete(self, domain, client_type): ''' This routine updates the dps client with the parameters @param domain: The Domain object for which this DPSHostClient was first created @type domain: Domain @param port: The DPS Client Port (for UDP communication) @type port: Integer @param client_type: What kind of Client is it @type client_type: Should be one of DpsClientType ''' if not self.valid: return try: del self.domains[domain.unique_id] except Exception: pass try: del self.client_types[client_type] except Exception: pass if len(self.domains) == 0 or len(self.client_types) == 0: self.delete() return #Get the client type with the highest (lowest in time difference) frequency heartbeat requirement try: client_types = self.client_types.keys() self.client_type = client_types[0] client_types = client_types[1:] for client_type in client_types: if DPSClientHost.heartbeat_frequency[ client_type] < DPSClientHost.heartbeat_frequency[ self.client_type]: self.client_type = client_type except Exception: pass return def touch(self): ''' This routine touches the DPS Client ''' self.last_contact = time.time() return def domain_add(self, domain): ''' This routine add a domain to the DPSClientHost @param domain: The Domain object @type domain: Domain ''' self.domains[domain.unique_id] = domain return def domain_delete(self, domain): ''' This routine deletes the domain from the DPSClientHost @param domain: The Domain object @type domain: Domain ''' try: del self.domains[domain.unique_id] except Exception: pass if len(self.domains) == 0: self.delete() return def vnid_random_get(self): ''' This gets a random vnid to send the heartbeat to. @raise exception: If no VNID is found ''' domain = self.domains.values()[0] vnid = domain.vnid_random_get() return vnid def delete(self): ''' This routine deletes the object ''' if not self.valid: return self.valid = False domains = self.domains.values() for domain in domains: try: if self.location.inet_type == socket.AF_INET: dps_client_domain = domain.DPSClients_Hash_IPv4[ self.location.ip_value] else: dps_client_domain = domain.DPSClients_Hash_IPv6[ self.location.ip_value] dps_client_domain.delete() except Exception: continue self.domains.clear() try: del DPSClientHost.Collection[self.location.ip_value] except Exception: pass return @staticmethod def Host_Add(domain, ip_type, ip_val, port, client_type): ''' This is the routine calling routines should invoke to add a DPS Client to the collection @attention: This routine must be called with the global lock held @param domain: The Domain object @type domain: Domain @param ip_type: socket.AF_INET6 or socket.AF_INET @type ip_type: Integer @param ip_val: The Value of the IP Address @type ip_val: String (IPv6) or Integer @param port: The DPS Client Port (for UDP communication) @type port: Integer @param client_type: What kind of Client is it @type client_type: Should be one of DpsClientType ''' #print 'Host_Add: Enter\r' try: dps_client = DPSClientHost.Collection[ip_val] dps_client.update_add(domain, port, client_type) except Exception: dps_client = DPSClientHost(domain, ip_type, ip_val, port, client_type) #print 'Host_Add: Exit\r' return @staticmethod def Host_Delete(domain, ip_val, client_type): ''' This is the routine calling routines should invoke to add a DPS Client to the collection @attention: This routine must be called with the global lock held @param domain: The Domain object @type domain: Domain @param ip_val: The Value of the IP Address @type ip_val: String (IPv6) or Integer @param client_type: What kind of Client is it @type client_type: Should be one of DpsClientType ''' try: dps_client = DPSClientHost.Collection[ip_val] dps_client.update_delete(domain, client_type) except Exception: pass return @staticmethod def Host_Delete_All(domain, ip_val): ''' This is the routine calling routines should invoke to add a DPS Client to the collection @attention: This routine must be called with the global lock held @param domain: The Domain object @type domain: Domain @param ip_val: The Value of the IP Address @type ip_val: String (IPv6) or Integer ''' try: dps_client = DPSClientHost.Collection[ip_val] dps_client.delete() except Exception: pass return @staticmethod def Host_Touch(ip_val, port): ''' This routine touches the Host @param ip_val: The value @param port: The port of the DPS Client ''' try: dps_client = DPSClientHost.Collection[ip_val] if port != 0: dps_client.location.port = port dps_client.touch() except Exception: pass return @staticmethod def Domain_Deleted_Locally(domain): ''' This routine should be called when a domain is deleted or de-activated from the local DCS Server Node @attention: This routine must be called with the global lock held @param domain: The Domain object @type domain: Domain ''' try: dps_clients = DPSClientHost.Collection.values() for dps_client in dps_clients: try: dps_client.domain_delete(domain) except Exception: pass except Exception: pass return @staticmethod def Send_Heartbeat(): ''' This routine sends Heartbeats to all DPS Client which have not been contacted for the specified amount of time. ''' curr_time = time.time() try: dps_clients = DPSClientHost.Collection.values() for dps_client in dps_clients: try: time_diff = int(curr_time - dps_client.last_contact) client_type = dps_client.client_type time_no_contact = DPSClientHost.heartbeat_no_contact[ client_type] time_heartbeat_send = DPSClientHost.heartbeat_frequency[ client_type] if time_diff > time_no_contact: print 'No contact from DPS Client %s for %s seconds. Deleting!!!\r' % ( dps_client.location.show_ip(), time_diff) dps_client.delete() elif time_diff >= time_heartbeat_send: vnid = dps_client.vnid_random_get() query_id = DpsCollection.generate_query_id() dcslib.send_heartbeat( dps_client.location.ip_value_packed, dps_client.location.port, vnid, query_id) except Exception: continue except Exception: pass return @staticmethod def show(): curr_time = time.time() print '%s %s\r' % ('DCS Clients'.rjust(20), 'Age Time'.rjust(20)) try: dps_clients = DPSClientHost.Collection.values() for dps_client in dps_clients: time_diff = int(curr_time - dps_client.last_contact) print '%s %s\r' % (dps_client.location.show_ip().rjust(20), str(time_diff).rjust(20)) except Exception: pass return
class DPSClient: ''' This represents the DPS Client which is communicating via the DPS Client Server Protocol. Each DPS Client is associated with one or more Tunnel Endpoints. NOTE: Each DPSClient will have multiple instances every every Domain it hosts TunnelEndpoint on. In other words if a DPSClient hosts TunnelEndpoint on Domain A and Domain B, then there will be 2 independent instances of that DPSClient, 1 in Domain A and 1 in Domain B. ''' #A maximum of "max_failure" failures is tolerated from a DPS Client. After #that the DPS Client will have been deemed to be down and will be removed #from the collection failure_count_max = 4 def __init__(self, domain, ip_type, ip_val, port): ''' Constructor: This routine assumes that the IP address of the DPS Client uniquely identifies the DPS Client. @param domain: The Domain object @type domain: Domain @param ip_type: socket.AF_INET6 or socket.AF_INET @type ip_type: Integer @param ip_val: The Value of the IP Address @type ip_val: String (IPv6) or Integer @param port: The DPS Client Port (for UDP communication) @type port: Integer ''' self.domain = domain #DPS Client Location i.e. the UDP Port and Location self.location = IPAddressLocation(ip_type, ip_val, port) #List of Tunnel Endpoints #This is to store the Tunnel Endpoint IP Address self.Tunnel_Endpoints_Hash_IPv4 = {} self.Tunnel_Endpoints_Hash_IPv6 = {} ##Failure count self.failure_count = self.failure_count_max self.version = 0 self.valid = True #Add to Domain collection Domain.dps_client_add(self.domain, self) #self.show(None) def tunnel_endpoint_add(self, tunnel_endpoint): ''' Add a Tunnel Endpoint to the collection @param tunnel_endpoint: The Tunnel Endpoint @type tunnel_endpoint: TunnelEndpoint Object ''' ip_list = tunnel_endpoint.ip_listv4.ip_list for ip_value in ip_list: self.Tunnel_Endpoints_Hash_IPv4[ip_value] = tunnel_endpoint ip_list = tunnel_endpoint.ip_listv6.ip_list for ip_value in ip_list: self.Tunnel_Endpoints_Hash_IPv6[ip_value] = tunnel_endpoint return def tunnel_endpoint_delete(self, tunnel_endpoint): ''' Removes a Tunnel Endpoint from the collection @param tunnel_endpoint: The Tunnel Endpoint @type tunnel_endpoint: TunnelEndpoint Object ''' #log.info('DPSClient.tunnel_endpoint_delete %s', tunnel_endpoint.primary_ip().show()) ip_list = tunnel_endpoint.ip_listv4.ip_list for ip_value in ip_list: try: del self.Tunnel_Endpoints_Hash_IPv4[ip_value] except Exception: pass ip_list = tunnel_endpoint.ip_listv6.ip_list for ip_value in ip_list: try: del self.Tunnel_Endpoints_Hash_IPv6[ip_value] except Exception: pass if ((len(self.Tunnel_Endpoints_Hash_IPv4) == 0) and (len(self.Tunnel_Endpoints_Hash_IPv6) == 0)): #log.info('DPSClient.tunnel_endpoint_delete: No tunnel endpoints') #No other tunnels attached Domain.dps_client_delete(self.domain, self) #self.show(None) def tunnel_endpoint_add_IP(self, tunnel_endpoint, inet_type, ip_value): ''' Adds a Tunnel Endpoint Physical IP Address to the Domain Collection @param tunnel_endpoint: The Tunnel Endpoint @type tunnel_endpoint: TunnelEndpoint Object @param inet_type: AF_INET or AF_INET6 @type inet_type: Integer @param ip_value: The IP address value @type ip_value: Integer or String ''' #TODO: Should we add all IPs to this hash or only the primary IP if inet_type == socket.AF_INET: ip_hash = self.Tunnel_Endpoints_Hash_IPv4 else: ip_hash = self.Tunnel_Endpoints_Hash_IPv6 ip_hash[ip_value] = tunnel_endpoint return def tunnel_endpoint_delete_IP(self, inet_type, ip_value): ''' Deletes a Tunnel Endpoint Physical IP Address to the Domain Collection @param tunnel_endpoint: The Tunnel Endpoint @type tunnel_endpoint: TunnelEndpoint Object @param inet_type: AF_INET or AF_INET6 @type inet_type: Integer @param ip_value: The IP address value @type ip_value: Integer or String ''' if inet_type == socket.AF_INET: ip_hash = self.Tunnel_Endpoints_Hash_IPv4 else: ip_hash = self.Tunnel_Endpoints_Hash_IPv6 try: del ip_hash[ip_value] except Exception: pass if ((len(self.Tunnel_Endpoints_Hash_IPv4) == 0) and (len(self.Tunnel_Endpoints_Hash_IPv6) == 0)): #log.info('DPSClient.tunnel_endpoint_delete: No tunnel endpoints') #No other tunnels attached Domain.dps_client_delete(self.domain, self) return def delete(self): ''' Destructor: ''' if not self.valid: return self.valid = False #Remove from GlobalCollection DPSClientHost.Host_Delete_All(self.domain, self.location.ip_value) #Remove self from VNID_Broadcast_Updates_To for key in DpsCollection.VNID_Broadcast_Updates_To.keys(): try: tuple_value = DpsCollection.VNID_Broadcast_Updates_To[key] dps_client = tuple_value[1] if dps_client == self: del DpsCollection.VNID_Broadcast_Updates_To[key] except Exception: pass #Remove self from DPS Client Updates for key in DpsCollection.Policy_Updates_To.keys(): try: tuple_value = DpsCollection.Policy_Updates_To[key] dps_client = tuple_value[1] if dps_client == self: del DpsCollection.Policy_Updates_To[key] except Exception: pass #Remove from Gateway_Updates_To for key in DpsCollection.Gateway_Updates_To.keys(): try: tuple_value = DpsCollection.Gateway_Updates_To[key] dps_client = tuple_value[1] if dps_client == self: del DpsCollection.Gateway_Updates_To[key] except Exception: pass #Remove from VNID_Multicast_Updates_To for key in DpsCollection.VNID_Multicast_Updates_To.keys(): try: tuple_value = DpsCollection.VNID_Multicast_Updates_To[key] dps_client = tuple_value[1] if dps_client == self: del DpsCollection.VNID_Multicast_Updates_To[key] except Exception: pass #Remove from Address_Resolution_Requests_To for key in DpsCollection.Address_Resolution_Requests_To.keys(): try: tuple_value = DpsCollection.Address_Resolution_Requests_To[key] dps_client = tuple_value[1] if dps_client == self: del DpsCollection.Address_Resolution_Requests_To[key] except Exception: continue for tunnel in self.Tunnel_Endpoints_Hash_IPv4.values(): tunnel.delete() for tunnel in self.Tunnel_Endpoints_Hash_IPv6.values(): tunnel.delete() Domain.dps_client_delete(self.domain, self) def show(self): ''' Display Details ''' print 'DPS Client: %s\r' % (self.location.show()) print '---------------------- Tunnel Endpoints --------------------------\r' ############################################################# #Show list of tunnels. ############################################################# #First create a unique tunnel list tunnel_set = {} for tunnel in self.Tunnel_Endpoints_Hash_IPv4.values(): tunnel_set[tunnel] = True for tunnel in self.Tunnel_Endpoints_Hash_IPv6.values(): tunnel_set[tunnel] = True for tunnel in tunnel_set.keys(): tunnel.show() tunnel_set.clear() print '------------------------------------------------------------------\r' return
def show(self): ''' ''' message = '----------------------------------------------' dcslib.dps_data_write_log(DpsLogLevels.NOTICE, message) if self.global_scope: message = 'GLOBAL SCOPE, VNID %s'%self.dvg.unique_id else: message = 'MULTICAST MAC %s, VNID %s'%(mac_show(self.mac), self.dvg.unique_id) dcslib.dps_data_write_log(DpsLogLevels.NOTICE, message) if len(self.receiver_all) > 0: message = 'MULTICAST Receivers (NO IP Address)' dcslib.dps_data_write_log(DpsLogLevels.NOTICE, message) count = 1 for tunnel in self.receiver_all.keys(): message = ' [%d] Tunnel %s'%(count, tunnel.primary_ip().show()) dcslib.dps_data_write_log(DpsLogLevels.NOTICE, message) count += 1 if len(self.receiver_iphash) > 0: for iphash_key in self.receiver_iphash.keys(): try: if type(iphash_key) == type(1): ip_address = IPAddressLocation(socket.AF_INET, iphash_key, 0) else: ip_address = IPAddressLocation(socket.AF_INET6, iphash_key, 0) except Exception: continue message = 'MULTICAST Receivers IP Address %s'%ip_address.show() dcslib.dps_data_write_log(DpsLogLevels.NOTICE, message) iphash = self.receiver_iphash[iphash_key] count = 1; for tunnel in iphash.keys(): message = ' [%d] Tunnel %s'%(count, tunnel.primary_ip().show()) dcslib.dps_data_write_log(DpsLogLevels.NOTICE, message) count += 1 if len(self.sender_all) > 0: message = 'MULTICAST Senders (NO IP Address)' dcslib.dps_data_write_log(DpsLogLevels.NOTICE, message) count = 1 for tunnel in self.sender_all.keys(): message = ' [%d] Tunnel %s'%(count, tunnel.primary_ip().show()) dcslib.dps_data_write_log(DpsLogLevels.NOTICE, message) count += 1 if len(self.sender_iphash) > 0: for iphash_key in self.sender_iphash.keys(): try: if type(iphash_key) == type(1): ip_address = IPAddressLocation(socket.AF_INET, iphash_key, 0) else: ip_address = IPAddressLocation(socket.AF_INET6, iphash_key, 0) except Exception: continue message = 'MULTICAST Senders IP Address %s'%ip_address.show() dcslib.dps_data_write_log(DpsLogLevels.NOTICE, message) iphash = self.sender_iphash[iphash_key] count = 1 for tunnel in iphash.keys(): message = ' [%d] Tunnel %s'%(count, tunnel.primary_ip().show()) dcslib.dps_data_write_log(DpsLogLevels.NOTICE, message) count += 1 message = '----------------------------------------------' dcslib.dps_data_write_log(DpsLogLevels.NOTICE, message) return
class DPSClientHost: ''' This represents the DPS Client which is communicating via the DPS Client Server Protocol. @attention: A DCSHostClient is not associated with any specific domain (unlike the DPSClient object). This object is maintained to keep in contact with that Host via heartbeat messages ''' Collection = {} #The frequency (seconds) at which to send heartbeat to DPS Clients heartbeat_frequency = {DpsClientType.dove_switch: 60, DpsClientType.external_gateway: 3, DpsClientType.vlan_gateway: 20 } #A maximum of no contact time before DPS Client is marked as down heartbeat_no_contact = {DpsClientType.dove_switch: 3600, DpsClientType.external_gateway: 20, DpsClientType.vlan_gateway: 600} def __init__(self, domain, ip_type, ip_val, port, client_type): ''' Constructor: This routine assumes that the IP address of the DPS Client uniquely identifies the DPS Client. @param domain: The Domain object for which this DPSHostClient was first created @type domain: Domain @param ip_type: socket.AF_INET6 or socket.AF_INET @type ip_type: Integer @param ip_val: The Value of the IP Address @type ip_val: String (IPv6) or Integer @param port: The DPS Client Port (for UDP communication) @type port: Integer @param client_type: What kind of Client is it @type client_type: Should be one of DpsClientType ''' self.frequency = self.heartbeat_frequency[client_type] self.domains = {} self.domains[domain.unique_id] = domain #DPS Client Location i.e. the UDP Port and Location self.location = IPAddressLocation(ip_type, ip_val, port) self.client_type = client_type self.client_types = {} self.client_types[client_type] = True self.last_contact = time.time() #print '%s added client_type %s\r'%(self.location.show_ip(), DpsClientType.types[client_type]) #Add self to global collection try: DPSClientHost.Collection[ip_val] = self except Exception: pass self.valid = True def update_add(self, domain, port, client_type): ''' This routine updates the dps client with the parameters @param domain: The Domain object for which this DPSHostClient was first created @type domain: Domain @param port: The DPS Client Port (for UDP communication) @type port: Integer @param client_type: What kind of Client is it @type client_type: Should be one of DpsClientType ''' if not self.valid: return self.domains[domain.unique_id] = domain self.location.port = port self.client_types[client_type] = True #Get the client type with the highest (lowest in time difference) frequency heartbeat requirement try: if DPSClientHost.heartbeat_frequency[client_type] < DPSClientHost.heartbeat_frequency[self.client_type]: self.client_type = client_type print '%s changing client_type to %s\r'%(self.location.show_ip(), DpsClientType.types[client_type]) except Exception: self.client_type = client_type return def update_delete(self, domain, client_type): ''' This routine updates the dps client with the parameters @param domain: The Domain object for which this DPSHostClient was first created @type domain: Domain @param port: The DPS Client Port (for UDP communication) @type port: Integer @param client_type: What kind of Client is it @type client_type: Should be one of DpsClientType ''' if not self.valid: return try: del self.domains[domain.unique_id] except Exception: pass try: del self.client_types[client_type] except Exception: pass if len(self.domains) == 0 or len(self.client_types) == 0: self.delete() return #Get the client type with the highest (lowest in time difference) frequency heartbeat requirement try: client_types = self.client_types.keys() self.client_type = client_types[0] client_types = client_types[1:] for client_type in client_types: if DPSClientHost.heartbeat_frequency[client_type] < DPSClientHost.heartbeat_frequency[self.client_type]: self.client_type = client_type except Exception: pass return def touch(self): ''' This routine touches the DPS Client ''' self.last_contact = time.time() return def domain_add(self, domain): ''' This routine add a domain to the DPSClientHost @param domain: The Domain object @type domain: Domain ''' self.domains[domain.unique_id] = domain return def domain_delete(self, domain): ''' This routine deletes the domain from the DPSClientHost @param domain: The Domain object @type domain: Domain ''' try: del self.domains[domain.unique_id] except Exception: pass if len(self.domains) == 0: self.delete() return def vnid_random_get(self): ''' This gets a random vnid to send the heartbeat to. @raise exception: If no VNID is found ''' domain = self.domains.values()[0] vnid = domain.vnid_random_get() return vnid def delete(self): ''' This routine deletes the object ''' if not self.valid: return self.valid = False domains = self.domains.values() for domain in domains: try: if self.location.inet_type == socket.AF_INET: dps_client_domain = domain.DPSClients_Hash_IPv4[self.location.ip_value] else: dps_client_domain = domain.DPSClients_Hash_IPv6[self.location.ip_value] dps_client_domain.delete() except Exception: continue self.domains.clear() try: del DPSClientHost.Collection[self.location.ip_value] except Exception: pass return @staticmethod def Host_Add(domain, ip_type, ip_val, port, client_type): ''' This is the routine calling routines should invoke to add a DPS Client to the collection @attention: This routine must be called with the global lock held @param domain: The Domain object @type domain: Domain @param ip_type: socket.AF_INET6 or socket.AF_INET @type ip_type: Integer @param ip_val: The Value of the IP Address @type ip_val: String (IPv6) or Integer @param port: The DPS Client Port (for UDP communication) @type port: Integer @param client_type: What kind of Client is it @type client_type: Should be one of DpsClientType ''' #print 'Host_Add: Enter\r' try: dps_client = DPSClientHost.Collection[ip_val] dps_client.update_add(domain, port, client_type) except Exception: dps_client = DPSClientHost(domain, ip_type, ip_val, port, client_type) #print 'Host_Add: Exit\r' return @staticmethod def Host_Delete(domain, ip_val, client_type): ''' This is the routine calling routines should invoke to add a DPS Client to the collection @attention: This routine must be called with the global lock held @param domain: The Domain object @type domain: Domain @param ip_val: The Value of the IP Address @type ip_val: String (IPv6) or Integer @param client_type: What kind of Client is it @type client_type: Should be one of DpsClientType ''' try: dps_client = DPSClientHost.Collection[ip_val] dps_client.update_delete(domain, client_type) except Exception: pass return @staticmethod def Host_Delete_All(domain, ip_val): ''' This is the routine calling routines should invoke to add a DPS Client to the collection @attention: This routine must be called with the global lock held @param domain: The Domain object @type domain: Domain @param ip_val: The Value of the IP Address @type ip_val: String (IPv6) or Integer ''' try: dps_client = DPSClientHost.Collection[ip_val] dps_client.delete() except Exception: pass return @staticmethod def Host_Touch(ip_val, port): ''' This routine touches the Host @param ip_val: The value @param port: The port of the DPS Client ''' try: dps_client = DPSClientHost.Collection[ip_val] if port != 0: dps_client.location.port = port dps_client.touch() except Exception: pass return @staticmethod def Domain_Deleted_Locally(domain): ''' This routine should be called when a domain is deleted or de-activated from the local DCS Server Node @attention: This routine must be called with the global lock held @param domain: The Domain object @type domain: Domain ''' try: dps_clients = DPSClientHost.Collection.values() for dps_client in dps_clients: try: dps_client.domain_delete(domain) except Exception: pass except Exception: pass return @staticmethod def Send_Heartbeat(): ''' This routine sends Heartbeats to all DPS Client which have not been contacted for the specified amount of time. ''' curr_time = time.time() try: dps_clients = DPSClientHost.Collection.values() for dps_client in dps_clients: try: time_diff = int(curr_time - dps_client.last_contact) client_type = dps_client.client_type time_no_contact = DPSClientHost.heartbeat_no_contact[client_type] time_heartbeat_send = DPSClientHost.heartbeat_frequency[client_type] if time_diff > time_no_contact: print 'No contact from DPS Client %s for %s seconds. Deleting!!!\r'%(dps_client.location.show_ip(), time_diff) dps_client.delete() elif time_diff >= time_heartbeat_send: vnid = dps_client.vnid_random_get() query_id = DpsCollection.generate_query_id() dcslib.send_heartbeat(dps_client.location.ip_value_packed, dps_client.location.port, vnid, query_id) except Exception: continue except Exception: pass return @staticmethod def show(): curr_time = time.time() print '%s %s\r'%('DCS Clients'.rjust(20), 'Age Time'.rjust(20)) try: dps_clients = DPSClientHost.Collection.values() for dps_client in dps_clients: time_diff = int(curr_time - dps_client.last_contact) print '%s %s\r'%(dps_client.location.show_ip().rjust(20),str(time_diff).rjust(20)) except Exception: pass return