コード例 #1
0
 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 ''
コード例 #2
0
ファイル: main.py プロジェクト: mF2C/ResourceManagement
    def post(self):
        """Reelection of the Leader"""
        found = False
        deviceIP = ''
        deviceID = api.payload['deviceID']
        for device in cimi('topology', default=[]):  # TODO: use real topology
            if device.get('deviceID') == deviceID:
                found = True
                deviceIP = device.get('deviceIP')
                break

        if not found:
            LOG.error('Device {} not found in the topology'.format(deviceID))
            return {'deviceID': deviceID, 'deviceIP': deviceIP}, 404
        if not arearesilience.imLeader():
            LOG.error(
                'Device is not a Leader, cannot perform a reelection in a non-leader device.'
            )
            return {'deviceID': deviceID, 'deviceIP': deviceIP}, 401

        correct = LeaderReelection.reelection(arearesilience, deviceID,
                                              deviceIP)
        if correct:
            return {'deviceID': deviceID, 'deviceIP': deviceIP}, 200
        else:
            return {'deviceID': deviceID, 'deviceIP': deviceIP}, 403
コード例 #3
0
ファイル: agentstart.py プロジェクト: mF2C/ResourceManagement
    def switch(self, imLeader):
        if not self.isStarted:
            LOG.error('Agent is not started!')
            return False

        if self.th_proc.is_alive():
            LOG.debug(
                self.TAG +
                'Stopping thread {} to switch...'.format(self.th_proc.name))
            self._connected = False
            self.th_proc.join()
        LOG.debug('Thread successfully stopped.')
        self._connected = True

        if self.imLeader != imLeader:
            LOG.warning(
                'imLeader state is not consequent!')  # TODO: Action required

        if self.imLeader:
            # Switch to Agent
            LOG.info(self.TAG + 'Switch to Agent')
            self.imLeader = False
            self.th_proc = threading.Thread(name='fcjp_agent',
                                            target=self.__agent_switch_flow,
                                            daemon=True)
        else:
            # Switch to Leader
            LOG.info(self.TAG + 'Switch to Leader')
            # TODO: Create a thread if we don't want blocking feature (AR wait until leader is set - slow)
            self.imLeader = True
            self.th_proc = threading.Thread(name='fcjp_leader',
                                            target=self.__leader_switch_flow,
                                            daemon=True)
        self.th_proc.start()
        return True
コード例 #4
0
    def reelection(arearesilience, deviceID, deviceIP):
        # 0. Check if is not a backup
        backups = arearesilience.getBackupDatabase()
        LOG.debug('Backup database query: {}'.format(backups))
        found = False
        for backup in backups:
            if backup.deviceID == deviceID:
                found = True
                break

        # If backup: Go to step # 2
        if not found:
            LOG.debug('Device {} is not an active backup.'.format(deviceID))
            # 1. Promote device to Backup
            # Ok? Go to 3, return False otherwise
            ok = arearesilience.addBackup(
                deviceID, deviceIP, arearesilience.PRIORITY_ON_REELECTION)
            if not ok:
                LOG.error(
                    'Proposed device cannot be promoted to backup for reelection'
                )
                return False
        else:
            LOG.info('Device {} is an active backup.'.format(deviceID))
            # 2. Change preference to 0
            backup.priority = arearesilience.PRIORITY_ON_REELECTION

        # 3. Demote other backups (if any)
        backups = arearesilience.getBackupDatabase()
        for backup in backups:
            if backup.deviceID != deviceID:
                # Delete
                ok = arearesilience.deleteBackup(backup.deviceID)
                if ok:
                    LOG.info(
                        'Backup {}[{}] demoted successfully due Leader Reelection.'
                        .format(backup.deviceID, backup.deviceIP))
                else:
                    LOG.error(
                        'Error on Backup deletion {}[{}] in Leader Reelection.'
                        .format(backup.deviceID, backup.deviceIP))

        # 4. Demote leader (rest call self)
        r = requests.get('{}agent'.format(
            URLS.build_url_address(URLS.URL_POLICIES_ROLECHANGE,
                                   portaddr=('127.0.0.1',
                                             CPARAMS.POLICIES_PORT))))
        if r.status_code == 200:
            # Correct
            LOG.info('Leader (self) demoted successfully')
            return True
        LOG.warning('Leader not demoted or confirmation not received')
        return False
