From 28d0b49ed58772b38c34b15a126d544fdc2b330f Mon Sep 17 00:00:00 2001 From: Prajyot-Parab Date: Fri, 25 Mar 2022 15:41:04 +0530 Subject: [PATCH] Add image import job layer to import process Signed-off-by: Prajyot-Parab --- cmd/image/import/import.go | 40 +++++++++++++++++++++++++--- pkg/client/image/image.go | 54 ++++++++++++++++++++------------------ pkg/client/job/job.go | 50 +++++++++++++++++++++++++++++++++++ pkg/client/pvmclient.go | 3 +++ 4 files changed, 118 insertions(+), 29 deletions(-) create mode 100644 pkg/client/job/job.go diff --git a/cmd/image/import/import.go b/cmd/image/import/import.go index 0209ffb9..0ee045b2 100644 --- a/cmd/image/import/import.go +++ b/cmd/image/import/import.go @@ -24,6 +24,7 @@ import ( "github.com/IBM-Cloud/bluemix-go/api/resource/resourcev2/controllerv2" "github.com/IBM-Cloud/bluemix-go/crn" "github.com/IBM-Cloud/bluemix-go/models" + pmodels "github.com/IBM-Cloud/power-go-client/power/models" "github.com/spf13/cobra" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/klog/v2" @@ -93,7 +94,7 @@ pvsadm image import -n upstream-core-lon04 -b --object rhel-83-1003 case2 := pkg.ImageCMDOptions.AccessKey != "" && pkg.ImageCMDOptions.SecretKey == "" if case1 || case2 { - return fmt.Errorf("Required both --accesskey and --secretkey values.") + return fmt.Errorf("required both --accesskey and --secretkey values") } return nil }, @@ -171,19 +172,50 @@ pvsadm image import -n upstream-core-lon04 -b --object rhel-83-1003 return err } - image, err := pvmclient.ImgClient.ImportImage(pvmclient.InstanceID, opt.ImageName, opt.ImageFilename, opt.Region, + jobRef, err := pvmclient.ImgClient.ImportImage(opt.ImageName, opt.ImageFilename, opt.Region, opt.AccessKey, opt.SecretKey, opt.BucketName, strings.ToLower(opt.StorageType)) if err != nil { return err } + start := time.Now() + pollErr := wait.PollImmediate(2*time.Minute, opt.WatchTimeout, func() (bool, error) { + job, err := pvmclient.JobClient.Get(*jobRef.ID) + if err != nil { + return false, err + } + if *job.Status.State == "completed" { + return true, nil + } + if *job.Status.State == "failed" { + return false, fmt.Errorf("image import job failed to complete, err: %v", job.Status.Message) + } + klog.Infof("Image Import Job in-progress, current state: %s", *job.Status.State) + return false, nil + }) + if pollErr == wait.ErrWaitTimeout { + pollErr = fmt.Errorf("timed out while waiting for image import job to complete") + } + + if pollErr != nil { + return fmt.Errorf("image import job failed to complete, err: %v", pollErr) + } + + var image *pmodels.ImageReference = &pmodels.ImageReference{} + for image.ImageID == nil { + image, err = pvmclient.ImgClient.GetImageByName(opt.ImageName) + if err != nil { + return err + } + klog.Infof("Retriving image details") + } + if !opt.Watch { klog.Infof("Importing Image %s is currently in %s state, Please check the Progress in the IBM Cloud UI\n", *image.Name, image.State) return nil } - start := time.Now() - pollErr := wait.PollImmediate(2*time.Minute, opt.WatchTimeout, func() (bool, error) { + pollErr = wait.PollImmediate(2*time.Minute, opt.WatchTimeout, func() (bool, error) { img, err := pvmclient.ImgClient.Get(*image.ImageID) if err != nil { return false, err diff --git a/pkg/client/image/image.go b/pkg/client/image/image.go index 000db51a..7c8f23c8 100644 --- a/pkg/client/image/image.go +++ b/pkg/client/image/image.go @@ -16,22 +16,20 @@ package image import ( "context" - "errors" "fmt" "regexp" "time" "github.com/IBM-Cloud/power-go-client/clients/instance" "github.com/IBM-Cloud/power-go-client/ibmpisession" - "github.com/IBM-Cloud/power-go-client/power/client/p_cloud_images" "github.com/IBM-Cloud/power-go-client/power/models" "github.com/ppc64le-cloud/pvsadm/pkg" - "k8s.io/klog/v2" ) type Client struct { session *ibmpisession.IBMPISession client *instance.IBMPIImageClient + jobclient *instance.IBMPIJobClient instanceID string } @@ -41,6 +39,7 @@ func NewClient(sess *ibmpisession.IBMPISession, powerinstanceid string) *Client instanceID: powerinstanceid, } c.client = instance.NewIBMPIImageClient(context.Background(), sess, powerinstanceid) + c.jobclient = instance.NewIBMPIJobClient(context.Background(), sess, powerinstanceid) return c } @@ -56,37 +55,29 @@ func (c *Client) Delete(id string) error { return c.client.Delete(id) } +func (c *Client) CreateCosImage(body models.CreateCosImageImportJob) (*models.JobReference, error) { + return c.client.CreateCosImage(&body) +} + //func ImportImage imports image from S3 Instance -func (c *Client) ImportImage(instanceID, imageName, s3Filename, region, accessKey, secretKey, bucketName, storageType string) (*models.Image, error) { - var source = "url" - var body = models.CreateImage{ - ImageName: imageName, - ImageFilename: s3Filename, - Region: region, +func (c *Client) ImportImage(imageName, s3Filename, region, accessKey, secretKey, bucketName, storageType string) (*models.JobReference, error) { + + var body = models.CreateCosImageImportJob{ + ImageName: &imageName, + ImageFilename: &s3Filename, + Region: ®ion, AccessKey: accessKey, SecretKey: secretKey, - BucketName: bucketName, - DiskType: storageType, - Source: &source, + BucketName: &bucketName, + StorageType: storageType, } - params := p_cloud_images.NewPcloudCloudinstancesImagesPostParamsWithTimeout(pkg.TIMEOUT).WithCloudInstanceID(instanceID).WithBody(&body) - resp1, resp2, err := c.session.Power.PCloudImages.PcloudCloudinstancesImagesPost(params, c.session.AuthInfo(c.instanceID)) - + jobRef, err := c.CreateCosImage(body) if err != nil { return nil, err } - if resp1 != nil { - klog.Errorf("Failed to intiate the import job") - return nil, errors.New("failed to initiate the import job") - } - - if resp2.Payload.State == "queued" { - klog.Infof("Post is successful %s", *resp2.Payload.ImageID) - } - - return resp2.Payload, nil + return jobRef, nil } func (c *Client) GetAllPurgeable(before, since time.Duration, expr string) ([]*models.ImageReference, error) { @@ -109,3 +100,16 @@ func (c *Client) GetAllPurgeable(before, since time.Duration, expr string) ([]*m } return candidates, nil } + +func (c *Client) GetImageByName(imageName string) (*models.ImageReference, error) { + images, err := c.GetAll() + if err != nil { + return nil, err + } + for _, img := range images.Images { + if *img.Name == imageName { + return img, nil + } + } + return nil, nil +} diff --git a/pkg/client/job/job.go b/pkg/client/job/job.go new file mode 100644 index 00000000..1736e2f2 --- /dev/null +++ b/pkg/client/job/job.go @@ -0,0 +1,50 @@ +// Copyright 2021 IBM Corp +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package job + +import ( + "context" + + "github.com/IBM-Cloud/power-go-client/clients/instance" + "github.com/IBM-Cloud/power-go-client/ibmpisession" + "github.com/IBM-Cloud/power-go-client/power/models" +) + +type Client struct { + session *ibmpisession.IBMPISession + client *instance.IBMPIJobClient + instanceID string +} + +func NewClient(sess *ibmpisession.IBMPISession, powerinstanceid string) *Client { + c := &Client{ + session: sess, + instanceID: powerinstanceid, + } + c.client = instance.NewIBMPIJobClient(context.Background(), sess, powerinstanceid) + return c +} + +func (c *Client) Get(id string) (*models.Job, error) { + return c.client.Get(id) +} + +func (c *Client) GetAll() (*models.Jobs, error) { + return c.client.GetAll() +} + +func (c *Client) Delete(id string) error { + return c.client.Delete(id) +} diff --git a/pkg/client/pvmclient.go b/pkg/client/pvmclient.go index 55b813b1..76c1cbd9 100644 --- a/pkg/client/pvmclient.go +++ b/pkg/client/pvmclient.go @@ -29,6 +29,7 @@ import ( "github.com/ppc64le-cloud/pvsadm/pkg/client/events" "github.com/ppc64le-cloud/pvsadm/pkg/client/image" "github.com/ppc64le-cloud/pvsadm/pkg/client/instance" + "github.com/ppc64le-cloud/pvsadm/pkg/client/job" "github.com/ppc64le-cloud/pvsadm/pkg/client/key" "github.com/ppc64le-cloud/pvsadm/pkg/client/network" "github.com/ppc64le-cloud/pvsadm/pkg/client/volume" @@ -43,6 +44,7 @@ type PVMClient struct { PISession *ibmpisession.IBMPISession InstanceClient *instance.Client ImgClient *image.Client + JobClient *job.Client VolumeClient *volume.Client NetworkClient *network.Client EventsClient *events.Client @@ -97,6 +99,7 @@ func NewPVMClient(c *Client, instanceID, instanceName, ep string) (*PVMClient, e } pvmclient.ImgClient = image.NewClient(pvmclient.PISession, instanceID) + pvmclient.JobClient = job.NewClient(pvmclient.PISession, instanceID) pvmclient.VolumeClient = volume.NewClient(pvmclient.PISession, instanceID) pvmclient.InstanceClient = instance.NewClient(pvmclient.PISession, instanceID) pvmclient.NetworkClient = network.NewClient(pvmclient.PISession, instanceID)