network.go
func (v *VM) AddNetworkAdapter(adapter *NetworkAdapter) error {
	isVMRunning, err := v.IsRunning()
	if err != nil {
		return err
	}

	if isVMRunning {
		return &Error{
			Code: 100000,
			Text: "The VM has to be powered off in order to change its vmx settings",
		}
	}

	vmxPath, err := v.VmxPath()
	if err != nil {
		return err
	}

	vmx, err := readVmx(vmxPath)
	if err != nil {
		return err
	}

	if adapter == nil {
		adapter = &NetworkAdapter{}
	}

	adapter.present = true

	if adapter.Vdevice == NETWORK_DEVICE_VMXNET3 {
		hwversion, err := strconv.Atoi(vmx["virtualhw.version"])
		if err != nil {
			return err
		}

		if hwversion < 7 {
			return &Error{
				Operation: "vm.AddNetworkAdapter",
				Code:      100001,
				Text:      fmt.Sprintf("Virtual hardware version needs to be 7 or higher in order to use vmxnet3. Current hardware version: %d", hwversion),
			}
		}
	}

	if adapter.LinkStatePropagation && (adapter.ConnType != NETWORK_BRIDGED) {
		return &Error{
			Operation: "vm.AddNetworkAdapter",
			Code:      100003,
			Text:      "Link state propagation is only permitted for bridged networks",
		}
	}

	macaddr := adapter.MacAddress.String()

	if macaddr != "" {
		if !strings.HasPrefix(macaddr, "00:50:56") {
			return &Error{
				Operation: "vm.AddNetworkAdapter",
				Code:      100004,
				Text:      "Static MAC addresses have to start with VMware officially assigned prefix: 00:50:56",
			}
		}
	}

	nextID := v.nextNetworkAdapterID(vmx)
	prefix := fmt.Sprintf("ethernet%d.", nextID)

	vmx[prefix+"present"] = strings.ToUpper(strconv.FormatBool(adapter.present))

	if string(adapter.ConnType) != "" {
		vmx[prefix+"connectionType"] = string(adapter.ConnType)
	} else {
		//default
		vmx[prefix+"connectionType"] = "nat"
	}

	if string(adapter.Vdevice) != "" {
		vmx[prefix+"virtualDev"] = string(adapter.Vdevice)
	} else {
		//default
		vmx[prefix+"virtualDev"] = "e1000"
	}

	vmx[prefix+"wakeOnPcktRcv"] = strconv.FormatBool(adapter.WakeOnPcktRcv)

	if string(adapter.MacAddrType) != "" {
		vmx[prefix+"addressType"] = string(adapter.MacAddrType)
	} else {
		//default
		vmx[prefix+"addressType"] = "generated"
	}

	if macaddr != "" {
		vmx[prefix+"address"] = macaddr
		vmx[prefix+"addressType"] = "static"

		// Makes sure a generated MAC address is removed if it exists
		delete(vmx, "generatedAddress")
		delete(vmx, "generatedAddressOffset")
	}

	if adapter.LinkStatePropagation {
		vmx[prefix+"linkStatePropagation.enable"] = strconv.FormatBool(adapter.LinkStatePropagation)
	}

	if adapter.ConnType == NETWORK_CUSTOM {
		if !ExistVSwitch(adapter.VSwitch.id) {
			return &Error{
				Operation: "vm.AddNetworkAdapter",
				Code:      100005,
				Text:      "VSwitch " + adapter.VSwitch.id + " does not exist",
			}
		}
		vmx[prefix+"vnet"] = string(adapter.VSwitch.id)
	}

	vmx[prefix+"startConnected"] = strconv.FormatBool(adapter.StartConnected)

	return writeVmx(vmxPath, vmx)
}
func (v *VM) AddNetworkAdapter(adapter *NetworkAdapter) error {
	isVMRunning, err := v.IsRunning()
	if err != nil {
		return err
	}

	if isVMRunning {
		return &Error{
			Code: 100000,
			Text: "The VM has to be powered off in order to change its vmx settings",
		}
	}

	vmxPath, err := v.VmxPath()
	if err != nil {
		return err
	}

	vmx, err := readVmx(vmxPath)
	if err != nil {
		return err
	}

	if adapter == nil {
		adapter = &NetworkAdapter{}
	}

	adapter.present = true

	if adapter.Vdevice == NETWORK_DEVICE_VMXNET3 {
		hwversion, err := strconv.Atoi(vmx["virtualhw.version"])
		if err != nil {
			return err
		}

		if hwversion < 7 {
			return &Error{
				Operation: "vm.AddNetworkAdapter",
				Code:      100001,
				Text:      fmt.Sprintf("Virtual hardware version needs to be 7 or higher in order to use vmxnet3. Current hardware version: %d", hwversion),
			}
		}
	}

	if adapter.LinkStatePropagation && (adapter.ConnType != NETWORK_BRIDGED) {
		return &Error{
			Operation: "vm.AddNetworkAdapter",
			Code:      100003,
			Text:      "Link state propagation is only permitted for bridged networks",
		}
	}

	macaddr := adapter.MacAddress.String()

	if macaddr != "" {
		if !strings.HasPrefix(macaddr, "00:50:56") {
			return &Error{
				Operation: "vm.AddNetworkAdapter",
				Code:      100004,
				Text:      "Static MAC addresses have to start with VMware officially assigned prefix: 00:50:56",
			}
		}
	}

	nextID := v.nextNetworkAdapterID(vmx)
	prefix := fmt.Sprintf("ethernet%d.", nextID)

	vmx[prefix+"present"] = strings.ToUpper(strconv.FormatBool(adapter.present))

	if string(adapter.ConnType) != "" {
		vmx[prefix+"connectionType"] = string(adapter.ConnType)
	} else {
		//default
		vmx[prefix+"connectionType"] = "nat"
	}

	if string(adapter.Vdevice) != "" {
		vmx[prefix+"virtualDev"] = string(adapter.Vdevice)
	} else {
		//default
		vmx[prefix+"virtualDev"] = "e1000"
	}

	vmx[prefix+"wakeOnPcktRcv"] = strconv.FormatBool(adapter.WakeOnPcktRcv)

	if string(adapter.MacAddrType) != "" {
		vmx[prefix+"addressType"] = string(adapter.MacAddrType)
	} else {
		//default
		vmx[prefix+"addressType"] = "generated"
	}

	if macaddr != "" {
		vmx[prefix+"address"] = macaddr
		vmx[prefix+"addressType"] = "static"

		// Makes sure a generated MAC address is removed if it exists
		delete(vmx, "generatedAddress")
		delete(vmx, "generatedAddressOffset")
	}

	if adapter.LinkStatePropagation {
		vmx[prefix+"linkStatePropagation.enable"] = strconv.FormatBool(adapter.LinkStatePropagation)
	}

	if adapter.ConnType == NETWORK_CUSTOM {
		if !ExistVSwitch(adapter.VSwitch.id) {
			return &Error{
				Operation: "vm.AddNetworkAdapter",
				Code:      100005,
				Text:      "VSwitch " + adapter.VSwitch.id + " does not exist",
			}
		}
		vmx[prefix+"vnet"] = string(adapter.VSwitch.id)
	}

	vmx[prefix+"startConnected"] = strconv.FormatBool(adapter.StartConnected)

	return writeVmx(vmxPath, vmx)
}
// AddNetworkAdapter adds a network adapter to the virtual machine.
//
// The "adapter" parameter is optional. If not specified this function will add,
// by default, a network adapter with NAT support; autogenerated MAC address,
// and e1000 as network device.
//
// Be aware that the adapter will not show up in the VMware Preferences user
// interface immediatelly. Once the virtual machine is started the UI will pick it up.