-
Notifications
You must be signed in to change notification settings - Fork 256
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
contrib: add pure python statefile parser #1789
base: master
Are you sure you want to change the base?
Conversation
Should we anticipate the usage of that decoding for also bareos-sd ? |
I haven't tested it, but maybe it just works? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work. I found a bug and added some suggestions as well.
"Q", # job start time | ||
"Q", # job end time |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Q", # job start time | |
"Q", # job end time | |
"q", # job start time | |
"q", # job end time |
time_t
(and utime_t
) are actually signed! the u
stands for unix
i believe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some useless trivia on the usability of time_t
: GNU libc guarantees that time_t
is signed and negative values are handled correctly, even though they're undefined as of POSIX.
POSIX only requires that time_t
is "an integer type" that represents seconds since epoch, so a system using int8_t
would still be compliant, even though it couldn't represent a time after 1970-01-01T00:02:07Z.
Last but not least ISO C defines time_t
as integer or float that you can pass to library functions that accept a time_t
.
But yes, in our case "q"
is more correct than "Q"
😃
|
||
results = [] | ||
offset = last_job_offset + NUM_FMT_LEN | ||
for _ in range(1, num_recs): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for _ in range(1, num_recs): | |
for _ in range(0, num_recs): |
why are we skipping the last one ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
um... off-by-one error? 🤦♂️
from dataclasses import dataclass | ||
from datetime import datetime | ||
|
||
HEADER_FMT = "".join( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think giving the specifiers useful names makes this much clearer. What do you think ?
def padding(count):
return str(count) + "x"
def cstring(max_size):
return str(max_size) + "s"
def repeat(type, count):
return str(count) + type
# using standard sizes
i32 = "i"
i64 = "q"
u32 = "I"
u64 = "Q"
HEADER_FMT = "".join(
(
"=", # native byte-order with standard sizes
cstring(14), # magic
padding(2),
i32, # version
padding(4),
u64, # last job offset
u64, # end of list
repeat(u64, 19), # reserved
)
)
HEADER_LEN = calcsize(HEADER_FMT)
NUM_FMT = "".join(
(
"=", # native byte-order with standard sizes
i32, # number of result records
)
)
NUM_FMT_LEN = calcsize(NUM_FMT)
RESULT_FMT = "".join(
(
"=", # native byte-order with standard sizes
padding(16),
i32, # errors
i32, # job type
i32, # job status
i32, # job level
u32, # job id
u32, # volume session id
u32, # volume session time
u32, # job files
u64, # job bytes
u64, # job start time
u64, # job end time
cstring(128), # job name
)
)
RESULT_LEN = calcsize(RESULT_FMT)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ofc job [start|end] time
should be i64
here as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't say that this is wrong. However, you will have to understand struct.pack()
/struct.unpack()
anyway. So I'm not convinced an extra level of indirection will really improve readability.
It just work when the state file in not empty. So good enough for contrib code. |
We should probably write at least one systemtest for this. Nothing major. A simple backup + read state file and check for consistency should be enough. |
But if we do that, then this isn't example-code for contrib anymore. Then we should clean it up, make sure it is portable and put it into the scripts directory. |
This PR adds a python module to read Bareos filedaemon statefiles.
Please check
If you have any questions or problems, please give a comment in the PR.
Helpful documentation and best practices
Checklist for the reviewer of the PR (will be processed by the Bareos team)
Make sure you check/merge the PR using
devtools/pr-tool
to have some simple automated checks run and a proper changelog record added.General
Required backport PRs have been createdSource code quality
Required documentation changes are present and part of the PRTests