/* * Read Data and send to File Daemon * * Returns: false on failure * true on success */ bool do_read_data(JCR *jcr) { BSOCK *fd = jcr->file_bsock; DCR *dcr = jcr->read_dcr; bool ok = true; Dmsg0(20, "Start read data.\n"); if (!bnet_set_buffer_size(fd, dcr->device->max_network_buffer_size, BNET_SETBUF_WRITE)) { return false; } if (jcr->NumReadVolumes == 0) { Jmsg(jcr, M_FATAL, 0, _("No Volume names found for restore.\n")); fd->fsend(FD_error); return false; } Dmsg2(200, "Found %d volumes names to restore. First=%s\n", jcr->NumReadVolumes, jcr->VolList->VolumeName); /* * Ready device for reading */ if (!acquire_device_for_read(dcr)) { fd->fsend(FD_error); return false; } /* * Let any SD plugin know now its time to setup the record translation infra. */ if (generate_plugin_event(jcr, bsdEventSetupRecordTranslation, dcr) != bRC_OK) { jcr->setJobStatus(JS_ErrorTerminated); return false; } /* * Tell File daemon we will send data */ fd->fsend(OK_data); jcr->sendJobStatus(JS_Running); ok = read_records(dcr, record_cb, mount_next_read_volume); /* * Send end of data to FD */ fd->signal(BNET_EOD); if (!release_device(jcr->read_dcr)) { ok = false; } Dmsg0(30, "Done reading.\n"); return ok; }
/* * Read Data and send to File Daemon * Returns: false on failure * true on success */ bool do_read_data(JCR *jcr) { BSOCK *fd = jcr->file_bsock; bool ok = true; DCR *dcr = jcr->read_dcr; Dmsg0(20, "Start read data.\n"); if (!bnet_set_buffer_size(fd, dcr->device->max_network_buffer_size, BNET_SETBUF_WRITE)) { return false; } if (jcr->NumReadVolumes == 0) { Jmsg(jcr, M_FATAL, 0, _("No Volume names found for restore.\n")); fd->fsend(FD_error); return false; } Dmsg2(200, "Found %d volumes names to restore. First=%s\n", jcr->NumReadVolumes, jcr->VolList->VolumeName); /* Ready device for reading */ if (!acquire_device_for_read(dcr)) { fd->fsend(FD_error); return false; } /* Tell File daemon we will send data */ fd->fsend(OK_data); jcr->sendJobStatus(JS_Running); ok = read_records(dcr, record_cb, mount_next_read_volume); /* Send end of data to FD */ fd->signal(BNET_EOD); if (!release_device(jcr->read_dcr)) { ok = false; } Dmsg0(30, "Done reading.\n"); return ok; }
/* * Run a File daemon Job -- File daemon already authorized * Director sends us this command. * * Basic task here is: * - Read a command from the File daemon * - Execute it * */ void run_job(JCR *jcr) { BSOCK *dir = jcr->dir_bsock; char ec1[30]; dir->set_jcr(jcr); Dmsg1(120, "Start run Job=%s\n", jcr->Job); dir->fsend(Job_start, jcr->Job); jcr->start_time = time(NULL); jcr->run_time = jcr->start_time; jcr->sendJobStatus(JS_Running); do_fd_commands(jcr); jcr->end_time = time(NULL); dequeue_messages(jcr); /* send any queued messages */ jcr->setJobStatus(JS_Terminated); generate_plugin_event(jcr, bsdEventJobEnd); dir->fsend(Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles, edit_uint64(jcr->JobBytes, ec1), jcr->JobErrors); dir->signal(BNET_EOD); /* send EOD to Director daemon */ free_plugins(jcr); /* release instantiated plugins */ }
/** * After writing a Volume, create the JobMedia record. */ bool SD_DCR::dir_create_jobmedia_record(bool zero) { BSOCK *dir = jcr->dir_bsock; char ed1[50]; /* * If system job, do not update catalog */ if (jcr->is_JobType(JT_SYSTEM)) { return true; } /* * Throw out records where FI is zero -- i.e. nothing done */ if (!zero && VolFirstIndex == 0 && (StartBlock != 0 || EndBlock != 0)) { Dmsg0(dbglvl, "JobMedia FI=0 StartBlock!=0 record suppressed\n"); return true; } if (!WroteVol) { return true; /* nothing written to tape */ } WroteVol = false; if (zero) { /* * Send dummy place holder to avoid purging */ dir->fsend(Create_job_media, jcr->Job, 0 , 0, 0, 0, 0, 0, 0, 0, edit_uint64(VolMediaId, ed1)); } else { dir->fsend(Create_job_media, jcr->Job, VolFirstIndex, VolLastIndex, StartFile, EndFile, StartBlock, EndBlock, Copy, Stripe, edit_uint64(VolMediaId, ed1)); } Dmsg1(dbglvl, ">dird %s", dir->msg); if (dir->recv() <= 0) { Dmsg0(dbglvl, "create_jobmedia error bnet_recv\n"); Jmsg(jcr, M_FATAL, 0, _("Error creating JobMedia record: ERR=%s\n"), dir->bstrerror()); return false; } Dmsg1(dbglvl, "<dird %s", dir->msg); if (!bstrcmp(dir->msg, OK_create)) { Dmsg1(dbglvl, "Bad response from Dir: %s\n", dir->msg); Jmsg(jcr, M_FATAL, 0, _("Error creating JobMedia record: %s\n"), dir->msg); return false; } return true; }
/* * End a replication session. */ static bool end_replication_session(JCR *jcr) { BSOCK *sd = jcr->store_bsock; Dmsg1(120, "stored<stored: %s", sd->msg); if (!jcr->session_opened) { pm_strcpy(jcr->errmsg, _("Attempt to close non-open session.\n")); sd->fsend(NOT_opened); return false; } return sd->fsend(OK_end_replicate); }
static bool append_end_session(JCR *jcr) { BSOCK *fd = jcr->file_bsock; Dmsg1(120, "store<file: %s", fd->msg); if (!jcr->session_opened) { pm_strcpy(jcr->errmsg, _("Attempt to close non-open session.\n")); fd->fsend(NOT_opened); return false; } return fd->fsend(OK_end); }
/* * Inititiate the communications with the Director. * He has made a connection to our server. * * Basic tasks done here: * We read Director's initial message and authorize him. */ bool authenticate_director(JCR *jcr) { BSOCK *dir = jcr->dir_bsock; if (!two_way_authenticate(R_DIRECTOR, dir, jcr)) { dir->fsend("%s", Dir_sorry); Emsg0(M_FATAL, 0, _("Unable to authenticate Director\n")); return false; } return dir->fsend("%s", (me->compatible) ? OK_hello_compat : OK_hello); }
/* * Query Device command from Director * Sends Storage Daemon's information on the device to the * caller (presumably the Director). * This command always returns "true" so that the line is * not closed on an error. * */ bool query_cmd(JCR *jcr) { POOL_MEM dev_name, VolumeName, MediaType, ChangerName; BSOCK *dir = jcr->dir_bsock; DEVRES *device; AUTOCHANGER *changer; bool ok; Dmsg1(100, "Query_cmd: %s", dir->msg); ok = sscanf(dir->msg, query_device, dev_name.c_str()) == 1; Dmsg1(100, "<dird: %s", dir->msg); if (ok) { unbash_spaces(dev_name); foreach_res(device, R_DEVICE) { /* Find resource, and make sure we were able to open it */ if (bstrcmp(dev_name.c_str(), device->name())) { if (!device->dev) { device->dev = init_dev(jcr, device); } if (!device->dev) { break; } ok = dir_update_device(jcr, device->dev); if (ok) { ok = dir->fsend(OK_query); } else { dir->fsend(NO_query); } return ok; } } foreach_res(changer, R_AUTOCHANGER) { /*Find resource, and make sure we were able to open it */ if (bstrcmp(dev_name.c_str(), changer->name())) { if (!changer->device || changer->device->size() == 0) { continue; /* no devices */ } ok = dir_update_changer(jcr, changer); if (ok) { ok = dir->fsend(OK_query); } else { dir->fsend(NO_query); } return ok; } } /* If we get here, the device/autochanger was not found */ unbash_spaces(dir->msg); pm_strcpy(jcr->errmsg, dir->msg); dir->fsend(NO_device, dev_name.c_str()); Dmsg1(100, ">dird: %s", dir->msg); } else {
/* * Inititiate the message channel with the Director. * He has made a connection to our server. * * Basic tasks done here: * Assume the Hello message is already in the input * buffer. We then authenticate him. * Get device, media, and pool information from Director * * This is the channel across which we will send error * messages and job status information. */ int authenticate_director(JCR *jcr) { BSOCK *dir = jcr->dir_bsock; if (!authenticate(R_DIRECTOR, dir, jcr)) { dir->fsend("%s", Dir_sorry); Dmsg1(dbglvl, "Unable to authenticate Director at %s.\n", dir->who()); Jmsg1(jcr, M_ERROR, 0, _("Unable to authenticate Director at %s.\n"), dir->who()); bmicrosleep(5, 0); return 0; } return dir->fsend("%s", OK_hello); }
static void do_client_cmd(UAContext *ua, CLIENTRES *client, const char *cmd) { BSOCK *fd; /* Connect to File daemon */ ua->jcr->res.client = client; /* Try to connect for 15 seconds */ ua->send_msg(_("Connecting to Client %s at %s:%d\n"), client->name(), client->address, client->FDport); if (!connect_to_file_daemon(ua->jcr, 1, 15, false, false)) { ua->error_msg(_("Failed to connect to Client.\n")); return; } Dmsg0(120, "Connected to file daemon\n"); fd = ua->jcr->file_bsock; fd->fsend("%s", cmd); if (fd->recv() >= 0) { ua->send_msg("%s", fd->msg); } fd->signal(BNET_TERMINATE); fd->close(); ua->jcr->file_bsock = NULL; return; }
static void do_storage_cmd(UAContext *ua, STORERES *store, const char *cmd) { BSOCK *sd; JCR *jcr = ua->jcr; USTORERES lstore; lstore.store = store; pm_strcpy(lstore.store_source, _("unknown source")); set_wstorage(jcr, &lstore); if (!(sd = open_sd_bsock(ua))) { ua->error_msg(_("Could not open SD socket.\n")); return; } Dmsg0(120, _("Connected to storage daemon\n")); sd = jcr->store_bsock; sd->fsend("%s", cmd); if (sd->recv() >= 0) { ua->send_msg("%s", sd->msg); } close_sd_bsock(ua); return; }
/* * Cancel a running job on a storage daemon. Used by the interactive cancel * command to cancel a JobId on a Storage Daemon this can be used when the * Director already removed the Job and thinks it finished but the Storage * Daemon still thinks its active. */ bool cancel_storage_daemon_job(UAContext *ua, STORERES *store, char *JobId) { BSOCK *sd; JCR *control_jcr; control_jcr = new_control_jcr("*JobCancel*", JT_SYSTEM); control_jcr->res.wstore = store; if (!connect_to_storage_daemon(control_jcr, 10, me->SDConnectTimeout, true)) { ua->error_msg(_("Failed to connect to Storage daemon.\n")); } Dmsg0(200, "Connected to storage daemon\n"); sd = control_jcr->store_bsock; sd->fsend("cancel Job=%s\n", JobId); while (sd->recv() >= 0) { ua->send_msg("%s", sd->msg); } sd->signal(BNET_TERMINATE); sd->close(); control_jcr->store_bsock = NULL; free_jcr(control_jcr); return true; }
bool dir_update_changer(JCR *jcr, AUTOCHANGER *changer) { BSOCK *dir = jcr->dir_bsock; POOL_MEM dev_name, MediaType; DEVRES *device; bool ok; pm_strcpy(dev_name, changer->hdr.name); bash_spaces(dev_name); device = (DEVRES *)changer->device->first(); pm_strcpy(MediaType, device->media_type); bash_spaces(MediaType); /* This is mostly to indicate that we are here */ ok = dir->fsend(Device_update, jcr->Job, dev_name.c_str(), /* Changer name */ 0, 0, 0, /* append, read, num_writers */ 0, 0, 0, /* is_open, is_labeled, offline */ 0, 0, /* reserved, max_writers */ 0, /* Autoselect */ changer->device->size(), /* Number of devices */ "0", /* PoolId */ "*", /* ChangerName */ MediaType.c_str(), /* MediaType */ "*"); /* VolName */ Dmsg1(dbglvl, ">dird: %s\n", dir->msg); return ok; }
/* * We get the number of slots in the changer from the SD */ static int get_num_slots_from_SD(UAContext *ua) { STORE *store = ua->jcr->wstore; char dev_name[MAX_NAME_LENGTH]; BSOCK *sd; int slots = 0; if (!(sd=open_sd_bsock(ua))) { return 0; } bstrncpy(dev_name, store->dev_name(), sizeof(dev_name)); bash_spaces(dev_name); /* Ask for autochanger number of slots */ sd->fsend(NT_("autochanger slots %s\n"), dev_name); while (sd->recv() >= 0) { if (sscanf(sd->msg, "slots=%d\n", &slots) == 1) { break; } else { ua->send_msg("%s", sd->msg); } } close_sd_bsock(ua); ua->send_msg(_("Device \"%s\" has %d slots.\n"), store->dev_name(), slots); return slots; }
static char *get_volume_name_from_SD(UAContext *ua, int Slot, int drive) { STORE *store = ua->jcr->wstore; BSOCK *sd; char dev_name[MAX_NAME_LENGTH]; char *VolName = NULL; int rtn_slot; if (!(sd=open_sd_bsock(ua))) { ua->error_msg(_("Could not open SD socket.\n")); return NULL; } bstrncpy(dev_name, store->dev_name(), sizeof(dev_name)); bash_spaces(dev_name); /* Ask for autochanger list of volumes */ sd->fsend(NT_("readlabel %s Slot=%d drive=%d\n"), dev_name, Slot, drive); Dmsg1(100, "Sent: %s", sd->msg); /* Get Volume name in this Slot */ while (sd->recv() >= 0) { ua->send_msg("%s", sd->msg); Dmsg1(100, "Got: %s", sd->msg); if (strncmp(sd->msg, NT_("3001 Volume="), 12) == 0) { VolName = (char *)malloc(sd->msglen); if (sscanf(sd->msg, NT_("3001 Volume=%s Slot=%d"), VolName, &rtn_slot) == 2) { break; } free(VolName); VolName = NULL; } } close_sd_bsock(ua); Dmsg1(100, "get_vol_name=%s\n", NPRT(VolName)); return VolName; }
/* * We get the number of drives in the changer from the SD */ int get_num_drives_from_SD(UAContext *ua) { STORERES *store = ua->jcr->res.wstore; char dev_name[MAX_NAME_LENGTH]; BSOCK *sd; int drives = 0; if (!(sd = open_sd_bsock(ua))) { return 0; } bstrncpy(dev_name, store->dev_name(), sizeof(dev_name)); bash_spaces(dev_name); /* * Ask for autochanger number of drives */ sd->fsend(changerdrivescmd, dev_name); while (sd->recv() >= 0) { if (sscanf(sd->msg, changerdrivesresponse, &drives) == 1) { break; } else { ua->send_msg("%s", sd->msg); } } close_sd_bsock(ua); // bsendmsg(ua, _("Device \"%s\" has %d drives.\n"), store->dev_name(), drives); return drives; }
/* * resolve a host on a storage daemon */ bool do_storage_resolve(UAContext *ua, STORERES *store) { BSOCK *sd; USTORERES lstore; lstore.store = store; pm_strcpy(lstore.store_source, _("unknown source")); set_wstorage(ua->jcr, &lstore); if (!(sd = open_sd_bsock(ua))) { return false; } for (int i = 1; i < ua->argc; i++) { if (!*ua->argk[i]) { continue; } sd->fsend("resolve %s", ua->argk[i]); while (sd->recv() >= 0) { ua->send_msg("%s", sd->msg); } } sd->signal(BNET_TERMINATE); sd->close(); ua->jcr->store_bsock = NULL; return true; }
/* * Get the status of a remote storage daemon. */ void do_native_storage_status(UAContext *ua, STORERES *store, char *cmd) { BSOCK *sd; USTORERES lstore; lstore.store = store; pm_strcpy(lstore.store_source, _("unknown source")); set_wstorage(ua->jcr, &lstore); /* * Try connecting for up to 15 seconds */ if (!ua->api) { ua->send_msg(_("Connecting to Storage daemon %s at %s:%d\n"), store->name(), store->address, store->SDport); } if (!connect_to_storage_daemon(ua->jcr, 10, me->SDConnectTimeout, false)) { ua->send_msg(_("\nFailed to connect to Storage daemon %s.\n====\n"), store->name()); if (ua->jcr->store_bsock) { ua->jcr->store_bsock->close(); delete ua->jcr->store_bsock; ua->jcr->store_bsock = NULL; } return; } Dmsg0(20, _("Connected to storage daemon\n")); sd = ua->jcr->store_bsock; if (cmd) { sd->fsend(dotstatuscmd, cmd); } else { sd->fsend(statuscmd); } while (sd->recv() >= 0) { ua->send_msg("%s", sd->msg); } sd->signal( BNET_TERMINATE); sd->close(); delete ua->jcr->store_bsock; ua->jcr->store_bsock = NULL; return; }
/** * Save OSX specific resource forks and finder info. */ static inline bool save_rsrc_and_finder(b_save_ctx &bsctx) { char flags[FOPTS_BYTES]; int rsrc_stream; BSOCK *sd = bsctx.jcr->store_bsock; bool retval = false; if (bsctx.ff_pkt->hfsinfo.rsrclength > 0) { if (bopen_rsrc(&bsctx.ff_pkt->bfd, bsctx.ff_pkt->fname, O_RDONLY | O_BINARY, 0) < 0) { bsctx.ff_pkt->ff_errno = errno; berrno be; Jmsg(bsctx.jcr, M_NOTSAVED, -1, _(" Cannot open resource fork for \"%s\": ERR=%s.\n"), bsctx.ff_pkt->fname, be.bstrerror()); bsctx.jcr->JobErrors++; if (is_bopen(&bsctx.ff_pkt->bfd)) { bclose(&bsctx.ff_pkt->bfd); } } else { int status; memcpy(flags, bsctx.ff_pkt->flags, sizeof(flags)); clear_bit(FO_COMPRESS, bsctx.ff_pkt->flags); clear_bit(FO_SPARSE, bsctx.ff_pkt->flags); clear_bit(FO_OFFSETS, bsctx.ff_pkt->flags); rsrc_stream = bit_is_set(FO_ENCRYPT, flags) ? STREAM_ENCRYPTED_MACOS_FORK_DATA : STREAM_MACOS_FORK_DATA; status = send_data(bsctx.jcr, rsrc_stream, bsctx.ff_pkt, bsctx.digest, bsctx.signing_digest); memcpy(bsctx.ff_pkt->flags, flags, sizeof(flags)); bclose(&bsctx.ff_pkt->bfd); if (!status) { goto bail_out; } } } Dmsg1(300, "Saving Finder Info for \"%s\"\n", bsctx.ff_pkt->fname); sd->fsend("%ld %d 0", bsctx.jcr->JobFiles, STREAM_HFSPLUS_ATTRIBUTES); Dmsg1(300, "filed>stored:header %s", sd->msg); pm_memcpy(sd->msg, bsctx.ff_pkt->hfsinfo.fndrinfo, 32); sd->msglen = 32; if (bsctx.digest) { crypto_digest_update(bsctx.digest, (uint8_t *)sd->msg, sd->msglen); } if (bsctx.signing_digest) { crypto_digest_update(bsctx.signing_digest, (uint8_t *)sd->msg, sd->msglen); } sd->send(); sd->signal(BNET_EOD); retval = true; bail_out: return retval; }
/* * Authenticate Director */ bool BSOCK::authenticate_with_director(JCR *jcr, const char *name, s_password &password, tls_t &tls, char *response, int response_len) { char bashed_name[MAX_NAME_LENGTH]; BSOCK *dir = this; /* for readability */ response[0] = 0; /* * Send my name to the Director then do authentication */ bstrncpy(bashed_name, name, sizeof(bashed_name)); bash_spaces(bashed_name); /* * Timeout Hello after 5 mins */ dir->start_timer(60 * 5); dir->fsend(hello, bashed_name); if (!authenticate_outbound_connection(jcr, "Director", name, password, tls)) { goto bail_out; } Dmsg1(6, ">dird: %s", dir->msg); if (dir->recv() <= 0) { dir->stop_timer(); bsnprintf(response, response_len, _("Bad response to Hello command: ERR=%s\n" "The Director at \"%s:%d\" is probably not running.\n"), dir->bstrerror(), dir->host(), dir->port()); return false; } dir->stop_timer(); Dmsg1(10, "<dird: %s", dir->msg); if (!bstrncmp(dir->msg, OKhello, sizeof(OKhello) - 1)) { bsnprintf(response, response_len, _("Director at \"%s:%d\" rejected Hello command\n"), dir->host(), dir->port()); return false; } else { bsnprintf(response, response_len, "%s", dir->msg); } return true; bail_out: dir->stop_timer(); bsnprintf(response, response_len, _("Authorization problem with Director at \"%s:%d\"\n" "Most likely the passwords do not agree.\n" "If you are using TLS, there may have been a certificate " "validation error during the TLS handshake.\n" "Please see %s for help.\n"), dir->host(), dir->port(), MANUAL_AUTH_URL); return false; }
/* * Terminate the signing digest and send it to the Storage daemon */ static inline bool terminate_signing_digest(b_save_ctx &bsctx) { uint32_t size = 0; bool retval = false; SIGNATURE *signature = NULL; BSOCK *sd = bsctx.jcr->store_bsock; if ((signature = crypto_sign_new(bsctx.jcr)) == NULL) { Jmsg(bsctx.jcr, M_FATAL, 0, _("Failed to allocate memory for crypto signature.\n")); goto bail_out; } if (!crypto_sign_add_signer(signature, bsctx.signing_digest, bsctx.jcr->crypto.pki_keypair)) { Jmsg(bsctx.jcr, M_FATAL, 0, _("An error occurred while signing the stream.\n")); goto bail_out; } /* * Get signature size */ if (!crypto_sign_encode(signature, NULL, &size)) { Jmsg(bsctx.jcr, M_FATAL, 0, _("An error occurred while signing the stream.\n")); goto bail_out; } /* * Grow the bsock buffer to fit our message if necessary */ if (sizeof_pool_memory(sd->msg) < (int32_t)size) { sd->msg = realloc_pool_memory(sd->msg, size); } /* * Send our header */ sd->fsend("%ld %ld 0", bsctx.jcr->JobFiles, STREAM_SIGNED_DIGEST); Dmsg1(300, "filed>stored:header %s", sd->msg); /* * Encode signature data */ if (!crypto_sign_encode(signature, (uint8_t *)sd->msg, &size)) { Jmsg(bsctx.jcr, M_FATAL, 0, _("An error occurred while signing the stream.\n")); goto bail_out; } sd->msglen = size; sd->send(); sd->signal(BNET_EOD); /* end of checksum */ retval = true; bail_out: if (signature) { crypto_sign_free(signature); } return retval; }
/* * Read Close session command * Close the read session */ static bool read_close_session(JCR *jcr) { BSOCK *fd = jcr->file_bsock; Dmsg1(120, "Read close session: %s\n", fd->msg); if (!jcr->session_opened) { fd->fsend(NOT_opened); return false; } /* Send final close msg to File daemon */ fd->fsend(OK_close, jcr->JobStatus); Dmsg1(160, ">filed: %s\n", fd->msg); fd->signal(BNET_EOD); /* send EOD to File daemon */ jcr->session_opened = false; return true; }
/* * Now talk to the SD and do what he says */ static void do_sd_commands(JCR *jcr) { int i, status; bool found, quit; BSOCK *sd = jcr->store_bsock; sd->set_jcr(jcr); quit = false; while (!quit) { /* * Read command coming from the Storage daemon */ status = sd->recv(); if (is_bnet_stop(sd)) { /* hardeof or error */ break; /* connection terminated */ } if (status <= 0) { continue; /* ignore signals and zero length msgs */ } Dmsg1(110, "<stored: %s", sd->msg); found = false; for (i = 0; sd_cmds[i].cmd; i++) { if (bstrncmp(sd_cmds[i].cmd, sd->msg, strlen(sd_cmds[i].cmd))) { found = true; /* indicate command found */ jcr->errmsg[0] = 0; if (!sd_cmds[i].func(jcr)) { /* do command */ /* * Note sd->msg command may be destroyed by comm activity */ if (!job_canceled(jcr)) { if (jcr->errmsg[0]) { Jmsg1(jcr, M_FATAL, 0, _("Command error with SD, hanging up. %s\n"), jcr->errmsg); } else { Jmsg0(jcr, M_FATAL, 0, _("Command error with SD, hanging up.\n")); } jcr->setJobStatus(JS_ErrorTerminated); } quit = true; } break; } } if (!found) { /* command not found */ if (!job_canceled(jcr)) { Jmsg1(jcr, M_FATAL, 0, _("SD command not found: %s\n"), sd->msg); Dmsg1(110, "<stored: Command not found: %s\n", sd->msg); } sd->fsend(serrmsg); break; } } sd->signal(BNET_TERMINATE); /* signal to SD job is done */ }
/* * Append Open session command * */ static bool append_open_session(JCR *jcr) { BSOCK *fd = jcr->file_bsock; Dmsg1(120, "Append open session: %s", fd->msg); if (jcr->session_opened) { pm_strcpy(jcr->errmsg, _("Attempt to open already open session.\n")); fd->fsend(NO_open); return false; } jcr->session_opened = true; /* Send "Ticket" to File Daemon */ fd->fsend(OK_open, jcr->VolSessionId); Dmsg1(110, ">filed: %s", fd->msg); return true; }
/* * Append Close session command * Close the append session and send back Statistics * (need to fix statistics) */ static bool append_close_session(JCR *jcr) { BSOCK *fd = jcr->file_bsock; Dmsg1(120, "<filed: %s", fd->msg); if (!jcr->session_opened) { pm_strcpy(jcr->errmsg, _("Attempt to close non-open session.\n")); fd->fsend(NOT_opened); return false; } /* Send final statistics to File daemon */ fd->fsend(OK_close, jcr->JobStatus); Dmsg1(120, ">filed: %s", fd->msg); fd->signal(BNET_EOD); /* send EOD to File daemon */ jcr->session_opened = false; return true; }
/* * Start of replication. */ static bool start_replication_session(JCR *jcr) { BSOCK *sd = jcr->store_bsock; Dmsg1(120, "Start replication session: %s", sd->msg); if (jcr->session_opened) { pm_strcpy(jcr->errmsg, _("Attempt to open already open session.\n")); sd->fsend(NO_open); return false; } jcr->session_opened = true; /* * Send "Ticket" to Storage Daemon */ sd->fsend(OK_start_replicate, jcr->VolSessionId); Dmsg1(110, ">stored: %s", sd->msg); return true; }
/* * Append Data command * Open Data Channel and receive Data for archiving * Write the Data to the archive device */ static bool append_data_cmd(JCR *jcr) { BSOCK *fd = jcr->file_bsock; Dmsg1(120, "Append data: %s", fd->msg); if (jcr->session_opened) { Dmsg1(110, "<bfiled: %s", fd->msg); jcr->set_JobType(JT_BACKUP); if (do_append_data(jcr)) { return true; } else { pm_strcpy(jcr->errmsg, _("Append data error.\n")); bnet_suppress_error_messages(fd, 1); /* ignore errors at this point */ fd->fsend(ERROR_append); } } else { pm_strcpy(jcr->errmsg, _("Attempt to append on non-open session.\n")); fd->fsend(NOT_opened); } return false; }
/* * Replicate data. * Open Data Channel and receive Data for archiving * Write the Data to the archive device */ static bool replicate_data(JCR *jcr) { BSOCK *sd = jcr->store_bsock; Dmsg1(120, "Replicate data: %s", sd->msg); if (jcr->session_opened) { Dmsg1(110, "<stored: %s", sd->msg); if (do_append_data(jcr, sd, "SD")) { return true; } else { pm_strcpy(jcr->errmsg, _("Replicate data error.\n")); bnet_suppress_error_messages(sd, 1); /* ignore errors at this point */ sd->fsend(ERROR_replicate); } } else { pm_strcpy(jcr->errmsg, _("Attempt to replicate on non-open session.\n")); sd->fsend(NOT_opened); } return false; }
bool send_bwlimit_to_sd(JCR *jcr, const char *Job) { BSOCK *sd = jcr->store_bsock; sd->fsend(bandwidthcmd, jcr->max_bandwidth, Job); if (!response(jcr, sd, OKBandwidth, "Bandwidth", DISPLAY_ERROR)) { jcr->max_bandwidth = 0; /* can't set bandwidth limit */ return false; } return true; }
/* * Run a File daemon Job -- File daemon already authorized * Director sends us this command. * * Basic task here is: * - Read a command from the File daemon * - Execute it * */ void run_job(JCR *jcr) { BSOCK *dir = jcr->dir_bsock; char ec1[30]; dir->set_jcr(jcr); Dmsg1(120, "Start run Job=%s\n", jcr->Job); dir->fsend(Job_start, jcr->Job); jcr->start_time = time(NULL); jcr->run_time = jcr->start_time; set_jcr_job_status(jcr, JS_Running); dir_send_job_status(jcr); /* update director */ do_fd_commands(jcr); jcr->end_time = time(NULL); dequeue_messages(jcr); /* send any queued messages */ set_jcr_job_status(jcr, JS_Terminated); generate_daemon_event(jcr, "JobEnd"); dir->fsend(Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles, edit_uint64(jcr->JobBytes, ec1), jcr->JobErrors); dir->signal(BNET_EOD); /* send EOD to Director daemon */ return; }