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