Skip to content

Commit

Permalink
Enhance importer to handle several issue
Browse files Browse the repository at this point in the history
- Import OpenStack server by UUID
- Import OpenStack server with upper case characters in its name

The following improvements have been done:
- Sanitize the configured `VirtualMachineName` field, e.g. convert upper case to lower case to make it RFC 1123 compliant.
- Convert UUID to real name for OpenStack imports
- Reduce waiting time to recheck if created VM is running from 5min to 2min
- Rename variable `uuid` to `serverUUID` in the OpenStack client code to do not collide with the imported uuid module
- Improve log messages
- Fix typos
- Add comments

Related to: harvester/harvester#6500
Related to: harvester/harvester#6505

Signed-off-by: Volker Theile <vtheile@suse.com>
  • Loading branch information
votdev committed Jan 22, 2025
1 parent d7f05ce commit 6e6b619
Show file tree
Hide file tree
Showing 8 changed files with 228 additions and 68 deletions.
26 changes: 19 additions & 7 deletions pkg/apis/migration.harvesterhci.io/v1beta1/virtualmachines.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,18 @@ type VirtualMachineImport struct {

// VirtualMachineImportSpec is used to create kubevirt VirtualMachines by exporting VM's from migration clusters.
type VirtualMachineImportSpec struct {
SourceCluster corev1.ObjectReference `json:"sourceCluster"`
VirtualMachineName string `json:"virtualMachineName"`
Folder string `json:"folder,omitempty"`
Mapping []NetworkMapping `json:"networkMapping,omitempty"` //If empty new VirtualMachineImport will be mapped to Management Network
StorageClass string `json:"storageClass,omitempty"`
SourceCluster corev1.ObjectReference `json:"sourceCluster"`

// VirtualMachineName is the name of the virtual machine that will be
// imported. It contains the name or ID of the source virtual machine.
// Note that these names may not be DNS1123 compliant and will therefore
// be sanitized later.
// Examples: "vm-1234", "my-VM" or "5649cac7-3871-4bb5-aab6-c72b8c18d0a2"
VirtualMachineName string `json:"virtualMachineName"`

Folder string `json:"folder,omitempty"`
Mapping []NetworkMapping `json:"networkMapping,omitempty"` //If empty new VirtualMachineImport will be mapped to Management Network
StorageClass string `json:"storageClass,omitempty"`
}

// VirtualMachineImportStatus tracks the status of the VirtualMachineImport export from migration and import into the Harvester cluster
Expand All @@ -34,6 +41,11 @@ type VirtualMachineImportStatus struct {
DiskImportStatus []DiskInfo `json:"diskImportStatus,omitempty"`
ImportConditions []common.Condition `json:"importConditions,omitempty"`
NewVirtualMachine string `json:"newVirtualMachine,omitempty"`

// ImportedVirtualMachineName is the sanitized and definite name of the
// target virtual machine that will be created in the Harvester cluster.
// The name is DNS1123 compliant.
ImportedVirtualMachineName string `json:"importedVirtualMachineName,omitempty"`
}

// DiskInfo contains the information about associated Disk in the Import migration.
Expand Down Expand Up @@ -70,14 +82,14 @@ const (
DiskImagesFailed ImportStatus = "diskImageFailed"
VirtualMachineCreated ImportStatus = "virtualMachineCreated"
VirtualMachineRunning ImportStatus = "virtualMachineRunning"
VirtualMachineInvalid ImportStatus = "virtualMachineInvalid"
VirtualMachineImportValid ImportStatus = "virtualMachineImportValid"
VirtualMachineImportInvalid ImportStatus = "virtualMachineImportInvalid"
VirtualMachinePoweringOff condition.Cond = "VMPoweringOff"
VirtualMachinePoweredOff condition.Cond = "VMPoweredOff"
VirtualMachineExported condition.Cond = "VMExported"
VirtualMachineImageSubmitted condition.Cond = "VirtualMachineImageSubmitted"
VirtualMachineImageReady condition.Cond = "VirtualMachineImageReady"
VirtualMachineImageFailed condition.Cond = "VirtualMachineImageFailed"
NotValidDNS1123Label string = "not a valid DNS1123 label"
VirtualMachineExportFailed condition.Cond = "VMExportFailed"
VirtualMachineMigrationFailed ImportStatus = "VMMigrationFailed"
)
20 changes: 11 additions & 9 deletions pkg/controllers/migration/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (h *virtualMachineHandler) reconcileDiskImageStatus(vm *migration.VirtualMa
// If VM has no disks associated ignore the VM
if len(orgStatus.DiskImportStatus) == 0 {
logrus.Errorf("Imported VM %s in namespace %s, has no disks, being marked as invalid and will be ignored", vm.Name, vm.Namespace)
vm.Status.Status = migration.VirtualMachineInvalid
vm.Status.Status = migration.VirtualMachineImportInvalid
return h.importVM.UpdateStatus(vm)

}
Expand Down Expand Up @@ -86,8 +86,8 @@ func (h *virtualMachineHandler) reconcileVirtualMachineStatus(vm *migration.Virt
return vm, err
}
if !ok {
// VM not running, requeue and check after 5mins
h.importVM.EnqueueAfter(vm.Namespace, vm.Name, 5*time.Minute)
// VM not running, requeue and check after 2mins
h.importVM.EnqueueAfter(vm.Namespace, vm.Name, 2*time.Minute)
return vm, nil
}

Expand All @@ -98,13 +98,15 @@ func (h *virtualMachineHandler) reconcileVirtualMachineStatus(vm *migration.Virt
func (h *virtualMachineHandler) reconcilePreFlightChecks(vm *migration.VirtualMachineImport) (*migration.VirtualMachineImport, error) {
err := h.preFlightChecks(vm)
if err != nil {
if err.Error() != migration.NotValidDNS1123Label {
return vm, err
}
logrus.Errorf("vm migration target %s in VM %s in namespace %s is not RFC 1123 compliant", vm.Spec.VirtualMachineName, vm.Name, vm.Namespace)
vm.Status.Status = migration.VirtualMachineInvalid
logrus.WithFields(logrus.Fields{
"name": vm.Name,
"namespace": vm.Namespace,
"spec.virtualMachineName": vm.Spec.VirtualMachineName,
}).Errorf("The preflight checks failed: %v", err)
// Stop the reconciling for good as the checks failed.
vm.Status.Status = migration.VirtualMachineImportInvalid
} else {
vm.Status.Status = migration.SourceReady
vm.Status.Status = migration.VirtualMachineImportValid
}
return h.importVM.UpdateStatus(vm)
}
Expand Down
5 changes: 3 additions & 2 deletions pkg/controllers/migration/openstack.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ func (h *openstackHandler) OnSourceChange(_ string, o *migration.OpenstackSource
"kind": o.Kind,
"name": o.Name,
"namespace": o.Namespace,
}).Info("Reconciling migration source")
}).Info("Reconciling source")

if o.Status.Status != migration.ClusterReady {
// process migration logic
secretObj, err := h.secret.Get(o.Spec.Credentials.Namespace, o.Spec.Credentials.Name, metav1.GetOptions{})
Expand All @@ -52,7 +53,7 @@ func (h *openstackHandler) OnSourceChange(_ string, o *migration.OpenstackSource

client, err := openstack.NewClient(h.ctx, o.Spec.EndpointAddress, o.Spec.Region, secretObj)
if err != nil {
return o, fmt.Errorf("error generating openstack client for openstack migration: %s: %v", o.Name, err)
return o, fmt.Errorf("error generating openstack client for openstack migration '%s': %v", o.Name, err)
}

err = client.Verify()
Expand Down
Loading

0 comments on commit 6e6b619

Please sign in to comment.