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