コード例 #5
0
    def __backupLeader_flow(self):
        if not self._connected:
            LOG.error('Module stoped due _connected = False')
            return

        if not self._imLeader:
            # I've been promoted as backup
            LOG.info(self.TAG + 'I\'m selected to be a backup. Seting up')
            self.__preBackupSetup()
            self.__becomeBackup()

        if not self._connected:
            return

        # Multiple backups support
        if self._backupPriority > 0:
            sleep_time = 1. + 10 * (self._backupPriority - 1)
            LOG.info(
                'Waiting {}s before leader takeover...'.format(sleep_time))
            sleep(sleep_time)
            if not self._connected:
                return
            LOG.debug('Checking if new Leader is up...')
            new_leader = self.__getCIMIData('disc_leaderIP', default='')
            LOG.debug('Stored Leader = [{}], Detected Leader = [{}]'.format(
                self._leaderIP, new_leader))
            if new_leader == '' or new_leader == self._leaderIP:
                LOG.warning('Leader not detected by Discovery')
            elif self._leaderIP != new_leader:
                LOG.info(
                    'Correct Leader takeover by a backup with more preference.'
                )
                try:  # TODO: Clean solution
                    r = requests.get('{}agent'.format(
                        URLS.build_url_address(URLS.URL_POLICIES_ROLECHANGE,
                                               addr='127.0.0.1',
                                               port=CPARAMS.POLICIES_PORT)),
                                     timeout=.5)
                except:
                    pass
                finally:
                    return

        if not self._connected:
            return

        if self._imLeader or self._leaderFailed:
            # I'm a leader
            LOG.info(self.TAG + 'Leader seting up')
            self.__becomeLeader()
            self.__backupSelection()
        return
コード例 #6
0
ファイル: agentstart.py プロジェクト: mF2C/ResourceManagement
 def __trigger_startScan(self):
     r = requests.get(self.URL_DISCOVERY)
     rjson = r.json()
     if 'found_leaders' in rjson and 'used_mac' in rjson and len(
             rjson['found_leaders']) > 0:
         self.detectedLeaderID, self.MACaddr, self.bssid = rjson[
             'found_leaders'][0]['Leader ID'], rjson['used_mac'], rjson[
                 'found_leaders'][0]['Bssid']
     else:
         LOG.error(
             self.TAG +
             'Discovery is not detecting a Leader \'{}\''.format(rjson))
         self.detectedLeaderID, self.MACaddr, self.bssid = None, None, None
コード例 #7
0
ファイル: main.py プロジェクト: mF2C/ResourceManagement
def initialization():
    global arearesilience, agentstart
    # 0. Waitting time
    LOG.info('INIT: Wait {:.2f}s to start'.format(CPARAMS.TIME_WAIT_INIT))
    sleep(CPARAMS.TIME_WAIT_INIT)
    LOG.debug('INIT: Wake Me up Before You Go-Go ♫')

    # 1. Area Resilience Module Creation
    LOG.debug('Area Resilience submodule creation')
    arearesilience = AreaResilience(cimi)
    LOG.debug('Area Resilience created')

    # 2. Leader Reelection Module Creation (None)

    # 3.1 Discovery IP adquisition
    result = subprocess.run(['/bin/ip', 'route'], stdout=subprocess.PIPE)
    route_ip = bytes(result.stdout).decode()
    route_ip_l = route_ip.split('\n')
    server_ip = ''
    if len(route_ip_l) > 0:
        for line in route_ip_l:
            if 'default' in line:
                server_ip = line.split(' ')[2]
                break
    if server_ip == '':
        LOG.error('Discovery IP cannot be received. Stopping.')
        exit(4)

    # 3. Agent Start Module Creation
    LOG.debug('Agent Start submodule creation')
    if CPARAMS.MF2C_FLAG:
        agentstart = AgentStart(addr_pol=('127.0.0.1', '46050'),
                                addr_dis=('{}'.format(server_ip), '46040'),
                                addr_cat=('resource-categorization', '46070'),
                                addr_id=('identification', '46060'))
    else:
        agentstart = AgentStart(addr_pol=('127.0.0.1', '46050'))
    if CPARAMS.LEADER_IP_FLAG is not None and len(CPARAMS.LEADER_IP_FLAG) != 0:
        agentstart.leaderIP = CPARAMS.LEADER_IP_FLAG
    LOG.debug('Agent Start created')

    return
コード例 #8
0
    def __backupLeader_flow(self):
        if not self._connected:
            LOG.error('Module stoped due _connected = False')
            return

        if not self._imLeader:
            # I've been promoted as backup
            LOG.info(self.TAG + 'I\'m selected to be a backup. Seting up')
            self.__preBackupSetup()
            self.__becomeBackup()

        if not self._connected:
            return

        if self._imLeader or self._leaderFailed:
            # I'm a leader
            LOG.info(self.TAG + 'Leader seting up')
            self.__becomeLeader()
            self.__backupSelection()
        return
コード例 #9
0
 def promotedToBackup(self, leaderIP):
     """
     The agent is promoted to be a backup
     :return:
     """
     # First check if Agent was electable
     self._leaderIP = leaderIP
     if self._imCapable:
         LOG.info(self.TAG + 'Becoming backup due leader selection.')
         # Then, check if AreaResilience thread is running
         if self.th_proc is None:
             pass
         elif not self.th_proc.is_alive():
             pass
         elif self._imLeader or self._imBackup:
             LOG.error(
                 'Agent is already a Backup/Leader. Cannot become a Backup.'
             )
             return False
         else:
             LOG.warning(
                 'Area Resilience still starting. Cannot promote on this state. Waiting...'
             )
             while self.th_proc.is_alive():
                 sleep(0.1)
             LOG.debug('Successful waiting.')
         LOG.debug('Module is ready for promotion.')
         self.th_proc = threading.Thread(name='area_res',
                                         target=self.__backupLeader_flow,
                                         daemon=True)
         self.th_proc.start()
         self.isStarted = True
         return True
     else:
         if not self._startupCorrect:
             LOG.warning(
                 'Area Resilience still starting. Cannot promote on this state.'
             )
         else:
             LOG.error('Agent not capable to be Backup/Leader')
         return False
