Revision 85b6ed25

View differences:

include/RaftHook.h
1
/* -------------------------------------------------------------------------- */
2
/* Copyright 2002-2016, OpenNebula Project, OpenNebula Systems                */
3
/*                                                                            */
4
/* Licensed under the Apache License, Version 2.0 (the "License"); you may    */
5
/* not use this file except in compliance with the License. You may obtain    */
6
/* a copy of the License at                                                   */
7
/*                                                                            */
8
/* http://www.apache.org/licenses/LICENSE-2.0                                 */
9
/*                                                                            */
10
/* Unless required by applicable law or agreed to in writing, software        */
11
/* distributed under the License is distributed on an "AS IS" BASIS,          */
12
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   */
13
/* See the License for the specific language governing permissions and        */
14
/* limitations under the License.                                             */
15
/* -------------------------------------------------------------------------- */
16

  
17
#ifndef RAFT_HOOK_H_
18
#define RAFT_HOOK_H_
19

  
20
#include <string>
21

  
22
#include "Hook.h"
23

  
24
class RaftHook : public Hook
25
{
26
public:
27
    RaftHook(const std::string& name,
28
             const std::string& command):
29
        Hook(name, command, "", Hook::UPDATE, false){};
30

  
31
    ~RaftHook(){};
32

  
33
    void do_hook(void *arg);
34
};
35

  
36
class RaftLeaderHook : public RaftHook
37
{
38
public:
39
    RaftLeaderHook(const std::string& command):
40
        RaftHook("RAFT_LEADER_HOOK", command){};
41

  
42
    ~RaftLeaderHook(){};
43
};
44

  
45
class RaftFollowerHook : public RaftHook
46
{
47
public:
48
    RaftFollowerHook(const std::string& command):
49
        RaftHook("RAFT_FOLLOWER_HOOK", command){};
50

  
51
    ~RaftFollowerHook(){};
52
};
53

  
54
#endif
include/RaftManager.h
21 21
#include "ReplicaManager.h"
22 22
#include "ReplicaRequest.h"
23 23
#include "Template.h"
24
#include "RaftHook.h"
24 25

  
25 26
extern "C" void * raft_manager_loop(void *arg);
26 27

  
......
43 44
    /**
44 45
     * Raft manager constructor
45 46
     *   @param server_id of this server
47
     *   @param leader_hook_mad to be executed when follower->leader
48
     *   @param follower_hook_mad to be executed when leader->follower
46 49
     *   @param log_purge period to purge logDB records
47 50
     *   @param bcast heartbeat broadcast timeout
48 51
     *   @param election timeout
49 52
     *   @param xmlrpc timeout for RAFT related xmlrpc API calls
50 53
     **/
51
    RaftManager(int server_id, time_t log_purge, long long bcast,
52
            long long election, time_t xmlrpc);
54
    RaftManager(int server_id, const VectorAttribute * leader_hook_mad,
55
        const VectorAttribute * follower_hook_mad, time_t log_purge,
56
        long long bcast, long long election, time_t xmlrpc,
57
        const string& remotes_location);
53 58

  
54
    virtual ~RaftManager(){};
59
    ~RaftManager()
60
    {
61
        if ( leader_hook != 0 )
62
        {
63
            delete(leader_hook);
64
        }
65

  
66
        if ( follower_hook != 0 )
67
        {
68
            delete(follower_hook);
69
        }
70
    };
55 71

  
56 72
    // -------------------------------------------------------------------------
57 73
    // Raft associated actions (synchronous)
......
366 382
    std::map<int, std::string>  servers;
367 383

  
368 384
    // -------------------------------------------------------------------------
385
    // Hooks
386
    // -------------------------------------------------------------------------
387

  
388
    RaftLeaderHook   * leader_hook;
389
    RaftFollowerHook * follower_hook;
390

  
391
    // -------------------------------------------------------------------------
369 392
    // Action Listener interface
370 393
    // -------------------------------------------------------------------------
