1 /* 2 Bacula(R) - The Network Backup Solution 3 4 Copyright (C) 2000-2019 Kern Sibbald 5 6 The original author of Bacula is Kern Sibbald, with contributions 7 from many others, a complete list can be found in the file AUTHORS. 8 9 You may use this file and others of this release according to the 10 license defined in the LICENSE file, which includes the Affero General 11 Public License, v3.0 ("AGPLv3") and some additional permissions and 12 terms pursuant to its AGPLv3 Section 7. 13 14 This notice must be preserved when any source code is 15 conveyed and/or propagated. 16 17 Bacula(R) is a registered trademark of Kern Sibbald. 18 */ 19 /* 20 * This is a Bacula plugin for backup/restore Docker using native tools. 21 * 22 * Author: Radosław Korzeniewski, MMXIX 23 * radoslaw@korzeniewski.net, radekk@inteos.pl 24 * Inteos Sp. z o.o. http://www.inteos.pl/ 25 */ 26 27 #ifndef _DKCOMMCTX_H_ 28 #define _DKCOMMCTX_H_ 29 30 #include "pluglib.h" 31 #include "lib/ini.h" 32 #include "lib/bregex.h" 33 34 #define USE_CMD_PARSER 35 #include "fd_common.h" 36 #include "dkinfo.h" 37 38 /* Plugin compile time variables */ 39 #ifndef DOCKER_CMD 40 #ifndef HAVE_WIN32 41 #define DOCKER_CMD "/usr/bin/docker" 42 #else 43 #define DOCKER_CMD "C:/Program Files/Docker/Docker/resources/bin/docker.exe" 44 #endif 45 #endif 46 47 #ifndef WORKDIR 48 #define WORKDIR "/opt/bacula/working" 49 #endif 50 51 #define BACULATARIMAGE "baculatar:" DOCKER_TAR_IMAGE 52 53 #define BACULACONTAINERFOUT "fout" 54 #define BACULACONTAINERFIN "fin" 55 #define BACULACONTAINERERRLOG "docker.err" 56 #define BACULACONTAINERARCHLOG "docker.log" 57 58 /* 59 * Supported backup modes 60 */ 61 typedef enum { 62 DKPAUSE, 63 DKNOPAUSE, 64 } DOCKER_BACKUP_MODE_T; 65 66 /* 67 * The list of restore options saved to the RestoreObject. 68 */ 69 static struct ini_items plugin_items_dump[] = { 70 // name handler comment required default 71 {"container_create", ini_store_bool, "Create container on restore", 0, "*Yes*"}, 72 {"container_run", ini_store_bool, "Run container on restore", 0, "*No*"}, 73 {"container_imageid", ini_store_bool, "Use Image Id for container creation/start", 0, "*No*"}, 74 {"container_defaultnames", ini_store_bool, "Use default docker Names on container creation", 0, "*No*"}, 75 {"docker_host", ini_store_str, "Use defined docker host to restore", 0, "*local*"}, 76 {"timeout", ini_store_int32, "Timeout connecting to volume container", 0, "*30*"}, 77 {NULL, NULL, NULL, 0, NULL} 78 }; 79 80 /* 81 * This is a low-level communication class which handles command tools execution. 82 */ 83 class DKCOMMCTX: public SMARTALLOC { 84 public: 85 char *command; 86 87 alist *get_all_containers(bpContext *ctx); 88 alist *get_all_images(bpContext *ctx); 89 alist *get_all_volumes(bpContext *ctx); 90 void release_all_dkinfo_list(alist **list); 91 void release_all_pm_list(alist **list); 92 void set_all_to_backup(bpContext *ctx); 93 void set_all_containers_to_backup(bpContext *ctx); 94 void set_all_images_to_backup(bpContext *ctx); 95 void set_all_volumes_to_backup(bpContext *ctx); 96 get_first_to_backup(bpContext * ctx)97 inline DKINFO *get_first_to_backup(bpContext *ctx) { return (DKINFO*)objs_to_backup->first(); }; get_next_to_backup(bpContext * ctx)98 inline DKINFO *get_next_to_backup(bpContext *ctx) { return (DKINFO*)objs_to_backup->next(); }; finish_backup_list(bpContext * ctx)99 inline void finish_backup_list(bpContext *ctx) { objs_to_backup->last(); }; 100 101 bRC container_commit(bpContext *ctx, DKINFO *dkinfo, int jobid); 102 bRC delete_container_commit(bpContext *ctx, DKINFO *dkinfo, int jobid); 103 bRC image_save(bpContext *ctx, DKID *dkid); 104 bRC backup_docker(bpContext *ctx, DKINFO *dkinfo, int jobid); 105 bRC restore_docker(bpContext *ctx, DKINFO *dkinfo, int jobid); 106 bRC docker_tag(bpContext* ctx, DKID &dkid, POOLMEM *tag); 107 bRC docker_create_run_container(bpContext* ctx, DKINFO *dkinfo); 108 bRC wait_for_restore(bpContext *ctx, DKID &dkid); 109 void update_vols_mounts(bpContext* ctx, DKINFO *container, DKVOLS *volume); 110 111 int32_t read_data(bpContext *ctx, POOLMEM *buf, int32_t len); 112 int32_t read_output(bpContext *ctx, POOL_MEM &out); 113 int32_t write_data(bpContext *ctx, POOLMEM *buf, int32_t len); 114 void terminate(bpContext *ctx); get_backend_pid()115 inline int get_backend_pid() { if (bpipe){ return bpipe->worker_pid; } return -1;}; 116 117 bRC parse_parameters(bpContext *ctx, char *argk, char *argv); 118 bRC parse_restoreobj(bpContext *ctx, restore_object_pkt *rop); 119 bRC prepare_bejob(bpContext *ctx, bool estimate); 120 bRC prepare_restore(bpContext *ctx); 121 bRC prepare_working_volume(bpContext* ctx, int jobid); 122 void clean_working_volume(bpContext* ctx); render_working_volume_filename(POOL_MEM & buf,const char * fname)123 inline void render_working_volume_filename(POOL_MEM &buf, const char *fname) 124 { Mmsg(buf, "%s/%s", workingvolume, fname); }; 125 void setworkingdir(char *workdir); 126 is_open()127 inline bool is_open() { return bpipe != NULL; }; is_closed()128 inline bool is_closed() { return bpipe == NULL; }; is_error()129 inline bool is_error() { return f_error || f_fatal; }; set_error()130 inline void set_error() { f_error = true; }; is_fatal()131 inline bool is_fatal() { return f_fatal || (f_error && abort_on_error); }; is_eod()132 inline bool is_eod() { return f_eod; }; clear_eod()133 inline void clear_eod() { f_eod = false; }; set_eod()134 inline void set_eod() { f_eod = true; }; set_abort_on_error()135 inline void set_abort_on_error() { abort_on_error = true; }; clear_abort_on_error()136 inline void clear_abort_on_error() { abort_on_error = false; }; is_abort_on_error()137 inline bool is_abort_on_error() { return abort_on_error; }; is_all_vols_to_backup()138 inline bool is_all_vols_to_backup() { return all_vols_to_backup; }; is_remote_docker()139 inline bool is_remote_docker() { return param_docker_host != NULL; }; timeout()140 inline int32_t timeout() { return param_timeout; }; 141 142 DKCOMMCTX(const char *cmd); 143 ~DKCOMMCTX(); 144 145 private: 146 BPIPE *bpipe; /* this is our bpipe to communicate with command tools */ 147 alist *param_include_container; /* the include parameter list which filter what container name to backup as regex */ 148 alist *param_include_image; /* the include parameter list which filter what image name to backup as regex */ 149 alist *param_exclude_container; /* the exclude parameter list which filter what container name to exclude from backup */ 150 alist *param_exclude_image; /* the exclude parameter list which filter what image name to exclude from backup */ 151 alist *param_container; /* the container parameter list which filter what container name or id to backup */ 152 alist *param_image; /* the image parameter list which filter what image name or id to backup */ 153 alist *param_volume; /* the volume parameter list which filter what volume name to backup */ 154 DOCKER_BACKUP_MODE_T param_mode; /* the mode parameter which is used with docker commit, default is pause */ 155 bool param_container_create; /* the restore parameter for container creation */ 156 bool param_container_run; /* the restore parameter for container creation and execution */ 157 bool param_container_imageid; /* the restore parameter for setting imageid during container creation/run */ 158 bool param_container_defaultnames; /* the restore parameter for setting default docker names on container creation */ 159 POOLMEM *param_docker_host; /* use defined docker host to docker operations */ 160 int32_t param_timeout; /* a timeout opening container communication pipe, the default is 30 */ 161 regex_t preg; /* this is a regex context for include/exclude */ 162 bool abort_on_error; /* abort on error flag */ 163 alist *all_containers; /* the list of all containers defined on Docker */ 164 alist *all_images; /* the list of all docker images defined on Docker */ 165 alist *all_volumes; /* the list of all docker volumes defined on Docker */ 166 alist *objs_to_backup; /* the list of all docker objects selected to backup or filtered */ 167 bool all_to_backup; /* if true use all_containers list to backup or containers_to_backup list when false */ 168 bool all_vols_to_backup; /* if true use all volumes for container to backup */ 169 bool f_eod; /* the command tool signaled EOD */ 170 bool f_error; /* the plugin signaled an error */ 171 bool f_fatal; /* the plugin signaled a fatal error */ 172 ConfigFile *ini; /* restore object config parser */ 173 POOLMEM *workingvolume; /* */ 174 POOLMEM *workingdir; /* runtime working directory from file daemon */ 175 176 bool execute_command(bpContext *ctx, POOLMEM *args); 177 bool execute_command(bpContext *ctx, const char *args); 178 bool execute_command(bpContext *ctx, POOL_MEM &args); 179 void parse_parameters(bpContext *ctx, ini_items &item); 180 bool render_param(bpContext *ctx, POOLMEM **param, const char *pname, const char *fmt, const char *name, char *value); 181 bool render_param(bpContext *ctx, POOLMEM **param, const char *pname, const char *fmt, const char *name, int value); 182 bool render_param(bpContext *ctx, POOLMEM **param, const char *pname, const char *name, char *value); 183 bool render_param(bpContext *ctx, bool *param, const char *pname, const char *name, bool value); 184 bool render_param(bpContext *ctx, int32_t *param, const char *pname, const char *name, int32_t value); 185 bool add_param_str(bpContext *ctx, alist **list, const char *pname, const char *name, char *value); 186 bool parse_param(bpContext *ctx, POOLMEM **param, const char *pname, const char *name, char *value); 187 bool parse_param(bpContext *ctx, bool *param, const char *pname, const char *name, char *value); 188 bool parse_param(bpContext *ctx, int32_t *param, const char *pname, const char *name, char *value); 189 bool parse_param(bpContext *ctx, DOCKER_BACKUP_MODE_T *param, const char *pname, const char *name, char *value); 190 191 void filter_param_to_backup(bpContext *ctx, alist *params, alist *dklist, bool estimate); 192 void filter_incex_to_backup(bpContext *ctx, alist *params_include, alist *params_exclude, alist *dklist); 193 void add_container_volumes_to_backup(bpContext *ctx); 194 void select_container_vols(bpContext *ctx); 195 alist *get_all_list_from_docker(bpContext* ctx, const char *cmd, int cols, alist **dklist, DKINFO_OBJ_t type); 196 void setup_dkinfo(bpContext* ctx, DKINFO_OBJ_t type, char *paramtab[], DKINFO *dkinfo); 197 void setup_container_dkinfo(bpContext* ctx, char *paramtab[], DKINFO *dkinfo); 198 void setup_image_dkinfo(bpContext* ctx, char *paramtab[], DKINFO *dkinfo); 199 void setup_volume_dkinfo(bpContext* ctx, char *paramtab[], DKINFO *dkinfo); 200 bRC run_container_volume_cmd(bpContext* ctx, const char *cmd, POOLMEM *volname, int jobid); 201 bRC run_container_volume_save(bpContext* ctx, POOLMEM *volname, int jobid); 202 bRC run_container_volume_load(bpContext* ctx, POOLMEM *volname, int jobid); 203 bool check_for_docker_errors(bpContext* ctx, char *buf); render_imagesave_name(POOL_MEM & out,DKINFO * dkinfo,int jobid)204 inline void render_imagesave_name(POOL_MEM &out, DKINFO *dkinfo, int jobid) 205 { Mmsg(out, "%s/%s/%d:backup", dkinfo->get_container_names(), 206 dkinfo->get_container_id()->digest_short(), jobid); }; 207 void dump_robjdebug(bpContext *ctx, restore_object_pkt *rop); 208 }; 209 210 #endif /* _DKCOMMCTX_H_ */