/
instance_manager.h
249 lines (201 loc) · 6.63 KB
/
instance_manager.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
/*
* Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
*/
#ifndef __AGENT_OPER_INSTANCE_MANAGER_H__
#define __AGENT_OPER_INSTANCE_MANAGER_H__
#include <boost/uuid/uuid.hpp>
#include "cmn/agent_signal.h"
#include "db/db_table.h"
#include "oper/service_instance.h"
#include "oper/instance_manager_adapter.h"
class Agent;
class DB;
class LoadbalancerHaproxy;
class InstanceState;
class InstanceTask;
class InstanceTaskQueue;
/*
* Starts and stops network namespaces corresponding to service-instances.
*
* In order to prevent concurrency issues between the signal hanlder leveraged
* by this class and the db::task context specific methods are protected by
* a mutex.
*/
class InstanceManager {
public:
enum CmdType {
Start = 1,
Stop
};
enum ChldEventType {
SigChldEvent = 1,
OnErrorEvent,
OnTaskTimeoutEvent
};
struct InstanceManagerChildEvent {
int type;
/*
* SigChld variables
*/
pid_t pid;
int status;
/*
* OnError variables
*/
InstanceTask *task;
std::string errors;
/*
* OnTimeout
*/
InstanceTaskQueue *task_queue;
};
static const int kTimeoutDefault = 30;
static const int kWorkersDefault = 1;
InstanceManager(Agent *);
~InstanceManager();
void Initialize(DB *database, AgentSignal *signal,
const std::string &netns_cmd, const std::string &docker_cmd,
const int netns_workers, const int netns_timeout);
void Terminate();
bool DequeueEvent(InstanceManagerChildEvent event);
InstanceState *GetState(ServiceInstance *) const;
bool StaleTimeout();
const LoadbalancerHaproxy &haproxy() const { return *(haproxy_.get()); }
void SetStaleTimerInterval(int minutes);
int StaleTimerInterval() { return stale_timer_interval_;}
void SetNamespaceStorePath(std::string path);
private:
friend class InstanceManagerTest;
class NamespaceStaleCleaner;
void HandleSigChild(const boost::system::error_code& error, int sig,
pid_t pid, int status);
void RegisterSigHandler();
void InitSigHandler(AgentSignal *signal);
InstanceManagerAdapter* FindApplicableAdapter(const ServiceInstance::Properties &props);
void StartServiceInstance(ServiceInstance *svc_instance,
InstanceState *state, bool update);
void StopServiceInstance(ServiceInstance *svc_instance,
InstanceState *state);
void StopStaleNetNS(ServiceInstance::Properties &props);
void OnError(InstanceTask *task, const std::string errors);
void RegisterSvcInstance(InstanceTask *task,
ServiceInstance *svc_instance);
void UnregisterSvcInstance(ServiceInstance *svc_instance);
ServiceInstance *UnregisterSvcInstance(InstanceTask *task);
ServiceInstance *GetSvcInstance(InstanceTask *task) const;
InstanceTaskQueue *GetTaskQueue(const std::string &str);
void Enqueue(InstanceTask *task, const boost::uuids::uuid &uuid);
void ScheduleNextTask(InstanceTaskQueue *task_queue);
bool StartTask(InstanceTaskQueue *task_queue, InstanceTask *task);
InstanceState *GetState(InstanceTask* task) const;
void SetState(ServiceInstance *svc_instance, InstanceState *state);
void ClearState(ServiceInstance *svc_instance);
bool DeleteState(ServiceInstance *svc_instance);
void UpdateStateStatusType(InstanceTask* task, int status);
void SetLastCmdType(ServiceInstance *svc_instance, int last_cmd_type);
int GetLastCmdType(ServiceInstance *svc_instance) const;
void ClearLastCmdType(ServiceInstance *svc_instance);
void OnTaskTimeout(InstanceTaskQueue *task_queue);
void SigChldEventHandler(InstanceManagerChildEvent event);
void OnErrorEventHandler(InstanceManagerChildEvent event);
void OnTaskTimeoutEventHandler(InstanceManagerChildEvent event);
/*
* Clear all the state entries. Used only at process shutdown.
*/
void StateClear();
/*
* Event observer for changes in the "db.service-instance.0" table.
*/
void EventObserver(DBTablePartBase *db_part, DBEntryBase *entry);
/*
* Event observer for changes in the "db.loadbalancer.0" table.
*/
void LoadbalancerObserver(DBTablePartBase *db_part, DBEntryBase *entry);
DBTableBase::ListenerId si_listener_;
DBTableBase::ListenerId lb_listener_;
std::string netns_cmd_;
int netns_timeout_;
WorkQueue<InstanceManagerChildEvent> work_queue_;
std::vector<InstanceTaskQueue *> task_queues_;
std::map<InstanceTask *, ServiceInstance *> task_svc_instances_;
std::map<std::string, int> last_cmd_types_;
std::string loadbalancer_config_path_;
std::string namespace_store_path_;
int stale_timer_interval_;
std::auto_ptr<LoadbalancerHaproxy> haproxy_;
Timer *stale_timer_;
std::auto_ptr<NamespaceStaleCleaner> stale_cleaner_;
Agent *agent_;
std::vector<InstanceManagerAdapter *> adapters_;
DISALLOW_COPY_AND_ASSIGN(InstanceManager);
};
class InstanceState : public DBState {
public:
enum StatusType {
Starting = 1,
Started,
Stopping,
Stopped,
Error,
Timeout
};
InstanceState();
void set_pid(const pid_t &pid) {
pid_ = pid;
}
pid_t pid() const {
return pid_;
}
void set_status(const int status) {
status_ = status;
}
pid_t status() const {
return status_;
}
void set_errors(const std::string &errors) {
errors_ = errors;
}
std::string errors() const {
return errors_;
}
void set_cmd(const std::string &cmd) {
cmd_ = cmd;
}
std::string cmd() const {
return cmd_;
}
void set_properties(const ServiceInstance::Properties &properties) {
properties_ = properties;
}
const ServiceInstance::Properties &properties() const {
return properties_;
}
void set_status_type(const int status) {
status_type_ = status;
}
int status_type() const {
return status_type_;
}
int tasks_running() const {
return tasks_running_;
}
int incr_tasks_running() {
return ++tasks_running_;
}
int decr_tasks_running() {
tasks_running_--;
assert(!(tasks_running_ < 0));
return tasks_running_;
}
void Clear();
private:
pid_t pid_;
int status_;
std::string errors_;
std::string cmd_;
int status_type_;
int tasks_running_;
ServiceInstance::Properties properties_;
boost::system::error_code ec_;
};
#endif