Motr  M0
console.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2012-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
23 #include <sysexits.h>
24 
25 #define M0_TRACE_SUBSYSTEM M0_TRACE_SUBSYS_OTHER
26 #include "lib/trace.h"
27 
28 #include "lib/errno.h" /* ETIMEDOUT */
29 #include "lib/memory.h" /* m0_free */
30 #include "lib/getopts.h" /* M0_GETOPTS */
31 #include "motr/init.h" /* m0_init */
32 #include "rpc/rpclib.h" /* m0_rpc_post_sync */
33 #include "fop/fop.h"
34 #include "fid/fid.h" /* M0_FID_TINIT */
35 #include "fis/fi_command_fops.h" /* m0_fi_command_fop_init */
36 #include "conf/obj.h" /* M0_CONF_PROCESS_TYPE */
37 #include "module/instance.h" /* m0 */
38 #include "console/console.h"
39 #include "console/console_mesg.h"
40 #include "console/console_it.h"
41 #include "console/console_yaml.h"
42 #include "console/console_fop.h"
43 
44 #define PROC_FT M0_CONF_PROCESS_TYPE.cot_ftype.ft_id
45 
51 
52 static uint32_t timeout;
53 
59 static int fop_info_show(uint32_t opcode)
60 {
61  struct m0_fop_type *ftype;
62 
63  fprintf(stdout, "\n");
64  ftype = m0_fop_type_find(opcode);
65  if (ftype == NULL) {
66  fprintf(stderr, "Invalid FOP opcode %.2d.\n", opcode);
67  return M0_ERR(-EINVAL);
68  }
70  fprintf(stdout, "\n");
71  return m0_cons_fop_show(ftype);
72 }
73 
80 static int fop_send_and_print(struct m0_rpc_client_ctx *cctx, uint32_t opcode,
81  const char *fop_input)
82 {
83  struct m0_fop_type *ftype;
84  struct m0_rpc_item *item;
85  struct m0_fop *fop;
86  struct m0_fop *rfop;
87  int rc;
88 
89  M0_ENTRY("opcode=%u fop_input=%s", opcode, fop_input);
90 
91  ftype = m0_fop_type_find(opcode);
92  if (ftype == NULL)
93  return M0_ERR_INFO(-EINVAL, "opcode=%u, fop type not found",
94  opcode);
96  if (fop == NULL)
97  return M0_ERR_INFO(-ENOMEM, "opcode=%u, m0_fop_alloc() failed",
98  opcode);
99  rc = fop_input == NULL ? m0_cons_fop_obj_input(fop) :
100  m0_xcode_read(&M0_FOP_XCODE_OBJ(fop), fop_input);
101  if (rc != 0)
102  return M0_ERR_INFO(rc, "rc=%d with fop_input=%s", rc,
103  fop_input);
104 
105  printf("Sending FOP: ");
106  m0_cons_fop_name_print(ftype);
107 
109  if (rc != 0)
110  return M0_ERR(rc);
111 
113  rc = m0_rpc_post_sync(fop, &cctx->rcx_session, NULL, 0 /* deadline*/);
114  if (rc != 0) {
116  return M0_ERR_INFO(-EINVAL, "Sending message failed");
117  }
118 
119  /* Fetch the FOP reply */
120  item = &fop->f_item;
121  if (item->ri_error != 0) {
123  return M0_ERR_INFO(-EINVAL, "rpc item receive failed");
124  }
125 
127  if(rfop == NULL) {
129  return M0_ERR_INFO(-EINVAL, "RPC item reply not received");
130  }
131 
132  /* Print reply */
133  printf("Server replied with FOP: ");
135 
136  rc = m0_cons_fop_obj_output(rfop);
137  if (rc == 0)
139  return M0_RC(rc);
140 }
141 
142 static const char *usage_msg = "Usage: m0console "
143  " { -l FOP list | -f FOP opcode }"
144  " [-s server (e.g. 172.18.50.40@o2ib1:12345:34:1) ]"
145  " [-c client (e.g. 172.18.50.40@o2ib1:12345:34:*) ]"
146  " [-t timeout]"
147  /*
148  * Please refer to xcode/xcode.h for more information on
149  * xcode read grammar
150  */
151  " [-d fop_description (in xcode read grammar)] "
152  " [[-i] [-y yaml_file_path]]"
153  " [-h] [-v]";
154 
155 static void usage(void)
156 {
157  fprintf(stderr, "%s\n", usage_msg);
158 }
159 
160 #ifdef CONSOLE_UT
161 static int console_init(void)
162 {
163  return 0;
164 }
165 
166 static void console_fini(void)
167 {
168 }
169 #else
170 static int console_init(void)
171 {
172  static struct m0 instance;
173  int rc;
174 
175  rc = m0_init(&instance);
176  if (rc != 0)
177  return M0_RC(rc);
178 
180  if (rc != 0)
181  m0_fini();
182  return M0_RC(rc);
183 }
184 
185 static void console_fini(void)
186 {
188  m0_fini();
189 }
190 #endif /* !CONSOLE_UT */
191 
207 #ifdef CONSOLE_UT
208 int console_main(int argc, char **argv)
209 #else
210 int main(int argc, char **argv)
211 #endif
212 {
213  int result;
214  uint32_t opcode = 0;
215  bool show = false;
216  bool input = false;
217  const char *client = NULL;
218  const char *server = NULL;
219  const char *yaml_path = NULL;
220  const char *fop_desc = NULL;
221  struct m0_net_domain client_net_dom = {};
224 
225  struct m0_rpc_client_ctx cctx = {
227  .rcx_local_addr = "0@lo:12345:34:*",
228  .rcx_remote_addr = "0@lo:12345:34:1",
229  .rcx_max_rpcs_in_flight = 1,
230  .rcx_fid = &M0_FID_TINIT(PROC_FT, 0, 1),
231  };
232 
233  m0_console_verbose = false;
234  yaml_support = false;
235  timeout = 10;
236 
237  result = console_init();
238  if (result != 0)
239  return EX_CONFIG;
240 
241  /*
242  * Gets the info to connect to the service and type of fop to be send.
243  */
244  result = M0_GETOPTS("m0console", argc, argv,
245  M0_HELPARG('h'),
246  M0_FLAGARG('l', "show list of fops", &show),
247  M0_FORMATARG('f', "fop type", "%u", &opcode),
248  M0_STRINGARG('s', "server",
249  LAMBDA(void, (const char *name) {
250  server = name;
251  })),
252  M0_STRINGARG('c', "client",
253  LAMBDA(void, (const char *name) {
254  client = name;
255  })),
256  M0_FORMATARG('t', "wait time(in seconds)",
257  "%u", &timeout),
258  M0_FLAGARG('i', "yaml input", &input),
259  M0_FORMATARG('q', "minimum TM receive queue length",
260  "%i", &tm_recv_queue_len),
261  M0_FORMATARG('m', "max rpc msg size", "%i",
263  M0_STRINGARG('y', "yaml file path",
264  LAMBDA(void, (const char *name) {
265  yaml_path = name;
266  })),
267  M0_STRINGARG('d', "fop description",
268  LAMBDA(void, (const char *fd) {
269  fop_desc = fd;
270  })),
271  M0_FLAGARG('v', "verbose", &m0_console_verbose));
272  if (result != 0)
273  /*
274  * No need to print "usage" here, M0_GETOPTS will automatically
275  * do it for us
276  */
277  return EX_USAGE;
278 
279  if (argc == 1 || (m0_console_verbose && argc == 2)) {
280  usage();
281  return EX_USAGE;
282  }
283 
284  /* Input is false but yaml is assigned path or
285  * both yaml and fop description is provided */
286  if ((!input && yaml_path != NULL) ||
287  (input && yaml_path == NULL) ||
288  (fop_desc != NULL && yaml_path != NULL)) {
289  usage();
290  return EX_USAGE;
291  }
292 
293  /* Init YAML info */
294  if (input) {
295  result = m0_cons_yaml_init(yaml_path);
296  if (result != 0) {
297  fprintf(stderr, "YAML Init failed\n");
298  return EX_NOINPUT;
299  }
300 
301  server = m0_cons_yaml_get_value("server");
302  if (server == NULL) {
303  fprintf(stderr, "Server assignment failed\n");
304  result = EX_DATAERR;
305  goto end;
306  }
307  client = m0_cons_yaml_get_value("client");
308  if (client == NULL) {
309  fprintf(stderr, "Client assignment failed\n");
310  result = EX_DATAERR;
311  goto end;
312  }
313  }
314 
315  if (show && opcode == 0) {
317  usage();
318  result = EX_USAGE;
319  goto end;
320  }
321 
322  if (show && opcode > 0) {
323  result = fop_info_show(opcode);
324  if (result == 0)
325  result = EX_OK;
326  goto end;
327  }
328 
330  M0_ASSERT(result == 0);
331 
332  /* Init the console members from CLI input */
333  if (server != NULL)
334  cctx.rcx_remote_addr = server;
335  if (client != NULL)
340 
341  printf("connecting from %s to %s\n", cctx.rcx_local_addr,
343  result = m0_rpc_client_start(&cctx);
344  if (result != 0) {
345  fprintf(stderr, "m0_rpc_client_start failed\n");
346  result = EX_SOFTWARE;
347  goto end;
348  }
349  printf("connected\n");
350 
351  printf("Console Address = %s\n", cctx.rcx_local_addr);
352  printf("Server Address = %s\n", cctx.rcx_remote_addr);
353 
354  /*
355  * Need to init fic fop explicitly here as normally it gets initialised
356  * at FI Service start (see fis_start()).
357  */
359  /* Build the fop/fom/item and send */
360  result = fop_send_and_print(&cctx, opcode, fop_desc);
361  if (result != 0) {
362  fprintf(stderr, "fop_send_and_print failed\n");
363  result = EX_SOFTWARE;
364  goto cleanup;
365  }
366 cleanup:
368  result = m0_rpc_client_stop(&cctx);
369  M0_ASSERT(result == 0);
370 end:
371  console_fini();
372  if (input)
374 
375  return result;
376 }
377 
379 #undef M0_TRACE_SUBSYSTEM
380 
381 /*
382  * Local variables:
383  * c-indentation-style: "K&R"
384  * c-basic-offset: 8
385  * tab-width: 8
386  * fill-column: 80
387  * scroll-step: 1
388  * End:
389  */
#define M0_GETOPTS(progname, argc, argv,...)
Definition: getopts.h:169
#define M0_FLAGARG(ch, desc, ptr)
Definition: getopts.h:232
#define NULL
Definition: misc.h:38
void m0_fini(void)
Definition: init.c:318
static struct m0_rpc_client_ctx cctx
Definition: console.c:72
static uint32_t max_rpc_msg_size
Definition: m0dixinit.c:72
M0_INTERNAL int m0_xcode_read(struct m0_xcode_obj *obj, const char *str)
Definition: string.c:162
int32_t ri_error
Definition: item.h:161
static void console_fini(void)
Definition: console.c:185
M0_INTERNAL int m0_cons_yaml_init(const char *file_path)
Inititalizes parser by opening given file. and also checks for error by getting root node...
Definition: console_yaml.c:94
int m0_init(struct m0 *instance)
Definition: init.c:310
static int fop_send_and_print(struct m0_rpc_client_ctx *cctx, uint32_t opcode, const char *fop_input)
Build the RPC item using FOP (Embedded into item) and send it.
Definition: console.c:80
static struct m0_rpc_item * item
Definition: item.c:56
return M0_RC(rc)
int main(int argc, char **argv)
The service to connect to is specified at the command line.
Definition: console.c:210
#define M0_ENTRY(...)
Definition: trace.h:170
int opcode
Definition: crate.c:301
#define M0_STRINGARG(ch, desc, func)
Definition: getopts.h:207
struct m0_fop_type * f_type
Definition: fop.h:81
#define M0_ERR_INFO(rc, fmt,...)
Definition: trace.h:215
static int console_init(void)
Definition: console.c:170
static int tm_recv_queue_len
Definition: fdmi_echo.c:85
return M0_ERR(-EOPNOTSUPP)
#define LAMBDA(T,...)
Definition: thread.h:153
const char * name
Definition: trace.c:110
#define M0_FID_TINIT(type, container, key)
Definition: fid.h:90
M0_INTERNAL void m0_cons_yaml_fini(void)
Deletes the parser and closes the YAML file.
Definition: console_yaml.c:147
#define M0_FORMATARG(ch, desc, fmt, ptr)
Definition: getopts.h:218
void client(struct client_params *params)
Definition: main.c:233
#define M0_ASSERT(cond)
uint32_t rcx_max_rpc_msg_size
Definition: rpclib.h:156
static int fop_info_show(uint32_t opcode)
Iterate over FOP and print names of its members.
Definition: console.c:59
Definition: client.h:37
int m0_rpc_client_stop(struct m0_rpc_client_ctx *cctx)
Definition: rpclib.c:217
Definition: instance.h:80
struct m0_net_xprt * m0_net_xprt_default_get(void)
Definition: net.c:151
int m0_rpc_client_start(struct m0_rpc_client_ctx *cctx)
Definition: rpclib.c:160
struct m0_rpc_item * ri_reply
Definition: item.h:163
uint32_t rcx_recv_queue_min_length
Definition: rpclib.h:153
int m0_rpc_post_sync(struct m0_fop *fop, struct m0_rpc_session *session, const struct m0_rpc_item_ops *ri_ops, m0_time_t deadline)
Definition: rpclib.c:284
uint64_t ri_nr_sent_max
Definition: item.h:146
M0_INTERNAL void m0_fi_command_fop_init(void)
M0_INTERNAL int m0_cons_fop_show(struct m0_fop_type *fopt)
Iterate over FOP fields and print names.
Definition: console_mesg.c:68
M0_INTERNAL int m0_cons_fop_obj_output(struct m0_fop *fop)
Helper function for FOP output.
Definition: console_it.c:272
bool m0_console_verbose
Definition: console.c:50
m0_time_t rcx_abs_timeout
Definition: rpclib.h:159
struct m0_net_domain * rcx_net_dom
Definition: rpclib.h:128
M0_INTERNAL struct m0_fop_type * m0_fop_type_find(uint32_t opcode)
Definition: fop.c:388
M0_INTERNAL int m0_cons_fop_obj_input(struct m0_fop *fop)
Helper function for FOP input.
Definition: console_it.c:267
static uint32_t timeout
Definition: console.c:52
static const char * usage_msg
Definition: console.c:142
static struct m0_net_domain client_net_dom
Definition: console.c:70
int m0_net_domain_init(struct m0_net_domain *dom, const struct m0_net_xprt *xprt)
Definition: domain.c:36
struct m0_rpc_session rcx_session
Definition: rpclib.h:147
m0_time_t m0_time_from_now(uint64_t secs, long ns)
Definition: time.c:96
const char * rcx_remote_addr
Definition: rpclib.h:134
M0_INTERNAL void * m0_cons_yaml_get_value(const char *name)
Search for specified string and set the respctive value form YAML file. (like "name : console") ...
Definition: console_yaml.c:177
#define M0_HELPARG(ch)
Definition: getopts.h:242
void m0_fop_put_lock(struct m0_fop *fop)
Definition: fop.c:199
static struct m0_fop * fop
Definition: item.c:57
static struct m0 instance
Definition: main.c:78
struct m0_fop * m0_rpc_item_to_fop(const struct m0_rpc_item *item)
Definition: fop.c:346
struct m0t1fs_filedata * fd
Definition: dir.c:1030
M0_INTERNAL bool yaml_support
Definition: console_yaml.c:92
const char * rcx_local_addr
Definition: rpclib.h:131
struct m0_rpc_machine rcx_rpc_machine
Definition: rpclib.h:145
M0_INTERNAL void m0_cons_fop_list_show(void)
Helper function to print list of FOPs.
Definition: console_mesg.c:88
M0_INTERNAL void m0_cons_fop_name_print(const struct m0_fop_type *ftype)
Definition: console_mesg.c:34
M0_INTERNAL void m0_fi_command_fop_fini(void)
M0_INTERNAL int m0_console_fop_init(void)
Definition: console_fop.c:51
#define M0_FOP_XCODE_OBJ(f)
Definition: fop.h:334
M0_INTERNAL void m0_console_fop_fini(void)
Definition: console_fop.c:42
static void usage(void)
Definition: console.c:155
struct m0_rpc_item f_item
Definition: fop.h:83
int32_t rc
Definition: trigger_fop.h:47
Definition: fop.h:79
struct m0_fop * m0_fop_alloc(struct m0_fop_type *fopt, void *data, struct m0_rpc_machine *mach)
Definition: fop.c:96
#define PROC_FT
Definition: console.c:44