github.com/vmware/govmomi@v0.51.0/cli/library/sync.go (about) 1 // © Broadcom. All Rights Reserved. 2 // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. 3 // SPDX-License-Identifier: Apache-2.0 4 5 package library 6 7 import ( 8 "context" 9 "flag" 10 "fmt" 11 12 "github.com/vmware/govmomi/cli" 13 "github.com/vmware/govmomi/cli/flags" 14 "github.com/vmware/govmomi/vapi/library" 15 "github.com/vmware/govmomi/vapi/vcenter" 16 ) 17 18 type sync struct { 19 *flags.FolderFlag 20 *flags.ResourcePoolFlag 21 22 force bool 23 vmtx string 24 } 25 26 func init() { 27 cli.Register("library.sync", &sync{}) 28 } 29 30 func (cmd *sync) Register(ctx context.Context, f *flag.FlagSet) { 31 cmd.FolderFlag, ctx = flags.NewFolderFlag(ctx) 32 cmd.FolderFlag.Register(ctx, f) 33 34 cmd.ResourcePoolFlag, ctx = flags.NewResourcePoolFlag(ctx) 35 cmd.ResourcePoolFlag.Register(ctx, f) 36 37 f.BoolVar(&cmd.force, "f", false, "Forcefully synchronize file content") 38 f.StringVar(&cmd.vmtx, "vmtx", "", "Sync subscribed library to local library as VM Templates") 39 } 40 41 func (cmd *sync) Process(ctx context.Context) error { 42 if err := cmd.FolderFlag.Process(ctx); err != nil { 43 return err 44 } 45 return cmd.ResourcePoolFlag.Process(ctx) 46 } 47 48 func (cmd *sync) Description() string { 49 return `Sync library NAME or ITEM. 50 51 Examples: 52 govc library.sync subscribed-library 53 govc library.sync subscribed-library/item 54 govc library.sync -vmtx local-library subscribed-library # convert subscribed OVFs to local VMTX` 55 } 56 57 func (cmd *sync) Usage() string { 58 return "NAME|ITEM" 59 } 60 61 func (cmd *sync) syncVMTX(ctx context.Context, m *library.Manager, src library.Library, dst library.Library, items ...library.Item) error { 62 if cmd.vmtx == "" { 63 return nil 64 } 65 66 pool, err := cmd.ResourcePool() 67 if err != nil { 68 return err 69 } 70 71 folder, err := cmd.Folder() 72 if err != nil { 73 return err 74 } 75 76 l := vcenter.TemplateLibrary{ 77 Source: src, 78 Destination: dst, 79 Placement: vcenter.Target{ 80 FolderID: folder.Reference().Value, 81 ResourcePoolID: pool.Reference().Value, 82 }, 83 Include: func(item library.Item, current *library.Item) bool { 84 fmt.Printf("Syncing /%s/%s to /%s/%s...", src.Name, item.Name, dst.Name, item.Name) 85 if current == nil { 86 fmt.Println() 87 return true 88 } 89 fmt.Println("already exists.") 90 return false 91 }, 92 } 93 94 return vcenter.NewManager(m.Client).SyncTemplateLibrary(ctx, l, items...) 95 } 96 97 func (cmd *sync) shouldSync(l library.Library) bool { 98 if cmd.vmtx == "" { 99 return true 100 101 } 102 // Allow library.sync -vmtx of LOCAL or SUBSCRIBED library 103 return l.Type == "SUBSCRIBED" 104 } 105 106 func (cmd *sync) Run(ctx context.Context, f *flag.FlagSet) error { 107 if f.NArg() != 1 { 108 return flag.ErrHelp 109 } 110 path := f.Arg(0) 111 112 c, err := cmd.FolderFlag.RestClient() 113 if err != nil { 114 return err 115 } 116 117 m := library.NewManager(c) 118 119 var local library.Library 120 if cmd.vmtx != "" { 121 l, err := flags.ContentLibrary(ctx, c, cmd.vmtx) 122 if err != nil { 123 return err 124 } 125 local = *l 126 } 127 128 res, err := flags.ContentLibraryResult(ctx, c, "", path) 129 if err != nil { 130 return err 131 } 132 133 fmt.Printf("Syncing %s...\n", path) 134 135 switch t := res.GetResult().(type) { 136 case library.Library: 137 if cmd.shouldSync(t) { 138 if err = m.SyncLibrary(ctx, &t); err != nil { 139 return err 140 } 141 } 142 return cmd.syncVMTX(ctx, m, t, local) 143 case library.Item: 144 lib := res.GetParent().GetResult().(library.Library) 145 if cmd.shouldSync(lib) { 146 if err = m.SyncLibraryItem(ctx, &t, cmd.force); err != nil { 147 return err 148 } 149 } 150 return cmd.syncVMTX(ctx, m, lib, local, t) 151 default: 152 return fmt.Errorf("%q is a %T", res.GetPath(), t) 153 } 154 }