Skip to content

Commit

Permalink
Add vm-uuid in cloud-config file required by Kubernetes vSphere Cloud…
Browse files Browse the repository at this point in the history
…Provider
  • Loading branch information
abrarshivani authored and robertojrojas committed Apr 26, 2017
1 parent c6196e9 commit cf10c9c
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 31 deletions.
95 changes: 68 additions & 27 deletions nodeup/pkg/model/cloudconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,22 @@ limitations under the License.
package model

import (
"bufio"
"fmt"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/apis/kops/util"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/nodeup/nodetasks"
"os"
"strings"
)

const CloudConfigFilePath = "/etc/kubernetes/cloud.config"

// Required for vSphere CloudProvider
const MinimumVersionForVMUUID = "1.5.3"
const VM_UUID_FILE_PATH = "/root/vm_uuid"

// CloudConfigBuilder creates the cloud configuration file
type CloudConfigBuilder struct {
*NodeupModelContext
Expand Down Expand Up @@ -59,37 +66,41 @@ func (b *CloudConfigBuilder) Build(c *fi.ModelBuilderContext) error {
if cloudConfig.DisableSecurityGroupIngress != nil {
lines = append(lines, fmt.Sprintf("DisableSecurityGroupIngress = %t", *cloudConfig.DisableSecurityGroupIngress))
}
}

if cloudConfig.VSphereUsername != nil {
lines = append(lines, "user = "+*cloudConfig.VSphereUsername)
}

if cloudConfig.VSpherePassword != nil {
lines = append(lines, "password = "+*cloudConfig.VSpherePassword)
}

if cloudConfig.VSphereServer != nil {
lines = append(lines, "server = "+*cloudConfig.VSphereServer)
lines = append(lines, "port = 443")
lines = append(lines, fmt.Sprintf("insecure-flag = %t", true))
}

if cloudConfig.VSphereDatacenter != nil {
lines = append(lines, "datacenter = "+*cloudConfig.VSphereDatacenter)
}

if cloudConfig.VSphereDatastore != nil {
lines = append(lines, "datastore = "+*cloudConfig.VSphereDatastore)
case "vsphere":
vm_uuid, err := getVMUUID(b.Cluster.Spec.KubernetesVersion)
if err != nil {
return err
}
// Note: Segregate configuration for different sections as below
// Global Config for vSphere CloudProvider
if cloudConfig.VSphereUsername != nil {
lines = append(lines, "user = "+*cloudConfig.VSphereUsername)
}
if cloudConfig.VSpherePassword != nil {
lines = append(lines, "password = "+*cloudConfig.VSpherePassword)
}
if cloudConfig.VSphereServer != nil {
lines = append(lines, "server = "+*cloudConfig.VSphereServer)
lines = append(lines, "port = 443")
lines = append(lines, fmt.Sprintf("insecure-flag = %t", true))
}
if cloudConfig.VSphereDatacenter != nil {
lines = append(lines, "datacenter = "+*cloudConfig.VSphereDatacenter)
}
if cloudConfig.VSphereDatastore != nil {
lines = append(lines, "datastore = "+*cloudConfig.VSphereDatastore)
}
if vm_uuid != "" {
lines = append(lines, "vm-uuid = "+strings.Trim(vm_uuid, "\n"))
}
// Disk Config for vSphere CloudProvider
// We need this to support Kubernetes vSphere CloudProvider < v1.5.3
lines = append(lines, "[disk]")
lines = append(lines, "scsicontrollertype = pvscsi")
}

config := "[global]\n" + strings.Join(lines, "\n") + "\n"

// We need this to support Kubernetes vSphere CloudProvider < v1.5.3
if fi.CloudProviderID(b.Cluster.Spec.CloudProvider) == fi.CloudProviderVSphere {
config += "[disk]\n" + "scsicontrollertype = pvscsi" + "\n"
}

t := &nodetasks.File{
Path: CloudConfigFilePath,
Contents: fi.NewStringResource(config),
Expand All @@ -99,3 +110,33 @@ func (b *CloudConfigBuilder) Build(c *fi.ModelBuilderContext) error {

return nil
}

// We need this for vSphere CloudProvider
// getVMUUID gets instance uuid of the VM from the file written by cloud-init
func getVMUUID(kubernetesVersion string) (string, error) {

actualKubernetesVersion, err := util.ParseKubernetesVersion(kubernetesVersion)
if err != nil {
return "", err
}
minimumVersionForUUID, err := util.ParseKubernetesVersion(MinimumVersionForVMUUID)
if err != nil {
return "", err
}

// VM UUID is required only for Kubernetes version greater than 1.5.3
if actualKubernetesVersion.GTE(*minimumVersionForUUID) {
file, err := os.Open(VM_UUID_FILE_PATH)
defer file.Close()
if err != nil {
return "", err
}
vm_uuid, err := bufio.NewReader(file).ReadString('\n')
if err != nil {
return "", err
}
return vm_uuid, err
}

return "", err
}
31 changes: 31 additions & 0 deletions upup/pkg/fi/cloudup/vsphere/vsphere_cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,37 @@ func (c *VSphereCloud) UploadAndAttachISO(vm *string, isoFile string) error {

}

// Returns VM's instance uuid
func (c *VSphereCloud) FindVMUUID(vm *string) (string, error) {
f := find.NewFinder(c.Client.Client, true)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

dc, err := f.Datacenter(ctx, c.Datacenter)
if err != nil {
return "", err
}
f.SetDatacenter(dc)

vmRef, err := f.VirtualMachine(ctx, *vm)
if err != nil {
return "", err
}

var refs []types.ManagedObjectReference
refs = append(refs, vmRef.Reference())
var vmResult mo.VirtualMachine

pc := property.DefaultCollector(c.Client.Client)
err = pc.RetrieveOne(ctx, vmRef.Reference(), []string{"config.uuid"}, &vmResult)
if err != nil {
return "", err
}
glog.V(4).Infof("vm property collector result :%+v\n", vmResult)
glog.V(3).Infof("retrieved vm uuid as %q for vm %q", vmResult.Config.Uuid, *vm)
return vmResult.Config.Uuid, nil
}

func getCloudInitFileName(vmName string) string {
return vmName + "/" + cloudInitFile
}
17 changes: 13 additions & 4 deletions upup/pkg/fi/cloudup/vspheretasks/attachiso.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,13 @@ func (_ *AttachISO) RenderVSphere(t *vsphere.VSphereAPITarget, a, e, changes *At
dir, err := ioutil.TempDir("", *changes.VM.Name)
defer os.RemoveAll(dir)

isoFile, err := createISO(changes, startupStr, dir, t.Cloud.CoreDNSServer)
// Need this in cloud config file for vSphere CloudProvider
vmUUID, err := t.Cloud.FindVMUUID(changes.VM.Name)
if err != nil {
return err
}

isoFile, err := createISO(changes, startupStr, dir, t.Cloud.CoreDNSServer, vmUUID)
if err != nil {
glog.Errorf("Failed to createISO for vspheretasks, err: %v", err)
return err
Expand All @@ -105,7 +111,7 @@ func (_ *AttachISO) RenderVSphere(t *vsphere.VSphereAPITarget, a, e, changes *At
return nil
}

func createUserData(startupStr string, dir string, dnsServer string) error {
func createUserData(startupStr string, dir string, dnsServer string, vmUUID string) error {
// Update the startup script to add the extra spaces for
// indentation when copied to the user-data file.
strArray := strings.Split(startupStr, "\n")
Expand All @@ -131,6 +137,9 @@ func createUserData(startupStr string, dir string, dnsServer string) error {
dnsUpdateStr := strings.Join(lines, "\n")
data = strings.Replace(data, "$DNS_SCRIPT", dnsUpdateStr, -1)

vmUUIDStr := " " + vmUUID + "\n"
data = strings.Replace(data, "$VM_UUID", vmUUIDStr, -1)

userDataFile := filepath.Join(dir, "user-data")
glog.V(4).Infof("User data file content: %s", data)

Expand All @@ -156,8 +165,8 @@ func createMetaData(dir string, vmName string) error {
return nil
}

func createISO(changes *AttachISO, startupStr string, dir string, dnsServer string) (string, error) {
err := createUserData(startupStr, dir, dnsServer)
func createISO(changes *AttachISO, startupStr string, dir string, dnsServer string, vmUUID string) (string, error) {
err := createUserData(startupStr, dir, dnsServer, vmUUID)
if err != nil {
return "", err
}
Expand Down
5 changes: 5 additions & 0 deletions upup/pkg/fi/cloudup/vspheretasks/cloud_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ $DNS_SCRIPT
owner: root:root
path: /root/update_dns.sh
permissions: "0644"
- content: |
$VM_UUID
owner: root:root
path: /root/vm_uuid
permissions: "0644"
runcmd:
- bash /root/update_dns.sh 2>&1 > /var/log/update_dns.log
Expand Down

0 comments on commit cf10c9c

Please sign in to comment.