OpenSDN source code
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/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 namespace boost::placeholders;
24 
25 using contrail::regex;
28 
29 class RestServerGetVmCfgTask : public Task {
30 public:
32  const struct RestServer::RESTData& data):
33  Task((TaskScheduler::GetInstance()->GetTaskId("Agent::RestApi")), 0),
34  pih_(pih),
35  vm_name_((*data.match)[1]),
36  data_(data),
37  context_(data_.session->get_context()) {
38  }
40  virtual bool Run() {
41  std::string info;
42  const std::string client_ctx = data_.session->get_client_context(context_);
43  // check session is not deleted
44  if ((!data_.session->set_client_context(context_, client_ctx)) ||
45  (context_.empty()))
46  return true;
47  if (pih_->GetVmVnCfgPort(vm_name_, info)) {
48  REST::SendResponse(data_.session, info, 200, context_);
49  } else {
50  REST::SendErrorResponse(data_.session, "{ Not Found }", 404, context_);
51  }
52  return true;
53  }
54  std::string Description() const { return "RestServerGetVmCfgTask"; }
55 private:
57  std::string vm_name_;
58  const struct RestServer::RESTData& data_;
59  const std::string context_;
61 };
62 
63 void RestServer::VmPortPostHandler(const struct RESTData& data) {
65  if (pih) {
66  std::string err_msg;
67  if (pih->AddPortFromJson(data.request->Body(), false, err_msg, true)) {
68  REST::SendResponse(data.session, "{}");
69  } else {
70  REST::SendErrorResponse(data.session, "{ " + err_msg + " }");
71  }
72  } else {
73  REST::SendErrorResponse(data.session, "{ Operation Not Supported }");
74  }
75 }
76 
77 void RestServer::VmPortSyncHandler(const struct RESTData& data) {
79  if (pih) {
80  pih->SyncHandler();
81  REST::SendResponse(data.session, "{}");
82  } else {
83  REST::SendErrorResponse(data.session, "{ Operation Not Supported }");
84  }
85 }
86 
87 void RestServer::VmPortDeleteHandler(const struct RESTData& data) {
88  std::string error;
89  const std::string& port_id = (*data.match)[1];
91  if (pih) {
92  if (pih->DeletePort(port_id, error)) {
93  REST::SendResponse(data.session, "{}");
94  } else {
95  REST::SendErrorResponse(data.session, "{" + error + "}");
96  }
97  } else {
98  REST::SendErrorResponse(data.session, "{ Operation Not Supported }");
99  }
100 }
101 
102 void RestServer::VmPortGetHandler(const struct RESTData& data) {
103  const std::string& port_id = (*data.match)[1];
105  if (pih) {
106  std::string info;
107  if (pih->GetPortInfo(port_id, info)) {
108  REST::SendResponse(data.session, info);
109  } else {
110  REST::SendErrorResponse(data.session, "{ Not Found }", 404);
111  }
112  } else {
113  REST::SendErrorResponse(data.session, "{ Operation Not Supported }");
114  }
115 }
116 
117 void RestServer::GatewayPostHandler(const struct RESTData& data) {
119  if (pih) {
120  std::string err_msg;
121  if (pih->AddVgwFromJson(data.request->Body(), err_msg)) {
122  REST::SendResponse(data.session, "{}");
123  } else {
124  REST::SendErrorResponse(data.session, "{ " + err_msg + " }");
125  }
126  } else {
127  REST::SendErrorResponse(data.session, "{ Operation Not Supported }");
128  }
129 }
130 
131 void RestServer::GatewayDeleteHandler(const struct RESTData& data) {
132  std::string error;
134  if (pih) {
135  std::string err_msg;
136  if (pih->DelVgwFromJson(data.request->Body(), err_msg)) {
137  REST::SendResponse(data.session, "{}");
138  } else {
139  REST::SendErrorResponse(data.session, "{" + error + "}");
140  }
141  } else {
142  REST::SendErrorResponse(data.session, "{ Operation Not Supported }");
143  }
144 }
145 
146 void RestServer::VmVnPortPostHandler(const struct RESTData& data) {
148  if (pih) {
149  std::string err_msg;
150  if (pih->AddVmVnPort(data.request->Body(), false, err_msg, true)) {
151  REST::SendResponse(data.session, "{}");
152  } else {
153  REST::SendErrorResponse(data.session, "{ " + err_msg + " }");
154  }
155  } else {
156  REST::SendErrorResponse(data.session, "{ Operation Not Supported }");
157  }
158 }
159 
160 void RestServer::VmVnPortDeleteHandler(const struct RESTData& data) {
161  std::string error;
162  const std::string &vm_uuid = (*data.match)[1];
164  if (pih) {
165  if (pih->DeleteVmVnPort(data.request->Body(), vm_uuid, error)) {
166  REST::SendResponse(data.session, "{}");
167  } else {
168  REST::SendErrorResponse(data.session, "{" + error + "}");
169  }
170  } else {
171  REST::SendErrorResponse(data.session, "{ Operation Not Supported }");
172  }
173 }
174 
175 void RestServer::VmVnPortGetHandler(const struct RESTData& data) {
176  std::string url = (*data.match)[0];
177  bool vmi_uuid_presence = false;
178  std::size_t pos = 4; // skip "/vm/"
179  std::size_t vmi_uuid_pos = url.find("/", pos);
180  if (vmi_uuid_pos != std::string::npos) {
181  vmi_uuid_presence = true;
182  }
183  std::string vm_uuid = url.substr(pos, vmi_uuid_pos);
184  std::string vmi_uuid = "";
185  if (vmi_uuid_presence) {
186  vmi_uuid = url.substr(vmi_uuid_pos+1, std::string::npos);
187  }
188 
190  if (pih) {
191  std::string info;
192  if (pih->GetVmVnPort(vm_uuid, vmi_uuid, info)) {
193  REST::SendResponse(data.session, info);
194  } else {
195  REST::SendErrorResponse(data.session, "{ Not Found }", 404);
196  }
197  } else {
198  REST::SendErrorResponse(data.session, "{ Operation Not Supported }");
199  }
200 }
201 
202 void RestServer::VmVnPortCfgGetHandler(const struct RESTData& data) {
204  if (pih) {
206  new RestServerGetVmCfgTask(pih, data);
208  scheduler->Enqueue(t);
209  } else {
210  REST::SendErrorResponse(data.session, "{ Operation Not Supported }");
211  }
212 }
213 
214 void RestServer::VmPortEnableHandler(const struct RESTData& data) {
215  std::string error;
216  const std::string& port_id = (*data.match)[1];
218  if (pih) {
219  if (pih->EnablePort(port_id, error)) {
220  REST::SendResponse(data.session, "{}");
221  } else {
222  REST::SendErrorResponse(data.session, "{" + error + "}");
223  }
224  } else {
225  REST::SendErrorResponse(data.session, "{ Operation Not Supported }");
226  }
227 }
228 
229 void RestServer::VmPortDisableHandler(const struct RESTData& data) {
230  std::string error;
231  const std::string& port_id = (*data.match)[1];
233  if (pih) {
234  if (pih->DisablePort(port_id, error)) {
235  REST::SendResponse(data.session, "{}");
236  } else {
237  REST::SendErrorResponse(data.session, "{" + error + "}");
238  }
239  } else {
240  REST::SendErrorResponse(data.session, "{ Operation Not Supported }");
241  }
242 }
243 
244 const std::vector<RestServer::HandlerSpecifier> RestServer::RESTHandlers_ =
245  boost::assign::list_of
246  (HandlerSpecifier(
247  regex("/port"),
248  HTTP_POST,
250  (HandlerSpecifier(
251  regex("/syncports"),
252  HTTP_POST,
254  (HandlerSpecifier(
255  regex("/port/"
256  "([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})"),
257  HTTP_DELETE,
259  (HandlerSpecifier(
260  regex("/port/"
261  "([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})"),
262  HTTP_GET,
264  (HandlerSpecifier(
265  regex("/gateway"),
266  HTTP_POST,
268  (HandlerSpecifier(
269  regex("/gateway"),
270  HTTP_DELETE,
272  (HandlerSpecifier(
273  regex("/vm"),
274  HTTP_POST,
276  (HandlerSpecifier(
277  regex("/vm/"
278  "([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})"),
279  HTTP_DELETE,
281  (HandlerSpecifier(
282  regex("/vm/"
283  "([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})"),
284  HTTP_GET,
286  (HandlerSpecifier(
287  regex("/vm/"
288  "([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/"
289  "([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})"),
290  HTTP_GET,
292  (HandlerSpecifier(
293  regex("/vm-cfg/(.*)"),
294  HTTP_GET,
296  (HandlerSpecifier(
297  regex("/enable-port/"
298  "([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})"),
299  HTTP_PUT,
301  (HandlerSpecifier(
302  regex("/disable-port/"
303  "([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})"),
304  HTTP_PUT,
306 
308  : agent_(agent), http_server_(new HttpServer(agent->event_manager())) {
310  boost::bind(&RestServer::HandleRequest, this, _1, _2));
311 }
312 
315  //only if RestServer is used via mocked agent
317  else //otherwise , use the hardcoded value
319 }
320 
322  const HttpRequest* request) {
323  std::string path = request->UrlPath();
324  BOOST_FOREACH(const RestServer::HandlerSpecifier& hs, RESTHandlers_) {
325  boost::smatch match;
326  if (regex_match(path, match, hs.request_regex) &&
327  request->GetMethod() == hs.method) {
328  struct RESTData data = {
329  &match,
330  request->GetMethod(),
331  session,
332  request
333  };
334  (this->*hs.handler_func)(data);
335  // Though IMHO it contradicts most programmers' intuition,
336  // currently handlers are responsible for freeing handled
337  // requests.
338  delete request;
339  return;
340  }
341  }
342  REST::SendErrorResponse(session, "Unknown Request", 404);
343 }
344 
346  if (http_server_) {
349  http_server_ = NULL;
350  }
351 }
352 
354 }
bool cat_is_agent_mocked() const
Definition: agent_param.h:567
uint16_t rest_port() const
Definition: agent_param.h:311
Definition: agent.h:360
PortIpcHandler * port_ipc_handler() const
Definition: agent.cc:1008
AgentParam * params() const
Definition: agent.h:1226
static const uint16_t PortIpcVrouterAgentPort()
const std::string & Body() const
Definition: http_request.h:39
http_method GetMethod() const
Definition: http_request.h:21
std::string UrlPath() const
Definition: http_request.cc:25
void RegisterHandler(const std::string &path, HttpHandlerFn handler)
Definition: http_server.cc:102
void Shutdown()
Definition: http_server.cc:71
bool DisablePort(const string &url, string &err_msg)
bool EnablePort(const string &url, string &err_msg)
bool DeletePort(const string &url, string &err_msg)
bool GetVmVnPort(const std::string &vm_uuid, const std::string &vmi_uuid, std::string &info) const
bool AddVgwFromJson(const std::string &json, std::string &err_msg) const
bool GetPortInfo(const std::string &uuid_str, std::string &info) const
bool AddPortFromJson(const string &json, bool check_port, string &err_msg, bool write_file)
bool DeleteVmVnPort(const boost::uuids::uuid &vmi_uuid, string &err_msg)
bool AddVmVnPort(const std::string &json, bool check_port, std::string &err_msg, bool write_file)
bool DelVgwFromJson(const std::string &json, std::string &err_msg) const
const PortIpcHandler * pih_
Definition: rest_server.cc:56
DISALLOW_COPY_AND_ASSIGN(RestServerGetVmCfgTask)
const struct RestServer::RESTData & data_
Definition: rest_server.cc:58
std::string Description() const
Gives a description of the task.
Definition: rest_server.cc:54
const std::string context_
Definition: rest_server.cc:59
RestServerGetVmCfgTask(PortIpcHandler *pih, const struct RestServer::RESTData &data)
Definition: rest_server.cc:31
virtual bool Run()
Code to execute in a task. Returns true if task is completed. Return false to reschedule the task.
Definition: rest_server.cc:40
virtual ~RestServerGetVmCfgTask()
Definition: rest_server.cc:39
contrail::regex request_regex
Definition: rest_server.h:44
enum http_method method
Definition: rest_server.h:45
HttpServer * http_server_
Definition: rest_server.h:70
void VmVnPortGetHandler(const struct RESTData &)
Definition: rest_server.cc:175
static const std::vector< HandlerSpecifier > RESTHandlers_
Definition: rest_server.h:49
void Shutdown()
Definition: rest_server.cc:345
void VmPortEnableHandler(const struct RESTData &data)
Definition: rest_server.cc:214
friend class RestServerGetVmCfgTask
Definition: rest_server.h:67
void VmPortGetHandler(const struct RESTData &)
Definition: rest_server.cc:102
void GatewayDeleteHandler(const struct RESTData &data)
Definition: rest_server.cc:131
RestServer(Agent *agent)
Definition: rest_server.cc:307
void VmVnPortPostHandler(const struct RESTData &)
Definition: rest_server.cc:146
void VmVnPortDeleteHandler(const struct RESTData &)
Definition: rest_server.cc:160
Agent * agent_
Definition: rest_server.h:69
void VmPortDeleteHandler(const struct RESTData &)
Definition: rest_server.cc:87
void VmPortDisableHandler(const struct RESTData &data)
Definition: rest_server.cc:229
void GatewayPostHandler(const struct RESTData &data)
Definition: rest_server.cc:117
virtual ~RestServer()
Definition: rest_server.cc:353
void VmVnPortCfgGetHandler(const struct RESTData &data)
Definition: rest_server.cc:202
void VmPortPostHandler(const struct RESTData &)
Definition: rest_server.cc:63
void InitDone()
Definition: rest_server.cc:313
void VmPortSyncHandler(const struct RESTData &data)
Definition: rest_server.cc:77
void HandleRequest(HttpSession *session, const HttpRequest *request)
Definition: rest_server.cc:321
The TaskScheduler keeps track of what tasks are currently schedulable. When a task is enqueued it is ...
Definition: task.h:304
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:642
static TaskScheduler * GetInstance()
Definition: task.cc:554
Task is a class to describe a computational task within OpenSDN control plane applications....
Definition: task.h:79
static void DeleteServer(TcpServer *server)
Definition: tcp_server.cc:658
virtual bool Initialize(unsigned short port)
Definition: tcp_server.cc:60
#define HTTP_WILDCARD_ENTRY
Definition: http_server.h:16
void SendErrorResponse(HttpSession *session, const std::string &error_msg, int status_code, std::string context)
Definition: rest_common.cc:31
void SendResponse(HttpSession *session, const std::string &msg, int status_code, std::string context)
Definition: rest_common.cc:15
static bool regex_search(const std::string &input, const regex &regex)
Definition: regex.h:25
static bool regex_match(const std::string &input, const regex &regex)
Definition: regex.h:34
const boost::smatch * match
Definition: rest_server.h:27
const HttpRequest * request
Definition: rest_server.h:30
HttpSession * session
Definition: rest_server.h:29