func (cmd *ovfx) Import(fpath string) (*types.ManagedObjectReference, error) { o, err := cmd.ReadOvf(fpath) if err != nil { return nil, err } e, err := cmd.ReadEnvelope(fpath) if err != nil { return nil, fmt.Errorf("failed to parse ovf: %s", err.Error()) } name := "Govc Virtual Appliance" if e.VirtualSystem != nil { name = e.VirtualSystem.ID } cisp := types.OvfCreateImportSpecParams{ DiskProvisioning: cmd.Options.DiskProvisioning, EntityName: name, IpAllocationPolicy: cmd.Options.IPAllocationPolicy, IpProtocol: cmd.Options.IPProtocol, OvfManagerCommonParams: types.OvfManagerCommonParams{ DeploymentOption: cmd.Options.Deployment, Locale: "US"}, PropertyMapping: cmd.Options.PropertyMapping, } m := object.NewOvfManager(cmd.Client) spec, err := m.CreateImportSpec(context.TODO(), string(o), cmd.ResourcePool, cmd.Datastore, cisp) if err != nil { return nil, err } if spec.Error != nil { return nil, errors.New(spec.Error[0].LocalizedMessage) } if spec.Warning != nil { for _, w := range spec.Warning { _, _ = cmd.Log(fmt.Sprintf("Warning: %s\n", w.LocalizedMessage)) } } // TODO: ImportSpec may have unitNumber==0, but this field is optional in the wsdl // and hence omitempty in the struct tag; but unitNumber is required for certain devices. s := &spec.ImportSpec.(*types.VirtualMachineImportSpec).ConfigSpec for _, d := range s.DeviceChange { n := &d.GetVirtualDeviceConfigSpec().Device.GetVirtualDevice().UnitNumber if *n == 0 { *n = -1 } } var host *object.HostSystem if cmd.SearchFlag.IsSet() { if host, err = cmd.HostSystem(); err != nil { return nil, err } } folder, err := cmd.Folder() if err != nil { return nil, err } lease, err := cmd.ResourcePool.ImportVApp(context.TODO(), spec.ImportSpec, folder, host) if err != nil { return nil, err } info, err := lease.Wait(context.TODO()) if err != nil { return nil, err } // Build slice of items and URLs first, so that the lease updater can know // about every item that needs to be uploaded, and thereby infer progress. var items []ovfFileItem for _, device := range info.DeviceUrl { for _, item := range spec.FileItem { if device.ImportKey != item.DeviceId { continue } u, err := cmd.Client.ParseURL(device.Url) if err != nil { return nil, err } i := ovfFileItem{ url: u, item: item, ch: make(chan progress.Report), } items = append(items, i) } } u := newLeaseUpdater(cmd.Client, lease, items) defer u.Done() for _, i := range items { err = cmd.Upload(lease, i) if err != nil { return nil, err } } return &info.Entity, lease.HttpNfcLeaseComplete(context.TODO()) }
func (cmd *ovfx) Import(fpath string) (*types.ManagedObjectReference, error) { ctx := context.TODO() o, err := cmd.ReadOvf(fpath) if err != nil { return nil, err } e, err := cmd.ReadEnvelope(fpath) if err != nil { return nil, fmt.Errorf("failed to parse ovf: %s", err.Error()) } name := "Govc Virtual Appliance" if e.VirtualSystem != nil { name = e.VirtualSystem.ID if e.VirtualSystem.Name != nil { name = *e.VirtualSystem.Name } } // Override name from options if specified if cmd.Options.Name != nil { name = *cmd.Options.Name } // Override name from arguments if specified if cmd.Name != "" { name = cmd.Name } cisp := types.OvfCreateImportSpecParams{ DiskProvisioning: cmd.Options.DiskProvisioning, EntityName: name, IpAllocationPolicy: cmd.Options.IPAllocationPolicy, IpProtocol: cmd.Options.IPProtocol, OvfManagerCommonParams: types.OvfManagerCommonParams{ DeploymentOption: cmd.Options.Deployment, Locale: "US"}, PropertyMapping: cmd.Map(cmd.Options.PropertyMapping), NetworkMapping: cmd.NetworkMap(e), } m := object.NewOvfManager(cmd.Client) spec, err := m.CreateImportSpec(ctx, string(o), cmd.ResourcePool, cmd.Datastore, cisp) if err != nil { return nil, err } if spec.Error != nil { return nil, errors.New(spec.Error[0].LocalizedMessage) } if spec.Warning != nil { for _, w := range spec.Warning { _, _ = cmd.Log(fmt.Sprintf("Warning: %s\n", w.LocalizedMessage)) } } if cmd.Options.Annotation != "" { switch s := spec.ImportSpec.(type) { case *types.VirtualMachineImportSpec: s.ConfigSpec.Annotation = cmd.Options.Annotation case *types.VirtualAppImportSpec: s.VAppConfigSpec.Annotation = cmd.Options.Annotation } } var host *object.HostSystem if cmd.SearchFlag.IsSet() { if host, err = cmd.HostSystem(); err != nil { return nil, err } } folder, err := cmd.Folder() if err != nil { return nil, err } lease, err := cmd.ResourcePool.ImportVApp(ctx, spec.ImportSpec, folder, host) if err != nil { return nil, err } info, err := lease.Wait(ctx) if err != nil { return nil, err } // Build slice of items and URLs first, so that the lease updater can know // about every item that needs to be uploaded, and thereby infer progress. var items []ovfFileItem for _, device := range info.DeviceUrl { for _, item := range spec.FileItem { if device.ImportKey != item.DeviceId { continue } u, err := cmd.Client.ParseURL(device.Url) if err != nil { return nil, err } i := ovfFileItem{ url: u, item: item, ch: make(chan progress.Report), } items = append(items, i) } } u := newLeaseUpdater(cmd.Client, lease, items) defer u.Done() for _, i := range items { err = cmd.Upload(lease, i) if err != nil { return nil, err } } return &info.Entity, lease.HttpNfcLeaseComplete(ctx) }
func (cmd *ovf) Import(fpath string) error { c := cmd.Client desc, err := cmd.ReadAll(fpath) if err != nil { return err } // extract name from .ovf for use as VM name ovf := struct { VirtualSystem struct { Name string } }{} if err := xml.Unmarshal(desc, &ovf); err != nil { return fmt.Errorf("failed to parse ovf: %s", err.Error()) } cisp := types.OvfCreateImportSpecParams{ EntityName: ovf.VirtualSystem.Name, OvfManagerCommonParams: types.OvfManagerCommonParams{ Locale: "US", }, } m := object.NewOvfManager(c) spec, err := m.CreateImportSpec(context.TODO(), string(desc), cmd.ResourcePool, cmd.Datastore, cisp) if err != nil { return err } if spec.Error != nil { return errors.New(spec.Error[0].LocalizedMessage) } if spec.Warning != nil { for _, w := range spec.Warning { _, _ = cmd.Log(fmt.Sprintf("Warning: %s\n", w.LocalizedMessage)) } } // TODO: ImportSpec may have unitNumber==0, but this field is optional in the wsdl // and hence omitempty in the struct tag; but unitNumber is required for certain devices. s := &spec.ImportSpec.(*types.VirtualMachineImportSpec).ConfigSpec for _, d := range s.DeviceChange { n := &d.GetVirtualDeviceConfigSpec().Device.GetVirtualDevice().UnitNumber if *n == 0 { *n = -1 } } var host *object.HostSystem if cmd.SearchFlag.IsSet() { if host, err = cmd.HostSystem(); err != nil { return err } } folder, err := cmd.Folder() if err != nil { return err } lease, err := cmd.ResourcePool.ImportVApp(context.TODO(), spec.ImportSpec, folder, host) if err != nil { return err } info, err := lease.Wait(context.TODO()) if err != nil { return err } // Build slice of items and URLs first, so that the lease updater can know // about every item that needs to be uploaded, and thereby infer progress. var items []ovfFileItem for _, device := range info.DeviceUrl { for _, item := range spec.FileItem { if device.ImportKey != item.DeviceId { continue } u, err := c.Client.ParseURL(device.Url) if err != nil { return err } i := ovfFileItem{ url: u, item: item, ch: make(chan progress.Report), } items = append(items, i) } } u := newLeaseUpdater(cmd.Client, lease, items) defer u.Done() for _, i := range items { err = cmd.Upload(lease, i) if err != nil { return err } } return lease.HttpNfcLeaseComplete(context.TODO()) }