def __send_demotion_message(self, address): """ Demote a backup to normal agent :param address: IP address for demotion :return: True if correct demotion, False otherwise """ try: r = requests.get('{}agent'.format( URLS.build_url_address(URLS.URL_POLICIES_ROLECHANGE, addr=address, port=CPARAMS.POLICIES_PORT)), timeout=1.5) if r.status_code == 200: # Correct return True else: LOG.warning( 'Selected device [{}] received {} status code received on removing a backup' .format(address, r.status_code)) return False except timeout: LOG.warning( 'Selected device [{}] cannot be demoted to Agent due timeout'. format(address)) return False except: LOG.exception( 'Selected device cannot become Agent due error in demotion message' ) return False
def __send_election_message(self, address): """ :param address: IP address for election :return: True if correct election, False otherwise """ try: r = requests.get('{}backup'.format( URLS.build_url_address(URLS.URL_POLICIES_ROLECHANGE, addr=address, port=self.POLICIES_EXTERNAL_PORT, secure=CPARAMS.MF2C_FLAG)), timeout=1.5, verify=False) if r.status_code == 200: # Correct return True else: LOG.warning( 'Selected device [{}] received {} status code received on electing a new backup' .format(address, r.status_code)) return False except timeout: LOG.warning( 'Selected device [{}] cannot become Backup due timeout'.format( address)) return False except: LOG.exception( 'Selected device [{}] cannot become Backup due error in election message' .format(address)) return False
def __becomeLeader(self): # TODO """ :return: """ # 1- Shutdown/Notify all the modules involving Agent to Leader transiction. if self._leaderFailed: # Only if leader fails, triggers are needed, otherwise no action is required try: r = requests.get( URLS.build_url_address( '{}leader'.format(URLS.URL_POLICIES_ROLECHANGE), portaddr=( '127.0.0.1', '46050'))) #TODO Addr+Prt by CPARAMS; Parametrize LOG.info( self.TAG + 'Trigger to AgentStart Switch done. {}'.format(r.json())) self._imLeader = True self._imBackup = False except Exception as ex: LOG.exception(self.TAG + '_becomeLeader trigger to AgentStart failed') self.th_keep = threading.Thread(name='ar_keeper', target=self.__keeper, daemon=True) self.th_keep.start()
def setJson(self, json): try: ljson = loads(json) return self.setDict(ljson) except JSONDecodeError: LOG.exception('Error on getting new device via JSON.') return False
def cimi(key, default=None): value = default if key == 'leader': value = CPARAMS.LEADER_FLAG elif key == 'topology': value = [] # 1. Try to get the real topology cimi_topology = CIMI.get_topology() if len(cimi_topology) > 0: used_topology = cimi_topology # used_topology = list() # for item in cimi_topology: # TODO: Dataclay doesnt sync device static information to the leader # qdeviceID = CIMI.get_deviceID_from_IP(item[1]) # if qdeviceID != '': # used_topology.append((qdeviceID, item[1])) else: used_topology = CPARAMS.TOPOLOGY_FLAG try: for item in used_topology: i = {'deviceID': item[0], 'deviceIP': item[1]} value.append(i) except: LOG.exception( 'Topology Environment variable format is not correct.') value = [] return value
def createAgentResource(agentResource): """ Create a new Agent Resource in CIMI :param agentResource: Agent resource dicc formated :return: Agent resource ID """ URL = CIMIcalls.CIMI_URL + CIMIcalls.CIMI_AGENT_RESOURCE payload = agentResource try: r = requests.post(URL, headers=CIMIcalls.CIMI_HEADERS, verify=False, json=payload) rjson = r.json() LOG.debug( 'CIMI create agent [{}] status_code {} resource-id {}'.format( URL, r.status_code, rjson.get('resource-id'))) if r.status_code == 409: LOG.error( 'CIMI create agent already exists! resource-id {}'.format( rjson.get('resource-id'))) return str(rjson.get('resource-id')) except: LOG.exception('CIMI agent [{}] failed'.format(URL)) return ''
def setDict(self, dict): try: self.deviceID = str(dict.get('deviceID')) self.deviceIP = str(dict.get('deviceIP')) self.cpu_cores = int(dict.get('cpu_cores')) self.mem_avail = float(dict.get('mem_avail')) self.stg_avail = float(dict.get('stg_avail')) return True except: LOG.exception('Error on getting new device via Dict.') return False
def set_json(self, json): with self.__lock: try: ljson = loads(json) for key in ljson.keys(): if key in self.POLICIES.keys(): self.POLICIES[key] = ljson[key] return True except JSONDecodeError: LOG.exception('Error on getting new policies.') return False
def recv_reply(self, payload, deviceIP): try: dev_obj = DeviceInformation(dict=payload) dev_obj.deviceIP = deviceIP with self._db_lock: self._db.update({dev_obj.deviceID: dev_obj}) LOG.debug('Topology added/modified device: {}'.format(dev_obj)) return True except: LOG.exception('Error on receiving reply from device to a beacon.') return False
def get_deviceID_from_IP(deviceIP): device_static_id = '' scode, dev_dyn_reply = CIMIcalls.get_resource( CIMIcalls.CIMI_DEVICE_DYNAMIC) if scode != 200: LOG.debug( 'Unable to query device-dynamic resource. IP cannot be found.') return '' try: if 'deviceDynamics' in dev_dyn_reply: device_dynamic_collection = dev_dyn_reply['deviceDynamics'] for item in device_dynamic_collection: if 'wifiAddress' in item and 'device' in item: if item['wifiAddress'] == deviceIP: device_static_id = item['device']['href'] LOG.debug( 'IP {} found! Device CIMI resource: {}'.format( deviceIP, device_static_id)) break else: LOG.error('deviceDynamics not found in {} resource'.format( CIMIcalls.CIMI_DEVICE_DYNAMIC)) return '' if device_static_id != '': scode2, dev_sta_reply = CIMIcalls.get_resource( device_static_id) if scode2 != 200: LOG.error( 'Unable to query device from device-dynamic. href:{}'. format(device_static_id)) return '' if 'deviceID' in dev_sta_reply: LOG.debug('IP corresponds to deviceID: {}'.format( dev_sta_reply['deviceID'])) return dev_sta_reply['deviceID'] else: LOG.error('deviceID not found in resource {}'.format( device_static_id)) return '' else: LOG.debug('IP {} not found in {} collection.'.format( deviceIP, CIMIcalls.CIMI_DEVICE_DYNAMIC)) return '' except: LOG.exception('Exception raised getting deviceID from IP') return ''
def deleteBackupOnAgentResource(backupIP): try: agent_resource, agent_resource_id = CIMI.getAgentResource() ar = AgentResource.load(agent_resource) if ar.backupIP != backupIP: LOG.warning( 'Backup [{}] does not match [{}] stored in Agent Resource'. format(backupIP, ar.backupIP)) ar2 = AgentResource(None, None, None, None, None, backupIP='') LOG.debug( 'Removing backup [{}] in Agent Resource. Updated agent resource: {}' .format(backupIP, ar2.getCIMIdicc())) CIMI.modify_resource(agent_resource_id, ar2.getCIMIdicc()) except: LOG.exception('Add backup in Agent resource failed')
def get_resource(resource_id): """ Get resource by ID if exists :param resource_id: CIMI resource id :return: status_code and resource if successful, None otherwise """ URL = CIMIcalls.CIMI_URL + '/' + resource_id try: r = requests.get(URL, headers=CIMIcalls.CIMI_HEADERS, verify=False) rjson = r.json() LOG.debug('CIMI GET resource [{}] status_code {}'.format( URL, r.status_code)) return r.status_code, rjson except: LOG.exception('CIMI GET resource [{}] failed.'.format(URL)) return None, None
def getAllAgentResources(): URL = CIMIcalls.CIMI_URL + CIMIcalls.CIMI_AGENT_RESOURCE try: r = requests.get(URL, headers=CIMIcalls.CIMI_HEADERS, verify=False) rjson = r.json() LOG.debug('CIMI agent [{}] status_code {} count {}'.format( URL, r.status_code, rjson.get('count'))) if len(rjson.get('agents')) > 0: LOG.debug('Agent resource found!') return rjson.get('agents') else: LOG.debug('Agent resource not found!') return [] except: LOG.exception('CIMI agent [{}] failed'.format(URL)) return []
def __categorize_device(self): try: cpu_cores = int( psutil.cpu_count()) if psutil.cpu_count() is not None else -1 mem_avail = float(psutil.virtual_memory().available / (2**30)) storage_avail = float( sum([ psutil.disk_usage(disk.mountpoint).free for disk in psutil.disk_partitions() ]) / 2**30) except: LOG.exception('Categorization not successful') cpu_cores = 0 mem_avail = .0 storage_avail = .0 finally: return cpu_cores, mem_avail, storage_avail
def delete_resource(resource_id): """ Delete resource by ID in CIMI :param resource_id: CIMI resource ID :return: status_code if successful, None otherwise """ URL = CIMIcalls.CIMI_URL + '/' + resource_id try: r = requests.delete(URL, headers=CIMIcalls.CIMI_HEADERS, verify=False) # rjson = r.json() LOG.debug('CIMI DELETE resource [{}] status_code {}'.format( URL, r.status_code)) return r.status_code except: LOG.exception('CIMI DELETE resource [{}] failed.'.format(URL)) return None
def getAgentResource(): """ Get Agent resource in CIMI :return: Dicc of the Agent Resource if found or empty dicc otherwise """ URL = CIMIcalls.CIMI_URL + CIMIcalls.CIMI_AGENT_RESOURCE try: r = requests.get(URL, headers=CIMIcalls.CIMI_HEADERS, verify=False) rjson = r.json() LOG.debug('CIMI agent [{}] status_code {} count {}'.format( URL, r.status_code, rjson.get('count'))) if len(rjson.get('agents')) > 0: LOG.debug('Agent resource found!') return rjson.get('agents')[0], rjson.get('agents')[0].get('id') else: LOG.debug('Agent resource not found!') return {}, '' except: LOG.exception('CIMI agent [{}] failed'.format(URL)) return {}, ''
def addBackupOnAgentResource(backupIP): try: agent_resource, agent_resource_id = CIMI.getAgentResource() ar = AgentResource.load(agent_resource) if ar.backupIP is not None or (ar.backupIP != '' and ar.backupIP is not None): LOG.warning( 'Non-empty backupIP value when adding a new backup! Agent resource: {}' .format(ar.getCIMIdicc())) ar2 = AgentResource(None, None, None, None, None, backupIP='{}'.format(backupIP)) LOG.debug( 'Adding backup [{}] in Agent Resource. Updated agent resource: {}'. format(backupIP, ar2.getCIMIdicc())) CIMI.modify_resource(agent_resource_id, ar2.getCIMIdicc()) except: LOG.exception('Add backup in Agent resource failed')
def __beaconning_flow(self): self._socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) beacon = dumps({'leaderID': self._deviceID}) while self._connected: try: LOG.debug('Sending beacon at [{}:{}]'.format( CPARAMS.BROADCAST_ADDR_FLAG, CPARAMS.LDISCOVERY_PORT)) self._socket.sendto( beacon.encode(), (CPARAMS.BROADCAST_ADDR_FLAG, CPARAMS.LDISCOVERY_PORT)) sleep_ticks = 0 while sleep_ticks < 5 / .1: # TODO: Policies if not self._connected: break else: sleep_ticks += 1 sleep(0.1) except: LOG.exception('Error sending beacons') self._connected = False
def modify_resource(resource_id, payload): """ Modify resource by ID in CIMI :param resource_id: CIMI resource id :param payload: new content of the resource :return: status_code if successful, None otherwise """ URL = CIMIcalls.CIMI_URL + '/' + resource_id try: r = requests.put(URL, headers=CIMIcalls.CIMI_HEADERS, verify=False, json=payload) # rjson = r.json() LOG.debug( 'CIMI EDIT resource [{}] status_code {} content {}'.format( URL, r.status_code, r.content)) return r.status_code except: LOG.exception('CIMI EDIT resource [{}] failed.'.format(URL)) return None
def distributePolicies(self, listIPs): # 1. Get all the policies payload = {} for policy in self.__POLICIES.keys(): payload.update({policy: self.__POLICIES.get(policy).get_json()}) LOG.debug('Policy Payload : [{}]'.format(payload)) # 2. Send to all the IPs for ip in listIPs: try: r = requests.post( URLS.build_url_address(URLS.URL_POLICIESDISTR_RECV, portaddr=(ip, CPARAMS.POLICIES_PORT)), json=payload, timeout=2) if r.status_code == 200: # Correct LOG.debug('Policies sent correctly to [{}]'.format(ip)) else: LOG.debug('Policies NOT sent correctly to [{}]'.format(ip)) except: LOG.exception('Error occurred sending to [{}] the payload [{}]'.format(ip, payload)) return
def getIPfromFile(file_path=CPARAMS.VPN_FILE_PATH): """ Get the IP of the device in the VPN network from the JSON file generated by the VPN client component. :param file_path: Path to the VPN JSON file :return: string with IP of the device, empty if failure """ ret_ip = '' try: with open(file_path, mode='r') as json_file: json_txt = json_file.readlines()[0] ljson = json.loads(json_txt) if ljson['status'] == 'connected': ret_ip = str(ljson['ip']) LOG.debug( 'VPN IP successfully parsed from JSON file at \'{}\'. Content: {} IP: {}' .format(file_path, str(ljson), ret_ip)) else: LOG.warning( 'VPN JSON status != \'connected\': Content: {}'.format( str(ljson))) except OSError: LOG.exception('VPN file cannot be open or found at \'{}\'.'.format( file_path)) except (IndexError, KeyError): LOG.exception('VPN error on parsing the IP.') except: LOG.exception('VPN generic error.') finally: return ret_ip
def cimi(key, default=None): value = default if key == 'leader': value = CPARAMS.LEADER_FLAG elif key == 'topology': value = [] try: # for item in CPARAMS.TOPOLOGY_FLAG: for item in lightdiscovery.get_topology(): i = { 'deviceID': item[0], 'deviceIP': item[1] } value.append(i) except: LOG.exception('Topology Environment variable format is not correct.') value = [] elif key == 'disc_leaderIP': value = lightdiscovery.leaderIP if value is None: value = default return value
def __scanning_flow(self): # 1. Get Beacon # 2. Categorize # 3. Send Categorization info self._socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) try: self._socket.bind(('0.0.0.0', CPARAMS.LDISCOVERY_PORT)) LOG.info('Scan server created correctly') except: LOG.exception('Error on creating the scan receiver') return while self._connected: try: data, addr = self._socket.recvfrom(4096) if not self._connected: break LOG.debug('Received beacon from [{}]: \"{}\"'.format( addr[0], data.decode())) self.leaderIP = addr[0] try: ddata = loads(data.decode()) self.leaderID = ddata.get('leaderID') except JSONDecodeError: LOG.warning('Beacon payload malformed') cpu, mem, stg = self.__categorize_device() LOG.debug('CPU: {}, MEM: {}, STG: {}'.format(cpu, mem, stg)) payload = DeviceInformation(deviceID=self._deviceID, cpuCores=cpu, memAvail=mem, stgAvail=stg).getDict() LOG.info('Sending beacon reply to Leader...') r = requests.post(URLS.build_url_address( URLS.URL_BEACONREPLY, portaddr=(addr[0], CPARAMS.POLICIES_PORT)), json=payload, timeout=2) if r.status_code == 200: LOG.info('Discovery Message successfully sent to Leader') else: LOG.warning( 'Discovery Message received error status code {}'. format(r.status_code)) except: LOG.exception('Error on beacon received') try: self._socket.close() LOG.info('Scan Server Stopped') except: LOG.exception('Server Stop not successful')
def __agent_startup_flow(self): while self._connected: # 0. Init self.detectedLeaderID, self.MACaddr = None, None # 0.1 Check CIMI is UP CIMIon = False while self._connected and not CIMIon: CIMIon = CIMI.checkCIMIstarted() if not CIMIon: LOG.debug(self.TAG + 'CIMI is not ready... Retry in {}s'.format( self.WAIT_TIME_CIMI)) sleep(self.WAIT_TIME_CIMI) LOG.info(self.TAG + 'CIMI is ready!') # 1. Identification if self._connected: self.identification_failed = True # Reset variable to avoid false positives LOG.debug(self.TAG + 'Sending trigger to Identification...') try: self.__trigger_requestID() self.identification_failed = False except Exception: LOG.exception(self.TAG + 'Identification trigger failed!') self.identification_failed = True LOG.info(self.TAG + 'Identification Trigger Done.') else: return if not CPARAMS.DEBUG_FLAG and self.identification_failed: LOG.critical( self.TAG + 'Identification failed, interrupting agent start.') return # 2. Check if im a Leader - PLE if self.imLeader: # switch to leader self.__leader_switch_flow() # TODO: imCapable? return # remain as agent # 3. Scan for Leaders count = 0 self.discovery_failed = True while self._connected and count < self.MAX_MISSING_SCANS and self.detectedLeaderID is None and self.MACaddr is None: # TODO: new protocol required LOG.debug(self.TAG + 'Sending scan trigger to Discovery...') try: self.__trigger_startScan() self.discovery_failed = False except Exception: LOG.debug(self.TAG + 'Discovery failed on attepmt {}.'.format(count)) self.discovery_failed = True if self.detectedLeaderID is not None and self.MACaddr is not None: LOG.info(self.TAG + 'Discovery Scan Trigger Done.') count += 1 LOG.info( self.TAG + 'Discovery trigger finished in #{} attempts and ok={}'.format( count, self.detectedLeaderID is not None and self.MACaddr is not None)) if not self._connected: return if not CPARAMS.DEBUG_FLAG and self.discovery_failed: LOG.critical(self.TAG + 'Discovery failed, interrupting agent start.') return # 4. If no leader detected, switch to leader IF policy and capable - ALE if not self.discovery_failed and self.detectedLeaderID is None and self.MACaddr is None and self.ALE_ENABLED: self.__leader_switch_flow() # TODO: imCapable? return # 5. CAU client if self._connected: self.cauclient_failed = True LOG.debug(self.TAG + 'Sending trigger to CAU client...') try: self.__trigger_triggerCAUclient() self.cauclient_failed = False except Exception: LOG.exception(self.TAG + 'CAUclient failed.') self.cauclient_failed = True LOG.info(self.TAG + 'CAU client Trigger Done.') else: return if not CPARAMS.DEBUG_FLAG and self.cauclient_failed: LOG.critical(self.TAG + 'CAU-Client failed, interrupting agent start.') return # 5. Categorization if self._connected and not self.categorization_started: self.categorization_failed = True LOG.debug(self.TAG + 'Sending start trigger to Categorization...') try: self.__trigger_startCategorization() self.categorization_failed = False self.categorization_started = True except Exception: LOG.exception(self.TAG + 'Categorization failed') self.categorization_failed = True LOG.info(self.TAG + 'Categorization Start Trigger Done.') elif not self._connected: return if not CPARAMS.DEBUG_FLAG and self.categorization_failed: LOG.critical( self.TAG + 'Categorization failed, interrupting agent start.') return # 6. Area Resilience if self._connected and not self.arearesilience_started: self.policies_failed = True LOG.debug(self.TAG + 'Sending start trigger to Policies...') try: success = self.__trigger_startLeaderProtectionPolicies() self.policies_failed = not success self.arearesilience_started = success except Exception: LOG.exception(self.TAG + 'Policies Area Resilience failed!') LOG.info(self.TAG + 'Policies Area Resilience Start Trigger Done.') elif not self._connected: return if not CPARAMS.DEBUG_FLAG and self.policies_failed: LOG.critical( self.TAG + 'Policies Area Resilience failed, interrupting agent start.' ) return # Print summary self.__print_summary() # Create/Modify Agent Resource # TODO. self.deviceIP = '' # TODO: Real value here (from categorization) self._cimi_agent_resource = AgentResource(self.deviceID, self.deviceIP, self.isAuthenticated, self.secureConnection, self.imLeader, leaderIP=self.leaderIP) if self._cimi_agent_resource_id is None: # Create agent resource self._cimi_agent_resource_id = CIMI.createAgentResource( self._cimi_agent_resource.getCIMIdicc()) else: # Agent resource already exists status = CIMI.modify_resource( self._cimi_agent_resource_id, self._cimi_agent_resource.getCIMIdicc()) # 7. Watch Leader if self._connected and not self.discovery_failed: LOG.debug(self.TAG + 'Start Discovery Leader Watch...') try: self.__trigger_startDiscoveryWatch() except Exception: LOG.exception(self.TAG + 'Watch Discovery Start Fail.') LOG.info(self.TAG + 'Watch Discovery Start Trigger Done.') elif self.discovery_failed: LOG.warning( self.TAG + 'Discovery Watch cancelled due Discovery Trigger failed') else: return alive = True while self._connected and not self.discovery_failed and alive: # 6 Check if discovery connection is alive LOG.debug(self.TAG + 'Discovery Alive Start Trigger.') try: alive = not self.__trigger_aliveDiscovery( ) # not disconnected except Exception: LOG.exception(self.TAG + 'Discovery Alive failed') alive = False if self._connected: sleep(CPARAMS.TIME_WAIT_ALIVE) LOG.info(self.TAG + 'Discovery Alive Start Trigger Done.') if not self._connected: return if CPARAMS.DEBUG_FLAG and self.discovery_failed: # TODO: Delete this in future versions LOG.debug(self.TAG + 'No rescan available. Stoping activity') return
def __agent_startup_flow(self): while self._connected: # 0. Init self.detectedLeaderID, self.MACaddr, self.bssid = None, None, None # 0.1 Check CIMI is UP CIMIon = False while self._connected and not CIMIon: CIMIon = CIMI.checkCIMIstarted() if not CIMIon: LOG.debug(self.TAG + 'CIMI is not ready... Retry in {}s'.format( self.WAIT_TIME_CIMI)) sleep(self.WAIT_TIME_CIMI) LOG.info(self.TAG + 'CIMI is ready!') # 1. Identification if self._connected: self.identification_failed = True # Reset variable to avoid false positives LOG.debug(self.TAG + 'Sending trigger to Identification...') try: self.__trigger_requestID() self.identification_failed = False except Exception: LOG.exception(self.TAG + 'Identification trigger failed!') self.identification_failed = True LOG.info(self.TAG + 'Identification Trigger Done.') else: return if not CPARAMS.DEBUG_FLAG and self.identification_failed: LOG.critical( self.TAG + 'Identification failed, interrupting agent start.') return # 2.1. Check if im Cloud Agent if self.imCloud: # start cloud flow self.__cloud_flow() return # 2.2. Check if im a Leader - PLE if self.imLeader: # switch to leader self.__leader_switch_flow() return # remain as agent # 3. Scan for Leaders count = 0 self.discovery_failed = True while self._connected and count < self.MAX_MISSING_SCANS and self.detectedLeaderID is None and self.MACaddr is None: # TODO: new protocol required LOG.debug(self.TAG + 'Sending SCAN trigger to Discovery...') try: self.__trigger_startScan() self.discovery_failed = False except Exception: LOG.debug(self.TAG + 'Discovery failed on attepmt {}.'.format(count)) self.discovery_failed = True if self.detectedLeaderID is not None and self.MACaddr is not None and self.bssid is not None: LOG.info(self.TAG + 'Discovery Scan Trigger Done.') count += 1 LOG.info( self.TAG + 'Discovery trigger finished in #{} attempts and ok={}'.format( count, self.detectedLeaderID is not None and self.MACaddr is not None and self.bssid is not None)) if not self._connected: return if not CPARAMS.DEBUG_FLAG and self.discovery_failed: LOG.critical(self.TAG + 'Discovery failed, interrupting agent start.') return # 4.1. If no leader detected, switch to leader IF policy and capable - ALE if not self.discovery_failed and self.detectedLeaderID is None and self.MACaddr is None and self.bssid is None and self.ALE_ENABLED: self.__leader_switch_flow() # TODO: imCapable? return # 4.2 If detected, join to the Leader if not self.discovery_failed and self.bssid is not None and self._connected: LOG.debug(self.TAG + 'Sending JOIN trigger to discovery...') try: r = self.__trigger_joinDiscovery() self.discovery_failed = not r self.discovery_joined = r if not self.discovery_failed: self.leaderIP = CPARAMS.LEADER_DISCOVERY_IP except Exception: LOG.exception(self.TAG + 'Discovery JOIN trigger failed.') self.discovery_failed = True self.discovery_joined = False LOG.debug(self.TAG + 'Discovery JOIN trigger Done.') # 4.3 If not detected or failed, static configuration if setup if self.discovery_failed or (self.detectedLeaderID is None and self.MACaddr is None and self.bssid is None): LOG.debug( self.TAG + 'Discovery failed or leader was not detected. Fetching deviceIP and leaderIP from env variables.' ) self.deviceIP = CPARAMS.DEVICE_IP_FLAG self.leaderIP = CPARAMS.LEADER_IP_FLAG # 5. CAU client if self._connected: self.cauclient_failed = True LOG.debug(self.TAG + 'Sending trigger to CAU client...') attempt = 0 r = False while self._connected and not r and attempt < self.MAX_CAUCLIENT_FAILURES: try: r = self.__trigger_triggerCAUclient() self.cauclient_failed = not r except Exception: LOG.exception(self.TAG + 'CAUclient failed.') self.cauclient_failed = True finally: attempt += 1 if not r: sleep(self.WAIT_TIME_CAUCLIENT) LOG.info(self.TAG + 'CAU client Trigger Done in {} attempts and ok={}.'. format(attempt, r)) else: return if not CPARAMS.DEBUG_FLAG and self.cauclient_failed: LOG.critical(self.TAG + 'CAU-Client failed, interrupting agent start.') return # 5.1. VPN get IP attempt = 0 while self._connected and self.vpnIP is None and attempt < self.MAX_VPN_FAILURES: vpn_ip = VPN.getIPfromFile() self.vpnIP = vpn_ip if vpn_ip != '' else None if self.vpnIP is None: LOG.debug(self.TAG + 'VPN IP cannot be obtained... Retry in {}s'. format(self.WAIT_TIME_VPN)) sleep(self.WAIT_TIME_VPN) attempt += 1 if self.vpnIP is None: LOG.warning(self.TAG + 'VPN IP cannot be obtained.') if not CPARAMS.DEBUG_FLAG: LOG.critical( self.TAG + 'Policies module cannot continue its activity without VPN IP' ) exit(4) else: LOG.info(self.TAG + 'VPN IP: [{}]'.format(self.vpnIP)) # 5.2 If not static configuration and no leader detected, VPN configuration if self.deviceIP is None and self.leaderIP is None: LOG.debug( self.TAG + 'Static configuration for deviceIP and leaderIP not found. Using VPN values' ) self.deviceIP = self.vpnIP self.leaderIP = self.cloudIP LOG.info(self.TAG + 'deviceIP={}, leaderIP={}'.format( self.deviceIP, self.leaderIP)) # 6. Categorization if self._connected and not self.categorization_started: self.categorization_failed = True LOG.debug(self.TAG + 'Sending start trigger to Categorization...') try: self.__trigger_startCategorization() self.categorization_failed = False self.categorization_started = True except Exception: LOG.exception(self.TAG + 'Categorization failed') self.categorization_failed = True LOG.info(self.TAG + 'Categorization Start Trigger Done.') elif not self._connected: return if not CPARAMS.DEBUG_FLAG and self.categorization_failed: LOG.critical( self.TAG + 'Categorization failed, interrupting agent start.') return # 7. Area Resilience if self._connected and not self.arearesilience_started: self.policies_failed = True LOG.debug(self.TAG + 'Sending start trigger to Policies...') try: success = self.__trigger_startLeaderProtectionPolicies() self.policies_failed = not success self.arearesilience_started = success except Exception: LOG.exception(self.TAG + 'Policies Area Resilience failed!') LOG.info(self.TAG + 'Policies Area Resilience Start Trigger Done.') elif not self._connected: return if not CPARAMS.DEBUG_FLAG and self.policies_failed: LOG.critical( self.TAG + 'Policies Area Resilience failed, interrupting agent start.' ) return # Print summary self.__print_summary() # Create/Modify Agent Resource self.deviceIP = '' if self.deviceIP is None else self.deviceIP self._cimi_agent_resource = AgentResource(self.deviceID, self.deviceIP, self.isAuthenticated, self.secureConnection, self.imLeader) LOG.debug(self.TAG + 'CIMI Agent Resource payload: {}'.format( self._cimi_agent_resource.getCIMIdicc())) if self._cimi_agent_resource_id is None: # Create agent resource self._cimi_agent_resource_id = CIMI.createAgentResource( self._cimi_agent_resource.getCIMIdicc()) sleep(.1) self._cimi_agent_resource = AgentResource( self.deviceID, self.deviceIP, self.isAuthenticated, self.secureConnection, self.imLeader, leaderIP=self.leaderIP) LOG.debug(self.TAG + 'CIMI Agent Resource payload: {}'.format( self._cimi_agent_resource.getCIMIdicc())) status = CIMI.modify_resource( self._cimi_agent_resource_id, self._cimi_agent_resource.getCIMIdicc()) if self._cimi_agent_resource_id == '': LOG.warning(self.TAG + 'Agent resource creation failed.') if not CPARAMS.DEBUG_FLAG: LOG.error( 'Stopping Policies module due to resource creation failure.' ) exit(4) else: # Agent resource already exists status = CIMI.modify_resource( self._cimi_agent_resource_id, self._cimi_agent_resource.getCIMIdicc()) sleep(.1) self._cimi_agent_resource = AgentResource( self.deviceID, self.deviceIP, self.isAuthenticated, self.secureConnection, self.imLeader, leaderIP=self.leaderIP) LOG.debug(self.TAG + 'CIMI Agent Resource payload: {}'.format( self._cimi_agent_resource.getCIMIdicc())) status = CIMI.modify_resource( self._cimi_agent_resource_id, self._cimi_agent_resource.getCIMIdicc()) # 8. Watch Leader if self._connected and not self.discovery_failed: LOG.debug(self.TAG + 'Start Discovery Leader Watch...') try: self.__trigger_startDiscoveryWatch() except Exception: LOG.exception(self.TAG + 'Watch Discovery Start Fail.') LOG.info(self.TAG + 'Watch Discovery Start Trigger Done.') elif self.discovery_failed: LOG.warning( self.TAG + 'Discovery Watch cancelled due Discovery Trigger failed') else: return self.isCompleted = True alive = True while self._connected and not self.discovery_failed and alive: # 6 Check if discovery connection is alive LOG.debug(self.TAG + 'Discovery Alive Start Trigger.') try: alive = not self.__trigger_aliveDiscovery( ) # not disconnected except Exception: LOG.exception(self.TAG + 'Discovery Alive failed') alive = False if self._connected: sleep(CPARAMS.TIME_WAIT_ALIVE) LOG.info(self.TAG + 'Discovery Alive Start Trigger Done.') if not self._connected: return if CPARAMS.DEBUG_FLAG and self.discovery_failed: LOG.debug(self.TAG + 'No rescan available. Stoping activity') return
def __leader_switch_flow(self): """ Agent become leader :return: """ # 1. Start sending beacons if self._connected: self.discovery_leader_failed = True self.discovery_failed = True LOG.debug(self.TAG + 'Sending Broadcast trigger to discovery...') try: r = self.__trigger_switch_discovery() self.detectedLeaderID = self.deviceID self.discovery_leader_failed = not r except Exception as ex: LOG.exception(self.TAG + 'Discovery broadcast trigger failed!') self.detectedLeaderID = self.deviceID LOG.info(self.TAG + 'Discovery Broadcast Trigger Done.') else: return if not CPARAMS.DEBUG_FLAG and self.discovery_leader_failed: LOG.critical( self.TAG + 'Discovery broadcast failed, interrupting leader switch.') return self.discovery_failed = self.discovery_leader_failed # 2. Start CAU-client if self._connected: self.cauclient_failed = True LOG.debug(self.TAG + 'Sending trigger to CAU client...') attempt = 0 r = False while self._connected and not r and attempt < self.MAX_CAUCLIENT_FAILURES: try: r = self.__trigger_triggerCAUclient() self.cauclient_failed = not r except Exception: LOG.exception(self.TAG + 'CAUclient failed.') self.cauclient_failed = True finally: attempt += 1 if not r: sleep(self.WAIT_TIME_CAUCLIENT) LOG.info(self.TAG + 'CAU client Trigger Done in {} attempts and ok={}.'. format(attempt, r)) else: return if not CPARAMS.DEBUG_FLAG and self.cauclient_failed: LOG.critical(self.TAG + 'CAU-Client failed, interrupting agent start.') return # 3. VPN get IP attempt = 0 while self._connected and self.vpnIP is None and attempt < self.MAX_VPN_FAILURES: vpn_ip = VPN.getIPfromFile() self.vpnIP = vpn_ip if vpn_ip != '' else None if self.vpnIP is None: LOG.debug(self.TAG + 'VPN IP cannot be obtained... Retry in {}s'.format( self.WAIT_TIME_VPN)) sleep(self.WAIT_TIME_VPN) attempt += 1 if self.vpnIP is None: LOG.warning(self.TAG + 'VPN IP cannot be obtained.') if not CPARAMS.DEBUG_FLAG: LOG.critical( self.TAG + 'Policies module cannot continue its activity without VPN IP' ) exit(4) else: LOG.info(self.TAG + 'VPN IP: [{}]'.format(self.vpnIP)) # 4. Switch leader categorization (or start if not started) if self.categorization_started: self.categorization_leader_failed = True # Switch! LOG.debug(self.TAG + 'Sending switch trigger to Categorization...') try: self.__trigger_switch_categorization() self.categorization_leader_failed = False except Exception: LOG.exception(self.TAG + 'Categorization switch to leader failed') LOG.info(self.TAG + 'Categorization Switch Trigger Done.') else: # Start as leader! LOG.debug(self.TAG + 'Sending start trigger to Categorization...') try: self.__trigger_startCategorization() self.categorization_leader_failed = False self.categorization_started = True except Exception: LOG.exception(self.TAG + 'Categorization failed') LOG.info(self.TAG + 'Categorization Start Trigger Done.') if not CPARAMS.DEBUG_FLAG and self.categorization_leader_failed: LOG.critical(self.TAG + 'Categorization failed, interrupting leader switch.') return self.categorization_failed = self.categorization_leader_failed # 5. Start Area Resilience (if not started) if not self.arearesilience_started: self.policies_failed = True LOG.debug(self.TAG + 'Sending start trigger to Policies...') try: self.__trigger_startLeaderProtectionPolicies() self.policies_failed = False self.arearesilience_started = True except Exception: LOG.exception(self.TAG + 'Policies Area Resilience failed!') LOG.info(self.TAG + 'Policies Area Resilience Start Trigger Done.') if not CPARAMS.DEBUG_FLAG and self.policies_failed: LOG.critical( self.TAG + 'Policies Area Resilience failed, interrupting agent start.') return # 8. Watch Leader if self._connected and not self.discovery_failed: LOG.debug(self.TAG + 'Start Discovery Leader Watch...') try: self.__trigger_startDiscoveryWatchLeader() except Exception: LOG.exception(self.TAG + 'Watch Discovery Start Fail.') LOG.info(self.TAG + 'Watch Discovery Start Trigger Done.') elif self.discovery_failed: LOG.warning( self.TAG + 'Discovery Watch cancelled due Discovery Trigger failed') # Create/Modify Agent Resource # IF static IP configuration setup self.deviceIP = CPARAMS.DEVICE_IP_FLAG self.leaderIP = CPARAMS.LEADER_IP_FLAG if self.deviceIP is None or self.leaderIP is None: LOG.debug( self.TAG + 'No static configuration was detected. Applying VPN values') self.deviceIP = self.vpnIP self.leaderIP = self.cloudIP LOG.info( self.TAG + 'deviceIP={}, leaderIP={}'.format(self.deviceIP, self.leaderIP)) # Print summary self.__print_summary() self._cimi_agent_resource = AgentResource(self.deviceID, self.deviceIP, True, True, self.imLeader, leaderIP=self.leaderIP) # deprecated: real values of Auth and Conn (as now are None in the Leader) if self._cimi_agent_resource_id is None: # Create agent resource self._cimi_agent_resource_id = CIMI.createAgentResource( self._cimi_agent_resource.getCIMIdicc()) else: # Agent resource already exists status = CIMI.modify_resource( self._cimi_agent_resource_id, self._cimi_agent_resource.getCIMIdicc()) # 6. Finish self.isCompleted = True return
def __cloud_flow(self): LOG.info(self.TAG + 'Cloud flow started.') # 0. Cloud Agent is Leader by definition self.imLeader = self.imCloud # 1. Discovery LOG.debug(self.TAG + 'Discovery trigger ignored in Cloud flow.') self.discovery_failed = False self.discovery_leader_failed = False self.detectedLeaderID = self.deviceID # 2. Start CAU-client if self._connected: self.cauclient_failed = True LOG.debug(self.TAG + 'Sending trigger to CAU client...') attempt = 0 r = False while self._connected and not r and attempt < self.MAX_CAUCLIENT_FAILURES: try: r = self.__trigger_triggerCAUclient() self.cauclient_failed = not r except Exception: LOG.exception(self.TAG + 'CAUclient failed.') self.cauclient_failed = True finally: attempt += 1 if not r: sleep(self.WAIT_TIME_CAUCLIENT) LOG.info(self.TAG + 'CAU client Trigger Done in {} attempts and ok={}.'. format(attempt, r)) else: return if not CPARAMS.DEBUG_FLAG and self.cauclient_failed: LOG.critical(self.TAG + 'CAU-Client failed, interrupting agent start.') return # 3. VPN get IP attempt = 0 while self._connected and self.vpnIP is None and attempt < self.MAX_VPN_FAILURES: vpn_ip = VPN.getIPfromFile() self.vpnIP = vpn_ip if vpn_ip != '' else None if self.vpnIP is None: LOG.debug(self.TAG + 'VPN IP cannot be obtained... Retry in {}s'.format( self.WAIT_TIME_VPN)) sleep(self.WAIT_TIME_VPN) attempt += 1 if self.vpnIP is None: LOG.warning(self.TAG + 'VPN IP cannot be obtained.') if not CPARAMS.DEBUG_FLAG: LOG.critical( self.TAG + 'Policies module cannot continue its activity without VPN IP' ) exit(4) else: LOG.info(self.TAG + 'VPN IP: [{}]'.format(self.vpnIP)) # 4. Switch leader categorization (or start if not started) if self._connected and not self.categorization_started: self.categorization_failed = True LOG.debug(self.TAG + 'Sending start trigger to Categorization...') try: self.__trigger_startCategorization() self.categorization_failed = False self.categorization_started = True except Exception: LOG.exception(self.TAG + 'Categorization failed') self.categorization_failed = True LOG.info(self.TAG + 'Categorization Start Trigger Done.') elif not self._connected: return if not CPARAMS.DEBUG_FLAG and self.categorization_failed: LOG.critical(self.TAG + 'Categorization failed, interrupting agent start.') return # 5. Area Resilience LOG.debug(self.TAG + 'Area Resilience trigger ignored in Cloud flow.') self.policies_failed = False # Print summary self.__print_summary() # Create Agent Resource self.deviceIP = self.vpnIP self.leaderIP = None self._cimi_agent_resource = AgentResource(self.deviceID, self.deviceIP, True, True, self.imLeader) LOG.debug(self.TAG + 'CIMI Agent Resource payload: {}'.format( self._cimi_agent_resource.getCIMIdicc())) if self._cimi_agent_resource_id is None: # Create agent resource self._cimi_agent_resource_id = CIMI.createAgentResource( self._cimi_agent_resource.getCIMIdicc()) if self._cimi_agent_resource_id == '': LOG.warning(self.TAG + 'Agent resource creation failed.') if not CPARAMS.DEBUG_FLAG: LOG.error( 'Stopping Policies module due to resource creation failure.' ) exit(4) else: # Agent resource already exists status = CIMI.modify_resource( self._cimi_agent_resource_id, self._cimi_agent_resource.getCIMIdicc()) self.isCompleted = True return
def __leader_switch_flow(self): """ Agent become leader :return: """ # 1. Start sending beacons if self._connected: self.discovery_leader_failed = True LOG.debug(self.TAG + 'Sending Broadcast trigger to discovery...') try: self.__trigger_switch_discovery( ) # TODO: Send deviceID when broadcasting self.detectedLeaderID = self.deviceID self.discovery_leader_failed = False except Exception as ex: LOG.exception(self.TAG + 'Discovery broadcast trigger failed!') LOG.info(self.TAG + 'Discovery Broadcast Trigger Done.') else: return if not CPARAMS.DEBUG_FLAG and self.discovery_leader_failed: LOG.critical( self.TAG + 'Discovery broadcast failed, interrupting leader switch.') return # 2. Start LeaderCAU (Not implemented) pass # TODO: Review this in IT-2 # 3. Switch leader categorization (or start if not started) if self.categorization_started: self.categorization_leader_failed = True # Switch! LOG.debug(self.TAG + 'Sending switch trigger to Categorization...') try: self.__trigger_switch_categorization() self.categorization_leader_failed = False except Exception: LOG.exception(self.TAG + 'Categorization switch to leader failed') LOG.info(self.TAG + 'Categorization Switch Trigger Done.') else: # Start as leader! LOG.debug(self.TAG + 'Sending start trigger to Categorization...') try: self.__trigger_startCategorization() self.categorization_leader_failed = False self.categorization_started = True except Exception: LOG.exception(self.TAG + 'Categorization failed') LOG.info(self.TAG + 'Categorization Start Trigger Done.') if not CPARAMS.DEBUG_FLAG and self.categorization_leader_failed: LOG.critical(self.TAG + 'Categorization failed, interrupting leader switch.') return # 4. Start Area Resilience (if not started) if not self.arearesilience_started: self.policies_failed = True LOG.debug(self.TAG + 'Sending start trigger to Policies...') try: self.__trigger_startLeaderProtectionPolicies() self.policies_failed = False self.arearesilience_started = True except Exception: LOG.exception(self.TAG + 'Policies Area Resilience failed!') LOG.info(self.TAG + 'Policies Area Resilience Start Trigger Done.') if not CPARAMS.DEBUG_FLAG and self.policies_failed: LOG.critical( self.TAG + 'Policies Area Resilience failed, interrupting agent start.') return # Create/Modify Agent Resource # TODO. self.deviceIP = '' # TODO: Real value here (from categorization) self._cimi_agent_resource = AgentResource(self.deviceID, self.deviceIP, self.isAuthenticated, self.secureConnection, self.imLeader, leaderIP=self.leaderIP) if self._cimi_agent_resource_id is None: # Create agent resource self._cimi_agent_resource_id = CIMI.createAgentResource( self._cimi_agent_resource.getCIMIdicc()) else: # Agent resource already exists status = CIMI.modify_resource( self._cimi_agent_resource_id, self._cimi_agent_resource.getCIMIdicc()) # 5. Finish return # TODO: Return something?