X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fdird%2Fdird.c;h=86e73503a90dffe0861f87662d7df19f637ef439;hb=5b6583c38af78bdd11114c43644ba940c2fc34e9;hp=db0c015d7c0daf229ed0a329be3fd2392085173e;hpb=3c6a5e41b212cf5aa56e641b5488c242486346ea;p=bacula%2Fbacula diff --git a/bacula/src/dird/dird.c b/bacula/src/dird/dird.c index db0c015d7c..86e73503a9 100644 --- a/bacula/src/dird/dird.c +++ b/bacula/src/dird/dird.c @@ -1,7 +1,7 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2000-2008 Free Software Foundation Europe e.V. + Copyright (C) 2000-2009 Free Software Foundation Europe e.V. The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. @@ -20,7 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - Bacula® is a registered trademark of John Walker. + Bacula® is a registered trademark of Kern Sibbald. The licensor of Bacula is the Free Software Foundation Europe (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, Switzerland, email:ftf@fsfeurope.org. @@ -37,16 +37,28 @@ #include "bacula.h" #include "dird.h" +#ifdef HAVE_PYTHON + +#undef _POSIX_C_SOURCE +#include + +#include "lib/pythonlib.h" + +/* Imported Functions */ +extern PyObject *job_getattr(PyObject *self, char *attrname); +extern int job_setattr(PyObject *self, char *attrname, PyObject *value); + +#endif /* HAVE_PYTHON */ + /* Forward referenced subroutines */ void terminate_dird(int sig); static bool check_resources(); -static bool check_catalog(); static void dir_sql_query(JCR *jcr, const char *cmd); /* Exported subroutines */ extern "C" void reload_config(int sig); extern void invalidate_schedules(); - +extern bool parse_dir_config(CONFIG *config, const char *configfile, int exit_code); /* Imported subroutines */ JCR *wait_for_next_job(char *runjob); @@ -64,7 +76,8 @@ void init_device_resources(); static char *runjob = NULL; static int background = 1; static void init_reload(void); - +static CONFIG *config; + /* Globals Exported */ DIRRES *director; /* Director resource */ int FDConnectTimeout; @@ -73,21 +86,25 @@ char *configfile = NULL; void *start_heap; /* Globals Imported */ -extern int r_first, r_last; /* first and last resources */ -extern RES_TABLE resources[]; -extern RES **res_head; extern RES_ITEM job_items[]; - #if defined(_MSC_VER) extern "C" { // work around visual compiler mangling variables - extern URES res_all; + extern URES res_all; } #else extern URES res_all; #endif +typedef enum { + CHECK_CONNECTION, /* Check catalog connection */ + UPDATE_CATALOG, /* Ensure that catalog is ok with conf */ + UPDATE_AND_FIX /* Ensure that catalog is ok, and fix old jobs */ +} cat_op; +static bool check_catalog(cat_op mode); + #define CONFIG_FILE "bacula-dir.conf" /* default configuration file */ + static void usage() { fprintf(stderr, _( @@ -129,6 +146,9 @@ int main (int argc, char *argv[]) bool test_config = false; char *uid = NULL; char *gid = NULL; +#ifdef HAVE_PYTHON + init_python_interpreter_args python_args; +#endif /* HAVE_PYTHON */ start_heap = sbrk(0); setlocale(LC_ALL, ""); @@ -226,7 +246,8 @@ int main (int argc, char *argv[]) configfile = bstrdup(CONFIG_FILE); } - parse_config(configfile); + config = new_config_parser(); + parse_dir_config(config, configfile, M_ERROR_TERM); if (init_crypto() != 0) { Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Cryptography library initialization failed.\n")); @@ -249,13 +270,16 @@ int main (int argc, char *argv[]) load_dir_plugins(director->plugin_directory); - drop(uid, gid); /* reduce privileges if requested */ + drop(uid, gid, false); /* reduce privileges if requested */ + + /* If we are in testing mode, we don't try to fix the catalog */ + cat_op mode=(test_config)?CHECK_CONNECTION:UPDATE_AND_FIX; - if (!check_catalog()) { + if (!check_catalog(mode)) { Jmsg((JCR *)NULL, M_ERROR_TERM, 0, _("Please correct configuration file: %s\n"), configfile); } - - if (test_config) { + + if (test_config) { terminate_dird(0); } @@ -268,16 +292,25 @@ int main (int argc, char *argv[]) FDConnectTimeout = (int)director->FDConnectTimeout; SDConnectTimeout = (int)director->SDConnectTimeout; - #if !defined(HAVE_WIN32) signal(SIGHUP, reload_config); #endif init_console_msg(working_directory); - init_python_interpreter(director->name(), director->scripts_directory, - "DirStartUp"); +#ifdef HAVE_PYTHON + python_args.progname = director->name(); + python_args.scriptdir = director->scripts_directory; + python_args.modulename = "DirStartUp"; + python_args.configfile = configfile; + python_args.workingdir = director->working_directory; + python_args.job_getattr = job_getattr; + python_args.job_setattr = job_setattr; + init_python_interpreter(&python_args); +#endif /* HAVE_PYTHON */ + + set_jcr_in_tsd(INVALID_JCR); set_thread_concurrency(director->MaxConcurrentJobs * 2 + 4 /* UA */ + 4 /* sched+watchdog+jobsvr+misc */); @@ -290,6 +323,8 @@ int main (int argc, char *argv[]) init_job_server(director->MaxConcurrentJobs); + dbg_jcr_add_hook(_dbg_print_db); /* used to debug B_DB connexion after fatal signal */ + // init_device_resources(); Dmsg0(200, "wait for next job\n"); @@ -297,6 +332,7 @@ int main (int argc, char *argv[]) while ( (jcr = wait_for_next_job(runjob)) ) { run_job(jcr); /* run job */ free_jcr(jcr); /* release jcr */ + set_jcr_in_tsd(INVALID_JCR); if (runjob) { /* command line, run a single job? */ break; /* yes, terminate */ } @@ -333,6 +369,7 @@ void terminate_dird(int sig) exit(1); } already_here = true; + debug_level = 0; /* turn off debug */ stop_watchdog(); generate_daemon_event(NULL, "Exit"); unload_plugins(); @@ -349,11 +386,16 @@ void terminate_dird(int sig) if (debug_level > 5) { print_memory_pool_stats(); } - free_config_resources(); + if (config) { + config->free_resources(); + free(config); + config = NULL; + } term_ua_server(); term_msg(); /* terminate message handler */ cleanup_crypto(); close_memory_pool(); /* release free memory in pool */ + lmgr_cleanup_main(); sm_dump(false); exit(sig); } @@ -475,13 +517,13 @@ void reload_config(int sig) } Dmsg1(100, "Reload_config njobs=%d\n", njobs); - reload_table[table].res_table = save_config_resources(); + reload_table[table].res_table = config->save_resources(); Dmsg1(100, "Saved old config in table %d\n", table); - ok = parse_config(configfile, 0, M_ERROR); /* no exit on error */ + ok = parse_dir_config(config, configfile, M_ERROR); Dmsg0(100, "Reloaded config file\n"); - if (!ok || !check_resources() || !check_catalog()) { + if (!ok || !check_resources() || !check_catalog(UPDATE_CATALOG)) { rtable = find_free_reload_table_entry(); /* save new, bad table */ if (rtable < 0) { Jmsg(NULL, M_ERROR, 0, _("Please correct configuration file: %s\n"), configfile); @@ -490,7 +532,7 @@ void reload_config(int sig) Jmsg(NULL, M_ERROR, 0, _("Please correct configuration file: %s\n"), configfile); Jmsg(NULL, M_ERROR, 0, _("Resetting previous configuration.\n")); } - reload_table[rtable].res_table = save_config_resources(); + reload_table[rtable].res_table = config->save_resources(); /* Now restore old resoure values */ int num = r_last - r_first + 1; RES **res_tab = reload_table[table].res_table; @@ -504,7 +546,7 @@ void reload_config(int sig) * Hook all active jobs so that they release this table */ foreach_jcr(jcr) { - if (jcr->JobType != JT_SYSTEM) { + if (jcr->get_JobType() != JT_SYSTEM) { reload_table[table].job_count++; job_end_push(jcr, reload_job_end_cb, (void *)((long int)table)); njobs++; @@ -655,7 +697,7 @@ static bool check_resources() /* Transfer default items from JobDefs Resource */ for (i=0; job_items[i].name; i++) { char **def_svalue, **svalue; /* string value */ - int *def_ivalue, *ivalue; /* integer value */ + uint32_t *def_ivalue, *ivalue; /* integer value */ bool *def_bvalue, *bvalue; /* bool value */ int64_t *def_lvalue, *lvalue; /* 64 bit values */ uint32_t offset; @@ -709,23 +751,24 @@ static bool check_resources() * Note, our store_bit does not handle bitmaped fields */ } else if (job_items[i].handler == store_bit || - job_items[i].handler == store_pint || + job_items[i].handler == store_pint32 || job_items[i].handler == store_jobtype || job_items[i].handler == store_level || - job_items[i].handler == store_pint || + job_items[i].handler == store_int32 || + job_items[i].handler == store_size32 || job_items[i].handler == store_migtype || job_items[i].handler == store_replace) { - def_ivalue = (int *)((char *)(job->jobdefs) + offset); + def_ivalue = (uint32_t *)((char *)(job->jobdefs) + offset); Dmsg5(400, "Job \"%s\", field \"%s\" def_ivalue=%d item %d offset=%u\n", job->name(), job_items[i].name, *def_ivalue, i, offset); - ivalue = (int *)((char *)job + offset); + ivalue = (uint32_t *)((char *)job + offset); *ivalue = *def_ivalue; set_bit(i, job->hdr.item_present); /* * Handle 64 bit integer fields */ } else if (job_items[i].handler == store_time || - job_items[i].handler == store_size || + job_items[i].handler == store_size64 || job_items[i].handler == store_int64) { def_lvalue = (int64_t *)((char *)(job->jobdefs) + offset); Dmsg5(400, "Job \"%s\", field \"%s\" def_lvalue=%" lld " item %d offset=%u\n", @@ -873,7 +916,13 @@ static bool check_resources() return OK; } -static bool check_catalog() +/* + * In this routine, + * - we can check the connection (mode=CHECK_CONNECTION) + * - we can synchronize the catalog with the configuration (mode=UPDATE_CATALOG) + * - we can synchronize, and fix old job records (mode=UPDATE_AND_FIX) + */ +static bool check_catalog(cat_op mode) { bool OK = true; bool need_tls; @@ -886,7 +935,7 @@ static bool check_catalog() * Make sure we can open catalog, otherwise print a warning * message because the server is probably not running. */ - db = db_init_database(NULL, catalog->db_name, catalog->db_user, + db = db_init(NULL, catalog->db_driver, catalog->db_name, catalog->db_user, catalog->db_password, catalog->db_address, catalog->db_port, catalog->db_socket, catalog->mult_db_connections); @@ -904,21 +953,53 @@ static bool check_catalog() continue; } + /* we are in testing mode, so don't touch anything in the catalog */ + if (mode == CHECK_CONNECTION) { + db_close_database(NULL, db); + continue; + } + /* Loop over all pools, defining/updating them in each database */ POOL *pool; foreach_res(pool, R_POOL) { - create_pool(NULL, db, pool, POOL_OP_UPDATE); /* update request */ + /* + * If the Pool has a catalog resource create the pool only + * in that catalog. + */ + if (!pool->catalog || pool->catalog == catalog) { + create_pool(NULL, db, pool, POOL_OP_UPDATE); /* update request */ + } } - /* Loop over all pools for updating RecyclePool */ + /* Once they are created, we can loop over them again, updating + * references (RecyclePool) + */ foreach_res(pool, R_POOL) { - update_pool_recyclepool(NULL, db, pool); + /* + * If the Pool has a catalog resource update the pool only + * in that catalog. + */ + if (!pool->catalog || pool->catalog == catalog) { + update_pool_references(NULL, db, pool); + } } + /* Ensure basic client record is in DB */ + CLIENT *client; + foreach_res(client, R_CLIENT) { + CLIENT_DBR cr; + memset(&cr, 0, sizeof(cr)); + bstrncpy(cr.Name, client->name(), sizeof(cr.Name)); + db_create_client_record(NULL, db, &cr); + } + + /* Ensure basic storage record is in DB */ STORE *store; foreach_res(store, R_STORAGE) { STORAGE_DBR sr; MEDIATYPE_DBR mr; + memset(&sr, 0, sizeof(sr)); + memset(&mr, 0, sizeof(mr)); if (store->media_type) { bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType)); mr.ReadOnly = 0; @@ -931,6 +1012,7 @@ static bool check_catalog() db_create_storage_record(NULL, db, &sr); store->StorageId = sr.StorageId; /* set storage Id */ if (!sr.created) { /* if not created, update it */ + sr.AutoChanger = store->autochanger; db_update_storage_record(NULL, db, &sr); } @@ -996,6 +1078,12 @@ static bool check_catalog() counter->CurrentValue = counter->MinValue; /* default value */ } } + /* cleanup old job records */ + if (mode == UPDATE_AND_FIX) { + db_sql_query(db, cleanup_created_job, NULL, NULL); + db_sql_query(db, cleanup_running_job, NULL, NULL); + } + db_close_database(NULL, db); } /* Set type in global for debugging */