OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
rest_server.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include <vector>
6 #include <string>
7 
8 #include <boost/bind.hpp>
9 #include <boost/assign.hpp>
10 #include <boost/foreach.hpp>
11 
12 #include "base/regex.h"
13 #include "http/http_server.h"
14 #include "http/http_request.h"
15 #include "http/http_session.h"
16 #include "base/contrail_ports.h"
18 #include "cmn/agent.h"
19 #include "rest_server.h"
20 #include "rest_common.h"
21 #include "init/agent_param.h"
22 
23 using contrail::regex;
26 
27 class RestServerGetVmCfgTask : public Task {
28 public:
30  const struct RestServer::RESTData& data):
31  Task((TaskScheduler::GetInstance()->GetTaskId("Agent::RestApi")), 0),
32  pih_(pih),
33  vm_name_((*data.match)[1]),
34  data_(data),
35  context_(data_.session->get_context()) {
36  }
38  virtual bool Run() {
39  std::string info;
40  const std::string client_ctx = data_.session->get_client_context(context_);
41  // check session is not deleted
42  if ((!data_.session->set_client_context(context_, client_ctx)) ||
43  (context_.empty()))
44  return true;
45  if (pih_->GetVmVnCfgPort(vm_name_, info)) {
47  } else {
48  REST::SendErrorResponse(data_.session, "{ Not Found }", 404, context_);
49  }
50  return true;
51  }
52  std::string Description() const { return "RestServerGetVmCfgTask"; }
53 private:
55  std::string vm_name_;
56  const struct RestServer::RESTData& data_;
57  const std::string context_;
59 };
60 
61 void RestServer::VmPortPostHandler(const struct RESTData& data) {
63  if (pih) {
64  std::string err_msg;
65  if (pih->AddPortFromJson(data.request->Body(), false, err_msg, true)) {
66  REST::SendResponse(data.session, "{}");
67  } else {
68  REST::SendErrorResponse(data.session, "{ " + err_msg + " }");
69  }
70  } else {
71  REST::SendErrorResponse(data.session, "{ Operation Not Supported }");
72  }
73 }
74 
75 void RestServer::VmPortSyncHandler(const struct RESTData& data) {
77  if (pih) {
78  pih->SyncHandler();
79  REST::SendResponse(data.session, "{}");
80  } else {
81  REST::SendErrorResponse(data.session, "{ Operation Not Supported }");
82  }
83 }
84 
85 void RestServer::VmPortDeleteHandler(const struct RESTData& data) {
86  std::string error;
87  const std::string& port_id = (*data.match)[1];
89  if (pih) {
90  if (pih->DeletePort(port_id, error)) {
91  REST::SendResponse(data.session, "{}");
92  } else {
93  REST::SendErrorResponse(data.session, "{" + error + "}");
94  }
95  } else {
96  REST::SendErrorResponse(data.session, "{ Operation Not Supported }");
97  }
98 }
99 
100 void RestServer::VmPortGetHandler(const struct RESTData& data) {
101  const std::string& port_id = (*data.match)[1];
103  if (pih) {
104  std::string info;
105  if (pih->GetPortInfo(port_id, info)) {
106  REST::SendResponse(data.session, info);
107  } else {
108  REST::SendErrorResponse(data.session, "{ Not Found }", 404);
109  }
110  } else {
111  REST::SendErrorResponse(data.session, "{ Operation Not Supported }");
112  }
113 }
114 
115 void RestServer::GatewayPostHandler(const struct RESTData& data) {
117  if (pih) {
118  std::string err_msg;
119  if (pih->AddVgwFromJson(data.request->Body(), err_msg)) {
120  REST::SendResponse(data.session, "{}");
121  } else {
122  REST::SendErrorResponse(data.session, "{ " + err_msg + " }");
123  }
124  } else {
125  REST::SendErrorResponse(data.session, "{ Operation Not Supported }");
126  }
127 }
128 
129 void RestServer::GatewayDeleteHandler(const struct RESTData& data) {
130  std::string error;
132  if (pih) {
133  std::string err_msg;
134  if (pih->DelVgwFromJson(data.request->Body(), err_msg)) {
135  REST::SendResponse(data.session, "{}");
136  } else {
137  REST::SendErrorResponse(data.session, "{" + error + "}");
138  }
139  } else {
140  REST::SendErrorResponse(data.session, "{ Operation Not Supported }");
141  }
142 }
143 
144 void RestServer::VmVnPortPostHandler(const struct RESTData& data) {
146  if (pih) {
147  std::string err_msg;
148  if (pih->AddVmVnPort(data.request->Body(), false, err_msg, true)) {
149  REST::SendResponse(data.session, "{}");
150  } else {
151  REST::SendErrorResponse(data.session, "{ " + err_msg + " }");
152  }
153  } else {
154  REST::SendErrorResponse(data.session, "{ Operation Not Supported }");
155  }
156 }
157 
158 void RestServer::VmVnPortDeleteHandler(const struct RESTData& data) {
159  std::string error;
160  const std::string &vm_uuid = (*data.match)[1];
162  if (pih) {
163  if (pih->DeleteVmVnPort(data.request->Body(), vm_uuid, error)) {
164  REST::SendResponse(data.session, "{}");
165  } else {
166  REST::SendErrorResponse(data.session, "{" + error + "}");
167  }
168  } else {
169  REST::SendErrorResponse(data.session, "{ Operation Not Supported }");
170  }
171 }
172 
173 void RestServer::VmVnPortGetHandler(const struct RESTData& data) {
174  std::string url = (*data.match)[0];
175  bool vmi_uuid_presence = false;
176  std::size_t pos = 4; // skip "/vm/"
177  std::size_t vmi_uuid_pos = url.find("/", pos);
178  if (vmi_uuid_pos != std::string::npos) {
179  vmi_uuid_presence = true;
180  }
181  std::string vm_uuid = url.substr(pos, vmi_uuid_pos);
182  std::string vmi_uuid = "";
183  if (vmi_uuid_presence) {
184  vmi_uuid = url.substr(vmi_uuid_pos+1, std::string::npos);
185  }
186 
188  if (pih) {
189  std::string info;
190  if (pih->GetVmVnPort(vm_uuid, vmi_uuid, info)) {
191  REST::SendResponse(data.session, info);
192  } else {
193  REST::SendErrorResponse(data.session, "{ Not Found }", 404);
194  }
195  } else {
196  REST::SendErrorResponse(data.session, "{ Operation Not Supported }");
197  }
198 }
199 
200 void RestServer::VmVnPortCfgGetHandler(const struct RESTData& data) {
202  if (pih) {
204  new RestServerGetVmCfgTask(pih, data);
206  scheduler->Enqueue(t);
207  } else {
208  REST::SendErrorResponse(data.session, "{ Operation Not Supported }");
209  }
210 }
211 
212 void RestServer::VmPortEnableHandler(const struct RESTData& data) {
213  std::string error;
214  const std::string& port_id = (*data.match)[1];
216  if (pih) {
217  if (pih->EnablePort(port_id, error)) {
218  REST::SendResponse(data.session, "{}");
219  } else {
220  REST::SendErrorResponse(data.session, "{" + error + "}");
221  }
222  } else {
223  REST::SendErrorResponse(data.session, "{ Operation Not Supported }");
224  }
225 }
226 
227 void RestServer::VmPortDisableHandler(const struct RESTData& data) {
228  std::string error;
229  const std::string& port_id = (*data.match)[1];
231  if (pih) {
232  if (pih->DisablePort(port_id, error)) {
233  REST::SendResponse(data.session, "{}");
234  } else {
235  REST::SendErrorResponse(data.session, "{" + error + "}");
236  }
237  } else {
238  REST::SendErrorResponse(data.session, "{ Operation Not Supported }");
239  }
240 }
241 
242 const std::vector<RestServer::HandlerSpecifier> RestServer::RESTHandlers_ =
243  boost::assign::list_of
244  (HandlerSpecifier(
245  regex("/port"),
246  HTTP_POST,
248  (HandlerSpecifier(
249  regex("/syncports"),
250  HTTP_POST,
252  (HandlerSpecifier(
253  regex("/port/"
254  "([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})"),
255  HTTP_DELETE,
257  (HandlerSpecifier(
258  regex("/port/"
259  "([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})"),
260  HTTP_GET,
262  (HandlerSpecifier(
263  regex("/gateway"),
264  HTTP_POST,
266  (HandlerSpecifier(
267  regex("/gateway"),
268  HTTP_DELETE,
270  (HandlerSpecifier(
271  regex("/vm"),
272  HTTP_POST,
274  (HandlerSpecifier(
275  regex("/vm/"
276  "([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})"),
277  HTTP_DELETE,
279  (HandlerSpecifier(
280  regex("/vm/"
281  "([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})"),
282  HTTP_GET,
284  (HandlerSpecifier(
285  regex("/vm/"
286  "([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/"
287  "([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})"),
288  HTTP_GET,
290  (HandlerSpecifier(
291  regex("/vm-cfg/(.*)"),
292  HTTP_GET,
294  (HandlerSpecifier(
295  regex("/enable-port/"
296  "([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})"),
297  HTTP_PUT,
299  (HandlerSpecifier(
300  regex("/disable-port/"
301  "([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})"),
302  HTTP_PUT,
304 
306  : agent_(agent), http_server_(new HttpServer(agent->event_manager())) {
308  boost::bind(&RestServer::HandleRequest, this, _1, _2));
309 }
310 
313  //only if RestServer is used via mocked agent
315  else //otherwise , use the hardcoded value
317 }
318 
320  const HttpRequest* request) {
321  std::string path = request->UrlPath();
322  BOOST_FOREACH(const RestServer::HandlerSpecifier& hs, RESTHandlers_) {
323  boost::smatch match;
324  if (regex_match(path, match, hs.request_regex) &&
325  request->GetMethod() == hs.method) {
326  struct RESTData data = {
327  &match,
328  request->GetMethod(),
329  session,
330  request
331  };
332  (this->*hs.handler_func)(data);
333  // Though IMHO it contradicts most programmers' intuition,
334  // currently handlers are responsible for freeing handled
335  // requests.
336  delete request;
337  return;
338  }
339  }
340  REST::SendErrorResponse(session, "Unknown Request", 404);
341 }
342 
344  if (http_server_) {
347  http_server_ = NULL;
348  }
349 }
350 
352 }
void VmPortDeleteHandler(const struct RESTData &)
Definition: rest_server.cc:85
friend class RestServerGetVmCfgTask
Definition: rest_server.h:67
void HandleRequest(HttpSession *session, const HttpRequest *request)
Definition: rest_server.cc:319
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
Definition: task.h:178
bool DeletePort(const string &url, string &err_msg)
void VmPortDisableHandler(const struct RESTData &data)
Definition: rest_server.cc:227
bool GetVmVnCfgPort(const string &vm, string &info) const
bool GetPortInfo(const std::string &uuid_str, std::string &info) const
void SendResponse(HttpSession *session, const std::string &msg, int status_code, std::string context)
Definition: rest_common.cc:15
virtual ~RestServerGetVmCfgTask()
Definition: rest_server.cc:37
bool DelVgwFromJson(const std::string &json, std::string &err_msg) const
PortIpcHandler * port_ipc_handler() const
Definition: agent.cc:1005
bool GetVmVnPort(const std::string &vm_uuid, const std::string &vmi_uuid, std::string &info) const
const std::string & Body() const
Definition: http_request.h:39
const HttpRequest * request
Definition: rest_server.h:30
void GatewayDeleteHandler(const struct RESTData &data)
Definition: rest_server.cc:129
static const std::vector< HandlerSpecifier > RESTHandlers_
Definition: rest_server.h:49
enum http_method method
Definition: rest_server.h:45
const boost::smatch * match
Definition: rest_server.h:27
void VmPortGetHandler(const struct RESTData &)
Definition: rest_server.cc:100
uint16_t rest_port() const
Definition: agent_param.h:313
void VmPortEnableHandler(const struct RESTData &data)
Definition: rest_server.cc:212
bool EnablePort(const string &url, string &err_msg)
void VmVnPortGetHandler(const struct RESTData &)
Definition: rest_server.cc:173
static std::string get_client_context(std::string const &s)
Definition: http_session.h:33
void VmPortSyncHandler(const struct RESTData &data)
Definition: rest_server.cc:75
bool AddVmVnPort(const std::string &json, bool check_port, std::string &err_msg, bool write_file)
bool DeleteVmVnPort(const boost::uuids::uuid &vmi_uuid, string &err_msg)
void GatewayPostHandler(const struct RESTData &data)
Definition: rest_server.cc:115
static bool regex_match(const std::string &input, const regex &regex)
Definition: regex.h:34
RestServer(Agent *agent)
Definition: rest_server.cc:305
const PortIpcHandler * pih_
Definition: rest_server.cc:54
std::string Description() const
Definition: rest_server.cc:52
virtual ~RestServer()
Definition: rest_server.cc:351
bool DisablePort(const string &url, string &err_msg)
Definition: agent.h:358
void VmPortPostHandler(const struct RESTData &)
Definition: rest_server.cc:61
HttpSession * session
Definition: rest_server.h:29
static TaskScheduler * GetInstance()
Definition: task.cc:547
void Enqueue(Task *task)
Enqueues a task for running. Starts task if all policy rules are met else puts task in waitq...
Definition: task.cc:636
void VmVnPortDeleteHandler(const struct RESTData &)
Definition: rest_server.cc:158
static const uint16_t PortIpcVrouterAgentPort()
void SendErrorResponse(HttpSession *session, const std::string &error_msg, int status_code, std::string context)
Definition: rest_common.cc:31
contrail::regex request_regex
Definition: rest_server.h:44
void Shutdown()
Definition: http_server.cc:71
HttpServer * http_server_
Definition: rest_server.h:70
void Shutdown()
Definition: rest_server.cc:343
static void DeleteServer(TcpServer *server)
Definition: tcp_server.cc:656
AgentParam * params() const
Definition: agent.h:1218
static bool regex_search(const std::string &input, const regex &regex)
Definition: regex.h:25
Agent * agent_
Definition: rest_server.h:69
static bool set_client_context(std::string const &s, const std::string &ctx)
Definition: http_session.h:38
http_method GetMethod() const
Definition: http_request.h:21
void InitDone()
Definition: rest_server.cc:311
RestServerGetVmCfgTask(PortIpcHandler *pih, const struct RestServer::RESTData &data)
Definition: rest_server.cc:29
#define HTTP_WILDCARD_ENTRY
Definition: http_server.h:16
int GetTaskId() const
Definition: task.h:118
void VmVnPortPostHandler(const struct RESTData &)
Definition: rest_server.cc:144
virtual bool Run()
Code to execute. Returns true if task is completed. Return false to reschedule the task...
Definition: rest_server.cc:38
struct RestServer::RESTData & data_
Definition: rest_server.cc:56
DISALLOW_COPY_AND_ASSIGN(RestServerGetVmCfgTask)
virtual bool Initialize(unsigned short port)
Definition: tcp_server.cc:59
bool AddPortFromJson(const string &json, bool check_port, string &err_msg, bool write_file)
void VmVnPortCfgGetHandler(const struct RESTData &data)
Definition: rest_server.cc:200
void RegisterHandler(const std::string &path, HttpHandlerFn handler)
Definition: http_server.cc:102
Task is a wrapper over tbb::task to support policies.
Definition: task.h:86
std::string UrlPath() const
Definition: http_request.cc:25
bool cat_is_agent_mocked() const
Definition: agent_param.h:569
bool AddVgwFromJson(const std::string &json, std::string &err_msg) const
const std::string context_
Definition: rest_server.cc:57