forked from harvester/harvester
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: futuretea <Hang.Yu@suse.com>
- Loading branch information
1 parent
03ecd27
commit abc91f0
Showing
9 changed files
with
663 additions
and
373 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,83 @@ | ||
package builder | ||
|
||
import ( | ||
corev1 "k8s.io/api/core/v1" | ||
kubevirtv1 "kubevirt.io/client-go/api/v1" | ||
) | ||
|
||
const ( | ||
CloudInitTypeNoCloud = "noCloud" | ||
CloudInitTypeConfigDrive = "configDrive" | ||
CloudInitDiskName = "cloudinitdisk" | ||
) | ||
|
||
type CloudInitSource struct { | ||
CloudInitType string | ||
UserDataSecretName string | ||
UserDataBase64 string | ||
UserData string | ||
NetworkDataSecretName string | ||
NetworkDataBase64 string | ||
NetworkData string | ||
} | ||
|
||
func (v *VMBuilder) CloudInit(diskName string, cloudInitSource CloudInitSource) *VMBuilder { | ||
var volume kubevirtv1.Volume | ||
switch cloudInitSource.CloudInitType { | ||
case CloudInitTypeNoCloud: | ||
volume = kubevirtv1.Volume{ | ||
Name: diskName, | ||
VolumeSource: kubevirtv1.VolumeSource{ | ||
CloudInitNoCloud: &kubevirtv1.CloudInitNoCloudSource{ | ||
UserData: cloudInitSource.UserData, | ||
UserDataBase64: cloudInitSource.UserDataBase64, | ||
NetworkData: cloudInitSource.NetworkData, | ||
NetworkDataBase64: cloudInitSource.NetworkDataBase64, | ||
}, | ||
}, | ||
} | ||
if cloudInitSource.UserDataSecretName != "" { | ||
volume.VolumeSource.CloudInitNoCloud.UserDataSecretRef = &corev1.LocalObjectReference{ | ||
Name: cloudInitSource.UserDataSecretName, | ||
} | ||
} | ||
if cloudInitSource.NetworkDataSecretName != "" { | ||
volume.VolumeSource.CloudInitNoCloud.UserDataSecretRef = &corev1.LocalObjectReference{ | ||
Name: cloudInitSource.NetworkDataSecretName, | ||
} | ||
} | ||
case CloudInitTypeConfigDrive: | ||
volume = kubevirtv1.Volume{ | ||
Name: diskName, | ||
VolumeSource: kubevirtv1.VolumeSource{ | ||
CloudInitConfigDrive: &kubevirtv1.CloudInitConfigDriveSource{ | ||
UserData: cloudInitSource.UserData, | ||
UserDataBase64: cloudInitSource.UserDataBase64, | ||
NetworkData: cloudInitSource.NetworkData, | ||
NetworkDataBase64: cloudInitSource.NetworkDataBase64, | ||
}, | ||
}, | ||
} | ||
if cloudInitSource.UserDataSecretName != "" { | ||
volume.VolumeSource.CloudInitConfigDrive.UserDataSecretRef = &corev1.LocalObjectReference{ | ||
Name: cloudInitSource.UserDataSecretName, | ||
} | ||
} | ||
if cloudInitSource.NetworkDataSecretName != "" { | ||
volume.VolumeSource.CloudInitConfigDrive.UserDataSecretRef = &corev1.LocalObjectReference{ | ||
Name: cloudInitSource.NetworkDataSecretName, | ||
} | ||
} | ||
} | ||
v.Volume(diskName, volume) | ||
return v | ||
} | ||
|
||
func (v *VMBuilder) CloudInitDisk(diskName, diskBus string, isCDRom bool, bootOrder int, cloudInitSource CloudInitSource) *VMBuilder { | ||
return v.Disk(diskName, diskBus, isCDRom, bootOrder).CloudInit(diskName, cloudInitSource) | ||
} | ||
|
||
func (v *VMBuilder) SSHKey(sshKeyName string) *VMBuilder { | ||
v.SSHNames = append(v.SSHNames, sshKeyName) | ||
return v | ||
} |
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,208 @@ | ||
package builder | ||
|
||
import ( | ||
"fmt" | ||
|
||
corev1 "k8s.io/api/core/v1" | ||
"k8s.io/apimachinery/pkg/api/resource" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/util/rand" | ||
kubevirtv1 "kubevirt.io/client-go/api/v1" | ||
cdiv1alpha1 "kubevirt.io/containerized-data-importer/pkg/apis/core/v1alpha1" | ||
) | ||
|
||
const ( | ||
StorageClassNamePrefix = "longhorn" | ||
|
||
DiskTypeDisk = "disk" | ||
DiskTypeCDRom = "cd-rom" | ||
|
||
DiskBusVirtio = "virtio" | ||
DiskBusScsi = "scsi" | ||
DiskBusSata = "sata" | ||
|
||
PersistentVolumeModeBlock = "Block" | ||
PersistentVolumeModeFilesystem = "Filesystem" | ||
|
||
PersistentVolumeAccessModeReadWriteOnce = "ReadWriteOnce" | ||
PersistentVolumeAccessModeReadOnlyMany = "ReadOnlyMany" | ||
PersistentVolumeAccessModeReadWriteMany = "ReadWriteMany" | ||
|
||
DefaultDiskSize = "10Gi" | ||
DefaultImagePullPolicy = "IfNotPresent" | ||
) | ||
|
||
type DataVolumeOption struct { | ||
ImageID string | ||
DownloadURL string | ||
VolumeMode corev1.PersistentVolumeMode | ||
AccessMode corev1.PersistentVolumeAccessMode | ||
StorageClassName *string | ||
} | ||
|
||
func UintPtr(in int) *uint { | ||
var out *uint | ||
u := uint(in) | ||
if in > 0 { | ||
out = &u | ||
} | ||
return out | ||
} | ||
|
||
func BuildImageStorageClassName(namespace, name string) string { | ||
if namespace != "" { | ||
return StorageClassNamePrefix + "-" + namespace + "-" + name | ||
} | ||
return StorageClassNamePrefix + "-" + name | ||
} | ||
|
||
func (v *VMBuilder) Disk(diskName, diskBus string, isCDRom bool, bootOrder int) *VMBuilder { | ||
var ( | ||
exist bool | ||
index int | ||
disks = v.VirtualMachine.Spec.Template.Spec.Domain.Devices.Disks | ||
) | ||
for i, disk := range disks { | ||
if disk.Name == diskName { | ||
exist = true | ||
index = i | ||
break | ||
} | ||
} | ||
diskDevice := kubevirtv1.DiskDevice{ | ||
Disk: &kubevirtv1.DiskTarget{ | ||
Bus: diskBus, | ||
}, | ||
} | ||
if isCDRom { | ||
diskDevice = kubevirtv1.DiskDevice{ | ||
CDRom: &kubevirtv1.CDRomTarget{ | ||
Bus: diskBus, | ||
}, | ||
} | ||
} | ||
disk := kubevirtv1.Disk{ | ||
Name: diskName, | ||
BootOrder: UintPtr(bootOrder), | ||
DiskDevice: diskDevice, | ||
} | ||
if exist { | ||
disks[index] = disk | ||
} else { | ||
disks = append(disks, disk) | ||
} | ||
v.VirtualMachine.Spec.Template.Spec.Domain.Devices.Disks = disks | ||
return v | ||
} | ||
|
||
func (v *VMBuilder) Volume(diskName string, volume kubevirtv1.Volume) *VMBuilder { | ||
var ( | ||
exist bool | ||
index int | ||
volumes = v.VirtualMachine.Spec.Template.Spec.Volumes | ||
) | ||
for i, e := range volumes { | ||
if e.Name == diskName { | ||
exist = true | ||
index = i | ||
break | ||
} | ||
} | ||
|
||
if exist { | ||
volumes[index] = volume | ||
} else { | ||
volumes = append(volumes, volume) | ||
} | ||
v.VirtualMachine.Spec.Template.Spec.Volumes = volumes | ||
return v | ||
} | ||
|
||
func (v *VMBuilder) ExistingDataVolume(diskName, dataVolumeName string) *VMBuilder { | ||
return v.Volume(diskName, kubevirtv1.Volume{ | ||
Name: diskName, | ||
VolumeSource: kubevirtv1.VolumeSource{ | ||
DataVolume: &kubevirtv1.DataVolumeSource{ | ||
Name: dataVolumeName, | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func (v *VMBuilder) ExistingVolumeDisk(diskName, diskBus string, isCDRom bool, bootOrder int, dataVolumeName string) *VMBuilder { | ||
return v.Disk(diskName, diskBus, isCDRom, bootOrder).ExistingDataVolume(diskName, dataVolumeName) | ||
} | ||
|
||
func (v *VMBuilder) ContainerDiskVolume(diskName, imageName, ImagePullPolicy string) *VMBuilder { | ||
return v.Volume(diskName, kubevirtv1.Volume{ | ||
Name: diskName, | ||
VolumeSource: kubevirtv1.VolumeSource{ | ||
ContainerDisk: &kubevirtv1.ContainerDiskSource{ | ||
Image: imageName, | ||
ImagePullPolicy: corev1.PullPolicy(ImagePullPolicy), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func (v *VMBuilder) ContainerDisk(diskName, diskBus string, isCDRom bool, bootOrder int, imageName, ImagePullPolicy string) *VMBuilder { | ||
return v.Disk(diskName, diskBus, isCDRom, bootOrder).ContainerDiskVolume(diskName, imageName, ImagePullPolicy) | ||
} | ||
|
||
func (v *VMBuilder) DataVolume(diskName, diskSize, dataVolumeName string, opt *DataVolumeOption) *VMBuilder { | ||
if opt == nil { | ||
opt = &DataVolumeOption{ | ||
VolumeMode: corev1.PersistentVolumeBlock, | ||
AccessMode: corev1.ReadWriteMany, | ||
} | ||
} | ||
if dataVolumeName == "" { | ||
dataVolumeName = fmt.Sprintf("%s-%s-%s", v.VirtualMachine.Name, diskName, rand.String(5)) | ||
} | ||
// DataVolumeTemplates | ||
dataVolumeTemplates := v.VirtualMachine.Spec.DataVolumeTemplates | ||
dataVolumeSpecSource := cdiv1alpha1.DataVolumeSource{ | ||
Blank: &cdiv1alpha1.DataVolumeBlankImage{}, | ||
} | ||
|
||
if opt.DownloadURL != "" { | ||
dataVolumeSpecSource = cdiv1alpha1.DataVolumeSource{ | ||
HTTP: &cdiv1alpha1.DataVolumeSourceHTTP{ | ||
URL: opt.DownloadURL, | ||
}, | ||
} | ||
} | ||
dataVolumeTemplate := kubevirtv1.DataVolumeTemplateSpec{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: dataVolumeName, | ||
}, | ||
Spec: cdiv1alpha1.DataVolumeSpec{ | ||
Source: dataVolumeSpecSource, | ||
PVC: &corev1.PersistentVolumeClaimSpec{ | ||
AccessModes: []corev1.PersistentVolumeAccessMode{ | ||
opt.AccessMode, | ||
}, | ||
Resources: corev1.ResourceRequirements{ | ||
Requests: corev1.ResourceList{ | ||
corev1.ResourceStorage: resource.MustParse(diskSize), | ||
}, | ||
}, | ||
VolumeMode: &opt.VolumeMode, | ||
StorageClassName: opt.StorageClassName, | ||
}, | ||
}, | ||
} | ||
if opt.ImageID != "" { | ||
dataVolumeTemplate.Annotations = map[string]string{ | ||
AnnotationKeyImageID: opt.ImageID, | ||
} | ||
} | ||
dataVolumeTemplates = append(dataVolumeTemplates, dataVolumeTemplate) | ||
v.VirtualMachine.Spec.DataVolumeTemplates = dataVolumeTemplates | ||
|
||
return v.ExistingDataVolume(diskName, dataVolumeName) | ||
} | ||
|
||
func (v *VMBuilder) DataVolumeDisk(diskName, diskBus string, isCDRom bool, bootOrder int, diskSize, dataVolumeName string, opt *DataVolumeOption) *VMBuilder { | ||
return v.Disk(diskName, diskBus, isCDRom, bootOrder).DataVolume(diskName, diskSize, dataVolumeName, opt) | ||
} |
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,70 @@ | ||
package builder | ||
|
||
import ( | ||
kubevirtv1 "kubevirt.io/client-go/api/v1" | ||
) | ||
|
||
const ( | ||
NetworkInterfaceTypeBridge = "bridge" | ||
NetworkInterfaceTypeMasquerade = "masquerade" | ||
|
||
LabelKeyNetworkType = "networks.harvesterhci.io/type" | ||
|
||
NetworkTypeVLAN = "L2VlanNetwork" | ||
NetworkTypeCustom = "Custom" | ||
|
||
NetworkVLANConfigTemplate = `{"cniVersion":"0.3.1","name":"%s","type":"bridge","bridge":"harvester-br0","promiscMode":true,"vlan":%d,"ipam":{}}` | ||
) | ||
|
||
func (v *VMBuilder) NetworkInterface(interfaceName, interfaceModel, interfaceMACAddress, interfaceType, networkName string) *VMBuilder { | ||
v.Interface(interfaceName, interfaceModel, interfaceMACAddress, interfaceType) | ||
v.Network(interfaceName, networkName) | ||
return v | ||
} | ||
|
||
func (v *VMBuilder) Network(interfaceName, networkName string) *VMBuilder { | ||
networks := v.VirtualMachine.Spec.Template.Spec.Networks | ||
network := kubevirtv1.Network{ | ||
Name: interfaceName, | ||
} | ||
if networkName != "" { | ||
network.NetworkSource = kubevirtv1.NetworkSource{ | ||
Multus: &kubevirtv1.MultusNetwork{ | ||
NetworkName: networkName, | ||
Default: false, | ||
}, | ||
} | ||
} else { | ||
network.NetworkSource = kubevirtv1.NetworkSource{ | ||
Pod: &kubevirtv1.PodNetwork{}, | ||
} | ||
} | ||
networks = append(networks, network) | ||
v.VirtualMachine.Spec.Template.Spec.Networks = networks | ||
return v | ||
} | ||
|
||
func (v *VMBuilder) Interface(interfaceName, interfaceModel, interfaceMACAddress string, interfaceType string) *VMBuilder { | ||
interfaces := v.VirtualMachine.Spec.Template.Spec.Domain.Devices.Interfaces | ||
networkInterface := kubevirtv1.Interface{ | ||
Name: interfaceName, | ||
Model: interfaceModel, | ||
MacAddress: interfaceMACAddress, | ||
InterfaceBindingMethod: kubevirtv1.InterfaceBindingMethod{ | ||
Bridge: &kubevirtv1.InterfaceBridge{}, | ||
}, | ||
} | ||
switch interfaceType { | ||
case NetworkInterfaceTypeBridge: | ||
networkInterface.InterfaceBindingMethod = kubevirtv1.InterfaceBindingMethod{ | ||
Bridge: &kubevirtv1.InterfaceBridge{}, | ||
} | ||
default: | ||
networkInterface.InterfaceBindingMethod = kubevirtv1.InterfaceBindingMethod{ | ||
Masquerade: &kubevirtv1.InterfaceMasquerade{}, | ||
} | ||
} | ||
interfaces = append(interfaces, networkInterface) | ||
v.VirtualMachine.Spec.Template.Spec.Domain.Devices.Interfaces = interfaces | ||
return v | ||
} |
Oops, something went wrong.