371 394
    /**
share/etc/oned.conf
108 108
#       MASTER     this oned is the master zone of the federation
109 109
#       SLAVE      this oned is a slave zone
110 110
#   ZONE_ID: The zone ID as returned by onezone command
111
#   SERVER_ID: ID identifying this server in the zone as returned by the 
112
#   onezone server-add command. This ID controls the HA configuration of 
111
#   SERVER_ID: ID identifying this server in the zone as returned by the
112
#   onezone server-add command. This ID controls the HA configuration of
113 113
#   OpenNebula:
114 114
#     -1 (default) OpenNebula will operate in "solo" mode no HA
115 115
#     <id> Operate in HA (leader election and state replication)
......
120 120
#   RAFT: Algorithm attributes
121 121
#     LOG_RETENTION: Number of DB log records kept, it determines the
122 122
#     synchronization window across servers and extra storage space needed.
123
#     LOG_PURGE_TIMEOUT: How often applied records are purged according the log 
123
#     LOG_PURGE_TIMEOUT: How often applied records are purged according the log
124 124
#     retention value. (in seconds)
125
#     ELECTION_TIMEOUT_MS: Timeout to start a election process if no hearbeat or 
125
#     ELECTION_TIMEOUT_MS: Timeout to start a election process if no hearbeat or
126 126
#     log is received from leader.
127 127
#     BROADCAST_TIMEOUT_MS: How often heartbeats are sent to  followers.
128 128
#     XMLRPC_TIMEOUT_MS: To timeout raft related API calls
......
141 141
]
142 142

  
143 143
RAFT = [
144
    LOG_RETENTION        = 500000, 
144
    LOG_RETENTION        = 500000,
145 145
    LOG_PURGE_TIMEOUT    = 600,
146 146
    ELECTION_TIMEOUT_MS  = 1500,
147 147
    BROADCAST_TIMEOUT_MS = 500,
148 148
    XMLRPC_TIMEOUT_MS    = 100
149
] 
149
]
150 150

  
151 151
#*******************************************************************************
152 152
# Default showback cost
......
278 278
#  DEFAULT_CDROM_DEVICE_PREFIX: Same as above but for CDROM devices.
279 279
#
280 280
#  DEFAULT_IMAGE_PERSISTENT: Control the default value for the PERSISTENT
281
#  attribute on image creation (oneimage clone, onevm disk-saveas). If blank 
281
#  attribute on image creation (oneimage clone, onevm disk-saveas). If blank
282 282
#  images will inherit the persistent attribute from the base image.
283 283
#
284
#  DEFAULT_IMAGE_PERSISTENT_NEW: Control the default value for the PERSISTENT 
284
#  DEFAULT_IMAGE_PERSISTENT_NEW: Control the default value for the PERSISTENT
285 285
#  attribute on image creation (oneimage create). By default images are no
286 286
#  persistent if not set.
287 287
#*******************************************************************************
......
742 742
# Please note: In a Federation, User and Group hooks can only be defined in
743 743
# the master OpenNebula.
744 744
#-------------------------------------------------------------------------------
745

  
746
# Executed when a server transit from follower->leader
747
RAFT_LEADER_HOOK = [
748
    COMMAND   = "raft/leader.sh"
749
]
750

  
751
# Executed when a server transit from leader->follower
752
RAFT_FOLLOWER_HOOK = [
753
    COMMAND   = "raft/follower.sh"
754
]
755

  
745 756
HM_MAD = [
746 757
    EXECUTABLE = "one_hm" ]
747 758

  
......
844 855

  
845 856
VM_ADMIN_OPERATIONS  = "migrate, delete, recover, retry, deploy, resched"
846 857

  
847
VM_MANAGE_OPERATIONS = "undeploy, hold, release, stop, suspend, resume, reboot, 
848
    poweroff, disk-attach, nic-attach, disk-snapshot, terminate, disk-resize, 
858
VM_MANAGE_OPERATIONS = "undeploy, hold, release, stop, suspend, resume, reboot,
859
    poweroff, disk-attach, nic-attach, disk-snapshot, terminate, disk-resize,
849 860
    snapshot, updateconf, rename, resize, update, disk-saveas"
850 861

  
851 862
VM_USE_OPERATIONS    = ""
src/nebula/Nebula.cc
669 669
    }
670 670

  
671 671
    // ---- Raft Manager ----
672

  
673
    const VectorAttribute * raft_leader_hook;
674
    const VectorAttribute * raft_follower_hook;
675

  
676
    raft_leader_hook   = nebula_configuration->get("RAFT_LEADER_HOOK");
677
    raft_follower_hook = nebula_configuration->get("RAFT_FOLLOWER_HOOK");
678

  
672 679
    try
673 680
    {
674
        raftm = new RaftManager(server_id, log_purge, bcast_ms, election_ms,
675
                xmlrpc_ms);
681
        raftm = new RaftManager(server_id, raft_leader_hook, raft_follower_hook,
682
                log_purge, bcast_ms, election_ms, xmlrpc_ms, remotes_location);
676 683
    }
677 684
    catch (bad_alloc&)
678 685
    {
src/raft/RaftHook.cc
1
/* -------------------------------------------------------------------------- */
2
/* Copyright 2002-2016, OpenNebula Project, OpenNebula Systems                */
3
/*                                                                            */
4
/* Licensed under the Apache License, Version 2.0 (the "License"); you may    */
5
/* not use this file except in compliance with the License. You may obtain    */
6
/* a copy of the License at                                                   */
7
/*                                                                            */
8
/* http://www.apache.org/licenses/LICENSE-2.0                                 */
9
/*                                                                            */
10
/* Unless required by applicable law or agreed to in writing, software        */
11
/* distributed under the License is distributed on an "AS IS" BASIS,          */
12
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   */
13
/* See the License for the specific language governing permissions and        */
14
/* limitations under the License.                                             */
15
/* -------------------------------------------------------------------------- */
16

  
17
#include "RaftHook.h"
18
#include "Nebula.h"
19

  
20
// -----------------------------------------------------------------------------
21
// -----------------------------------------------------------------------------
22

  
23
void RaftHook::do_hook(void *arg)
24
{
25
    Nebula& ne                    = Nebula::instance();
26
    HookManager * hm              = ne.get_hm();
27
    const HookManagerDriver * hmd = hm->get();
28

  
29
    if ( hmd != 0 )
30
    {
31
        hmd->execute(-1, name, cmd, "");
32
    }
33
}
src/raft/RaftManager.cc
44 44
/* -------------------------------------------------------------------------- */
45 45
/* -------------------------------------------------------------------------- */
46 46

  
47
RaftManager::RaftManager(int id, time_t log_purge, long long bcast,
48
        long long elect, time_t xmlrpc):server_id(id), term(0), num_servers(0),
