mirror of
https://github.com/postgrespro/pg_probackup.git
synced 2025-02-13 14:58:35 +02:00
[Issue #204] Make version check of remote agent more robust
This commit is contained in:
parent
497f5b2e9e
commit
2c711bd57b
@ -44,7 +44,7 @@ slurpFile(const char *datadir, const char *path, size_t *filesize, bool safe, fi
|
||||
fullpath, strerror(errno));
|
||||
}
|
||||
|
||||
if (fio_fstat(fd, &statbuf) < 0)
|
||||
if (fio_stat(fullpath, &statbuf, true, location) < 0)
|
||||
{
|
||||
if (safe)
|
||||
return NULL;
|
||||
|
@ -343,16 +343,8 @@ main(int argc, char *argv[])
|
||||
else if (strcmp(argv[1], "ssh") == 0)
|
||||
launch_ssh(argv);
|
||||
#endif
|
||||
else if (strcmp(argv[1], "agent") == 0 && argc > 2)
|
||||
else if (strcmp(argv[1], "agent") == 0)
|
||||
{
|
||||
remote_agent = argv[2];
|
||||
if (strcmp(remote_agent, PROGRAM_VERSION) != 0)
|
||||
{
|
||||
uint32 agent_version = parse_program_version(remote_agent);
|
||||
elog(agent_version != AGENT_PROTOCOL_VERSION ? ERROR : WARNING,
|
||||
"Agent version %s doesn't match master pg_probackup version %s",
|
||||
PROGRAM_VERSION, remote_agent);
|
||||
}
|
||||
fio_communicate(STDIN_FILENO, STDOUT_FILENO);
|
||||
return 0;
|
||||
}
|
||||
@ -528,8 +520,7 @@ main(int argc, char *argv[])
|
||||
{
|
||||
/* Ensure that backup_path is a path to a directory */
|
||||
if (!S_ISDIR(st.st_mode))
|
||||
elog(ERROR, "-B, --backup-path must be a path to directory. Inode: %lu. ST_MODE: %u",
|
||||
st.st_ino, st.st_mode);
|
||||
elog(ERROR, "-B, --backup-path must be a path to directory");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -185,6 +185,19 @@ static ssize_t fio_write_all(int fd, void const* buf, size_t size)
|
||||
return offs;
|
||||
}
|
||||
|
||||
/* Get version of remote agent */
|
||||
int fio_get_agent_version(void)
|
||||
{
|
||||
fio_header hdr;
|
||||
hdr.cop = FIO_AGENT_VERSION;
|
||||
hdr.size = 0;
|
||||
|
||||
IO_CHECK(fio_write_all(fio_stdout, &hdr, sizeof(hdr)), sizeof(hdr));
|
||||
IO_CHECK(fio_read_all(fio_stdin, &hdr, sizeof(hdr)), sizeof(hdr));
|
||||
|
||||
return hdr.arg;
|
||||
}
|
||||
|
||||
/* Open input stream. Remote file is fetched to the in-memory buffer and then accessed through Linux fmemopen */
|
||||
FILE* fio_open_stream(char const* path, fio_location location)
|
||||
{
|
||||
@ -728,44 +741,6 @@ ssize_t fio_read(int fd, void* buf, size_t size)
|
||||
}
|
||||
}
|
||||
|
||||
/* Get information about stdio file */
|
||||
int fio_ffstat(FILE* f, struct stat* st)
|
||||
{
|
||||
return fio_is_remote_file(f)
|
||||
? fio_fstat(fio_fileno(f), st)
|
||||
: fio_fstat(fileno(f), st);
|
||||
}
|
||||
|
||||
/* Get information about file descriptor */
|
||||
int fio_fstat(int fd, struct stat* st)
|
||||
{
|
||||
if (fio_is_remote_fd(fd))
|
||||
{
|
||||
fio_header hdr;
|
||||
|
||||
hdr.cop = FIO_FSTAT;
|
||||
hdr.handle = fd & ~FIO_PIPE_MARKER;
|
||||
hdr.size = 0;
|
||||
|
||||
IO_CHECK(fio_write_all(fio_stdout, &hdr, sizeof(hdr)), sizeof(hdr));
|
||||
|
||||
IO_CHECK(fio_read_all(fio_stdin, &hdr, sizeof(hdr)), sizeof(hdr));
|
||||
Assert(hdr.cop == FIO_FSTAT);
|
||||
IO_CHECK(fio_read_all(fio_stdin, st, sizeof(*st)), sizeof(*st));
|
||||
|
||||
if (hdr.arg != 0)
|
||||
{
|
||||
errno = hdr.arg;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return fstat(fd, st);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get information about file */
|
||||
int fio_stat(char const* path, struct stat* st, bool follow_symlink, fio_location location)
|
||||
{
|
||||
@ -2065,11 +2040,9 @@ void fio_communicate(int in, int out)
|
||||
if (hdr.size != 0)
|
||||
IO_CHECK(fio_write_all(out, buf, hdr.size), hdr.size);
|
||||
break;
|
||||
case FIO_FSTAT: /* Get information about opened file */
|
||||
hdr.size = sizeof(st);
|
||||
hdr.arg = fstat(fd[hdr.handle], &st) < 0 ? errno : 0;
|
||||
case FIO_AGENT_VERSION:
|
||||
hdr.arg = AGENT_PROTOCOL_VERSION;
|
||||
IO_CHECK(fio_write_all(out, &hdr, sizeof(hdr)), sizeof(hdr));
|
||||
IO_CHECK(fio_write_all(out, &st, sizeof(st)), sizeof(st));
|
||||
break;
|
||||
case FIO_STAT: /* Get information about file with specified path */
|
||||
hdr.size = sizeof(st);
|
||||
|
@ -27,7 +27,6 @@ typedef enum
|
||||
FIO_READ,
|
||||
FIO_LOAD,
|
||||
FIO_STAT,
|
||||
FIO_FSTAT,
|
||||
FIO_SEND,
|
||||
FIO_ACCESS,
|
||||
FIO_OPENDIR,
|
||||
@ -47,6 +46,8 @@ typedef enum
|
||||
/* messages for closing connection */
|
||||
FIO_DISCONNECT,
|
||||
FIO_DISCONNECTED,
|
||||
/* message for compatibility check */
|
||||
FIO_AGENT_VERSION
|
||||
} fio_operations;
|
||||
|
||||
typedef enum
|
||||
@ -79,6 +80,7 @@ extern fio_location MyLocation;
|
||||
extern void fio_redirect(int in, int out, int err);
|
||||
extern void fio_communicate(int in, int out);
|
||||
|
||||
extern int fio_get_agent_version(void);
|
||||
extern FILE* fio_fopen(char const* name, char const* mode, fio_location location);
|
||||
extern size_t fio_fwrite(FILE* f, void const* buf, size_t size);
|
||||
extern ssize_t fio_fwrite_compressed(FILE* f, void const* buf, size_t size, int compress_alg);
|
||||
|
@ -111,6 +111,7 @@ bool launch_agent(void)
|
||||
int outfd[2];
|
||||
int infd[2];
|
||||
int errfd[2];
|
||||
int agent_version;
|
||||
|
||||
ssh_argc = 0;
|
||||
#ifdef WIN32
|
||||
@ -163,24 +164,24 @@ bool launch_agent(void)
|
||||
}
|
||||
}
|
||||
if (needs_quotes(instance_config.remote.path) || needs_quotes(PROGRAM_NAME_FULL))
|
||||
snprintf(cmd, sizeof(cmd), "\"%s\\%s\" agent %s",
|
||||
instance_config.remote.path, probackup, PROGRAM_VERSION);
|
||||
snprintf(cmd, sizeof(cmd), "\"%s\\%s\" agent",
|
||||
instance_config.remote.path, probackup);
|
||||
else
|
||||
snprintf(cmd, sizeof(cmd), "%s\\%s agent %s",
|
||||
instance_config.remote.path, probackup, PROGRAM_VERSION);
|
||||
snprintf(cmd, sizeof(cmd), "%s\\%s agent",
|
||||
instance_config.remote.path, probackup);
|
||||
#else
|
||||
if (needs_quotes(instance_config.remote.path) || needs_quotes(PROGRAM_NAME_FULL))
|
||||
snprintf(cmd, sizeof(cmd), "\"%s/%s\" agent %s",
|
||||
instance_config.remote.path, probackup, PROGRAM_VERSION);
|
||||
snprintf(cmd, sizeof(cmd), "\"%s/%s\" agent",
|
||||
instance_config.remote.path, probackup);
|
||||
else
|
||||
snprintf(cmd, sizeof(cmd), "%s/%s agent %s",
|
||||
instance_config.remote.path, probackup, PROGRAM_VERSION);
|
||||
snprintf(cmd, sizeof(cmd), "%s/%s agent",
|
||||
instance_config.remote.path, probackup);
|
||||
#endif
|
||||
} else {
|
||||
if (needs_quotes(PROGRAM_NAME_FULL))
|
||||
snprintf(cmd, sizeof(cmd), "\"%s\" agent %s", PROGRAM_NAME_FULL, PROGRAM_VERSION);
|
||||
snprintf(cmd, sizeof(cmd), "\"%s\" agent", PROGRAM_NAME_FULL);
|
||||
else
|
||||
snprintf(cmd, sizeof(cmd), "%s agent %s", PROGRAM_NAME_FULL, PROGRAM_VERSION);
|
||||
snprintf(cmd, sizeof(cmd), "%s agent", PROGRAM_NAME_FULL);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
@ -228,5 +229,22 @@ bool launch_agent(void)
|
||||
|
||||
fio_redirect(infd[0], outfd[1], errfd[0]); /* write to stdout */
|
||||
}
|
||||
|
||||
/* Make sure that remote agent has the same version
|
||||
* TODO: we must also check PG version and fork edition
|
||||
*/
|
||||
agent_version = fio_get_agent_version();
|
||||
if (agent_version != AGENT_PROTOCOL_VERSION)
|
||||
{
|
||||
char agent_version_str[1024];
|
||||
sprintf(agent_version_str, "%d.%d.%d",
|
||||
agent_version / 10000,
|
||||
(agent_version / 100) % 100,
|
||||
agent_version % 100);
|
||||
|
||||
elog(ERROR, "Remote agent version %s does not match local program version %s",
|
||||
agent_version_str, PROGRAM_VERSION);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user