コード例 #10
0
ファイル: CIMI.py プロジェクト: mF2C/recommender-test
    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 ''
コード例 #11
0
ファイル: agentstart.py プロジェクト: mF2C/ResourceManagement
 def __trigger_joinDiscovery(self):
     payload = {'interface': CPARAMS.WIFI_DEV_FLAG, 'bssid': self.bssid}
     try:
         r = requests.post(self.URL_DISCOVERY_JOIN,
                           json=payload,
                           timeout=20.)
     except (timeout, timeout2):
         LOG.error(self.TAG + 'JOIN trigger timeout.')
         return False
     rjson = r.json()
     if r.status_code != 200:
         LOG.warning(self.TAG +
                     'JOIN operation failed. Reply from discovery: {}'.
                     format(rjson['message']))
         return False
     else:
         LOG.debug(self.TAG + 'Sending MYIP trigger to Discovery...')
         try:
             r2 = requests.get(self.URL_DISCOVERY_MYIP, timeout=20.)
         except (timeout, timeout2):
             LOG.error(self.TAG + 'MYIP trigger timeout.')
             return False
         rjson2 = r2.json()
         if r2.status_code != 200:
             LOG.warning(self.TAG +
                         'MYIP operation failed. Reply from discovery: {}'.
                         format(rjson2))
             return False
         elif 'IP_address' not in rjson2 or rjson2[
                 'IP_address'] is None or len(rjson2['IP_address']) == 0:
             LOG.error(
                 self.TAG +
                 'MYIP operation returned an OK code BUT IP_address is empty! json: {}'
                 .format(rjson2))
             return False
         LOG.debug(self.TAG +
                   'MYIP trigger success. Reply form Discovery: {}'.format(
                       rjson2['IP_address']))
         self.deviceIP = rjson2['IP_address']
         return True
コード例 #12
0
    def __becomeBackup(self):
        """

        :return:
        """
        # 1- Send the KeepAlive message to the leader.
        # 2- Receive the reply (with preference number).
        # If leader down, Backup becomes leader.
        # Else repeat.

        attempt = 0
        counter = 0
        payload = {'deviceID': self._deviceID}
        self._imBackup = True
        while self._connected and attempt < self._lpp.get(
                self._lpp.MAX_RETRY_ATTEMPTS):
            stopLoop = False
            while self._connected and not stopLoop:
                try:
                    # 1. Requests to Leader Keepalive endpoint
                    r = requests.post(URLS.build_url_address(
                        URLS.URL_POLICIES_KEEPALIVE,
                        portaddr=(self._leaderIP, CPARAMS.POLICIES_PORT)),
                                      json=payload,
                                      timeout=0.5)
                    LOG.debug(self.TAG +
                              'Keepalive sent [#{}]'.format(counter))
                    # 2. Process Reply
                    jreply = r.json()
                    if r.status_code == 200:
                        leaderID = jreply['deviceID']  # Todo: Use this
                        priority = jreply['backupPriority']
                        # 3. Update Preference
                        self._backupPriority = priority
                        LOG.debug(
                            self.TAG +
                            'Reply received, Leader still alive: LeaderID: {}'.
                            format(leaderID))
                        attempt = 0
                    else:
                        # Error?
                        LOG.error('KeepAlive status_code = {}'.format(
                            r.status_code))
                        if r.status_code == 403 and self.PRIORITY_ON_DEMOTION == jreply[
                                'backupPriority']:
                            LOG.warning(
                                'Backup has been removed from database or not authorized to send keepalive messages'
                            )
                        elif r.status_code == 405 and self.PRIORITY_ON_FAILURE == jreply[
                                'backupPriority']:
                            LOG.warning(
                                'Sending message to a Device that is not a Leader!'
                            )
                            stopLoop = True
                        else:
                            stopLoop = True

                    if not stopLoop:
                        # 4. Sleep
                        sleep(self._lpp.get(self._lpp.TIME_KEEPALIVE))
                    counter += 1
                except:
                    # Connection broke, backup assumes that Leader is down.
                    LOG.debug('Keepalive connection refused')
                    stopLoop = True
            LOG.warning(
                'Keepalive connection is broken... Retry Attempts: {}'.format(
                    self._lpp.get(self._lpp.MAX_RETRY_ATTEMPTS) -
                    (attempt + 1)))
            attempt += 1

        if not self._connected:
            LOG.info('Backup stopped.')
        else:
            LOG.warning(self.TAG + '## LEADER IS DOWN! ##')
        self._leaderFailed = True
        return
コード例 #13
0
ファイル: agentstart.py プロジェクト: mF2C/ResourceManagement
    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
コード例 #14
0
ファイル: agentstart.py プロジェクト: mF2C/ResourceManagement
    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