49
	commit(0)
47
RaftManager::RaftManager(int id, const VectorAttribute * leader_hook_mad,
48
        const VectorAttribute * follower_hook_mad, time_t log_purge,
49
        long long bcast, long long elect, time_t xmlrpc,
50
        const string& remotes_location):server_id(id), term(0), num_servers(0),
51
        commit(0),leader_hook(0),follower_hook(0)
50 52
{
51 53
    Nebula& nd    = Nebula::instance();
52 54
    LogDB * logdb = nd.get_logdb();
53 55

  
54
    std::string raft_xml;
56
    std::string raft_xml, cmd;
55 57

  
56 58
	pthread_mutex_init(&mutex, 0);
57 59

  
......
64 66
    //   - votedfor
65 67
    //   - term
66 68
    // -------------------------------------------------------------------------
69

  
67 70
    if ( logdb->get_raft_state(raft_xml) != 0 )
68 71
    {
69 72
        raft_state.replace("TERM", 0);
......
102 105
    // -------------------------------------------------------------------------
103 106
    // Initialize Raft timers
104 107
    // -------------------------------------------------------------------------
108

  
105 109
    purge_period_ms   = log_purge * 1000;
106 110
    xmlrpc_timeout_ms = xmlrpc;
107 111

  
......
109 113
    set_timeout(elect, election_timeout);
110 114

  
111 115
    // 5 seconds warm-up to start election
112
	clock_gettime(CLOCK_REALTIME, &last_heartbeat);
113
	last_heartbeat.tv_sec += 5;
116
    clock_gettime(CLOCK_REALTIME, &last_heartbeat);
117
    last_heartbeat.tv_sec += 5;
118

  
119
    // -------------------------------------------------------------------------
120
    // Initialize Hooks
121
    // -------------------------------------------------------------------------
122

  
123
    if ( leader_hook_mad != 0 )
124
    {
125
        cmd = leader_hook_mad->vector_value("COMMAND");
126

  
127
        if ( cmd.empty() )
128
        {
129
            ostringstream oss;
130

  
131
            oss << "Empty COMMAND attribute in RAFT_LEADER_HOOK. Hook "
132
                << "not registered!";
133

  
134
            NebulaLog::log("ONE", Log::WARNING, oss);
135
        }
136
        else
137
        {
138
            if (cmd[0] != '/')
139
            {
140
                ostringstream cmd_os;
141
                cmd_os << remotes_location << "/hooks/" << cmd;
142
                cmd = cmd_os.str();
143
            }
144

  
145
            leader_hook = new RaftLeaderHook(cmd);
146
        }
147
    }
148

  
149
    if ( follower_hook_mad != 0 )
150
    {
151
        cmd = follower_hook_mad->vector_value("COMMAND");
152

  
153
        if ( cmd.empty() )
154
        {
155
            ostringstream oss;
156

  
157
            oss << "Empty COMMAND attribute in RAFT_FOLLOWER_HOOK. Hook "
158
                << "not registered!";
159

  
160
            NebulaLog::log("ONE", Log::WARNING, oss);
161
        }
162
        else
163
        {
164
            if (cmd[0] != '/')
165
            {
166
                ostringstream cmd_os;
167
                cmd_os << remotes_location << "/hooks/" << cmd;
168
                cmd = cmd_os.str();
169
            }
170

  
171
            follower_hook = new RaftFollowerHook(cmd);
172
        }
173
    }
114 174
};
115 175

  
116 176
/* -------------------------------------------------------------------------- */
......
311 371

  
312 372
    requests.clear();
313 373

  
374
    leader_hook->do_hook(0);
375

  
314 376
    state = LEADER;
315 377

  
316 378
    commit   = _applied;
......
363 425

  
364 426
    pthread_mutex_lock(&mutex);
365 427

  
428
    if ( state == LEADER )
429
    {
430
        follower_hook->do_hook(0);
431
    }
432

  
366 433
    replica_manager.stop_replica_threads();
367 434

  
368 435
    state = FOLLOWER;
src/raft/SConstruct
25 25
    'RaftManager.cc',
26 26
    'ReplicaManager.cc',
27 27
    'ReplicaThread.cc',
28
    'FedReplicaManager.cc'
28
    'FedReplicaManager.cc',
29
    'RaftHook.cc'
29 30
]
30 31

  
31 32
# Build library

Also available in: Unified diff