Beispiel #1
0
func (d *Dispatcher) reconfigureApplianceSpec(vm *vm.VirtualMachine, conf *config.VirtualContainerHostConfigSpec, settings *data.InstallerData) (*types.VirtualMachineConfigSpec, error) {
	defer trace.End(trace.Begin(""))

	var devices object.VirtualDeviceList
	var err error

	spec := &types.VirtualMachineConfigSpec{
		Name:    conf.Name,
		GuestId: "other3xLinux64Guest",
		Files:   &types.VirtualMachineFileInfo{VmPathName: fmt.Sprintf("[%s]", conf.ImageStores[0].Host)},
	}

	if devices, err = d.configIso(conf, vm, settings); err != nil {
		return nil, err
	}

	deviceChange, err := devices.ConfigSpec(types.VirtualDeviceConfigSpecOperationAdd)
	if err != nil {
		log.Errorf("Failed to create config spec for appliance: %s", err)
		return nil, err
	}

	spec.DeviceChange = deviceChange

	cfg := make(map[string]string)
	extraconfig.Encode(extraconfig.MapSink(cfg), conf)
	spec.ExtraConfig = append(spec.ExtraConfig, vmomi.OptionValueFromMap(cfg)...)
	return spec, nil
}
Beispiel #2
0
func (h *Handle) Commit(ctx context.Context, sess *session.Session, waitTime *int32) error {
	cfg := make(map[string]string)

	// Set timestamps based on target state
	switch h.TargetState() {
	case StateRunning:
		for _, sc := range h.ExecConfig.Sessions {
			sc.StartTime = time.Now().UTC().Unix()
			sc.Started = ""
			sc.ExitStatus = 0
		}
	case StateStopped:
		for _, sc := range h.ExecConfig.Sessions {
			sc.StopTime = time.Now().UTC().Unix()
		}
	}

	extraconfig.Encode(extraconfig.MapSink(cfg), h.ExecConfig)
	s := h.Spec.Spec()
	s.ExtraConfig = append(s.ExtraConfig, vmomi.OptionValueFromMap(cfg)...)

	if err := Commit(ctx, sess, h, waitTime); err != nil {
		return err
	}

	removeHandle(h.key)
	return nil
}
Beispiel #3
0
func (d *Dispatcher) createApplianceSpec(conf *config.VirtualContainerHostConfigSpec, vConf *data.InstallerData) (*types.VirtualMachineConfigSpec, error) {
	defer trace.End(trace.Begin(""))

	var devices object.VirtualDeviceList
	var err error

	cfg, err := d.encodeConfig(conf)
	if err != nil {
		return nil, err
	}

	spec := &spec.VirtualMachineConfigSpec{
		VirtualMachineConfigSpec: &types.VirtualMachineConfigSpec{
			Name:     conf.Name,
			GuestId:  "other3xLinux64Guest",
			Files:    &types.VirtualMachineFileInfo{VmPathName: fmt.Sprintf("[%s]", conf.ImageStores[0].Host)},
			NumCPUs:  int32(vConf.ApplianceSize.CPU.Limit),
			MemoryMB: vConf.ApplianceSize.Memory.Limit,
			// Encode the config both here and after the VMs created so that it can be identified as a VCH appliance as soon as
			// creation is complete.
			ExtraConfig: vmomi.OptionValueFromMap(cfg),
		},
	}

	if devices, err = d.addIDEController(devices); err != nil {
		return nil, err
	}

	if devices, err = d.addParaVirtualSCSIController(devices); err != nil {
		return nil, err
	}

	if devices, err = d.addNetworkDevices(conf, spec, devices); err != nil {
		return nil, err
	}

	deviceChange, err := devices.ConfigSpec(types.VirtualDeviceConfigSpecOperationAdd)
	if err != nil {
		return nil, err
	}

	spec.DeviceChange = deviceChange
	return spec.VirtualMachineConfigSpec, nil
}
Beispiel #4
0
func (d *Dispatcher) reconfigVCH(conf *config.VirtualContainerHostConfigSpec, isoFile string) error {
	defer trace.End(trace.Begin(isoFile))

	spec := &types.VirtualMachineConfigSpec{}

	deviceChange, err := d.switchISO(isoFile)
	if err != nil {
		return err
	}

	spec.DeviceChange = deviceChange

	if conf != nil {
		cfg, cerr := d.encodeConfig(conf)
		if cerr != nil {
			return cerr
		}

		spec.ExtraConfig = append(spec.ExtraConfig, vmomi.OptionValueFromMap(cfg)...)
	}

	if spec.DeviceChange == nil && spec.ExtraConfig == nil {
		// nothing need to do
		log.Debugf("Nothing changed, no need to reconfigure appliance")
		return nil
	}

	// reconfig
	log.Infof("Setting VM configuration")
	info, err := d.appliance.WaitForResult(d.ctx, func(ctx context.Context) (tasks.Task, error) {
		return d.appliance.Reconfigure(ctx, *spec)
	})

	if err != nil {
		log.Errorf("Error while reconfiguring appliance: %s", err)
		return err
	}
	if info.State != types.TaskInfoStateSuccess {
		log.Errorf("Reconfiguring appliance reported: %s", info.Error.LocalizedMessage)
		return err
	}
	return nil
}
Beispiel #5
0
func (h *Handle) Commit(ctx context.Context, sess *session.Session, waitTime *int32) error {
	if h.committed {
		return nil // already committed
	}

	// make sure there is a spec
	h.SetSpec(nil)
	cfg := make(map[string]string)
	extraconfig.Encode(extraconfig.MapSink(cfg), h.ExecConfig)
	s := h.Spec.Spec()
	s.ExtraConfig = append(s.ExtraConfig, vmomi.OptionValueFromMap(cfg)...)

	if err := h.Container.Commit(ctx, sess, h, waitTime); err != nil {
		return err
	}

	h.committed = true
	removeHandle(h.key)
	return nil
}
Beispiel #6
0
// NewVirtualMachineConfigSpec returns a VirtualMachineConfigSpec
func NewVirtualMachineConfigSpec(ctx context.Context, session *session.Session, config *VirtualMachineConfigSpecConfig) (*VirtualMachineConfigSpec, error) {
	defer trace.End(trace.Begin(config.ID))

	log.Debugf("Adding metadata to the configspec: %+v", config.Metadata)
	// TEMPORARY

	// set VM name to prettyname-ID, to make it readable a little bit
	// if prettyname-ID is longer than max vm name length, truncate pretty name, instead of UUID, to make it unique
	nameMaxLen := maxVMNameLength - len(config.ID)
	prettyName := config.Name
	if len(prettyName) > nameMaxLen-1 {
		prettyName = prettyName[:nameMaxLen-1]
	}
	fullName := fmt.Sprintf("%s-%s", prettyName, config.ID)
	config.VMFullName = fullName

	VMPathName := config.VMPathName
	if !session.IsVSAN(ctx) {
		// VMFS requires the full path to vmx or everything but the datastore is ignored
		VMPathName = fmt.Sprintf("%s/%s/%s.vmx", config.VMPathName, config.VMFullName, config.ID)
	}

	s := &types.VirtualMachineConfigSpec{
		Name: fullName,
		Uuid: config.BiosUUID,
		Files: &types.VirtualMachineFileInfo{
			VmPathName: VMPathName,
		},
		NumCPUs:             config.NumCPUs,
		CpuHotAddEnabled:    &config.VMForkEnabled, // this disables vNUMA when true
		MemoryMB:            config.MemoryMB,
		MemoryHotAddEnabled: &config.VMForkEnabled,

		ExtraConfig: []types.BaseOptionValue{
			// lets us see the UUID for the containerfs disk (hidden from daemon)
			&types.OptionValue{Key: "disk.EnableUUID", Value: "true"},
			// needed to avoid the questions that occur when attaching multiple disks with the same uuid (bugzilla 1362918)
			&types.OptionValue{Key: "answer.msg.disk.duplicateUUID", Value: "Yes"},
			// needed to avoid the question that occur when opening a file backed serial port
			&types.OptionValue{Key: "answer.msg.serial.file.open", Value: "Append"},

			&types.OptionValue{Key: "sched.mem.lpage.maxSharedPages", Value: "256"},
			// seems to be needed to avoid children hanging shortly after fork
			&types.OptionValue{Key: "vmotion.checkpointSVGAPrimarySize", Value: "4194304"},

			// trying this out - if it works then we need to determine if we can rely on serial0 being the correct index.
			&types.OptionValue{Key: "serial0.hardwareFlowControl", Value: "TRUE"},

			// https://enatai-jira.eng.vmware.com/browse/BON-257
			// Hotadd memory above 3 GB not working
			&types.OptionValue{Key: "memory.noHotAddOver4GB", Value: "FALSE"},
			&types.OptionValue{Key: "memory.maxGrow", Value: "512"},

			// http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=2030189
			&types.OptionValue{Key: "tools.remindInstall", Value: "FALSE"},
			&types.OptionValue{Key: "tools.upgrade.policy", Value: "manual"},
		},
	}

	// encode the config as optionvalues
	cfg := map[string]string{}
	extraconfig.Encode(extraconfig.MapSink(cfg), config.Metadata)
	metaCfg := vmomi.OptionValueFromMap(cfg)

	// merge it with the sec
	s.ExtraConfig = append(s.ExtraConfig, metaCfg...)

	vmcs := &VirtualMachineConfigSpec{
		Session:                  session,
		VirtualMachineConfigSpec: s,
		config: config,
	}

	log.Debugf("Virtual machine config spec created: %+v", vmcs)
	return vmcs, nil
}