Taking fast and efficient volume snapshots with XenServer (and your storage provider) - #1403
Conversation
|
Here's a copy of my Marvin integration tests (I added a .txt file type so that I could upload the file as it's not permitted to upload a file of type .py): Here are the most recent test results: |
| if (errMsg == null) { | ||
| snapshotInfo.processEvent(Event.OperationSuccessed); | ||
| if (copyCmdAnswer == null || !copyCmdAnswer.getResult()) { | ||
| if (copyCmdAnswer != null && copyCmdAnswer.getDetails() != null && !copyCmdAnswer.getDetails().isEmpty()) { |
There was a problem hiding this comment.
@mike-tutkowski Could you please use StringUtils.isEmpty (https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/StringUtils.html#isEmpty(java.lang.String))?
This is a null safe test if the String copyCmdAnswer.getDetails is empty (you can use this method at lines 260, 363 and 403 -- in the StorageSystemDataMotionStrategy class).
Thanks.
|
Thanks for the comments, Gabriel. I have pushed a new commit with those updates. |
| return Boolean.parseBoolean(property); | ||
| } | ||
|
|
||
| private Void handleCreateTemplateFromSnapshot(SnapshotInfo snapshotInfo, TemplateInfo templateInfo, AsyncCompletionCallback<CopyCommandResult> callback) { |
There was a problem hiding this comment.
Hi @mike-tutkowski ,
Consider changing "Void" to "void" and removing the "return null;" at the end of this method.
Another suggestion is to create a single method, if possible, for the lines 260 to 266 and 363 to 371, this would avoid some duplication of code.
There was a problem hiding this comment.
Thanks. Initially this method was patterned off of an existing set of methods that used the "Void" approach. I wasn't sure if there was a good reason for why they did it that way and erred on the side of caution and just repeated the pattern.
As it turned out, someone later changed those methods from "Void" to "void" and so I ended up doing so in my sandbox (but haven't yet pushed the changes).
There was a problem hiding this comment.
I see... Using "Void" instead of "void" is not a good programming practice and should be "avoided" =P.
Another suggestion that I forgot to mention is to squash your commits into one.
There was a problem hiding this comment.
I believe our current best practice is to not squash commits (i.e. to preserve the history).
There was a problem hiding this comment.
@mike-tutkowski if commits are atomic and not breaking ci, yes, else, no. Please use your own judgement.
|
LGTM. I've also been testing this in my dev environment with no issues so far |
|
Mike Tutkowski on dev@cloudstack.apache.org replies: |
e2c8be2 to
a425e41
Compare
005367b to
61352d6
Compare
ACS CI BVT RunSumarry: The follwing tests have known issues Link to logs Folder (search by build_no): https://www.dropbox.com/sh/yj3wnzbceo9uef2/AAB6u-Iap-xztdm6jHX9SjPja?dl=0 Failed tests:
Skipped tests: Passed test suits: |
ecc5e4d to
af73300
Compare
0270bcc to
b93daca
Compare
|
Here are my updated Marvin tests for this feature (with a "txt" extension because GitHub doesn't allow you to upload files with a "py" extension): TestSnapshots.py.txt |
|
Can you rebase and give me a squashed commit for this? Also, regarding the code. I have seen a lot of people cleaning up code to remove the I will add this to my queue to run a full CI against it again. Also, I am looking for two distinct LGTM for every PR, so I would like another LGTM code review. Can someone from the dev list please give me a review? Thx... |
|
Hi @swill - No problem for me to squash the commits, but are you sure you want to lose the history of the individual commits? Also, from what I've seen over the years, it seems more common to prefix instance member variables with "_" than to not do so, but I'm not sure if we have a coding guideline around that or not. Can you clarify, too, if a LGTM has to come from a committer or can it be any dev on the list? If any dev on the list, we have Syed and I believe Gabriel (although I didn't see a literal LGTM from him, but rather he provided his comments on the code). Thanks! |
|
I have not seen a style guide, but I have not looked. I have just seen a bunch of PRs recently and there seems to be a consistent work to remove the I am not requiring the LGTM code reviews to come from committers. If you are active on on Github and are adding value to the project by reviewing code, I am willing to work with that. Because I am not being strict about who is reviewing the code, I am also enforcing at least 2 people review the code so I get more eyes on ever PR. As for the squash. It may make sense to have some history, but there are a lot of commits in there that are entirely useless outside the greater context of this PR. To me, the final version of the code merged trumps all. If it is squashed then we can more easily evaluate the changes associated with this commit later. If you think there are some points in the history of this feature that make sense to be called out as important, you can squash into 3 or 4 commits, but 43 commits for a single PR is crazy and will add more confusion than clarity. |
|
No problem, @swill, I can just squash them all. I was just thinking that the fact that we are merging can preserve the individual history better (in a different branch that makes its way back to the master branch), but I'm fine with just dropping the history and having a single commit. |
b93daca to
1396cad
Compare
|
@mike-tutkowski @swill I don't think a formal guideline has been set, but we have been pushing toward adopting more idiomatic Java naming conventions. The use of |
|
@mike-tutkowski why can't the Marbin test cases be checked in? While we can't run them, it would be nice to review them to understand exactly how the feature is being tested. We can exclude them by default to avoid running into problems on full runs that don't have SolidFire hardware available. |
|
The CloudStack community can definitely have those tests, if it wants them. Right now, however, we don't have any way to enable other people (besides those who own SolidFire equipment) to successfully run those tests. Perhaps SolidFire will have a virtual node at some point that can be handed over to Apache Infra for this purpose. |
| private boolean _executeInSequence = true; | ||
|
|
||
| public ResignatureCommand(final Map<String, String> details) { | ||
| _details = details; |
There was a problem hiding this comment.
Copy the details to an ImmutableMap map to avoid any side-effects by the caller making subsequence changes to the map. It will also prevent the same side-effects when returned from getDetails.
|
I'm not sure what the standard for "idiomatic" is here. :) I've pretty much usually seen _ (and sometimes m_) used to note a member variable versus a local variable. That is then used in concert with camel case. Also, for static member variables that are public, I usually have seen all upper case with individual words separated by an underscore (but the variable not prefixed with an underscore). We should probably develop a community standard. |
| } | ||
|
|
||
| private boolean canHandle(DataStore dataStore) { | ||
| private boolean canHandle(DataObject dataObject) { |
There was a problem hiding this comment.
- What is
dataObjectisnull? - Would it be possible to add some unit test cases for this method?
There was a problem hiding this comment.
I would say that that is an infrastructure fail on the part of CloudStack (passing in null there). We could defend against it, but then we should probably do so everywhere where canHandle is implemented.
There was a problem hiding this comment.
@mike-tutkowski while it's unlikely, we should defend against if for nothing more than providing a better error than an NPE. Seems like a good place to use Preconditions.checkArgument with a meaningful error message. It also better pinpoints the origin of the failure.
|
@DaanHoogland I think I addressed all your concerns. I plan to rebuild this locally, then push to GitHub in a bit. |
|
@DaanHoogland I had to put the "Void" return types back. It is used for AOP and won't compile with "void" for those two methods. |
bbeaaf1 to
d52ef81
Compare
| } | ||
|
|
||
| return true; | ||
| } |
There was a problem hiding this comment.
The DAO calls in the for loop are concerning from a performance perspective (both for the speed of this call and the load placed on the database). Ideally, it would be calculated in a single join. Would it be possible to craft a query across the details for all hosts in a cluster where the detail key = "supportsResign" and the value = "true"?
There was a problem hiding this comment.
Isn't there a limit of like 16 - 32 hosts in a cluster (therefore only 16 - 32 DB calls in the for loop)?
There was a problem hiding this comment.
See what you think...I just added a method on the HostDetailsDao to return a Map where the key is the ID of the host and the value is true or false (you pass in the "name" field you are interested in).
This way we just do one query and then look up the results in the map each time through the "for" loop.
If we want to do a join of the host, host_details, and cluster tables (which, I believe, would be necessary to reduce the results coming back from the DB), perhaps you know of somewhere in our codebase where we do some similar action? Thanks
There was a problem hiding this comment.
Actually, I think we just need to join the host and the host_details tables (because cluster ID should be in the host table).
We'd want all of the hosts with a particular cluster ID selected from the host table and then we'd want to join on host ID in the host_details table and further refine the returned hosts by those that have a "supportsResign" value in the name field.
Do you happen to know of any code of ours that allows you to SQL filter the returned values based on values that exist in not just one, but two tables? From what I've seen, we seem to be pretty heavily filtering only on data present in one table (even when we join with another table).
If this were just raw SQL, it would be pretty easy, but we've got that Java DB layer that this needs to fit within.
d52ef81 to
45e2bdc
Compare
45e2bdc to
2bd035d
Compare
|
@jburwell @DaanHoogland I have a solution for quickly looking up if a cluster supports resigning that I think we'll all be happy with. Upon a host connecting to the management server is when I check to see if the host supports resigning (and update the host_details table). I added logic to this connection code to not only update the host_details table with info about resigning, but also the cluster_details table about resigning. A host connecting to the management server should not be a frequent occurrence, so I believe it's OK at this point to run through the list of hosts in the cluster of the connecting host and see if all of those hosts support resigning. If they do, then I update the cluster_details table that the cluster in question supports resigning. I also changed the logic to not bother to add a row to either the host_details table or the cluster_details table if the "supportsResign" property would be false (only a true value is stored now). We can then save space by understanding that a missing "supportsResign" property for a host or cluster indicates false (I was proceeding under that assumption anyways). When the time comes to ask the cluster if it supports resigning, it's a simple matter of looking for the "supportsResign" property in the cluster_details table. |
|
@DaanHoogland in my experience, stack traces are a critical piece of information for operationally debugging CloudStack. Unfortunately, our logging lacks the clarity and specify to use the error message alone. I hope our logging improves overtime to omit them from |
38f8cdf to
aa6f12b
Compare
|
Then log the warning with just the message and add a debug statement with the stacktrace. logging stacktraces at a level even more strict then INFO does not compute. |
aa6f12b to
d9e2d62
Compare
d9e2d62 to
9d21556
Compare
CI RESULTSAssociated Uploads
Uploads will be available until Comment created by |
|
this one is ready... |
A XenServer storage repository (SR) and virtual disk image (VDI) each have UUIDs that are immutable.
This poses a problem for SAN snapshots, if you intend on mounting the underlying snapshot SR alongside the source SR (duplicate UUIDs).
VMware has a solution for this called re-signaturing (so, in other words, the snapshot UUIDs can be changed).
This PR only deals with the CloudStack side of things, but it works in concert with a new XenServer storage manager created by CloudOps (this storage manager enables re-signaturing of XenServer SR and VDI UUIDs).
I have written Marvin integration tests to go along with this, but cannot yet check those into the CloudStack repo as they rely on SolidFire hardware.
If anyone would like to see these integration tests, please let me know.
JIRA ticket: https://issues.apache.org/jira/browse/CLOUDSTACK-9281
Here's a video I made that shows this feature in action:
https://www.youtube.com/watch?v=YQ3pBeL-WaA&list=PLqOXKM0Bt13DFnQnwUx8ZtJzoyDV0Uuye&index=13