'Registers new agent in the database or updates existing.
Returns tuple of agent status and state.
Status is from server point of view: alive, new or revived.
It could be used by agent to do some sync with the server if needed.'

@db_api.retry_if_session_inactive()
def create_or_update_agent(self, context, agent_state):

    status = n_const.AGENT_ALIVE
    with context.session.begin(subtransactions=True):
        res_keys = ['agent_type', 'binary', 'host', 'topic']
        res = dict(((k, agent_state[k]) for k in res_keys))
        if ('availability_zone' in agent_state):
            res['availability_zone'] = agent_state['availability_zone']
        configurations_dict = agent_state.get('configurations', {})
        res['configurations'] = jsonutils.dumps(configurations_dict)
        resource_versions_dict = agent_state.get('resource_versions')
        if resource_versions_dict:
            res['resource_versions'] = jsonutils.dumps(resource_versions_dict)
        res['load'] = self._get_agent_load(agent_state)
        current_time = timeutils.utcnow()
        try:
            agent_db = self._get_agent_by_type_and_host(context, agent_state['agent_type'], agent_state['host'])
            if (not agent_db.is_active):
                status = n_const.AGENT_REVIVED
                if ('resource_versions' not in agent_state):
                    agent_state['resource_versions'] = self._get_dict(agent_db, 'resource_versions', ignore_missing=True)
            res['heartbeat_timestamp'] = current_time
            if agent_state.get('start_flag'):
                res['started_at'] = current_time
            greenthread.sleep(0)
            self._log_heartbeat(agent_state, agent_db, configurations_dict)
            agent_db.update(res)
            event_type = events.AFTER_UPDATE
        except ext_agent.AgentNotFoundByTypeHost:
            greenthread.sleep(0)
            res['created_at'] = current_time
            res['started_at'] = current_time
            res['heartbeat_timestamp'] = current_time
            res['admin_state_up'] = cfg.CONF.enable_new_agents
            agent_db = agent_model.Agent(**res)
            greenthread.sleep(0)
            context.session.add(agent_db)
            event_type = events.AFTER_CREATE
            self._log_heartbeat(agent_state, agent_db, configurations_dict)
            status = n_const.AGENT_NEW
        greenthread.sleep(0)
    registry.notify(resources.AGENT, event_type, self, context=context, host=agent_state['host'], plugin=self, agent=agent_state)
    return (status, agent_state)
