-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(migrate): add support for CR status reporting (#65)
Signed-off-by: shubham <[email protected]>
- Loading branch information
1 parent
f92acb0
commit fd566a8
Showing
10 changed files
with
684 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
# Copyright © 2020 The OpenEBS Authors | ||
# | ||
# 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. | ||
|
||
--- | ||
apiVersion: apiextensions.k8s.io/v1 | ||
kind: CustomResourceDefinition | ||
metadata: | ||
annotations: | ||
controller-gen.kubebuilder.io/version: v0.4.0 | ||
creationTimestamp: null | ||
name: migrationtasks.openebs.io | ||
spec: | ||
group: openebs.io | ||
names: | ||
kind: MigrationTask | ||
listKind: MigrationTaskList | ||
plural: migrationtasks | ||
shortNames: | ||
- mtask | ||
singular: migrationtask | ||
scope: Namespaced | ||
versions: | ||
- name: v1alpha1 | ||
schema: | ||
openAPIV3Schema: | ||
description: MigrationTask represents an migration task | ||
properties: | ||
apiVersion: | ||
description: 'APIVersion defines the versioned schema of this representation | ||
of an object. Servers should convert recognized schemas to the latest | ||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' | ||
type: string | ||
kind: | ||
description: 'Kind is a string value representing the REST resource this | ||
object represents. Servers may infer this from the endpoint the client | ||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' | ||
type: string | ||
metadata: | ||
type: object | ||
spec: | ||
description: Spec i.e. specifications of the MigrationTask | ||
properties: | ||
cstorPool: | ||
description: MigrateCStorPool contains the details of the cstor pool | ||
to be migrated | ||
properties: | ||
rename: | ||
description: If a CSPC with the same name as SPC already exists | ||
then we can rename SPC during migration using Rename | ||
type: string | ||
spcName: | ||
description: SPCName contains the name of the storage pool claim | ||
to be migrated | ||
type: string | ||
type: object | ||
cstorVolume: | ||
description: MigrateCStorVolume contains the details of the cstor | ||
volume to be migrated | ||
properties: | ||
pvName: | ||
description: PVName contains the name of the pv associated with | ||
the cstor volume to be migrated | ||
type: string | ||
type: object | ||
type: object | ||
status: | ||
description: Status of MigrationTask | ||
properties: | ||
completedTime: | ||
description: CompletedTime of Migrate | ||
format: date-time | ||
nullable: true | ||
type: string | ||
migrationDetailedStatuses: | ||
description: MigrationDetailedStatuses contains the list of statuses | ||
of each step | ||
items: | ||
description: MigrationDetailedStatuses represents the latest available | ||
observations of a MigrationTask current state. | ||
properties: | ||
lastUpdatedAt: | ||
description: LastUpdatedTime of a MigrateStep | ||
format: date-time | ||
nullable: true | ||
type: string | ||
message: | ||
description: A human-readable message indicating details about | ||
why the migrationStep is in this state | ||
type: string | ||
phase: | ||
description: Phase indicates if the MigrateStep is waiting, | ||
errored or completed. | ||
type: string | ||
reason: | ||
description: Reason is a brief CamelCase string that describes | ||
any failure and is meant for machine parsing and tidy display | ||
in the CLI | ||
type: string | ||
startTime: | ||
description: StartTime of a MigrateStep | ||
format: date-time | ||
nullable: true | ||
type: string | ||
step: | ||
type: string | ||
type: object | ||
type: array | ||
phase: | ||
description: Phase indicates if a migrationTask is started, success | ||
or errored | ||
type: string | ||
retries: | ||
description: Retries is the number of times the job attempted to migration | ||
the resource | ||
type: integer | ||
startTime: | ||
description: StartTime of Migrate | ||
format: date-time | ||
nullable: true | ||
type: string | ||
type: object | ||
required: | ||
- spec | ||
type: object | ||
served: true | ||
storage: true | ||
status: | ||
acceptedNames: | ||
kind: "" | ||
plural: "" | ||
conditions: [] | ||
storedVersions: [] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
/* | ||
Copyright 2020 The OpenEBS Authors. | ||
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 executor | ||
|
||
import ( | ||
"os" | ||
"strings" | ||
|
||
"k8s.io/client-go/rest" | ||
|
||
v1Alpha1API "github.com/openebs/api/v2/pkg/apis/openebs.io/v1alpha1" | ||
openebsclientset "github.com/openebs/api/v2/pkg/client/clientset/versioned" | ||
"github.com/openebs/maya/pkg/util" | ||
cmdUtil "github.com/openebs/upgrade/cmd/util" | ||
migrate "github.com/openebs/upgrade/pkg/migrate/cstor" | ||
errors "github.com/pkg/errors" | ||
"github.com/spf13/cobra" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/client-go/kubernetes" | ||
) | ||
|
||
var ( | ||
resourceMigrateCmdHelpText = ` | ||
This command migrates the resource mentioned in the MigrationTask CR. | ||
The name of the MigrationTask CR is extracted from the ENV UPGRADE_TASK | ||
Usage: migrate resource | ||
` | ||
) | ||
|
||
// ResourceOptions stores information required for migrationTask migrate | ||
type ResourceOptions struct { | ||
name string | ||
} | ||
|
||
// NewMigrateResourceJob migrate a resource from migrationTask | ||
func NewMigrateResourceJob() *cobra.Command { | ||
cmd := &cobra.Command{ | ||
Use: "resource", | ||
Short: "Migrate a resource using the details specified in the MigrationTask CR.", | ||
Long: resourceMigrateCmdHelpText, | ||
Example: `migrate resource`, | ||
Run: func(cmd *cobra.Command, args []string) { | ||
client, err := initClient() | ||
util.CheckErr(err, util.Fatal) | ||
name := args[0] | ||
openebsNamespace := cmdUtil.GetOpenEBSNamespace() | ||
migrationTaskObj, err := client.OpenebsV1alpha1(). | ||
MigrationTasks(openebsNamespace). | ||
Get(name, metav1.GetOptions{}) | ||
util.CheckErr(err, util.Fatal) | ||
util.CheckErr(options.InitializeFromMigrationTaskResource(migrationTaskObj), util.Fatal) | ||
util.CheckErr(options.RunPreFlightChecks(), util.Fatal) | ||
err = options.RunResourceMigrate() | ||
if err != nil { | ||
migrationTaskObj, uerr := client.OpenebsV1alpha1().MigrationTasks(openebsNamespace). | ||
Get(name, metav1.GetOptions{}) | ||
if uerr != nil { | ||
util.Fatal(uerr.Error()) | ||
} | ||
backoffLimit, uerr := getBackoffLimit(openebsNamespace) | ||
if uerr != nil { | ||
util.Fatal(uerr.Error()) | ||
} | ||
migrationTaskObj.Status.Retries = migrationTaskObj.Status.Retries + 1 | ||
if migrationTaskObj.Status.Retries == backoffLimit { | ||
migrationTaskObj.Status.Phase = v1Alpha1API.MigrateError | ||
migrationTaskObj.Status.CompletedTime = metav1.Now() | ||
} | ||
_, uerr = client.OpenebsV1alpha1().MigrationTasks(openebsNamespace). | ||
Update(migrationTaskObj) | ||
if uerr != nil { | ||
util.Fatal(uerr.Error()) | ||
} | ||
util.Fatal(err.Error()) | ||
} else { | ||
migrationTaskObj, uerr := client.OpenebsV1alpha1().MigrationTasks(openebsNamespace). | ||
Get(name, metav1.GetOptions{}) | ||
if uerr != nil { | ||
util.Fatal(uerr.Error()) | ||
} | ||
migrationTaskObj.Status.Phase = v1Alpha1API.MigrateSuccess | ||
migrationTaskObj.Status.CompletedTime = metav1.Now() | ||
_, uerr = client.OpenebsV1alpha1().MigrationTasks(openebsNamespace). | ||
Update(migrationTaskObj) | ||
if uerr != nil { | ||
util.Fatal(uerr.Error()) | ||
} | ||
} | ||
}, | ||
} | ||
return cmd | ||
} | ||
|
||
// InitializeFromMigrationTaskResource will populate the MigrateOptions from given MigrationTask | ||
func (m *MigrateOptions) InitializeFromMigrationTaskResource( | ||
migrationTaskObj *v1Alpha1API.MigrationTask) error { | ||
|
||
if len(strings.TrimSpace(m.openebsNamespace)) == 0 { | ||
return errors.Errorf("Cannot execute migrate job: namespace is missing") | ||
} | ||
|
||
switch { | ||
case migrationTaskObj.Spec.MigrateResource.MigrateCStorPool != nil: | ||
m.resourceKind = "storagePoolClaim" | ||
m.spcName = migrationTaskObj.Spec.MigrateCStorPool.SPCName | ||
m.cspcName = migrationTaskObj.Spec.MigrateCStorPool.Rename | ||
|
||
case migrationTaskObj.Spec.MigrateResource.MigrateCStorVolume != nil: | ||
m.resourceKind = "cstorVolume" | ||
m.pvName = migrationTaskObj.Spec.MigrateCStorVolume.PVName | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// RunResourceMigrate migrates the given migrationTask | ||
func (m *MigrateOptions) RunResourceMigrate() error { | ||
migrate.IsMigrationTaskJob = true | ||
var err error | ||
switch m.resourceKind { | ||
case "storagePoolClaim": | ||
err = m.RunCStorSPCMigrate() | ||
case "cstorVolume": | ||
err = m.RunCStorVolumeMigrate() | ||
} | ||
return err | ||
} | ||
|
||
func initClient() (openebsclientset.Interface, error) { | ||
cfg, err := rest.InClusterConfig() | ||
if err != nil { | ||
return nil, errors.Wrap(err, "error building kubeconfig") | ||
} | ||
client, err := openebsclientset.NewForConfig(cfg) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "error building openebs clientset") | ||
} | ||
return client, nil | ||
} | ||
|
||
func getBackoffLimit(openebsNamespace string) (int, error) { | ||
cfg, err := rest.InClusterConfig() | ||
if err != nil { | ||
return 0, errors.Wrap(err, "error building kubeconfig") | ||
} | ||
client, err := kubernetes.NewForConfig(cfg) | ||
if err != nil { | ||
return 0, errors.Wrap(err, "error building openebs clientset") | ||
} | ||
podName := os.Getenv("POD_NAME") | ||
podObj, err := client.CoreV1().Pods(openebsNamespace). | ||
Get(podName, metav1.GetOptions{}) | ||
if err != nil { | ||
return 0, errors.Wrapf(err, "failed to get backoff limit") | ||
} | ||
jobObj, err := client.BatchV1().Jobs(openebsNamespace). | ||
Get(podObj.OwnerReferences[0].Name, metav1.GetOptions{}) | ||
if err != nil { | ||
return 0, errors.Wrapf(err, "failed to get backoff limit") | ||
} | ||
// if backoffLimit not present it returns the default as 6 | ||
if jobObj.Spec.BackoffLimit == nil { | ||
return 6, nil | ||
} | ||
backoffLimit := int(*jobObj.Spec.BackoffLimit) | ||
return backoffLimit, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.