func (d *Driver) Create() error {
	b2dutils := mcnutils.NewB2dUtils(d.StorePath)
	if err := b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, d.MachineName); err != nil {
		return err
	}

	log.Infof("Generating SSH Keypair...")
	if err := ssh.GenerateSSHKey(d.GetSSHKeyPath()); err != nil {
		return err
	}

	// Create context
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	c, err := d.vsphereLogin(ctx)
	if err != nil {
		return err
	}
	defer c.Logout(ctx)

	// Create a new finder
	f := find.NewFinder(c.Client, true)

	dc, err := f.DatacenterOrDefault(ctx, d.Datacenter)
	if err != nil {
		return err
	}

	f.SetDatacenter(dc)

	dss, err := f.DatastoreOrDefault(ctx, d.Datastore)
	if err != nil {
		return err
	}

	networks := make(map[string]object.NetworkReference)
	for _, netName := range d.Networks {
		net, err := f.NetworkOrDefault(ctx, netName)
		if err != nil {
			return err
		}
		networks[netName] = net
	}

	var hs *object.HostSystem
	if d.HostSystem != "" {
		var err error
		hs, err = f.HostSystemOrDefault(ctx, d.HostSystem)
		if err != nil {
			return err
		}
	}

	var rp *object.ResourcePool
	if d.Pool != "" {
		// Find specified Resource Pool
		rp, err = f.ResourcePool(ctx, d.Pool)
		if err != nil {
			return err
		}
	} else if d.HostSystem != "" {
		// Pick default Resource Pool for Host System
		rp, err = hs.ResourcePool(ctx)
		if err != nil {
			return err
		}
	} else {
		// Pick the default Resource Pool for the Datacenter.
		rp, err = f.DefaultResourcePool(ctx)
		if err != nil {
			return err
		}
	}

	spec := types.VirtualMachineConfigSpec{
		Name:     d.MachineName,
		GuestId:  "otherLinux64Guest",
		Files:    &types.VirtualMachineFileInfo{VmPathName: fmt.Sprintf("[%s]", dss.Name())},
		NumCPUs:  int32(d.CPU),
		MemoryMB: int64(d.Memory),
	}

	scsi, err := object.SCSIControllerTypes().CreateSCSIController("pvscsi")
	if err != nil {
		return err
	}

	spec.DeviceChange = append(spec.DeviceChange, &types.VirtualDeviceConfigSpec{
		Operation: types.VirtualDeviceConfigSpecOperationAdd,
		Device:    scsi,
	})

	log.Infof("Creating VM...")
	folders, err := dc.Folders(ctx)
	folder := folders.VmFolder
	if d.Folder != "" {
		folder, err = f.Folder(ctx, fmt.Sprintf("%s/%s", folders.VmFolder.InventoryPath, d.Folder))
		if err != nil {
			return err
		}
	}
	task, err := folder.CreateVM(ctx, spec, rp, hs)
	if err != nil {
		return err
	}

	info, err := task.WaitForResult(ctx, nil)
	if err != nil {
		return err
	}

	log.Infof("Uploading Boot2docker ISO ...")
	dsurl, err := dss.URL(ctx, dc, fmt.Sprintf("%s/%s", d.MachineName, isoFilename))
	if err != nil {
		return err
	}
	p := soap.DefaultUpload
	if err = c.Client.UploadFile(d.ISO, dsurl, &p); err != nil {
		return err
	}

	// Retrieve the new VM
	vm := object.NewVirtualMachine(c.Client, info.Result.(types.ManagedObjectReference))

	devices, err := vm.Device(ctx)
	if err != nil {
		return err
	}

	var add []types.BaseVirtualDevice

	controller, err := devices.FindDiskController("scsi")
	if err != nil {
		return err
	}

	disk := devices.CreateDisk(controller, dss.Reference(),
		dss.Path(fmt.Sprintf("%s/%s.vmdk", d.MachineName, d.MachineName)))

	// Convert MB to KB
	disk.CapacityInKB = int64(d.DiskSize) * 1024

	add = append(add, disk)
	ide, err := devices.FindIDEController("")
	if err != nil {
		return err
	}

	cdrom, err := devices.CreateCdrom(ide)
	if err != nil {
		return err
	}

	add = append(add, devices.InsertIso(cdrom, dss.Path(fmt.Sprintf("%s/%s", d.MachineName, isoFilename))))

	for _, netName := range d.Networks {
		backing, err := networks[netName].EthernetCardBackingInfo(ctx)
		if err != nil {
			return err
		}

		netdev, err := object.EthernetCardTypes().CreateEthernetCard("vmxnet3", backing)
		if err != nil {
			return err
		}

		log.Infof("adding network: %s", netName)
		add = append(add, netdev)
	}

	log.Infof("Reconfiguring VM")
	if vm.AddDevice(ctx, add...); err != nil {
		return err
	}

	// Adding some guestinfo data
	var opts []types.BaseOptionValue
	for _, param := range d.CfgParams {
		v := strings.SplitN(param, "=", 2)
		key := v[0]
		value := ""
		if len(v) > 1 {
			value = v[1]
		}
		fmt.Printf("Setting %s to %s\n", key, value)
		opts = append(opts, &types.OptionValue{
			Key:   key,
			Value: value,
		})
	}
	if d.CloudInit != "" {
		if _, err := url.ParseRequestURI(d.CloudInit); err == nil {
			log.Infof("setting guestinfo.cloud-init.data.url to %s\n", d.CloudInit)
			opts = append(opts, &types.OptionValue{
				Key:   "guestinfo.cloud-init.config.url",
				Value: d.CloudInit,
			})
		} else {
			if _, err := os.Stat(d.CloudInit); err == nil {
				if value, err := ioutil.ReadFile(d.CloudInit); err == nil {
					log.Infof("setting guestinfo.cloud-init.data to encoded content of %s\n", d.CloudInit)
					encoded := base64.StdEncoding.EncodeToString(value)
					opts = append(opts, &types.OptionValue{
						Key:   "guestinfo.cloud-init.config.data",
						Value: encoded,
					})
					opts = append(opts, &types.OptionValue{
						Key:   "guestinfo.cloud-init.data.encoding",
						Value: "base64",
					})
				}
			}
		}
	}

	task, err = vm.Reconfigure(ctx, types.VirtualMachineConfigSpec{
		ExtraConfig: opts,
	})
	if err != nil {
		return err
	}
	task.Wait(ctx)

	if err := d.Start(); err != nil {
		return err
	}

	log.Infof("Provisioning certs and ssh keys...")
	// Generate a tar keys bundle
	if err := d.generateKeyBundle(); err != nil {
		return err
	}

	opman := guest.NewOperationsManager(c.Client, vm.Reference())

	fileman, err := opman.FileManager(ctx)
	if err != nil {
		return err
	}

	src := d.ResolveStorePath("userdata.tar")
	s, err := os.Stat(src)
	if err != nil {
		return err
	}

	auth := AuthFlag{}
	flag := FileAttrFlag{}
	auth.auth.Username = B2DUser
	auth.auth.Password = B2DPass
	flag.SetPerms(0, 0, 660)
	url, err := fileman.InitiateFileTransferToGuest(ctx, auth.Auth(), "/home/docker/userdata.tar", flag.Attr(), s.Size(), true)
	if err != nil {
		return err
	}
	u, err := c.Client.ParseURL(url)
	if err != nil {
		return err
	}
	if err = c.Client.UploadFile(src, u, nil); err != nil {
		return err
	}

	procman, err := opman.ProcessManager(ctx)
	if err != nil {
		return err
	}

	// first, untar - only boot2docker has /var/lib/boot2docker
	// TODO: don't hard-code to docker & staff - they are also just b2d
	var env []string
	guestspec := types.GuestProgramSpec{
		ProgramPath:      "/usr/bin/sudo",
		Arguments:        "/usr/bin/sudo /bin/sh -c \"tar xvf /home/docker/userdata.tar -C /home/docker > /var/log/userdata.log 2>&1 && chown -R docker:staff /home/docker\"",
		WorkingDirectory: "",
		EnvVariables:     env,
	}

	_, err = procman.StartProgram(ctx, auth.Auth(), &guestspec)
	if err != nil {
		return err
	}

	// now move to /var/lib/boot2docker if its there
	guestspec = types.GuestProgramSpec{
		ProgramPath:      "/usr/bin/sudo",
		Arguments:        "/bin/mv /home/docker/userdata.tar /var/lib/boot2docker/userdata.tar",
		WorkingDirectory: "",
		EnvVariables:     env,
	}

	_, err = procman.StartProgram(ctx, auth.Auth(), &guestspec)
	if err != nil {
		return err
	}

	return nil
}
func (d *Driver) Create() error {
	b2dutils := mcnutils.NewB2dUtils(d.StorePath)
	if err := b2dutils.CopyIsoToMachineDir(d.Boot2DockerURL, d.MachineName); err != nil {
		return err
	}

	log.Infof("Generating SSH Keypair...")
	if err := ssh.GenerateSSHKey(d.GetSSHKeyPath()); err != nil {
		return err
	}

	
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	c, err := d.vsphereLogin(ctx)
	if err != nil {
		return err
	}
	defer c.Logout(ctx)

	
	f := find.NewFinder(c.Client, true)

	dc, err := f.DatacenterOrDefault(ctx, d.Datacenter)
	if err != nil {
		return err
	}

	f.SetDatacenter(dc)

	dss, err := f.DatastoreOrDefault(ctx, d.Datastore)
	if err != nil {
		return err
	}

	networks := make(map[string]object.NetworkReference)
	for _, netName := range d.Networks {
		net, err := f.NetworkOrDefault(ctx, netName)
		if err != nil {
			return err
		}
		networks[netName] = net
	}

	var hs *object.HostSystem
	if d.HostSystem != "" {
		var err error
		hs, err = f.HostSystemOrDefault(ctx, d.HostSystem)
		if err != nil {
			return err
		}
	}

	var rp *object.ResourcePool
	if d.Pool != "" {
		
		rp, err = f.ResourcePool(ctx, d.Pool)
		if err != nil {
			return err
		}
	} else if d.HostSystem != "" {
		
		rp, err = hs.ResourcePool(ctx)
		if err != nil {
			return err
		}
	} else {
		
		rp, err = f.DefaultResourcePool(ctx)
		if err != nil {
			return err
		}
	}

	spec := types.VirtualMachineConfigSpec{
		Name:     d.MachineName,
		GuestId:  "otherLinux64Guest",
		Files:    &types.VirtualMachineFileInfo{VmPathName: fmt.Sprintf("[%s]", dss.Name())},
		NumCPUs:  int32(d.CPU),
		MemoryMB: int64(d.Memory),
	}

	scsi, err := object.SCSIControllerTypes().CreateSCSIController("pvscsi")
	if err != nil {
		return err
	}

	spec.DeviceChange = append(spec.DeviceChange, &types.VirtualDeviceConfigSpec{
		Operation: types.VirtualDeviceConfigSpecOperationAdd,
		Device:    scsi,
	})

	log.Infof("Creating VM...")
	folders, err := dc.Folders(ctx)
	folder := folders.VmFolder
	if d.Folder != "" {
		folder, err = f.Folder(ctx, fmt.Sprintf("%s/%s", folders.VmFolder.InventoryPath, d.Folder))
		if err != nil {
			return err
		}
	}
	task, err := folder.CreateVM(ctx, spec, rp, hs)
	if err != nil {
		return err
	}

	info, err := task.WaitForResult(ctx, nil)
	if err != nil {
		return err
	}

	log.Infof("Uploading Boot2docker ISO ...")
	dsurl, err := dss.URL(ctx, dc, fmt.Sprintf("%s/%s", d.MachineName, isoFilename))
	if err != nil {
		return err
	}
	p := soap.DefaultUpload
	if err = c.Client.UploadFile(d.ISO, dsurl, &p); err != nil {
		return err
	}

	
	vm := object.NewVirtualMachine(c.Client, info.Result.(types.ManagedObjectReference))

	devices, err := vm.Device(ctx)
	if err != nil {
		return err
	}

	var add []types.BaseVirtualDevice

	controller, err := devices.FindDiskController("scsi")
	if err != nil {
		return err
	}

	disk := devices.CreateDisk(controller, dss.Reference(),
		dss.Path(fmt.Sprintf("%s/%s.vmdk", d.MachineName, d.MachineName)))

	
	disk.CapacityInKB = int64(d.DiskSize) * 1024

	add = append(add, disk)
	ide, err := devices.FindIDEController("")
	if err != nil {
		return err
	}

	cdrom, err := devices.CreateCdrom(ide)
	if err != nil {
		return err
	}

	add = append(add, devices.InsertIso(cdrom, dss.Path(fmt.Sprintf("%s/%s", d.MachineName, isoFilename))))

	for _, netName := range d.Networks {
		backing, err := networks[netName].EthernetCardBackingInfo(ctx)
		if err != nil {
			return err
		}

		netdev, err := object.EthernetCardTypes().CreateEthernetCard("vmxnet3", backing)
		if err != nil {
			return err
		}

		log.Infof("adding network: %s", netName)
		add = append(add, netdev)
	}

	log.Infof("Reconfiguring VM")
	if vm.AddDevice(ctx, add...); err != nil {
		return err
	}

	
	var opts []types.BaseOptionValue
	for _, param := range d.CfgParams {
		v := strings.SplitN(param, "=", 2)
		key := v[0]
		value := ""
		if len(v) > 1 {
			value = v[1]
		}
		fmt.Printf("Setting %s to %s\n", key, value)
		opts = append(opts, &types.OptionValue{
			Key:   key,
			Value: value,
		})
	}
	if d.CloudInit != "" {
		if _, err := url.ParseRequestURI(d.CloudInit); err == nil {
			log.Infof("setting guestinfo.cloud-init.data.url to %s\n", d.CloudInit)
			opts = append(opts, &types.OptionValue{
				Key:   "guestinfo.cloud-init.config.url",
				Value: d.CloudInit,
			})
		} else {
			if _, err := os.Stat(d.CloudInit); err == nil {
				if value, err := ioutil.ReadFile(d.CloudInit); err == nil {
					log.Infof("setting guestinfo.cloud-init.data to encoded content of %s\n", d.CloudInit)
					encoded := base64.StdEncoding.EncodeToString(value)
					opts = append(opts, &types.OptionValue{
						Key:   "guestinfo.cloud-init.config.data",
						Value: encoded,
					})
					opts = append(opts, &types.OptionValue{
						Key:   "guestinfo.cloud-init.data.encoding",
						Value: "base64",
					})
				}
			}
		}
	}

	task, err = vm.Reconfigure(ctx, types.VirtualMachineConfigSpec{
		ExtraConfig: opts,
	})
	if err != nil {
		return err
	}
	task.Wait(ctx)

	if err := d.Start(); err != nil {
		return err
	}

	log.Infof("Provisioning certs and ssh keys...")
	
	if err := d.generateKeyBundle(); err != nil {
		return err
	}

	opman := guest.NewOperationsManager(c.Client, vm.Reference())

	fileman, err := opman.FileManager(ctx)
	if err != nil {
		return err
	}

	src := d.ResolveStorePath("userdata.tar")
	s, err := os.Stat(src)
	if err != nil {
		return err
	}

	auth := AuthFlag{}
	flag := FileAttrFlag{}
	auth.auth.Username = B2DUser
	auth.auth.Password = B2DPass
	flag.SetPerms(0, 0, 660)
	url, err := fileman.InitiateFileTransferToGuest(ctx, auth.Auth(), "/home/docker/userdata.tar", flag.Attr(), s.Size(), true)
	if err != nil {
		return err
	}
	u, err := c.Client.ParseURL(url)
	if err != nil {
		return err
	}
	if err = c.Client.UploadFile(src, u, nil); err != nil {
		return err
	}

	procman, err := opman.ProcessManager(ctx)
	if err != nil {
		return err
	}

	
	
	var env []string
	guestspec := types.GuestProgramSpec{
		ProgramPath:      "/usr/bin/sudo",
		Arguments:        "/usr/bin/sudo /bin/sh -c \"tar xvf /home/docker/userdata.tar -C /home/docker > /var/log/userdata.log 2>&1 && chown -R docker:staff /home/docker\"",
		WorkingDirectory: "",
		EnvVariables:     env,
	}

	_, err = procman.StartProgram(ctx, auth.Auth(), &guestspec)
	if err != nil {
		return err
	}

	
	guestspec = types.GuestProgramSpec{
		ProgramPath:      "/usr/bin/sudo",
		Arguments:        "/bin/mv /home/docker/userdata.tar /var/lib/boot2docker/userdata.tar",
		WorkingDirectory: "",
		EnvVariables:     env,
	}

	_, err = procman.StartProgram(ctx, auth.Auth(), &guestspec)
	if err != nil {
		return err
	}

	return nil
}
func ( d * Driver ) Create ( ) error { b2dutils := mcnutils . NewB2dUtils ( d . StorePath ) if err := b2dutils . CopyIsoToMachineDir ( d . Boot2DockerURL , d . MachineName ) ; err != nil { return err } log . Infof ( " " ) if err := ssh . GenerateSSHKey ( d . GetSSHKeyPath ( ) ) ; err != nil { return err } // Create context ctx , cancel := context . WithCancel ( context . Background ( ) ) defer cancel ( ) c , err := d . vsphereLogin ( ctx ) if err != nil { return err } defer c . Logout ( ctx ) // Create a new finder f := find . NewFinder ( c . Client , true ) dc , err := f . DatacenterOrDefault ( ctx , d . Datacenter ) if err != nil { return err } f . SetDatacenter ( dc ) dss , err := f . DatastoreOrDefault ( ctx , d . Datastore ) if err != nil { return err } networks := make ( map [ string ] object . NetworkReference ) for _ , netName := range d . Networks { net , err := f . NetworkOrDefault ( ctx , netName ) if err != nil { return err } networks [ netName ] = net } var hs * object . HostSystem if d . HostSystem != " " { var err error hs , err = f . HostSystemOrDefault ( ctx , d . HostSystem ) if err != nil { return err } } var rp * object . ResourcePool if d . Pool != " " { // Find specified Resource Pool rp , err = f . ResourcePool ( ctx , d . Pool ) if err != nil { return err } } else if d . HostSystem != " " { // Pick default Resource Pool for Host System rp , err = hs . ResourcePool ( ctx ) if err != nil { return err } } else { // Pick the default Resource Pool for the Datacenter. rp , err = f . DefaultResourcePool ( ctx ) if err != nil { return err } } spec := types . VirtualMachineConfigSpec { Name : d . MachineName , GuestId : " " , Files : & types . VirtualMachineFileInfo { VmPathName : fmt . Sprintf ( " " , dss . Name ( ) ) } , NumCPUs : int32 ( d . CPU ) , MemoryMB : int64 ( d . Memory ) , } scsi , err := object . SCSIControllerTypes ( ) . CreateSCSIController ( " " ) if err != nil { return err } spec . DeviceChange = append ( spec . DeviceChange , & types . VirtualDeviceConfigSpec { Operation : types . VirtualDeviceConfigSpecOperationAdd , Device : scsi , } ) log . Infof ( " " ) folders , err := dc . Folders ( ctx ) folder := folders . VmFolder if d . Folder != " " { folder , err = f . Folder ( ctx , fmt . Sprintf ( " " , folders . VmFolder . InventoryPath , d . Folder ) ) if err != nil { return err } } task , err := folder . CreateVM ( ctx , spec , rp , hs ) if err != nil { return err } info , err := task . WaitForResult ( ctx , nil ) if err != nil { return err } log . Infof ( " " ) dsurl , err := dss . URL ( ctx , dc , fmt . Sprintf ( " " , d . MachineName , isoFilename ) ) if err != nil { return err } p := soap . DefaultUpload if err = c . Client . UploadFile ( d . ISO , dsurl , & p ) ; err != nil { return err } // Retrieve the new VM vm := object . NewVirtualMachine ( c . Client , info . Result . ( types . ManagedObjectReference ) ) devices , err := vm . Device ( ctx ) if err != nil { return err } var add [ ] types . BaseVirtualDevice controller , err := devices . FindDiskController ( " " ) if err != nil { return err } disk := devices . CreateDisk ( controller , dss . Reference ( ) , dss . Path ( fmt . Sprintf ( " " , d . MachineName , d . MachineName ) ) ) // Convert MB to KB disk . CapacityInKB = int64 ( d . DiskSize ) * 1024 add = append ( add , disk ) ide , err := devices . FindIDEController ( " " ) if err != nil { return err } cdrom , err := devices . CreateCdrom ( ide ) if err != nil { return err } add = append ( add , devices . InsertIso ( cdrom , dss . Path ( fmt . Sprintf ( " " , d . MachineName , isoFilename ) ) ) ) for _ , netName := range d . Networks { backing , err := networks [ netName ] . EthernetCardBackingInfo ( ctx ) if err != nil { return err } netdev , err := object . EthernetCardTypes ( ) . CreateEthernetCard ( " " , backing ) if err != nil { return err } log . Infof ( " " , netName ) add = append ( add , netdev ) } log . Infof ( " " ) if vm . AddDevice ( ctx , add ... ) ; err != nil { return err } // Adding some guestinfo data var opts [ ] types . BaseOptionValue for _ , param := range d . CfgParams { v := strings . SplitN ( param , " " , 2 ) key := v [ 0 ] value := " " if len ( v ) > 1 { value = v [ 1 ] } fmt . Printf ( " \n " , key , value ) opts = append ( opts , & types . OptionValue { Key : key , Value : value , } ) } if d . CloudInit != " " { if _ , err := url . ParseRequestURI ( d . CloudInit ) ; err == nil { log . Infof ( " \n " , d . CloudInit ) opts = append ( opts , & types . OptionValue { Key : " " , Value : d . CloudInit , } ) } else { if _ , err := os . Stat ( d . CloudInit ) ; err == nil { if value , err := ioutil . ReadFile ( d . CloudInit ) ; err == nil { log . Infof ( " \n " , d . CloudInit ) encoded := base64 . StdEncoding . EncodeToString ( value ) opts = append ( opts , & types . OptionValue { Key : " " , Value : encoded , } ) opts = append ( opts , & types . OptionValue { Key : " " , Value : " " , } ) } } } } task , err = vm . Reconfigure ( ctx , types . VirtualMachineConfigSpec { ExtraConfig : opts , } ) if err != nil { return err } task . Wait ( ctx ) if err := d . Start ( ) ; err != nil { return err } log . Infof ( " " ) // Generate a tar keys bundle if err := d . generateKeyBundle ( ) ; err != nil { return err } opman := guest . NewOperationsManager ( c . Client , vm . Reference ( ) ) fileman , err := opman . FileManager ( ctx ) if err != nil { return err } src := d . ResolveStorePath ( " " ) s , err := os . Stat ( src ) if err != nil { return err } auth := AuthFlag { } flag := FileAttrFlag { } auth . auth . Username = B2DUser auth . auth . Password = B2DPass flag . SetPerms ( 0 , 0 , 660 ) url , err := fileman . InitiateFileTransferToGuest ( ctx , auth . Auth ( ) , " " , flag . Attr ( ) , s . Size ( ) , true ) if err != nil { return err } u , err := c . Client . ParseURL ( url ) if err != nil { return err } if err = c . Client . UploadFile ( src , u , nil ) ; err != nil { return err } procman , err := opman . ProcessManager ( ctx ) if err != nil { return err } // first, untar - only boot2docker has /var/lib/boot2docker // TODO: don't hard-code to docker & staff - they are also just b2d var env [ ] string guestspec := types . GuestProgramSpec { ProgramPath : " " , Arguments : " \" \" " , WorkingDirectory : " " , EnvVariables : env , } _ , err = procman . StartProgram ( ctx , auth . Auth ( ) , & guestspec ) if err != nil { return err } // now move to /var/lib/boot2docker if its there guestspec = types . GuestProgramSpec { ProgramPath : " " , Arguments : " " , WorkingDirectory : " " , EnvVariables : env , } _ , err = procman . StartProgram ( ctx , auth . Auth ( ) , & guestspec ) if err != nil { return err } return nil }
// Create has the following implementation:
// 1. check whether the docker directory contains the boot2docker ISO
// 2. generate an SSH keypair and bundle it in a tar.
// 3. create a virtual machine with the boot2docker ISO mounted;
// 4. reconfigure the virtual machine network and disk size;
Create has the following implementation : 1 . check whether the docker directory contains the boot2docker ISO 2 . generate an SSH keypair and bundle it in a tar . 3 . create a virtual machine with the boot2docker ISO mounted ; 4 . reconfigure the virtual machine network and disk size ;