Skip to content
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

Catalog upload feature2 #98

Merged
merged 32 commits into from
Oct 2, 2018
Merged

Catalog upload feature2 #98

merged 32 commits into from
Oct 2, 2018

Conversation

vbauzys
Copy link
Contributor

@vbauzys vbauzys commented Sep 25, 2018

Second part of missing functionality Related issue: (#50)

Enhanced upload functionality for catalog item. Returns special upload task which allows monitor upload if required and later can wait until vCD import task finishes. Upload happens in background. Other improvements:
Added Missing tests
Code improvements
Removed lock to xml first element
Better error handling
Verified and improved that "sanitizedName" func is enough to cover security issue -> See vmware-archive/pyvcloud#268.
Use new logging system
Error handling return within xml of response
Checked and parse errors when vCD fails after ovf file upload.
Multiupload verified.
Report percentage progress.
Check against nil catalog
Files unarchived to temp folder and cleaned
Checked files: from the tarball header with the size we have extracted
Make upload chunking working as function parameter
Specific check to avoid cryptic error then item already exist.

Note: Exist one question how to handle between AdminCatalog and Catalog object if needed. Current implementation allows working from Catalog object perspective.

Copy link

@hodgesrm hodgesrm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good but needs more commentary. I think the biggest requirement is to explain the upload protocol in an accessible way as it's not a simple process and not everyone will have it in their heads when working on this code.

Test cases are great. Thanks taking the care to put them in.

govcd/catalog.go Outdated
@@ -125,7 +128,7 @@ type Envelope struct {
} `xml:"References>File"`
}

// If catalogitem is a valid CatalogItem and the call succeds,
// If catalog item is a valid CatalogItem and the call succeeds,
// then the function returns a CatalogItem. If the item does not
// exist, then it returns an empty CatalogItem. If The call fails

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: 'If The call' should be 'If the call'

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

