-
Notifications
You must be signed in to change notification settings - Fork 1.3k
CLOUDSTACK-9252: Support configurable NFS version for Secondary Storage mounts #1361
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
Conversation
|
Hi @ nvazquez, If you a look at the doc in [1] and [2], you will see that if we do not provide a NFS protocol version to be used, it (the mount program) will first try version 4, then 3, and version 2 as the last one. If the default behavior of mount is to try every possible protocol available, I do not see why we need to add some extra code to enable us to specify one. Wasn’t your problem caused by something else? [1] http://man7.org/linux/man-pages/man8/mount.8.html |
|
Unfortunately NFS version negotiation doesn't work properly with all storage vendors. Some vendors e.g. Tintri require that vers=3 is supplied in mount command likely due to the fact they don't support negotiations on the server side. |
|
@serg38, I did not know that, giving your explanation I rest my arguments ;) @nvazquez, you changed the method “getMountPoint” to receive a NFS protocol version, that method uses the version in another method that is called “mount”, in which you added a conditional to check if the version != null, then you add it to the mount command. I am ok with that code. I only have a doubt, if the version may be required why aren’t you using it in most of the code? It seems that you mostly call the “getMountPoint” method as “mountService.getMountPoint(secondaryStorageUrl, null)”. Actually, the only time I see you using the NFS protocol version is when you use the “prepareSecondaryStorageStore” method. As @serg38 nicely explained that there are vendors that do not support version negotiation, wouldn’t that be the case to always use the version that you already have in hand? |
|
I believe the main reason is to provide the most of backward compatibility. image_store_details doesn't have NFS version in existing installations so after the upgrade to this code it will continue working without any additional changes. However if particular NFS secondary datastore requires explicit version users simply populate table and restart SSVM. |
|
Thanks for your review! I agree with @serg38, it was thought just to extend the functionality by adding an entry on |
|
Ok, I understood that you want to maintain compatibility. Additionally, you have duplicated the code of “getNfsVersion” in two or three places, I believe we should avoid those duplicated code. I would also add a Java doc to the “getNfsVersion”, stating what it does, what parameters it looks for, what happens if it does not find the parameter and where (in the DB) those parameters are stored. |
|
Ok, @rafaelweingartner I'll work on refactoring this. |
|
@rafaelweingartner I pushed some changes according to your comments. Is it better like this? |
|
It is better now. 2 – The java doc you created for “com.cloud.storage.ImageStoreDetailsUtil.getNfsVersion(long)” is pretty nice. I would like to see the same in “com.cloud.storage.ImageStoreDetailsUtil.getNfsVersionByUuid(String)”. Moreover, I think those methods deserve some test case. |
|
Thanks for your comments! I've been working following your indications, however I didn't create any test case. |
|
Hi @nvazquez, At the “spring-engine-storage-image-core-context.xml” line 31, I noticed that you added the bean “imageStoreDetailsUtilImpl” as a dependency of the “templateServiceImpl” bean; that is not necessary, if the bean “templateServiceImpl” has a property of type “imageStoreDetailsUtilImpl” annotated with "@Inject/@Autowired", Spring will automatically sort and create the hierarchy of beans dependencies to instantiate and inject. That “depends-on” configuration can be used for some things that are slightly different; if you are curious about that we can chat in off, just call me on slack or shoot me an email. Still on “spring-engine-storage-image-core-context.xml” at line 40, you declared the bean “imageStoreDetailsUtilImpl”, that is only necessary if you were not using the “@component” annotation (there are others that you could use too, such as @service, @bean and others, each one to mark a different use type of bean); having said that, there is no need to declare the bean in the XML. If you tried to build and run the ACS with your changes, but ended up with the application not going up because some problem with Spring dependency resolution; that might have happened because of ACS application contexts hierarchy, If that happened I can help you find the best place to declare the bean; otherwise, you can just use the annotation that is fine, no need to re-declare the bean in an XML file. I do not think that problem will happen because the bean will be created at one of the top-level application contexts of ACS. Now about the bean itself; I noticed that you created an interface to declare the bean's methods. Normally, when we are creating DAO or service classes that is the right way to do things, create an interface and then the implementation, allowing to use object orientation (O.O.) to change the implementation in the future with configurations in an XML file; (an opinion) this is not the same as creating code for the future, but it is preparing the architecture of a system for the future, I dislike the first one and like the second one. However, with the use of annotations, it is not that easy to change implementation as it is when using XML spring beans declaration; it is not possible to inject a different object that implemented the same interface, since annotations make everything pretty straightforward, so I think it is better to lose the interface and work just with a single class that is the component itself. Additionally, I noticed that in your interface (that I suggest you not to use in this specific case) you extended the interface “Manager” that brings a lot of things that you do not use, I am guessing you did that because you have seen some other classes, and they all do that. Well, guess what, in your case that is not needed. Actually, in most cases that the "Manager" interface is being used that interface is not needed; I find the “Manager” interface hierarchy a real nightmare, but that is a topic for another chat. In all of the places you injected the” imageStoreDetailsUtil” object, I suggest you removing the “_” from the attribute name and making them private. Now the problem with poor application architecture planning appears (it is not your fault, you are actually doing a great job). In some “service/manager/others” that should work as singletons, but are not, your “@Inject” will not work. I recommend you after applying those changes, you should try to build and start up the application (ACS with your PR) to check if everything is getting injected and is working as expected. If you run into any problems, just call me. @nvazquez, that is the way to do it, unit tests using mock DAOs, you are on the right track ;) BTW: I liked very much your code, small methods, with test cases (still to come) and java doc |
|
@rafaelweingartner thanks for your reply! I'm familiar to Spring, I've worked with it, I know how it works but I wouldn't say I know it in depth. If you don't mind I would find your detailed explanation really helpful for this feature and future tasks. About bean injection in I agree with you about not extending I could start ACS but didn't fully test Thanks a lot for your help! |
|
@nvazquez, if you have any doubt in some of the spring modules, just shoot me an email (If I have the knowledge I will not hesitate to help you). Looking at the ACS structure, I believe that one of the best places to put this bean would be the “spring-engine-storage-core-context”, instead of “spring-engine-storage-image-core-context”. I find it better to make the bean you created available to every project/plugin-in that works with storage. I will be waiting to see the result from your test with a VMware environment. |
|
Hi @DaanHoogland can you help us with Jenkins build? A test file Thanks |
|
@nvazquez That is very strange. As far as I can tell there isn't a file with that name neither on the current master nor on your branch. There is however a file with that name and containing those exact methods (the ones causing the errors) to be added in PR #1360. That PR has not yet been merged though... |
|
@nvazquez I think the job doesn't clean the prior classes well. I cleared the workspace. Can you push again? |
|
Thanks @DaanHoogland, I pushed again |
|
This time it failed for timeout |
|
Since it timed out, what about squashing those 3 last commits into one, and crossing the fingers hoping that jenkins succeeds. |
|
Sure, I'll do it |
|
@nvazquez
|
|
One more query: |
|
@nvazquez, luckily the Jenkins build finished with success now. @kishankavala, for now, I believe the simplest solution is the better. When more details are necessary, we change the code to send a map or some other structure, I personally do not like using maps to move data around, I prefer simple and descriptive POJOs. Additionally, the task to move getters and setters to an upper class is not easily achievable. I thought about that a while, and after inspecting the command classes that would have to be changed, I decided to mark that as a future work; of course, if you have an easy, nice and neat solution, you are welcome to share. @nvazquez had around worked around a lot of problems and had written a pretty nice, well documented and tested code. @nvazquez, after all emails and messages exchanged, I can give an LGTM to this PR. Great job man ;) |
|
Thanks a lot @rafaelweingartner for your words and your help! |
|
Hi committers, |
|
@serg38 , @nvazquez, we still need some other LGTM here. You could ask for some help reviewing this PR at Slack or @dev. Even with other LGTM, I think it would be good to have some integration test executed for this PR, just to make sure that those changes did not break something else. I know that you have already worked pretty hard here and have tested in your environment, but still I believe that those tests are needed. |
|
@nvazquez
|
|
Sure @kishankavala, to set NFS version for a store with id
|
|
If requirements to use particular NFS version is known beforehand it can be specified during the image store creation using details argument details[0].key=nfs.version&details[0].value=3 e.g. |
|
Hi @rafaelweingartner @kishankavala I've run |
|
@nvazquez LGTM based on integration tests and code. |
CLOUDSTACK-9252: Support configurable NFS version for Secondary Storage mountsJIRA Ticket: https://issues.apache.org/jira/browse/CLOUDSTACK-9252 ### Description of the problem After starting secondary storage VM, secondary storage tries to be mounted but fails with error: <code>Protocol family not supported</code> It was found out that adding <code>-o vers=X</code> to mount command it would work, where <code>X</code> is the desired NFS version to use. If it is desired to mount a store with a specific NFS version, it has passed in <code>image_store_details</code> table for a store with id <code>Y</code> as a property: | store_id| name| value | |:-------------:|:-------------:|:-------------:| |Y|nfs.version|X (e.g. 3)| Where X stands for NFS version * pr/1361: CLOUDSTACK-9252: Last refactor, passing nfs version to ssvm CLOUDSTACK-9252: Add missing licence header CLOUDSTACK-9252: Little refactor CLOUDSTACK-9252: Mock application context for unit test CLOUDSTACK-9252: Add unit tests CLOUDSTACK-9252: New refactor CLOUDSTACK-9252: Remove static dependencies, refactor CLOUDSTACK-9252: Remove duplicates getNfsVersion, refactor CLOUDSTACK-9252: Support configurable nfs version CLOUDSTACK-9252: Add nfs version to commands Signed-off-by: Rafael Weingärtner <[email protected]>
|
merged based on testes and reviews |
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: |
Fix new error found in findbugs slow build #3455Fix new find bug error that was introduced in PR #1361 Report: http://jenkins.buildacloud.org/job/build-master-slowbuild/3455/findbugsResult/new/ It is the same fix as the one proposed in #1427; the difference is that this PR tried to change only the code that was strictly needed. However, I took the liberty to remove a dead code and few lines of code (annotations) that were not needed * pr/1438: Fix findbugs slow build 3455 Signed-off-by: Rafael Weingärtner <[email protected]>
CLOUDSTACK-9368: Fix for Support configurable NFS version for Secondary Storage mounts## Description JIRA TICKET: https://issues.apache.org/jira/browse/CLOUDSTACK-9368 This pull request address a problem introduced in #1361 in which NFS version couldn't be changed after hosts resources were configured on startup (for hosts using `VmwareResource`), and as host parameters didn't include `nfs.version` key, it was set `null`. ## Proposed solution In this proposed solution `nfsVersion` would be passed in `NfsTO` through `CopyCommand` to `VmwareResource`, who will check if NFS version is still configured or not. If not, it will use the one sent in the command and will set it to its storage processor and storage handler. After those setups, it will proceed executing command. * pr/1518: CLOUDSTACK-9368: Fix for Support configurable NFS version for Secondary Storage mounts Signed-off-by: Will Stevens <[email protected]>
CLOUDSTACK-9438: Fix for CLOUDSTACK-9252 - Make NFS version changeable in UIJIRA TICKET: https://issues.apache.org/jira/browse/CLOUDSTACK-9438 ### Introduction From #1361 it was possible to configure NFS version for secondary storage mount. However, changing NFS version requires inserting an new detail on `image_store_details` table, with `name = 'nfs.version'` and `value = X` where X is desired NFS version, and then restarting management server for changes to take effect. Our improvement aims to make NFS version changeable from UI, instead of previously described workflow. ### Proposed solution Basically, NFS version is defined as an image store ConfigKey, this implied: * Adding a new Config scope: **ImageStore** * Make `ImageStoreDetailsDao` class to extend `ResourceDetailsDaoBase` and `ImageStoreDetailVO` implement `ResourceDetail` * Insert `'display'` column on `image_store_details` table * Extending `ListCfgsCmd` and `UpdateCfgCmd` to support **ImageStore** scope, which implied: ** Injecting `ImageStoreDetailsDao` and `ImageStoreDao` on `ConfigurationManagerImpl` class, on `cloud-server` module. ### Important It is important to mention that `ImageStoreDaoImpl` and `ImageStoreDetailsDaoImpl` classes were moved from `cloud-engine-storage` to `cloud-engine-schema` module in order to Spring find those beans to inject on `ConfigurationManagerImpl` in `cloud-server` module. We had this maven dependencies between modules: * `cloud-server --> cloud-engine-schema` * `cloud-engine-storage --> cloud-secondary-storage --> cloud-server` As `ImageStoreDaoImpl` and `ImageStoreDetailsDao` were defined in `cloud-engine-storage`, and they needed in `cloud-server` module, to be injected on `ConfigurationManagerImpl`, if we added dependency from `cloud-server` to `cloud-engine-storage` we would introduce a dependency cycle. To avoid this cycle, we moved those classes to `cloud-engine-schema` module * pr/1615: CLOUDSTACK-9438: Fix for CLOUDSTACK-9252 - Make NFS version changeable in UI Signed-off-by: Rajani Karuturi <[email protected]>
JIRA Ticket: https://issues.apache.org/jira/browse/CLOUDSTACK-9252
Description of the problem
After starting secondary storage VM, secondary storage tries to be mounted but fails with error:
Protocol family not supportedIt was found out that adding
-o vers=Xto mount command it would work, whereXis the desired NFS version to use.If it is desired to mount a store with a specific NFS version, it has passed in
image_store_detailstable for a store with idYas a property:Where X stands for NFS version