/* DRBD linuxconf module Original code by Daniel Mealha Cabrita (dancab@conectiva.com) 05/2002 - heavily modificated to accept new configuration file, using new objects and parser. Loïc Jeannin - loic@conectiva.com.br - tahorg - gcu Conectiva Corporation (c) 2002 */ #include "drbdconf.h" #include "drbdconf.m" #include #include #include #include #include #include "drbd_parser.h" #define TYPICAL_INPUT_SIZE 50 #define DRBD_SYSTEMDEF "drbd" #define DRBD_DEFAULT_RESTART_COMMAND "drbd restart" #define TYPICAL_STRING_SIZE 100 #define MAX_DRBD_RESSOURCES 10 HELP_FILE editdrbdfile_help("drbdconf", "drbdopts"); HELP_FILE drbdlist_help("drbdconf", "drbdlist"); /* new drbd objects */ parser Drbd_Parser; resource * Drbd_Resource=NULL; /* */ /* execute command line, in silence (no stdout output) */ int execute_proggy(char *given_command_line) { char my_command[500]; char my_args[500]; char *where_to_cut; my_command[0]=0; my_args[0]=0; strcpy(my_command, given_command_line); if((where_to_cut=strchr(my_command, ' '))){ *where_to_cut=0; where_to_cut++; strcpy(my_args, where_to_cut); } return(netconf_system_if(my_command, my_args)); } void informational_window(const char *my_title, const char *my_text) { int nothing=0; DIALOG uhoh_dialog; uhoh_dialog.editmenu(my_title, my_text, help_nil, nothing, 0); } /* returns true if drbd config directory exists if false, means that probably drbd is not installed on system */ int is_drbd_installed(void) { struct stat my_statbuff; /* this thing exists? */ if(stat(SAVE_FILE, &my_statbuff)) return(0); else return(1); } /* [snip]*/ //void strgname(SSTRING &givenstr) //{ // if(!(strcmp(givenstr.get(), "drbdconfcredits"))){ // int nothing=0; // DIALOG uhoh_dialog; // uhoh_dialog.editmenu("do you like lame easter eggs?", "this module was created by\nDaniel Mealha Cabrita\n(dancab@conectiva.com)\ninitial version: May, 2000", help_nil, nothing, 0); // } //} /* sorry I don't - Loïc */ void save_config() { resource *d; unlink(SAVE_FILE); d=Drbd_Resource; do { d->print(); } while ((d=d->next)!=NULL); } void edit_given_resource(resource *drbd_r) { /* this is the data to be assigned to dialog */ SSTRING s_resource_name, s_master_node, s_slave_node, s_protocol, s_master_device, s_slave_device, s_master_partition, s_slave_partition, s_master_if, s_slave_if; /* these are supposed to carry integer or BLANK string, only */ int i_flag_t, i_flag_r, i_flag_s, i_flag_d; int i_port_master, i_port_slave; char b_flag_k, b_flag_p; /* bool */ /* these are the readen values which need to be processed * before being sent to the correct variables */ DIALOG dia_editdrbd; FIELD_LIST *pop_protocol; VIEWITEMS vitems_drbd; //char my_filename[TYPICAL_PATH_SIZE]; int my_selection; int my_button; const char *my_returned_string; char proto[2]; /* fill with defaults */ b_flag_k=0; b_flag_p=0; /* assumes SSTRING variables in empty state, * just after their creation */ /* type conflicts to fix - loic */ if(drbd_r->o_disk.getDoPanic()==1) b_flag_p=1; if(drbd_r->o_net.getSkipSync()==1) b_flag_k=1; if((my_returned_string=drbd_r->getName())) s_resource_name.setfrom(my_returned_string); if((my_returned_string=drbd_r->o_block_1.getName())) s_master_node.setfrom(my_returned_string); if((my_returned_string=drbd_r->o_block_2.getName())) s_slave_node.setfrom(my_returned_string); if((my_returned_string=drbd_r->o_block_1.getDevice())) s_master_device.setfrom(my_returned_string); if((my_returned_string=drbd_r->o_block_2.getDevice())) s_slave_device.setfrom(my_returned_string); if((my_returned_string=drbd_r->o_block_1.getDisk())) s_master_partition.setfrom(my_returned_string); if((my_returned_string=drbd_r->o_block_2.getDisk())) s_slave_partition.setfrom(my_returned_string); if((*proto=drbd_r->getProtocol())) // returns a char -> BAD { proto[1]='\0'; s_protocol.setfrom(proto); } if((my_returned_string=drbd_r->o_block_1.getAddress())) s_master_if.setfrom(my_returned_string); if((my_returned_string=drbd_r->o_block_2.getAddress())) s_slave_if.setfrom(my_returned_string); i_flag_s=drbd_r->o_net.getTlSize(); i_flag_t=drbd_r->o_net.getTimeout(); i_flag_r=drbd_r->o_net.getSyncRate(); i_flag_d=drbd_r->o_disk.getSize(); i_port_master=drbd_r->o_block_1.getPort(); i_port_slave=drbd_r->o_block_2.getPort(); /* here starts the dialog construction.. */ dia_editdrbd.newf_str(MSG_U(F_RESSOURCENAME, "Resource:"), s_resource_name, TYPICAL_INPUT_SIZE); dia_editdrbd.newf_title(MSG_U(I_SETTINGSFORMASTER, "Settings for Master"), 1, "", MSG_R(I_SETTINGSFORMASTER)); dia_editdrbd.newf_str(MSG_U(F_MASTERNODE, "Node:"), s_master_node, TYPICAL_INPUT_SIZE); dia_editdrbd.newf_str(MSG_U(F_MASTERIP, "IP:"), s_master_if, TYPICAL_INPUT_SIZE); dia_editdrbd.newf_num(MSG_U(F_MASTERPORT, "Port:"), i_port_master); dia_editdrbd.newf_str(MSG_U(F_MASTERDEV, "Device:"), s_master_device, TYPICAL_INPUT_SIZE); dia_editdrbd.newf_str(MSG_U(F_MASTERPAR, "Partition:"), s_master_partition, TYPICAL_INPUT_SIZE); dia_editdrbd.newf_title(MSG_U(I_SETTINGSFORSLAVE, "Settings for Slave"), 1, "", MSG_R(I_SETTINGSFORSLAVE)); dia_editdrbd.newf_str(MSG_U(F_SLAVENODE, "Node:"), s_slave_node, TYPICAL_INPUT_SIZE); dia_editdrbd.newf_str(MSG_U(F_SLAVEIP, "IP (optional):"), s_slave_if, TYPICAL_INPUT_SIZE); dia_editdrbd.newf_num(MSG_U(F_SLAVEPORT, "Port:"), i_port_slave); dia_editdrbd.newf_str(MSG_U(F_SLAVEDEV, "Device:"), s_slave_device, TYPICAL_INPUT_SIZE); dia_editdrbd.newf_str(MSG_U(F_SLAVEPAR, "Partition:"), s_slave_partition, TYPICAL_INPUT_SIZE); dia_editdrbd.newf_title(MSG_U(I_OTHERPROPS, "Other properties"), 1, "", MSG_R(I_OTHERPROPS)); dia_editdrbd.newf_num(MSG_U(F_TIMEOUT, "Timeout (1/10th sec):"), i_flag_t); dia_editdrbd.newf_num(MSG_U(F_SYNCRATE, "Sync rate (KB/sec):"), i_flag_r); dia_editdrbd.newf_num(MSG_U(F_TRANSFERLOGSIZE, "Transfer log size (entries):"), i_flag_s); dia_editdrbd.newf_num(MSG_U(F_DISKSIZE, "Disk size (KB):") , i_flag_d); dia_editdrbd.newf_chk("", b_flag_k, MSG_U(F_SKIPSYNC, "Skip synchronization")); dia_editdrbd.newf_chk("", b_flag_p, MSG_U(F_KERNELPANIC, "Enable kernel panic")); pop_protocol=dia_editdrbd.newf_list(MSG_U(F_USEPROTOCOL, "Use protocol:"), s_protocol); { pop_protocol->addopt("A"); pop_protocol->addopt("B"); pop_protocol->addopt("C"); } /* opens window.. */ { char my_dialog_title[TYPICAL_STRING_SIZE]; my_selection=0; sprintf(my_dialog_title, MSG_U(T_EDITING, "Editing %s"), drbd_r->getName()); my_button=dia_editdrbd.editmenu(my_dialog_title, "", editdrbdfile_help, my_selection, MENUBUT_QUIT|MENUBUT_ACCEPT|MENUBUT_DEL); // we don't really need easter Eggs that lame ;) // strgname(s_master_node); } /* now user pressed some button, let's have some processing.. */ /* react according pressed dialog button */ switch(my_button){ case MENU_QUIT: case MENU_ESCAPE: return; case MENU_DEL: { char my_remconfirm_title[TYPICAL_STRING_SIZE]; resource *d; sprintf(my_remconfirm_title, MSG_U(T_REMOVINGDEF, "Removing definition %s"), drbd_r->getName()); if(dialog_yesno(my_remconfirm_title, MSG_U(I_REMOVETXT, "Do you really want\nto remove this definition?") , help_nil)==MENU_YES) { if(drbd_r==Drbd_Resource && !Drbd_Resource->next) break; // don't handle this case ... if(drbd_r==Drbd_Resource) { d=Drbd_Resource->next; free(Drbd_Resource); Drbd_Resource=d; } else { d=Drbd_Resource; while(d->next!=drbd_r) d=d->next; d->next=drbd_r->next; free(drbd_r); } save_config(); } } break; case MENU_ACCEPT: { /* Have to find a way to get char * from SSTRING */ drbd_r->o_disk.setDoPanic(b_flag_p); drbd_r->o_disk.setSize(i_flag_d); drbd_r->o_net.setSkipSync(b_flag_k); drbd_r->o_net.setTlSize(i_flag_s); drbd_r->o_net.setTimeout(i_flag_t); drbd_r->o_net.setSyncRate(i_flag_r); drbd_r->setName(s_resource_name.get()); drbd_r->o_block_1.setName(s_master_node.get()); drbd_r->o_block_1.setDevice(s_master_device.get()); drbd_r->o_block_1.setDisk(s_master_partition.get()); drbd_r->o_block_1.setAddress(s_master_if.get()); drbd_r->o_block_1.setPort(i_port_master); drbd_r->o_block_2.setName(s_slave_node.get()); drbd_r->o_block_2.setDevice(s_slave_device.get()); drbd_r->o_block_2.setDisk(s_slave_partition.get()); drbd_r->o_block_2.setAddress(s_slave_if.get()); drbd_r->o_block_2.setPort(i_port_slave); drbd_r->setProtocol(*s_protocol.get()); /* missing informations */ /* we save all de resource config */ save_config(); } break; } } /* returns !=-1 if entry couldn't be added */ resource * add_drbdresource(void) { int i=1; resource *d; d=Drbd_Resource; if(!d) { Drbd_Resource = new resource(); Drbd_Resource->setName("drbd_change_me"); return (Drbd_Resource); } while(d->next!=NULL && d!=NULL) { d=d->next; i++; } /* we are on the last item */ d->next = new resource(); /* Creating a new name for the resource */ d->next->setName("drbd_change_me"); return d->next; } void free_resource_list() { resource *d,*e; d=Drbd_Resource; if(d==NULL) return; while(d->next!=NULL) { e=d->next; free(d); d=e; } } void select_drbdfile_to_edit(void) { int my_button=0; int my_selection=0; DIALOG_RECORDS dia_drbdfilelist; dia_drbdfilelist.newf_head("", MSG_U(F_CONFIGFILELIST, "configuration resource")); while(1) { /* initialisation of the data */ if (!Drbd_Resource) { free_resource_list(); Drbd_Resource=Drbd_Parser.read(); /*add one if the archive's empty*/ } { int line_counter=0; resource *d; d=Drbd_Resource; while(d!=NULL && line_countergetName(), ""); d=d->next; } // remove entries below (they're the previous ones and useless now) dia_drbdfilelist.remove_last(line_counter+1); my_button=dia_drbdfilelist.editmenu(MSG_U(T_DRBDCONFIGURATOR, "DRBD configurator"), MSG_U(I_THESEARE, "These are the definitions present\nin this system."), drbdlist_help, my_selection, MENUBUT_QUIT|MENUBUT_ADD); } switch(my_button){ case MENU_QUIT: case MENU_ESCAPE: return; case MENU_ADD: { resource * added_drbd; added_drbd=add_drbdresource(); if(added_drbd!=NULL) edit_given_resource(added_drbd); else { informational_window(MSG_U(T_UNABLETOADDENTRY, "Unable to add entry"), MSG_U(I_UNABLETOADDENTRY, "The maximum number of entries has reached.\ \n\nYou have to delete some one in\norder to \ be able to add a new one.")); } } break; default: { resource *d; d=Drbd_Resource; for(int i=0;inext; edit_given_resource(d); } break; } } } void drbd_module_starter(void) { if(perm_rootaccess("")){ if(!is_drbd_installed()){ char drbd_missing_warning_text[500]; sprintf(drbd_missing_warning_text, MSG_U(I_DRBDNOTDETECTED, "Couldn't find the configuration file \"%s\".\nSeems that DRBD \ wasn't properly installed\nor not installed at all."), SAVE_FILE); informational_window(MSG_U(T_DRBDDETECTED, "Unable to configure DRBD"), drbd_missing_warning_text); return; } select_drbdfile_to_edit(); /* old and dirty method.. now drbdconf probes the right way */ // if(dialog_yesno(MSG_U(T_RESTARTINGDRBD, "Restarting DRBD"), MSG_U(I_RESTARTINGDRBD, "DRBD needs to be restarted in order\nto changes take effect.\n\nDo you want to restart DRBD services?"), help_nil)==MENU_YES){ // execute_proggy(DRBD_DEFAULT_RESTART_COMMAND); // } } }