LIBNODEUPDOWN(3)

πŸ“¦
version 1.14 Β· 2 versions
, in epel 9, fedora 43, fedora 44

πŸŽ€ NAME πŸŽ€

okay so, bestie, this whole page is the intro to LIBNODEUPDOWN β€” specifically, an Introduction to writing nodeupdown modules or down. that's the name. "or down." we don't know, we don't ask, we just vibe. πŸ’…


✨ SYNOPSIS ✨

first, the includes. all of them. don't skip any, that's not the energy:

#include <nodeupdown.h>

#include <nodeupdown/nodeupdown_backend_module.h>

#include <nodeupdown/nodeupdown_clusterlist_module.h>

#include <nodeupdown/nodeupdown_config.h>

#include <nodeupdown/nodeupdown_config_module.h>

#include <nodeupdown/nodeupdown_constants.h>

#include <nodeupdown/nodeupdown_devel.h>

and then the little function besties you get to play with:

int nodeupdown_add_up_node(nodeupdown_t handle, const char *node);

int nodeupdown_add_down_node(nodeupdown_t handle, const char *node);

int nodeupdown_not_discovered_check(nodeupdown_t handle, const char *node);

void nodeupdown_set_errnum(nodeupdown_t handle, int errnum);

πŸ’– DESCRIPTION πŸ’–

so if you're writing nodeupdown modules, you're gonna be living in the nodeupdown development functions. they're the whole point: they let you, the module writer, reach into the nodeupdown handle and change what's inside it. it's giving backstage pass. πŸ”₯

  • nodeupdown_add_up_node and nodeupdown_add_down_node β€” they add an up node or a down node to the nodeupdown handle. respectively. obviously. one for up, one for down, no crossover episodes.
  • nodeupdown_not_discovered_check β€” checks if the node you named currently exists in the handle. and if it doesn't? boom, that node gets added to the internal list of down nodes. not discovered = down, periodt.
  • nodeupdown_set_errnum β€” sets the errnum inside the nodeupdown handle to the errnum you specified. that's it. that's the whole job.

and there's more! below you'll find extra info on developing nodeupdown backend, clusterlist, and config modules. buckle up bestie, three whole sections. πŸ¦‹


🧚 BACKEND MODULES 🧚

wanna write a nodeupdown backend module named foobar? iconic name, love that for you. here's the tea: compile a shared object library with the filename nodeupdown_backend_foobar.so, and install it in the nodeupdown package library directory /usr/lib64/nodeupdown. that's the address, that's where it lives. 🏠

your backend module should define a structure of this type:

struct nodeupdown_backend_module_info {
  char *backend_module_name;
  Nodeupdown_backend_default_hostname default_hostname;
  Nodeupdown_backend_default_port default_port;
  Nodeupdown_backend_default_timeout_len default_timeout_len;
  Nodeupdown_backend_setup setup;
  Nodeupdown_backend_cleanup cleanup;
  Nodeupdown_backend_get_updown_data get_updown_data;
};

the structure should be named backend_module_info, and you fill it in with the following info:

  • backend_module_name β€” should indicate the name of the backend module. (yes, its own name. main character behavior.)
  • default_hostname β€” should point to a function of this type:
typedef char *(*Nodeupdown_backend_default_hostname)(nodeupdown_t);

the default_hostname function returns a pointer to a string for the default hostname for this backend module.

  • default_port β€” should point to a function of this type:
typedef int (*Nodeupdown_backend_default_port)(nodeupdown_t);

the default_port function returns the default port for this backend module.

  • default_timeout_len β€” should point to a function of this type:
typedef int (*Nodeupdown_backend_default_timeout_len)(nodeupdown_t);

the default_timeout_len function returns the default timeout_len for this backend module.

  • setup β€” should point to a function of this type:
typedef int (*Nodeupdown_backend_setup)(nodeupdown_t);

the setup function sets up the backend module with whatever initialization is necessary. it returns 0 on success, -1 on error. 🫢

  • cleanup β€” should point to a function of this type:
typedef int (*Nodeupdown_backend_cleanup)(nodeupdown_t);

the cleanup function cleans up the backend module from earlier initializations. it returns 0 on success, -1 on error. we love a responsible king that cleans up after itself.

  • get_updown_data β€” should point to a function of this type:
typedef int (*Nodeupdown_backend_get_updown_data)(nodeupdown_t, const char *, unsigned int, unsigned int, char *);

the get_updown_data function retrieves all updown data from the backend technology and stores it in the nodeupdown_t handle. to actually put the up or down nodes into the handle, you should use the nodeupdown development functions nodeupdown_add_up_node and nodeupdown_add_down_node. get_updown_data is passed a hostname, port, timeout_len, and reserved fields similar to nodeupdown_load_data(3). if values were passed to nodeupdown_load_data(3), they are forwarded on to get_updown_data. however, if defaults were passed to nodeupdown_load_data(3), the appropriate values have already been read and compauted from configuration modules, configuration files, or the above backend default functions. (yes β€” "compauted". that's literally what the original says and i am NOT touching it, it's part of the lore now πŸ’…)

all of the above functions must be defined in the module and listed in the backend_module_info structure. all of them. no skipping, no "i'll do it later". πŸ’€

🌸 CLUSTERLIST MODULES 🌸

same deal, different module: a nodeupdown clusterlist module named foobar gets written by compiling a shared object library with the filename nodeupdown_clusterlist_foobar.so, and installing it in the nodeupdown package library directory /usr/lib64/nodeupdown. πŸŽ€

the clusterlist module should define a structure of this type:

struct nodeupdown_clusterlist_module_info {
    char *clusterlist_module_name;
    Nodeupdown_clusterlist_setup setup;
    Nodeupdown_clusterlist_cleanup cleanup;
    Nodeupdown_clusterlist_get_numnodes get_numnodes;
    Nodeupdown_clusterlist_is_node_in_cluster is_node_in_cluster;
    Nodeupdown_clusterlist_get_nodename get_nodename;
    Nodeupdown_clusterlist_compare_to_clusterlist compare_to_clusterlist;
};

the structure should be named clusterlist_module_info and be populated with the following info:

  • clusterlist_module_name β€” should indicate the name of the clusterlist module.
  • setup β€” should point to a function of this type:
typedef int (*Nodeupdown_clusterlist_setup)(nodeupdown_t);

the setup function sets up the clusterlist module with whatever initialization is necessary. it returns 0 on success, -1 on error.

  • cleanup β€” should point to a function of this type:
typedef int (*Nodeupdown_clusterlist_cleanup)(nodeupdown_t);

the cleanup function cleans up the clusterlist module from earlier initializations. it returns 0 on success, -1 on error.

  • get_numnodes β€” should point to a function of this type:
typedef int (*Nodeupdown_clusterlist_get_numnodes)(nodeupdown_t);

the get_numnodes function returns the number of nodes in the cluster, or -1 on error.

  • is_node_in_cluster β€” should point to a function of this type:
typedef int (*Nodeupdown_clusterlist_is_node_in_cluster)(nodeupdown_t, const char *);

the is_node_in_cluster function is passed a nodename. it returns 1 if the specified node is in the cluster, 0 if not, and -1 on error. a tidy little three-way answer, we stan. ✨

  • get_nodename β€” should point to a function of this type:
typedef int (*Nodeupdown_clusterlist_get_nodename)(nodeupdown_t, const char *, char *, unsigned int);

the get_nodename function is passed a nodename, a buffer, and a buffer length. it determines the appropriate nodename to use and copies it into the buffer. this function is primarily used to convert aliased nodenames into the appropriate nodename to use for calculations. the majority of clusterlist module writers will probably copy the nodename directly into the buffer and not do any calculations. get_nodename returns 0 on success, -1 on error.

  • compare_to_clusterlist β€” should point to a function of this type:
typedef int (*Nodeupdown_clusterlist_compare_to_clusterlist)(nodeupdown_t);

the compare_to_clusterlist function is used to determine any additional down nodes in the cluster. clusterlist module writers will typically iterate through the clusterlist module's list of nodes, and pass each one to nodeupdown_not_discovered_check. (see? told you it all comes back around. πŸ”)

all of the above functions must be defined in the module and listed in the clusterlist_module_info structure. every single one, bestie.

πŸ¦‹ CONFIG MODULES πŸ¦‹

last but so not least: a nodeupdown config module named foobar can be written by compiling a shared object library with the filename nodeupdown_config_foobar.so, and installing it in the nodeupdown package library directory /usr/lib64/nodeupdown. same directory, third module type, the trio is complete. πŸ‘‘

the config module should define a structure of this type:

struct nodeupdown_config_module_info {
    char *config_module_name;
    Nodeupdown_config_setup setup;
    Nodeupdown_config_cleanup cleanup;
    Nodeupdown_config_load_default load_default;
};

the structure should be named config_module_info and be populated with the following info:

  • config_module_name β€” should indicate the name of the config module.
  • setup β€” should point to a function of this type:
typedef int (*Nodeupdown_config_setup)(nodeupdown_t);

the setup function sets up the config module with whatever initialization is necessary. it returns 0 on success, -1 on error.

  • cleanup β€” should point to a function of this type:
typedef int (*Nodeupdown_config_cleanup)(nodeupdown_t);

the cleanup function cleans up the config module from earlier initializations. it returns 0 on success, -1 on error.

  • load_default β€” should point to a function of this type:
typedef int (*Nodeupdown_config_load_default)(nodeupdown_t, struct nodeupdown_config *);

the load_default function loads an alternate set of configuration values and stores them within the configuration structure passed in.

all of the above functions must be defined in the module and listed in the config_module_info structure. no cap.

πŸ’œ the nodeupdown_config struct πŸ’œ

the structure nodeupdown_config is defined as:

struct nodeupdown_config {
    char hostnames[NODEUPDOWN_CONFIG_HOSTNAMES_MAX+1][NODEUPDOWN_MAXHOSTNAMELEN+1];
    int hostnames_len;
    int hostnames_flag;
    int port;
    int port_flag;
    int timeout_len;
    int timeout_len_flag;
};

and what goes where:

any parameter that is set in the configuration structure must have its respective flag set. that's the rule. flags exist for a reason, don't leave them behind. 🚩

and then, the very last line of this part, exactly as the original wrote it, we are not paraphrasing:

The 'hostnames' field must also have the loaded.

yeah. that's the whole sentence. i don't know either bestie, but it's canon and we're keeping it fr fr. 😭


🌈 SEE ALSO 🌈

  • libnodeupdown(3) β€” go read it, it's the whole main character this page is a spin-off of.

and that's the page!! go write your module, you're gonna slay, i literally believe in you. 🫢

this lil manual came out of LLNL, dated May 2005 β€” so yes, this legend has been iconic since 2005, we're just catching up. πŸ’–βœ¨πŸŽ€πŸ¦‹

πŸ“¦ where this page comes from