Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / common / admin_socket_client.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4  * Ceph - scalable distributed file system
5  *
6  * Copyright (C) 2011 New Dream Network
7  *
8  * This is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License version 2.1, as published by the Free Software
11  * Foundation.  See file COPYING.
12  *
13  */
14
15 #include "common/admin_socket.h"
16 #include "common/errno.h"
17 #include "common/safe_io.h"
18 #include "common/admin_socket_client.h"
19
20 #include <sys/un.h>
21
22 using std::ostringstream;
23
24 const char* get_rand_socket_path()
25 {
26   static char *g_socket_path = NULL;
27
28   if (g_socket_path == NULL) {
29     char buf[512];
30     const char *tdir = getenv("TMPDIR");
31     if (tdir == NULL) {
32       tdir = "/tmp";
33     }
34     snprintf(buf, sizeof(((struct sockaddr_un*)0)->sun_path),
35              "%s/perfcounters_test_socket.%ld.%ld",
36              tdir, (long int)getpid(), time(NULL));
37     g_socket_path = (char*)strdup(buf);
38   }
39   return g_socket_path;
40 }
41
42 static std::string asok_connect(const std::string &path, int *fd)
43 {
44   int socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
45   if(socket_fd < 0) {
46     int err = errno;
47     ostringstream oss;
48     oss << "socket(PF_UNIX, SOCK_STREAM, 0) failed: " << cpp_strerror(err);
49     return oss.str();
50   }
51
52   struct sockaddr_un address;
53   memset(&address, 0, sizeof(struct sockaddr_un));
54   address.sun_family = AF_UNIX;
55   snprintf(address.sun_path, sizeof(address.sun_path), "%s", path.c_str());
56
57   if (::connect(socket_fd, (struct sockaddr *) &address, 
58         sizeof(struct sockaddr_un)) != 0) {
59     int err = errno;
60     ostringstream oss;
61     oss << "connect(" << socket_fd << ") failed: " << cpp_strerror(err);
62     close(socket_fd);
63     return oss.str();
64   }
65
66   struct timeval timer;
67   timer.tv_sec = 5;
68   timer.tv_usec = 0;
69   if (::setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, &timer, sizeof(timer))) {
70     int err = errno;
71     ostringstream oss;
72     oss << "setsockopt(" << socket_fd << ", SO_RCVTIMEO) failed: "
73         << cpp_strerror(err);
74     close(socket_fd);
75     return oss.str();
76   }
77   timer.tv_sec = 5;
78   timer.tv_usec = 0;
79   if (::setsockopt(socket_fd, SOL_SOCKET, SO_SNDTIMEO, &timer, sizeof(timer))) {
80     int err = errno;
81     ostringstream oss;
82     oss << "setsockopt(" << socket_fd << ", SO_SNDTIMEO) failed: "
83         << cpp_strerror(err);
84     close(socket_fd);
85     return oss.str();
86   }
87
88   *fd = socket_fd;
89   return "";
90 }
91
92 static std::string asok_request(int socket_fd, std::string request)
93 {
94   ssize_t res = safe_write(socket_fd, request.c_str(), request.length() + 1);
95   if (res < 0) {
96     int err = res;
97     ostringstream oss;
98     oss << "safe_write(" << socket_fd << ") failed to write request code: "
99         << cpp_strerror(err);
100     return oss.str();
101   }
102   return "";
103 }
104
105 AdminSocketClient::
106 AdminSocketClient(const std::string &path)
107   : m_path(path)
108 {
109 }
110
111 std::string AdminSocketClient::ping(bool *ok)
112 {
113   std::string version;
114   std::string result = do_request("{\"prefix\":\"0\"}", &version);
115   *ok = result == "" && version.length() == 1;
116   return result;
117 }
118
119 std::string AdminSocketClient::do_request(std::string request, std::string *result)
120 {
121   int socket_fd = 0, res;
122   std::string buffer;
123   uint32_t message_size_raw, message_size;
124
125   std::string err = asok_connect(m_path, &socket_fd);
126   if (!err.empty()) {
127     goto out;
128   }
129   err = asok_request(socket_fd, request);
130   if (!err.empty()) {
131     goto done;
132   }
133   res = safe_read_exact(socket_fd, &message_size_raw,
134                                 sizeof(message_size_raw));
135   if (res < 0) {
136     int e = res;
137     ostringstream oss;
138     oss << "safe_read(" << socket_fd << ") failed to read message size: "
139         << cpp_strerror(e);
140     err = oss.str();
141     goto done;
142   }
143   message_size = ntohl(message_size_raw);
144   buffer.resize(message_size, 0);
145   res = safe_read_exact(socket_fd, &buffer[0], message_size);
146   if (res < 0) {
147     int e = res;
148     ostringstream oss;
149     oss << "safe_read(" << socket_fd << ") failed: " << cpp_strerror(e);
150     err = oss.str();
151     goto done;
152   }
153   //printf("MESSAGE FROM SERVER: %s\n", buffer.c_str());
154   std::swap(*result, buffer);
155 done:
156   close(socket_fd);
157  out:
158   return err;
159 }