govcd/catalog.go Outdated
@@ -163,37 +166,47 @@ func (cat *Catalog) FindCatalogItem(catalogitem string) (CatalogItem, error) {

// uploads an ova file to a catalog. This method only uploads bits to vCD spool area.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leading sentence should be capitalized.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

govcd/catalog.go Outdated
@@ -163,37 +166,47 @@ func (cat *Catalog) FindCatalogItem(catalogitem string) (CatalogItem, error) {

// uploads an ova file to a catalog. This method only uploads bits to vCD spool area.
// Returns errors if any occur during upload from vCD or upload process.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a catalog upload fails does the client program have to do any cleanup?

Copy link
Contributor Author

@vbauzys vbauzys Sep 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expanded comment.

govcd/catalog.go Outdated

for _, catalogItemName := range getExistingCatalogItems(cat) {
if catalogItemName == itemName {
return UploadTask{}, fmt.Errorf("catalog item by name: '%s' already exist. Upload with different name", itemName)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Message is not fully grammatical. Suggestion: "Catalog item'%s' already exists. Upload with different name."

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

govcd/catalog.go Outdated
uploadProgress = (float64(bytesUploaded) / float64(totalSize)) * 100
}

go uploadFiles(cat.client, vappTemplate, &ovfFileDesc, tempPath, filesAbsPaths, uploadPieceSize, callBack, tmpDir)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a comment to explain the concurrent processing you are doing here? IT's not easy to read out of the code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

catalog, org := findCatalog(vcd, check, catalogName)
AddToCleanupList(itemName, "catalogItem", vcd.org.Org.Name, "Test_UploadOvf")

//execute

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary comment. (Same applies to verify below.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.

@@ -0,0 +1,33 @@
package govcd

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs a proper Apache 2 header. Please copy from another file. Also any file you touch should have the copyright date 2018 added.

Copy link
Contributor Author

@vbauzys vbauzys Sep 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added and updated year on files I touched everywhere.

*Task
}

func NewUploadTask(task *Task, uploadProgress *float64) *UploadTask {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a comment to document public APIs in this file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

util/tar.go Outdated
func Unpack(tarFile string) ([]string, error) {
const TmpDirPrefix = "govcd"

//extract files to system tmp dir with name govcd+random number. Created folder with files isn't deleted.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the output of this function? Also 'extract' should be capitalized.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

"testing"
)

func TestSanitizedName(t *testing.T) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please a comment describing what this test is checking.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

Copy link
Contributor

@dataclouder dataclouder left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests should conform to the general structure of the other tests.
As for the binaries in the code directory, I'd move them in a separate repository, but I'll let the team decide what's the best place for them.


const (
OvaPath = "/test_vapp_template.ova"
OvaChunkedPath = "/template_with_custom_chunk_size.ova"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see two problems with these two files:

  1. binary artifacts should not be in the code directory. Our repo will end up in someone else's vendor directory, and many would object to having non-text files mixed up with code.
  2. test components should be referred to in the configuration file. These two items should be added to the config structure in api_vcd_test.go and used accordingly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. I would agree with https://medium.com/@matryer/5-simple-tips-and-tricks-for-writing-unit-tests-in-golang-619653f90742 and move all test to different package - in that away we can avoid more clutter in future and separate stuff. And solve issue mentioned by you as binary files would be in different package. Otherwise we create issue that test exist but they fail for others if they won't checkout special folder with binary files.

  2. Yes, I can move constants to api_vcd_test.go

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have already tests that depend on user defined artifacts. This test should be no different. It may pass with the artifacts that we recommend, but we must see how it behaves with user defined items.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move binaries to test-resources. Ova paths are configured if empty, tests are skipped.

@@ -84,3 +96,179 @@ func (vcd *TestVCD) Test_DeleteCatalog(check *C) {
check.Assert(catalog, Equals, Catalog{})

}

func (vcd *TestVCD) Test_UploadOvf(check *C) {
checkUploadOvf(vcd, check, getCurrentPath()+OvaPath, TestCreateCatalog, "item1")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every item created by the tests should have a name that refers to the function that creates it. See the constants in api_vcd_test.go for some examples.
Thus, "item1" should become "TestUploadOvf", and TestCreateCatalog should not be used. If you need to create a new catalog for this function, it should have a function related name.
Is there a reason not to use the catalog indicated in the test configuration file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, I missed this - will correct it.


func (vcd *TestVCD) Test_UploadOvf_progress_works(check *C) {
catalogName := TestCreateCatalog + "3"
itemName := "item3"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the above comments for the name of the items.
Moreover, the upload tests are creating four catalogs. Why?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's test independence question. Test can't depend on other tests result (e.g. what id did with catalog in previous test).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If more catalogs are needed, we should name them according to their purposes.
In general, we should make tests that work with the material provided by users (i.e the catalog defined in the configuration file).
We should create new catalogs only when testing something relating to catalog creation or if we run an operation that requires two catalogs. Otherwise, we should always use the catalog given by users.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

setupCatalog(vcd, check, catalogName)

catalog, org := findCatalog(vcd, check, catalogName)
AddToCleanupList(itemName, "catalogItem", vcd.org.Org.Name, "Test_UploadOvf")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cleanup procedure in api_vcd_test.go does not recognize "catalogItem" yet. It should be updated to handle this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked and think we can avoid it as catalog cleanup allows to delete catalog with items. So removing AddToCleanupList should be sufficient.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. All the tests are removing their artifacts. The cleanup list is the safety net to remove things when the test fails and aborts prematurely.
We should keep it and update the cleanup function accordingly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CatalogItem cleanup added.

org := getOrg(vcd, check)

// creating catalog
adminCatalog, err := org.CreateCatalog(testCreateCatalog, TestCreateCatalogDesc, true)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this test is using an AdminCatalog, it should check whether skipAdminTests is set, and skip the test if it is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will add.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this isn't needed cause tests rung fine with org user or admin.

return org
}

func skipThenOvaPathMissing(vcd *TestVCD, check *C) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be called skipWhenOvaPathMissing

//setupCatalog(vcd, check, testCreateCatalog)

catalog, org := findCatalog(vcd, check, vcd.config.VCD.Catalog.Name)
AddToCleanupList(itemName, "catalogItem", vcd.org.Org.Name+"|"+vcd.config.VCD.Catalog.Name, "Test_UploadOvf")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The call to AddToCleanupList should only happen after the successful creation of an item.

govcd/catalog.go Outdated
@@ -202,58 +223,94 @@ func (cat *Catalog) UploadOvf(ovaFileName, itemName, description string, chunkSi
for _, filePath := range filesAbsPaths {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are assuming here that the extracted file contains a .ovf.
If this is not true, the procedure hangs. This check needs to happen before the item is created.

}
}
}
vcd.infoCleanup(removedMsg, entity.EntityType, entity.Name, entity.CreatedBy)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something is missing in this procedure. When I use a non existing OVA in the test, it still prints Removed catalogItem '<ITEM_NAME>' created by Test_UploadOvf.

govcd/catalog.go Outdated
}

filesAbsPaths, err := util.Unpack(ovaFileName)
filesAbsPaths, tmpDir, err := util.Unpack(ovaFileName)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The unpack should happen before we create the item. If the unpack fails, the item will stay unused and waiting for an upload that won't come.

Copy link
Collaborator

@lvirbalas lvirbalas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please merge after implementing Giuseppe's feedback.

// Upload files for vCD created upload links. Different approach then vmdk file are
// chunked (e.g. test.vmdk.000000000, test.vmdk.000000001 or test.vmdk). vmdk files are chunked if
// in description file attribute ChunkSize is not zero.
func uploadFiles(client *Client, vappTemplate *types.VAppTemplate, ovfFileDesc *Envelope, tempPath string, filesAbsPaths []string, uploadPieceSize int64, callBack func(bytesUpload, totalSize int64)) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function has too many positional arguments.
Please add documentation about the meaning of every argument. Consider doing the same for every function that has more than three args.

vbauzys added 15 commits October 2, 2018 15:06
Signed-off-by: Vaidotas Bauzys <[email protected]>
…t with callback when we add it.

Signed-off-by: Vaidotas Bauzys <[email protected]>
…ou can check progress and wait for task completion.

Signed-off-by: Vaidotas Bauzys <[email protected]>
…00 without explanation.

Signed-off-by: Vaidotas Bauzys <[email protected]>
…errors, like: storage quota exceeded

Signed-off-by: Vaidotas Bauzys <[email protected]>
vbauzys added 17 commits October 2, 2018 15:06
Signed-off-by: Vaidotas Bauzys <[email protected]>
Signed-off-by: Vaidotas Bauzys <[email protected]>
Signed-off-by: Vaidotas Bauzys <[email protected]>
Signed-off-by: Vaidotas Bauzys <[email protected]>
Signed-off-by: Vaidotas Bauzys <[email protected]>
… remove api function and test. Moved binaries to test-resources folder.

Signed-off-by: Vaidotas Bauzys <[email protected]>
Signed-off-by: Vaidotas Bauzys <[email protected]>
… catalog item created on various fails anymore.

Signed-off-by: Vaidotas Bauzys <[email protected]>
Signed-off-by: Vaidotas Bauzys <[email protected]>
Signed-off-by: Vaidotas Bauzys <[email protected]>
Signed-off-by: Vaidotas Bauzys <[email protected]>
Signed-off-by: Vaidotas Bauzys <[email protected]>
@vbauzys vbauzys merged commit 7ff4554 into vmware:master Oct 2, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants