1 /*
2    Copyright (c) 2003, 2021, Oracle and/or its affiliates.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #ifndef MgmtSrvr_H
26 #define MgmtSrvr_H
27 
28 #include "Config.hpp"
29 #include "ConfigSubscriber.hpp"
30 
31 #include <mgmapi.h>
32 #include <Vector.hpp>
33 #include <NodeBitmask.hpp>
34 #include <ndb_version.h>
35 #include <EventLogger.hpp>
36 
37 #include <SignalSender.hpp>
38 
39 #define MGM_ERROR_MAX_INJECT_SESSION_ONLY 10000
40 
41 class SetLogLevelOrd;
42 
43 class Ndb_mgmd_event_service : public EventLoggerBase
44 {
45   friend class MgmtSrvr;
46 public:
47   struct Event_listener : public EventLoggerBase {
Event_listenerNdb_mgmd_event_service::Event_listener48     Event_listener() {}
49     NDB_SOCKET_TYPE m_socket;
50     Uint32 m_parsable;
51   };
52 
53 private:
54   class MgmtSrvr * m_mgmsrv;
55   MutexVector<Event_listener> m_clients;
56 public:
Ndb_mgmd_event_service(class MgmtSrvr * m)57   Ndb_mgmd_event_service(class MgmtSrvr * m) : m_clients(5) {
58     m_mgmsrv = m;
59   }
60 
61   void add_listener(const Event_listener&);
62   void check_listeners();
63   void update_max_log_level(const LogLevel&);
64   void update_log_level(const LogLevel&);
65 
66   void log(int eventType, const Uint32* theData, Uint32 len, NodeId nodeId);
67 
68   void stop_sessions();
69 
operator [](unsigned i)70   Event_listener& operator[](unsigned i) { return m_clients[i]; }
operator [](unsigned i) const71   const Event_listener& operator[](unsigned i) const { return m_clients[i]; }
lock()72   void lock() { m_clients.lock(); }
unlock()73   void unlock(){ m_clients.unlock(); }
74 };
75 
76 
77 
78 /**
79   @class MgmtSrvr
80   @brief Main class for the management server.
81  */
82 class MgmtSrvr : private ConfigSubscriber, public trp_client {
83 
84 public:
85   /**
86    *   This enum specifies the different signal loggig modes possible to set
87    *   with the setSignalLoggingMode method.
88    */
89   enum LogMode {In, Out, InOut, Off};
90 
91   /**
92      @struct MgmtOpts
93      @brief Options used to control how the management server is started
94   */
95 
96   struct MgmtOpts {
97     int daemon;
98     int non_interactive;
99     int interactive;
100     const char* config_filename;
101     int mycnf;
102     int config_cache;
103     const char* bind_address;
104     int no_nodeid_checks;
105     int print_full_config;
106     const char* configdir;
107     int verbose;
MgmtOptsMgmtSrvr::MgmtOpts108     MgmtOpts() : configdir(MYSQLCLUSTERDIR) {};
109     int reload;
110     int initial;
111     NodeBitmask nowait_nodes;
112   };
113 
114   MgmtSrvr(); // Not implemented
115   MgmtSrvr(const MgmtSrvr&); // Not implemented
116   MgmtSrvr(const MgmtOpts&);
117 
118   ~MgmtSrvr();
119 
120 private:
121   /* Function used from 'init' */
122   const char* check_configdir() const;
123 
124 public:
125   /*
126     To be called after constructor.
127   */
128   bool init();
129 
130   /*
131     To be called after 'init', starts up the services
132     this server will expose
133    */
134   bool start(void);
135 private:
136   /* Functions used from 'start' */
137   bool start_transporter(const Config*);
138   bool start_mgm_service(const Config*);
139   bool connect_to_self(void);
140 
141 public:
142 
getOwnNodeId() const143   NodeId getOwnNodeId() const {return _ownNodeId;};
144 
145   /**
146    * Get status on a node.
147    * address may point to a common area (e.g. from inet_addr)
148    * There is no guarentee that it is preserved across calls.
149    * Copy the string if you are not going to use it immediately.
150    */
151   int status(int nodeId,
152 	     ndb_mgm_node_status * status,
153 	     Uint32 * version,
154 	     Uint32 * mysql_version,
155 	     Uint32 * phase,
156 	     bool * systemShutdown,
157 	     Uint32 * dynamicId,
158 	     Uint32 * nodeGroup,
159 	     Uint32 * connectCount,
160 	     const char **address,
161              char *addr_buf,
162              size_t addr_buf_size);
163 
164   /**
165    *   Stop a list of nodes
166    */
167   int stopNodes(const Vector<NodeId> &node_ids, int *stopCount, bool abort,
168                 bool force, int *stopSelf);
169 
170   int shutdownMGM(int *stopCount, bool abort, int *stopSelf);
171 
172   /**
173    * shutdown the DB nodes
174    */
175   int shutdownDB(int * cnt = 0, bool abort = false);
176 
177   /**
178    *   Maintenance on the system
179    */
180   int enterSingleUser(int * cnt = 0, Uint32 singleuserNodeId = 0);
181 
182 
183   /**
184    *   Resume from maintenance on the system
185    */
186   int exitSingleUser(int * cnt = 0, bool abort = false);
187 
188   /**
189    *   Start DB process by sending START_ORD to it.
190    *   @param   processId: Id of the DB process to start
191    *   @return 0 if succeeded, otherwise: as stated above, plus:
192    */
193  int sendSTART_ORD(int processId);
194 
195   /**
196    *   Restart a list of nodes
197    */
198   int restartNodes(const Vector<NodeId> &node_ids,
199                    int *stopCount, bool nostart,
200                    bool initialStart, bool abort, bool force,
201                    int *stopSelf,
202                    unsigned int num_secs_to_wait_for_node = 120);
203 
204   /**
205    *   Restart all DB nodes
206    */
207   int restartDB(bool nostart, bool initialStart,
208                 bool abort = false,
209                 int * stopCount = 0,
210                 unsigned int num_secs_to_wait_for_node = 120);
211 
212   /**
213    * Backup functionallity
214    */
215   int startBackup(Uint32& backupId, int waitCompleted= 2, Uint32 input_backupId= 0, Uint32 backuppoint= 0);
216   int abortBackup(Uint32 backupId);
217   int performBackup(Uint32* backupId);
218 
219   //**************************************************************************
220   // Description: Set event report level for a DB process
221   // Parameters:
222   //  processId: Id of the DB process
223   //  level: Event report level
224   //  isResend: Flag to indicate for resending log levels during node restart
225   // Returns: 0 if succeeded, otherwise: as stated above, plus:
226   //  INVALID_LEVEL
227   //**************************************************************************
228 
229   int setEventReportingLevelImpl(int processId, const EventSubscribeReq& ll);
230   int setNodeLogLevelImpl(int processId, const SetLogLevelOrd & ll);
231 
232   /**
233    *   Insert an error in a DB process.
234    *   @param   processId: Id of the DB process
235    *   @param   errorNo: The error number. > 0.
236    *   @return  0 if succeeded, otherwise: as stated above, plus:
237    *            INVALID_ERROR_NUMBER
238    */
239   int insertError(int processId, int errorNo, Uint32 * extra = 0);
240 
241 
242 
243   int setTraceNo(int processId, int traceNo);
244   //**************************************************************************
245   // Description: Set trace number in a DB process.
246   // Parameters:
247   //  processId: Id of the DB process
248   //  trace: Trace number
249   // Returns: 0 if succeeded, otherwise: as stated above, plus:
250   //  INVALID_TRACE_NUMBER
251   //**************************************************************************
252 
253 
254   int setSignalLoggingMode(int processId, LogMode mode,
255 			   const Vector<BaseString> &blocks);
256 
setSignalLoggingMode(int processId,LogMode mode,BaseString & block)257   int setSignalLoggingMode(int processId, LogMode mode,
258 			   BaseString &block) {
259     Vector<BaseString> v;
260     v.push_back(block);
261     return setSignalLoggingMode(processId, mode, v);
262   }
263   //**************************************************************************
264   // Description: Set signal logging mode for blocks in a DB process.
265   // Parameters:
266   //  processId: Id of the DB process
267   //  mode: The log mode
268   //  blocks: Which blocks to be affected (container of strings)
269   // Returns: 0 if succeeded, otherwise: as stated above, plus:
270   //  INVALID_BLOCK_NAME
271   //**************************************************************************
272 
273 
274   int startSignalTracing(int processId);
275   //**************************************************************************
276   // Description: Start signal tracing for a DB process.
277   // Parameters:
278   //  processId: Id of the DB process
279   // Returns: 0 if succeeded, otherwise: as stated above.
280   //**************************************************************************
281 
282 
283   int stopSignalTracing(int processId);
284   //**************************************************************************
285   // Description: Stop signal tracing for a DB process.
286   // Parameters:
287   //  processId: Id of the DB process
288   // Returns: 0 if succeeded, otherwise: as stated above.
289   //**************************************************************************
290 
291   /**
292    *   Dump State
293    */
294   int dumpState(int processId, const Uint32 args[], Uint32 argNo);
295   int dumpState(int processId, const char* args);
296 
297   /**
298    * Get next node id (node id gt than _nodeId)
299    *  of specified type and save it in _nodeId
300    *
301    *   @return false if none found
302    */
303   bool getNextNodeId(NodeId * _nodeId, enum ndb_mgm_node_type type) const ;
304 
305   bool change_config(Config& new_config, BaseString& msg);
306 
307   /**
308    *   Get error text
309    *
310    *   @param   errorCode: Error code to get a match error text for.
311    *   @return  The error text.
312    */
313   const char* getErrorText(int errorCode, char *buf, int buf_sz);
314 
315 private:
316   void config_changed(NodeId, const Config*);
317   void setClusterLog(const Config* conf);
318   void configure_eventlogger(const BaseString& logdestination) const;
319 public:
320 
321   /**
322    * Returns the port number where MgmApiService is started
323    * @return port number.
324    */
getPort() const325   int getPort() const { return m_port; };
326 
327   int setDbParameter(int node, int parameter, const char * value, BaseString&);
328   int setConnectionDbParameter(int node1, int node2, int param, int value,
329 			       BaseString& msg);
330 
331   struct DynPortSpec {
332    int node; /* The node which should use below port */
333    int port; /* The port to use */
334   };
335   bool setDynamicPorts(int node, DynPortSpec ports[],
336                        unsigned num_ports, BaseString &msg);
337   int getConnectionDbParameter(int node1, int node2, int param,
338 			       int *value, BaseString& msg);
339 
340   bool transporter_connect(NDB_SOCKET_TYPE sockfd,
341                            BaseString& errormsg,
342                            bool& close_with_reset);
343 
get_socket_server()344   SocketServer *get_socket_server() { return &m_socket_server; }
345 
346   int createNodegroup(int *nodes, int count, int *ng);
347   int dropNodegroup(int ng);
348 
349   int startSchemaTrans(SignalSender& ss, NodeId & out_nodeId,
350                        Uint32 transId, Uint32 & out_transKey);
351   int endSchemaTrans(SignalSender& ss, NodeId nodeId,
352                      Uint32 transId, Uint32 transKey, Uint32 flags);
353 
354 private:
355   int guess_master_node(SignalSender&);
356 
357   void status_api(int nodeId,
358                   ndb_mgm_node_status& node_status,
359                   Uint32& version, Uint32& mysql_version,
360                   const char **address,
361                   char *addr_buf,
362                   size_t addr_buf_size);
363   void status_mgmd(NodeId node_id,
364                    ndb_mgm_node_status& node_status,
365                    Uint32& version, Uint32& mysql_version,
366                    const char **address,
367                    char *addr_buf,
368                    size_t addr_buf_size);
369 
370   int sendVersionReq(int processId,
371                      Uint32 &version,
372                      Uint32& mysql_version,
373                      const char **address,
374                      char *addr_buf,
375                      size_t addr_buf_size);
376 
377   int sendStopMgmd(NodeId nodeId,
378                    bool abort,
379                    bool stop,
380                    bool restart,
381                    bool nostart,
382                    bool initialStart);
383 
384   int sendall_STOP_REQ(NodeBitmask &stoppedNodes,
385                        bool abort,
386                        bool stop,
387                        bool restart,
388                        bool nostart,
389                        bool initialStart);
390 
391   int sendSTOP_REQ(const Vector<NodeId> &node_ids,
392 		   NodeBitmask &stoppedNodes,
393 		   bool abort,
394 		   bool stop,
395 		   bool restart,
396 		   bool nostart,
397 		   bool initialStart,
398                    int *stopSelf);
399 
400   /**
401    *   Check if it is possible to send a signal to a (DB) process
402    *
403    *   @param   processId: Id of the process to send to
404    *   @return  0 OK, 1 process dead, 2 API or MGMT process, 3 not configured
405    */
406   int okToSendTo(NodeId nodeId, bool unCond = false);
407 
408   bool is_any_node_starting(void);
409   bool is_any_node_stopping(void);
410   bool is_cluster_single_user(void);
411 
412   //**************************************************************************
413 
414   const MgmtOpts& m_opts;
415   int _blockNumber;
416   NodeId _ownNodeId;
417   Uint32 m_port;
418   SocketServer m_socket_server;
419 
420   NdbMutex* m_local_config_mutex;
421   const Config* m_local_config;
422 
423   BlockReference _ownReference;
424 
425   class ConfigManager* m_config_manager;
426 
427   bool m_need_restart;
428 
429   struct in_addr m_connect_address[MAX_NODES];
430   const char *get_connect_address(NodeId node_id,
431                                   char *addr_buf,
432                                   size_t addr_buf_size);
433   void clear_connect_address_cache(NodeId nodeid);
434 
435   /**
436    * trp_client interface
437    */
438   virtual void trp_deliver_signal(const NdbApiSignal* signal,
439                                   const struct LinearSectionPtr ptr[3]);
440   virtual void trp_node_status(Uint32 nodeId, Uint32 event);
441 
442   /**
443    * An event from <i>nodeId</i> has arrived
444    */
445   void eventReport(const Uint32 * theData, Uint32 len);
446 
447   class TransporterFacade * theFacade;
448 
449   bool _isStopThread;
450   int _logLevelThreadSleep;
451   MutexVector<NodeId> m_started_nodes;
452   MutexVector<EventSubscribeReq> m_log_level_requests;
453   LogLevel m_nodeLogLevel[MAX_NODES];
454   enum ndb_mgm_node_type nodeTypes[MAX_NODES];
455   friend class MgmApiSession;
456   friend class Ndb_mgmd_event_service;
457   Ndb_mgmd_event_service m_event_listner;
458 
459   NodeId m_master_node;
460 
461   ndb_mgm_node_type getNodeType(NodeId) const;
462 
463   /**
464    * Handles the thread wich upon a 'Node is started' event will
465    * set the node's previous loglevel settings.
466    */
467   struct NdbThread* _logLevelThread;
468   static void *logLevelThread_C(void *);
469   void logLevelThreadRun();
470   void report_unknown_signal(SimpleSignal *signal);
471 
472   void make_sync_req(SignalSender& ss, Uint32 nodeId);
473 public:
474   /* Get copy of configuration packed with base64 */
475   bool get_packed_config(ndb_mgm_node_type nodetype,
476                          BaseString& buf64, BaseString& error);
477 
478   /* Get copy of configuration packed with base64 from node nodeid */
479   bool get_packed_config_from_node(NodeId nodeid,
480                          BaseString& buf64, BaseString& error);
481 
482   void print_config(const char* section_filter = NULL,
483                     NodeId nodeid_filter = 0,
484                     const char* param_filter = NULL,
485                     NdbOut& out = ndbout);
486 
487   bool reload_config(const char* config_filename,
488                      bool mycnf, BaseString& msg);
489 
490   void show_variables(NdbOut& out = ndbout);
491 
492 private:
493   class NodeIdReservations {
494     struct Reservation {
495       NDB_TICKS m_start;
496       unsigned m_timeout; // Milliseconds
497     };
498     Reservation m_reservations[MAX_NODES];
499   public:
500     NodeIdReservations();
501     void check_array(NodeId n) const;
502     bool get(NodeId n) const;
503     void set(NodeId n, unsigned timeout);
504     void clear(NodeId n);
505     BaseString pretty_str() const;
506     bool has_timedout(NodeId n, NDB_TICKS now) const;
507   } m_reserved_nodes;
508   NdbMutex* m_reserved_nodes_mutex;
509 
510   void release_local_nodeid_reservation(NodeId nodeid);
511   struct PossibleNode
512   {
513     unsigned id;
514     BaseString host;
515     bool exact_match;
516   };
517   int alloc_node_id_req(NodeId free_node_id,
518                         ndb_mgm_node_type type,
519                         Uint32 timeout_ms);
520   int try_alloc(NodeId id,
521                 ndb_mgm_node_type type,
522                 Uint32 timeout_ms);
523   bool try_alloc_from_list(NodeId& nodeid,
524                            ndb_mgm_node_type type,
525                            Uint32 timeout_ms,
526                            Vector<PossibleNode>& nodes_info);
527   int find_node_type(NodeId nodeid,
528                      ndb_mgm_node_type type,
529                      const struct sockaddr* client_addr,
530                      Vector<PossibleNode>& nodes_info,
531                      int& error_code, BaseString& error_string);
532   bool alloc_node_id_impl(NodeId& nodeid,
533                           ndb_mgm_node_type type,
534                           const struct sockaddr* client_addr,
535                           int& error_code, BaseString& error_string,
536                           Uint32 timeout_s = 20);
537 public:
538   /*
539     Nodeid allocation
540     - MGM will never allocate a nodeid since either there is
541       only one(and thus it's nodeid is well known by looking
542       in config) or when running with two or more, they will
543       have nodeid specified on command line when starting.
544     - API nodes will always allocate a nodeid in the data nodes
545       since those have transporter connections with hearbeat
546       mechanism and can thus detect when the allocation should
547       be cleared.
548     - NDB nodes will prefer to allocate a nodeid in the data nodes
549       since the allocations will then be known by all connected
550       nodes(as well as hearbeat). But in order to startup a
551       nodeid can also be reserved locally in the mgmtsrvr node
552       only, such a reservations is cleared as soon as the
553       data node has connected via transporter to the mgmtsrvr.
554    */
555   bool alloc_node_id(NodeId& nodeid,
556                      ndb_mgm_node_type type,
557 		     const struct sockaddr* client_addr,
558 		     int& error_code, BaseString& error_string,
559                      bool log_event = true,
560 		     Uint32 timeout_s = 20);
561 
562 private:
563   BaseString m_version_string;
564 public:
get_version_string(void) const565   const char* get_version_string(void) const {
566     return m_version_string.c_str();
567   }
568 
569   bool request_events(NdbNodeBitmask nodes, Uint32 reports_per_node,
570                       Uint32 dump_type,
571                       Vector<SimpleSignal>& events);
572 };
573 
574 #endif // MgmtSrvr_H
575