OpenSDN source code
instance_manager.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
3  */
4 
6 
7 #include <boost/bind/bind.hpp>
8 #include <boost/functional/hash.hpp>
9 #include <boost/filesystem.hpp>
10 #include <boost/tokenizer.hpp>
11 #include <sys/wait.h>
12 #include "cmn/agent.h"
13 #include "db/db.h"
14 #include "io/event_manager.h"
15 #include "oper/instance_task.h"
16 #include "oper/operdb_init.h"
17 #include "oper/service_instance.h"
18 #include "oper/vm.h"
21 #ifdef WITH_LIBVIRT
23 #endif
24 #include "base/util.h"
25 
26 using namespace boost::placeholders;
27 
28 using boost::uuids::uuid;
30  SandeshTraceBufferCreate("InstanceManager", 1000));
31 
32 static const char loadbalancer_config_path_default[] =
33  "/var/lib/contrail/loadbalancer/";
34 static const char namespace_store_path_default[] =
35  "/var/run/netns";
36 static const char namespace_prefix[] = "vrouter-";
37 
39 public:
41  : agent_(agent), manager_(manager) {
42  }
43 
45  namespace fs = boost::filesystem;
46 
47  //Read all the Namepaces in the system
48  fs::path ns(manager_->namespace_store_path_);
49  if ( !fs::exists(ns) || !fs::is_directory(ns)) {
50  return;
51  }
52 
53  typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
54  boost::char_separator<char> slash_sep("/");
55  boost::char_separator<char> colon_sep(":");
56  fs::directory_iterator end_iter;
57  for(fs::directory_iterator iter(ns); iter != end_iter; iter++) {
58 
59  // Get to the name of namespace by removing complete path
60  tokenizer tokens(iter->path().string(), slash_sep);
61  std::string ns_name;
62  for(tokenizer::iterator it=tokens.begin(); it!=tokens.end(); it++){
63  ns_name = *it;
64  }
65 
66  //We are interested only in namespaces starting with a given
67  //prefix
68  std::size_t vrouter_found;
69  vrouter_found = ns_name.find(namespace_prefix);
70  if (vrouter_found == std::string::npos) {
71  continue;
72  }
73 
74  //Remove the standard prefix
75  ns_name.replace(vrouter_found, strlen(namespace_prefix), "");
76 
77  //Namespace might have a ":". Extract both left and right of
78  //":" Left of ":" is the VM uuid. If not found in Agent's VM
79  //DB, it can be deleted
80  tokenizer tok(ns_name, colon_sep);
81  boost::uuids::uuid vm_uuid = StringToUuid(*tok.begin());
82  VmKey key(vm_uuid);
83  if (agent_->vm_table()->Find(&key, true)) {
84  continue;
85  }
86 
88  prop.instance_id = vm_uuid;
90  tokenizer::iterator next_tok = ++(tok.begin());
91  //Loadbalancer namespace
92  if (next_tok != tok.end()) {
93  prop.loadbalancer_id = *next_tok;
95  }
96 
97  //Delete Namespace
98  manager_->StopStaleNetNS(prop);
99 
100  //If Loadbalncer, delete the config files as well
102  //Delete the complete directory
103  std::stringstream pathgen;
104  pathgen << manager_->loadbalancer_config_path_
105  << prop.loadbalancer_id << ".conf";
106 
107  boost::system::error_code error;
108  if (fs::exists(pathgen.str())) {
109  fs::remove(pathgen.str(), error);
110  if (error) {
111  std::stringstream ss;
112  ss << "Stale loadbalancer cfg fle delete error ";
113  ss << error.message();
114  INSTANCE_MANAGER_TRACE(Trace, ss.str().c_str());
115  }
116  }
117  }
118  }
119  }
120 
121 private:
124 };
125 
127  TimerManager::DeleteTimer(stale_timer_);
128  STLDeleteValues(&adapters_);
129 }
130 
132  : si_listener_(DBTableBase::kInvalidId),
133  netns_timeout_(-1),
134  work_queue_(TaskScheduler::GetInstance()->GetTaskId(INSTANCE_MANAGER_TASK_NAME), 0,
135  boost::bind(&InstanceManager::DequeueEvent, this, _1)),
136  loadbalancer_config_path_(loadbalancer_config_path_default),
137  namespace_store_path_(namespace_store_path_default),
138  stale_timer_interval_(5 * 60 * 1000),
139  stale_timer_(TimerManager::CreateTimer(*(agent->event_manager()->io_service()),
140  "NameSpaceStaleTimer", TaskScheduler::GetInstance()->
141  GetTaskId(INSTANCE_MANAGER_TASK_NAME), 0)), agent_(agent) {
142  if (agent->isMockMode()) {
143  loadbalancer_config_path_ = "/tmp/" + agent->AgentGUID()
145  namespace_store_path_ = "/tmp/" + agent->AgentGUID()
147  }
148  work_queue_.set_name("Instance Manager");
149 
150 }
151 
152 void InstanceManager::Initialize(DB *database, const std::string &netns_cmd,
153  const std::string &docker_cmd,
154  const int netns_workers,
155  const int netns_timeout) {
157  assert(si_table);
158  si_listener_ = si_table->Register(
159  boost::bind(&InstanceManager::EventObserver, this, _1, _2));
160 
161  netns_cmd_ = netns_cmd;
162  if (netns_cmd_.length() == 0) {
163  LOG(ERROR, "NetNS path for network namespace command not specified "
164  "in the config file, the namespaces won't be started");
165  }
166  if (docker_cmd.length() == 0) {
167  LOG(ERROR, "Path for Docker starter command not specified "
168  "in the config file, the Docker instances won't be started");
169  }
170 
171  std::stringstream pathgen;
172  pathgen << loadbalancer_config_path_;
173  boost::filesystem::path dir(pathgen.str());
174  boost::system::error_code error;
175  boost::filesystem::create_directories(dir, error);
176  if (error) {
177  LOG(ERROR, "Falied to create Loadbalancer Directory " << pathgen.str());
178  }
179 
180  adapters_.push_back(new DockerInstanceAdapter(docker_cmd, agent_));
181  adapters_.push_back(new NetNSInstanceAdapter(netns_cmd,
183 #ifdef WITH_LIBVIRT
185  "qemu:///system"));
186 #endif
187 
189  if (netns_timeout >= 1) {
190  netns_timeout_ = netns_timeout;
191  }
192 
194 
195  int workers = kWorkersDefault;
196  if (netns_workers > 0) {
197  workers = netns_workers;
198  }
199 
200  task_queues_.resize(workers);
201  for (std::vector<InstanceTaskQueue *>::iterator iter = task_queues_.begin();
202  iter != task_queues_.end(); ++iter) {
203  InstanceTaskQueue *task_queue =
205  assert(task_queue);
206  task_queue->set_on_timeout_cb(
207  boost::bind(&InstanceManager::OnTaskTimeout,
208  this, _1));
209  *iter = task_queue;
210  }
212  boost::bind(&InstanceManager::StaleTimeout, this));
213 
214 }
215 
216 void InstanceManager::SetNetNSCmd(const std::string &netns_cmd) {
218  prop.virtualization_type =
219  ServiceInstance::ServiceInstance::NetworkNamespace;
220  NetNSInstanceAdapter *adapter = static_cast<NetNSInstanceAdapter
221  *>(FindApplicableAdapter(prop));
222  if (adapter)
223  adapter->set_cmd(netns_cmd);
224 }
225 
227  stale_timer_interval_ = minutes * 60 * 1000;
228 }
229 
232  event.type = OnTaskTimeoutEvent;
233  event.task_queue = task_queue;
234 
235  work_queue_.Enqueue(event);
236 }
237 
239  std::stringstream ss;
240  ss << "TaskTimeOut for the TaskQ " << event.task_queue;
241  INSTANCE_MANAGER_TRACE(Trace, ss.str().c_str());
242 
244 }
245 
247  ServiceInstance *svc_instance = GetSvcInstance(event.task);
248  if (!svc_instance) {
249  return;
250  }
251 
252  std::stringstream ss;
253  ss << "Error for the Task " << event.task << " " << event.errors;
254  INSTANCE_MANAGER_TRACE(Trace, ss.str().c_str());
255 
256  InstanceState *state = GetState(svc_instance);
257  if (state != NULL) {
258  state->set_errors(event.errors);
259  }
260 }
261 
263  ServiceInstance *svc_instance = GetSvcInstance(event.task);
264  if (!svc_instance) {
265  return;
266  }
267 
268  std::stringstream ss;
269  ss << "Exit event for the Task " << event.task;
270  INSTANCE_MANAGER_TRACE(Trace, ss.str().c_str());
271 
272  UpdateStateStatusType(event);
273  for (std::vector<InstanceTaskQueue *>::iterator iter =
274  task_queues_.begin();
275  iter != task_queues_.end(); ++iter) {
276  InstanceTaskQueue *task_queue = *iter;
277  if (!task_queue->Empty()) {
278  if (task_queue->Front() == event.task) {
279  task_queue->Pop();
280  delete event.task;
281  task_queue->StopTimer();
282  DeleteState(svc_instance);
283  ScheduleNextTask(task_queue);
284  return;
285  }
286  }
287  }
288 
289 }
290 
292  if (event.type == OnErrorEvent) {
293  OnErrorEventHandler(event);
294  } else if (event.type == OnTaskTimeoutEvent) {
296  } else if (event.type == OnExitEvent) {
297  OnExitEventHandler(event);
298  }
299 
300  return true;
301 }
302 
304  ServiceInstance* svc_instance = UnregisterSvcInstance(event.task);
305  if (svc_instance) {
306  InstanceState *state = GetState(svc_instance);
307 
308  // The below code might not really capture the errors that
309  // occured in the child process. As we are relying on the pipe
310  // status to identify child exit, even if child process ends up
311  // in error state, pipe might return "success" because pipe is
312  // closed without erros. But what we want to reflect is the
313  // error of child process. If there is any error in the pipe
314  // status, we show that as is. If not, if there is any error string
315  // in error_, we mark the error status as -1.
316  // pipe returning boost::system::errc::no_such_file_or_directory
317  // error is considered as no pipe errors
318 
319  if (state != NULL) {
320  int error_status = event.error_val;
321  if (error_status ==
322  boost::system::errc::no_such_file_or_directory) {
323  error_status = 0;
324  }
325  if (!state->errors().empty()) {
326  if (error_status == 0) {
327  error_status = -1;
328  }
329  }
330 
331  state->set_status(error_status);
332 
333  if (error_status != 0) {
334  if (state->status_type() != InstanceState::Timeout) {
336  }
337  } else if (state->status_type() == InstanceState::Starting) {
339  } else if (state->status_type() == InstanceState::Stopping) {
341  }
342 
343  std::stringstream ss;
344  ss << "For the task " << event.task << " error status " <<
345  error_status << " status type " << state->status_type();
346  INSTANCE_MANAGER_TRACE(Trace, ss.str().c_str());
347  }
348  }
349 }
350 
352  return static_cast<InstanceState *>(
353  svc_instance->GetState(agent_->service_instance_table(),
354  si_listener_));
355 }
356 
358  ServiceInstance* svc_instance = GetSvcInstance(task);
359  if (svc_instance) {
360  InstanceState *state = GetState(svc_instance);
361  return state;
362  }
363  return NULL;
364 }
365 
367  InstanceState *state) {
368  svc_instance->SetState(agent_->service_instance_table(),
369  si_listener_,state);
370 }
371 
374 }
375 
377 
378  if (!svc_instance || !svc_instance->IsDeleted()) {
379  return false;
380  }
381 
382  InstanceState *state = GetState(svc_instance);
383  if (state && !state->tasks_running()) {
384  ClearState(svc_instance);
385  delete state;
386  ClearLastCmdType(svc_instance);
387  return true;
388  }
389 
390  return false;
391 }
392 
393 
395  DBTablePartition *partition = static_cast<DBTablePartition *>(
397 
398  if (!partition)
399  return;
400 
401  DBEntryBase *next = NULL;
402  for (DBEntryBase *entry = partition->GetFirst(); entry; entry = next) {
403  next = partition->GetNext(entry);
404  DBState *state =
405  entry->GetState(agent_->service_instance_table(), si_listener_);
406  if (state != NULL) {
407  entry->ClearState(agent_->service_instance_table(), si_listener_);
408  delete state;
409  ClearLastCmdType(static_cast<ServiceInstance *>(entry));
410  }
411  }
412 }
413 
415  StateClear();
418 
419  InstanceTaskQueue *task_queue;
420  for (std::vector<InstanceTaskQueue *>::iterator iter = task_queues_.begin();
421  iter != task_queues_.end(); ++iter) {
422  if ((task_queue = *iter) == NULL) {
423  continue;
424  }
425  task_queue->Clear();
426 
427  delete task_queue;
428  }
429  work_queue_.Shutdown();
430 }
431 
433  const boost::uuids::uuid &uuid) {
434  std::stringstream ss;
435  ss << uuid;
436  InstanceTaskQueue *task_queue = GetTaskQueue(ss.str());
437  task_queue->Push(task);
438  ScheduleNextTask(task_queue);
439 }
440 
442  boost::hash<std::string> hash;
443  int index = hash(str) % task_queues_.size();
444  return task_queues_[index];
445 }
446 
447 //After Run(), if child process is running, we keep the task status as
448 //"Starting" or "Stopping". We start a timer to track TaskTimeout time.
449 //if process is not runnning, we verify how many times we already attempted
450 //to run. If netns_reattempts_ are already crossed, we return false,
451 // so that caller deletes the task without running any further.
452 //If required reattempts are not done, we start a timer and return true
453 // so that same task is run again after the timeout. The task status is set to
454 //"reattempt" to track reattempt case
456  InstanceTask *task) {
457 
458 
459  InstanceState *state = GetState(task);
460  if (state) {
461  state->reset_errors();
462  }
463 
464  pid_t pid;
465  bool status = task->Run();
466 
467  std::stringstream ss;
468  ss << "Run status for the task " << task << " " << status;
469  ss << " With running status " << task->is_running();
470  INSTANCE_MANAGER_TRACE(Trace, ss.str().c_str());
471 
472  if (status || task->is_running()) {
473  pid = task->pid();
474  if (state != NULL) {
475  state->set_pid(pid);
476  state->set_cmd(task->cmd());
477  if (task->cmd_type() == Start) {
479  } else {
481  }
482  }
483  } else {
484 
485  ss.str(std::string());
486  ss << "Run failure for the task " << task << " attempt " << task->reattempts();
487  INSTANCE_MANAGER_TRACE(Trace, ss.str().c_str());
488 
489  if (state) {
491  state->set_cmd(task->cmd());
492  }
493  if (task->incr_reattempts() > netns_reattempts_) {
494  ss.str(std::string());
495  ss << "Run failure for the task " << task << " attempts exceeded";
496  INSTANCE_MANAGER_TRACE(Trace, ss.str().c_str());
497  return false;
498  }
499  }
500 
501  task_queue->StartTimer(netns_timeout_ * 1000);
502 
503  return true;
504 }
505 
506 //If Starting the task succeds we wait for another event on that task.
507 //If not the task is removed from the front of the queue and is delted.
509  while (!task_queue->Empty()) {
510 
511  InstanceTask *task = task_queue->Front();
512  InstanceState *state = GetState(task);
513 
514  if (!task->is_running()) {
515  bool status = StartTask(task_queue, task);
516  if (status) {
517  return;
518  }
519  } else {
520  int delay = time(NULL) - task->start_time();
521  if (delay < netns_timeout_) {
522  return;
523  }
524  if (state) {
526  }
527 
528  std::stringstream ss;
529  ss << "Timeout for the Task " << task << " delay " << delay;
530  ss << " netns timeout " << netns_timeout_ << " ";
531  ss << task->cmd();
532  INSTANCE_MANAGER_TRACE(Trace, ss.str().c_str());
533 
534  if (delay >= (netns_timeout_ * 2)) {
535  task->Terminate();
536  if (task->IsSetup())
537  return;
538  } else {
539  task->Stop();
540  return;
541  }
542  }
543 
544  task_queue->StopTimer();
545  task_queue->Pop();
546 
547  ServiceInstance* svc_instance = GetSvcInstance(task);
548  if (state && svc_instance)
549  state->decr_tasks_running();
550 
551  task_svc_instances_.erase(task);
552 
553  std::stringstream ss;
554  ss << "Delete of the Task " << task;
555  INSTANCE_MANAGER_TRACE(Trace, ss.str().c_str());
556 
557  DeleteState(svc_instance);
558 
559  delete task;
560  }
561 }
562 
564  TaskSvcMap::const_iterator iter =
566  if (iter != task_svc_instances_.end()) {
567  return iter->second;
568  }
569  return NULL;
570 }
571 
573  ServiceInstance *svc_instance) {
574  pair<TaskSvcMap::iterator, bool> result =
575  task_svc_instances_.insert(std::make_pair(task, svc_instance));
576  assert(result.second);
577 
578  InstanceState *state = GetState(svc_instance);
579  assert(state);
580  state->incr_tasks_running();
581 }
582 
584  for (TaskSvcMap::iterator iter =
585  task_svc_instances_.begin();
586  iter != task_svc_instances_.end(); ++iter) {
587  if (task == iter->first) {
588  ServiceInstance *svc_instance = iter->second;
589  InstanceState *state = GetState(svc_instance);
590  assert(state);
591  state->decr_tasks_running();
592  task_svc_instances_.erase(iter);
593  return svc_instance;
594  }
595  }
596 
597  return NULL;
598 }
599 
601 
602  InstanceState *state = GetState(svc_instance);
603  assert(state);
604 
605  TaskSvcMap::iterator iter =
606  task_svc_instances_.begin();
607  while(iter != task_svc_instances_.end()) {
608  if (svc_instance == iter->second) {
609  task_svc_instances_.erase(iter++);
610  state->decr_tasks_running();
611  } else {
612  ++iter;
613  }
614  }
615 }
616 
618  for (std::vector<InstanceManagerAdapter *>::iterator iter = adapters_.begin();
619  iter != adapters_.end(); ++iter) {
620  InstanceManagerAdapter *adapter = *iter;
621  if (adapter != NULL && adapter->isApplicable(props)) {
622  return adapter;
623  }
624  }
625  return NULL;
626 }
627 
629  InstanceState *state, bool update) {
630  const ServiceInstance::Properties &props = svc_instance->properties();
631  InstanceManagerAdapter *adapter = this->FindApplicableAdapter(props);
632  std::stringstream ss;
633  if (adapter != NULL) {
634  InstanceTask *task = adapter->CreateStartTask(props, update);
635  if (task != NULL) {
636  ss << "Starting the Task " << task << " " << task->cmd();
637  ss << " for " << props.instance_id;
638  INSTANCE_MANAGER_TRACE(Trace, ss.str().c_str());
639  task->set_on_data_cb(boost::bind(&InstanceManager::OnError,
640  this, _1, _2));
641  task->set_on_exit_cb(boost::bind(&InstanceManager::OnExit,
642  this, _1, _2));
643  state->set_properties(props);
644  RegisterSvcInstance(task, svc_instance);
645  std::stringstream info;
646  Enqueue(task, props.instance_id);
647  } else {
648  ss << "Error Starting the Task for " << props.instance_id;
649  INSTANCE_MANAGER_TRACE(Trace, ss.str().c_str());
650  }
651  } else {
652  ss << "Unknown virtualization type " << props.virtualization_type;
653  ss << " for " << svc_instance->ToString();
654  INSTANCE_MANAGER_TRACE(Trace, ss.str().c_str());
655  }
656 }
657 
658 
660  InstanceState *state) {
661  const ServiceInstance::Properties &props = state->properties();
662  InstanceManagerAdapter *adapter = this->FindApplicableAdapter(props);
663  std::stringstream ss;
664  if (adapter != NULL) {
665  InstanceTask *task = adapter->CreateStopTask(props);
666  if (task != NULL) {
667  ss << "Stopping the Task " << task << " " << task->cmd();
668  ss << " for " << props.instance_id;
669  INSTANCE_MANAGER_TRACE(Trace, ss.str().c_str());
670  task->set_on_data_cb(boost::bind(&InstanceManager::OnError,
671  this, _1, _2));
672  task->set_on_exit_cb(boost::bind(&InstanceManager::OnExit,
673  this, _1, _2));
674  RegisterSvcInstance(task, svc_instance);
675  std::stringstream info;
676  Enqueue(task, props.instance_id);
677  } else {
678  std::stringstream ss;
679  ss << "Error Stopping the Task for " << props.instance_id;
680  INSTANCE_MANAGER_TRACE(Trace, ss.str().c_str());
681  }
682  } else {
683  ss << "Unknown virtualization type " << props.virtualization_type;
684  ss << " for " << svc_instance->ToString();
685  INSTANCE_MANAGER_TRACE(Trace, ss.str().c_str());
686  }
687 }
688 
690  const std::string errors) {
691 
693  event.type = OnErrorEvent;
694  event.task = task;
695  event.errors = errors;
696 
697  work_queue_.Enqueue(event);
698 }
699 
701  const boost::system::error_code &ec) {
702 
704  event.type = OnExitEvent;
705  event.task = task;
706  event.error_val = ec.value();
707 
708  work_queue_.Enqueue(event);
709 }
710 
712  std::stringstream cmd_str;
713 
714  if (netns_cmd_.length() == 0) {
715  return;
716  }
717  cmd_str << netns_cmd_ << " destroy";
718 
719  cmd_str << " " << props.ServiceTypeString();
720  cmd_str << " " << UuidToString(props.instance_id);
721  cmd_str << " " << UuidToString(boost::uuids::nil_uuid());
722  cmd_str << " " << UuidToString(boost::uuids::nil_uuid());
724  if (props.loadbalancer_id.empty()) {
725  LOG(ERROR, "loadbalancer id is missing for service instance: "
726  << UuidToString(props.instance_id));
727  return;
728  }
729  cmd_str << " --loadbalancer-id " << props.loadbalancer_id;
730  }
731 
732  std::string cmd = cmd_str.str();
733  std::vector<std::string> argv;
734  boost::split(argv, cmd, boost::is_any_of(" "), boost::token_compress_on);
735  std::vector<const char *> c_argv(argv.size() + 1);
736  for (std::size_t i = 0; i != argv.size(); ++i) {
737  c_argv[i] = argv[i].c_str();
738  }
739 
740  std::stringstream ss;
741  ss << "StaleNetNS " << cmd;
742  INSTANCE_MANAGER_TRACE(Trace, ss.str().c_str());
743 
744  pid_t pid = vfork();
745  if (pid == 0) {
746  CloseTaskFds();
747  execvp(c_argv[0], (char **) c_argv.data());
748  perror("execvp");
749 
750  _exit(127);
751  }
752 }
753 
755  int last_cmd_type) {
756  std::string uuid = UuidToString(svc_instance->uuid());
757  std::map<std::string, int>::iterator iter =
758  last_cmd_types_.find(uuid);
759  if (iter != last_cmd_types_.end()) {
760  iter->second = last_cmd_type;
761  } else {
762  last_cmd_types_.insert(std::make_pair(uuid, last_cmd_type));
763  }
764 }
765 
767  std::string uuid = UuidToString(svc_instance->uuid());
768  std::map<std::string, int>::const_iterator iter =
769  last_cmd_types_.find(uuid);
770  if (iter != last_cmd_types_.end()) {
771  return iter->second;
772  }
773 
774  return 0;
775 }
776 
778  std::string uuid = UuidToString(svc_instance->uuid());
779  std::map<std::string, int>::iterator iter =
780  last_cmd_types_.find(uuid);
781  if (iter != last_cmd_types_.end()) {
782  last_cmd_types_.erase(iter);
783  }
784 }
785 
787  DBTablePartBase *db_part, DBEntryBase *entry) {
788  ServiceInstance *svc_instance = static_cast<ServiceInstance *>(entry);
789 
790  InstanceState *state = GetState(svc_instance);
791  if (svc_instance->IsDeleted()) {
792  if (state) {
793  if (GetLastCmdType(svc_instance) == Start) {
794  StopServiceInstance(svc_instance, state);
795  SetLastCmdType(svc_instance, Stop);
796  }
797  if (DeleteState(svc_instance)) {
798  return;
799  }
800  }
801  ClearLastCmdType(svc_instance);
802  } else {
803  if (state == NULL) {
804  state = new InstanceState();
805  SetState(svc_instance, state);
806  }
807 
808  bool usable = svc_instance->IsUsable();
809 
810  std::stringstream ss;
811  ss << "NetNS event notification for uuid: " << svc_instance->ToString();
812  ss << (usable ? " usable" : " not usable");
813  INSTANCE_MANAGER_TRACE(Trace, ss.str().c_str());
814 
815  if (!usable && GetLastCmdType(svc_instance) == Start) {
816  StopServiceInstance(svc_instance, state);
817  SetLastCmdType(svc_instance, Stop);
818  } else if (usable) {
819  if (GetLastCmdType(svc_instance) == Start && state->properties().CompareTo(
820  svc_instance->properties()) != 0) {
821  StartServiceInstance(svc_instance, state, true);
822  } else if (GetLastCmdType(svc_instance) != Start) {
823  StartServiceInstance(svc_instance, state, false);
824  SetLastCmdType(svc_instance, Start);
825  }
826  }
827  }
828 }
829 
831 
832  if (stale_cleaner_.get())
833  return false;
834  stale_cleaner_.reset(new NamespaceStaleCleaner(agent_, this));
835  stale_cleaner_->CleanStaleEntries();
836  stale_cleaner_.reset(NULL);
837  return false;
838 }
839 
841  namespace_store_path_ = path;
842 }
843 
844 /*
845  * InstanceState class
846  */
848  pid_(0), status_(0), status_type_(0), tasks_running_(0) {
849 }
850 
852  pid_ = 0;
853  status_ = 0;
854  errors_.clear();
855  cmd_.clear();
856 }
#define INSTANCE_MANAGER_TASK_NAME
Definition: agent.h:298
static void CloseTaskFds(void)
Definition: agent_cmn.h:79
virtual void Clear()
Definition: agent_db.cc:215
Definition: agent.h:360
EventManager * event_manager() const
Definition: agent.h:1105
std::string AgentGUID() const
Definition: agent.cc:157
ServiceInstanceTable * service_instance_table() const
Definition: agent.h:819
bool isMockMode() const
Definition: agent.cc:153
DBState * GetState(DBTableBase *tbl_base, ListenerId listener) const
Definition: db_entry.cc:37
void ClearState(DBTableBase *tbl_base, ListenerId listener)
Definition: db_entry.cc:73
bool IsDeleted() const
Definition: db_entry.h:48
void SetState(DBTableBase *tbl_base, ListenerId listener, DBState *state)
Definition: db_entry.cc:22
ListenerId Register(ChangeCallback callback, const std::string &name="unspecified")
Definition: db_table.cc:207
void Unregister(ListenerId listener)
Definition: db_table.cc:212
virtual DBEntry * GetNext(const DBEntryBase *entry)
virtual DBEntry * GetFirst()
virtual DBTablePartBase * GetTablePartition(const DBRequestKey *key)
Definition: db_table.cc:462
Definition: db.h:24
virtual InstanceTask * CreateStartTask(const ServiceInstance::Properties &props, bool update)=0
virtual InstanceTask * CreateStopTask(const ServiceInstance::Properties &props)=0
virtual bool isApplicable(const ServiceInstance::Properties &props)=0
NamespaceStaleCleaner(Agent *agent, InstanceManager *manager)
std::vector< InstanceManagerAdapter * > adapters_
void SetStaleTimerInterval(int minutes)
void OnExitEventHandler(InstanceManagerChildEvent event)
bool StartTask(InstanceTaskQueue *task_queue, InstanceTask *task)
std::string netns_cmd_
ServiceInstance * GetSvcInstance(InstanceTask *task) const
bool DequeueEvent(InstanceManagerChildEvent event)
void Enqueue(InstanceTask *task, const boost::uuids::uuid &uuid)
void OnTaskTimeoutEventHandler(InstanceManagerChildEvent event)
void SetNamespaceStorePath(std::string path)
void ClearLastCmdType(ServiceInstance *svc_instance)
void SetState(ServiceInstance *svc_instance, InstanceState *state)
static const int kWorkersDefault
void SetNetNSCmd(const std::string &netns_cmd)
void OnExit(InstanceTask *task, const boost::system::error_code &ec)
static const int kReattemptsDefault
void UpdateStateStatusType(InstanceManagerChildEvent event)
std::vector< InstanceTaskQueue * > task_queues_
InstanceTaskQueue * GetTaskQueue(const std::string &str)
void OnError(InstanceTask *task, const std::string errors)
static const int kTimeoutDefault
InstanceState * GetState(ServiceInstance *) const
void UnregisterSvcInstance(ServiceInstance *svc_instance)
bool DeleteState(ServiceInstance *svc_instance)
InstanceManagerAdapter * FindApplicableAdapter(const ServiceInstance::Properties &props)
DBTableBase::ListenerId si_listener_
void Initialize(DB *database, const std::string &netns_cmd, const std::string &docker_cmd, const int netns_workers, const int netns_timeout)
void ClearState(ServiceInstance *svc_instance)
void OnErrorEventHandler(InstanceManagerChildEvent event)
std::map< std::string, int > last_cmd_types_
void ScheduleNextTask(InstanceTaskQueue *task_queue)
WorkQueue< InstanceManagerChildEvent > work_queue_
std::unique_ptr< NamespaceStaleCleaner > stale_cleaner_
void OnTaskTimeout(InstanceTaskQueue *task_queue)
void StopStaleNetNS(ServiceInstance::Properties &props)
TaskSvcMap task_svc_instances_
void SetLastCmdType(ServiceInstance *svc_instance, int last_cmd_type)
void StopServiceInstance(ServiceInstance *svc_instance, InstanceState *state)
void StartServiceInstance(ServiceInstance *svc_instance, InstanceState *state, bool update)
void RegisterSvcInstance(InstanceTask *task, ServiceInstance *svc_instance)
std::string loadbalancer_config_path_
std::string namespace_store_path_
int GetLastCmdType(ServiceInstance *svc_instance) const
void EventObserver(DBTablePartBase *db_part, DBEntryBase *entry)
void set_pid(const pid_t &pid)
int status_type() const
std::string errors() const
int tasks_running() const
void set_cmd(const std::string &cmd)
std::string cmd_
const ServiceInstance::Properties & properties() const
void set_status(const int status)
void set_errors(const std::string &errors)
void set_status_type(const int status)
void set_properties(const ServiceInstance::Properties &properties)
std::string errors_
InstanceTask * Front()
void StartTimer(int time)
void Push(InstanceTask *task)
void set_on_timeout_cb(OnTimeoutCallback cb)
void set_cmd(const std::string &netns_cmd)
const Properties & properties() const
const boost::uuids::uuid & uuid() const
bool IsUsable() const
virtual std::string ToString() const
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
Definition: task.h:304
static bool DeleteTimer(Timer *Timer)
Definition: timer.cc:221
bool Start(int time, Handler handler, ErrorHandler error_handler=NULL)
Definition: timer.cc:107
Definition: trace.h:288
SandeshTraceBufferPtr InstanceManagerTraceBuf(SandeshTraceBufferCreate("InstanceManager", 1000))
static const char namespace_store_path_default[]
static const char namespace_prefix[]
static const char loadbalancer_config_path_default[]
#define INSTANCE_MANAGER_TRACE(obj,...)
#define LOG(_Level, _Msg)
Definition: logging.h:34
boost::shared_ptr< TraceBuffer< SandeshTrace > > SandeshTraceBufferPtr
Definition: sandesh_trace.h:18
SandeshTraceBufferPtr SandeshTraceBufferCreate(const std::string &buf_name, size_t buf_size, bool trace_enable=true)
Definition: sandesh_trace.h:46
static boost::uuids::uuid StringToUuid(const std::string &str)
Definition: string_util.h:145
static std::string UuidToString(const boost::uuids::uuid &id)
Definition: string_util.h:138
boost::uuids::uuid instance_id
int CompareTo(const Properties &rhs) const
const std::string & ServiceTypeString() const
Definition: vm.h:16
boost::tokenizer< boost::char_separator< char > > tokenizer
struct task_ task
void STLDeleteValues(Container *container)
Definition: util.h:101
boost::uuids::uuid uuid