github.com/vmware/govmomi@v0.43.0/govc/library/sync.go (about)

     1  /*
     2  Copyright (c) 2019-2024 VMware, Inc. All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package library
    18  
    19  import (
    20  	"context"
    21  	"flag"
    22  	"fmt"
    23  
    24  	"github.com/vmware/govmomi/govc/cli"
    25  	"github.com/vmware/govmomi/govc/flags"
    26  	"github.com/vmware/govmomi/vapi/library"
    27  	"github.com/vmware/govmomi/vapi/vcenter"
    28  )
    29  
    30  type sync struct {
    31  	*flags.FolderFlag
    32  	*flags.ResourcePoolFlag
    33  
    34  	force bool
    35  	vmtx  string
    36  }
    37  
    38  func init() {
    39  	cli.Register("library.sync", &sync{})
    40  }
    41  
    42  func (cmd *sync) Register(ctx context.Context, f *flag.FlagSet) {
    43  	cmd.FolderFlag, ctx = flags.NewFolderFlag(ctx)
    44  	cmd.FolderFlag.Register(ctx, f)
    45  
    46  	cmd.ResourcePoolFlag, ctx = flags.NewResourcePoolFlag(ctx)
    47  	cmd.ResourcePoolFlag.Register(ctx, f)
    48  
    49  	f.BoolVar(&cmd.force, "f", false, "Forcefully synchronize file content")
    50  	f.StringVar(&cmd.vmtx, "vmtx", "", "Sync subscribed library to local library as VM Templates")
    51  }
    52  
    53  func (cmd *sync) Process(ctx context.Context) error {
    54  	if err := cmd.FolderFlag.Process(ctx); err != nil {
    55  		return err
    56  	}
    57  	return cmd.ResourcePoolFlag.Process(ctx)
    58  }
    59  
    60  func (cmd *sync) Description() string {
    61  	return `Sync library NAME or ITEM.
    62  
    63  Examples:
    64    govc library.sync subscribed-library
    65    govc library.sync subscribed-library/item
    66    govc library.sync -vmtx local-library subscribed-library # convert subscribed OVFs to local VMTX`
    67  }
    68  
    69  func (cmd *sync) Usage() string {
    70  	return "NAME|ITEM"
    71  }
    72  
    73  func (cmd *sync) syncVMTX(ctx context.Context, m *library.Manager, src library.Library, dst library.Library, items ...library.Item) error {
    74  	if cmd.vmtx == "" {
    75  		return nil
    76  	}
    77  
    78  	pool, err := cmd.ResourcePool()
    79  	if err != nil {
    80  		return err
    81  	}
    82  
    83  	folder, err := cmd.Folder()
    84  	if err != nil {
    85  		return err
    86  	}
    87  
    88  	l := vcenter.TemplateLibrary{
    89  		Source:      src,
    90  		Destination: dst,
    91  		Placement: vcenter.Target{
    92  			FolderID:       folder.Reference().Value,
    93  			ResourcePoolID: pool.Reference().Value,
    94  		},
    95  		Include: func(item library.Item, current *library.Item) bool {
    96  			fmt.Printf("Syncing /%s/%s to /%s/%s...", src.Name, item.Name, dst.Name, item.Name)
    97  			if current == nil {
    98  				fmt.Println()
    99  				return true
   100  			}
   101  			fmt.Println("already exists.")
   102  			return false
   103  		},
   104  	}
   105  
   106  	return vcenter.NewManager(m.Client).SyncTemplateLibrary(ctx, l, items...)
   107  }
   108  
   109  func (cmd *sync) shouldSync(l library.Library) bool {
   110  	if cmd.vmtx == "" {
   111  		return true
   112  
   113  	}
   114  	// Allow library.sync -vmtx of LOCAL or SUBSCRIBED library
   115  	return l.Type == "SUBSCRIBED"
   116  }
   117  
   118  func (cmd *sync) Run(ctx context.Context, f *flag.FlagSet) error {
   119  	if f.NArg() != 1 {
   120  		return flag.ErrHelp
   121  	}
   122  	path := f.Arg(0)
   123  
   124  	c, err := cmd.FolderFlag.RestClient()
   125  	if err != nil {
   126  		return err
   127  	}
   128  
   129  	m := library.NewManager(c)
   130  
   131  	var local library.Library
   132  	if cmd.vmtx != "" {
   133  		l, err := flags.ContentLibrary(ctx, c, cmd.vmtx)
   134  		if err != nil {
   135  			return err
   136  		}
   137  		local = *l
   138  	}
   139  
   140  	res, err := flags.ContentLibraryResult(ctx, c, "", path)
   141  	if err != nil {
   142  		return err
   143  	}
   144  
   145  	fmt.Printf("Syncing %s...\n", path)
   146  
   147  	switch t := res.GetResult().(type) {
   148  	case library.Library:
   149  		if cmd.shouldSync(t) {
   150  			if err = m.SyncLibrary(ctx, &t); err != nil {
   151  				return err
   152  			}
   153  		}
   154  		return cmd.syncVMTX(ctx, m, t, local)
   155  	case library.Item:
   156  		lib := res.GetParent().GetResult().(library.Library)
   157  		if cmd.shouldSync(lib) {
   158  			if err = m.SyncLibraryItem(ctx, &t, cmd.force); err != nil {
   159  				return err
   160  			}
   161  		}
   162  		return cmd.syncVMTX(ctx, m, lib, local, t)
   163  	default:
   164  		return fmt.Errorf("%q is a %T", res.GetPath(), t)
   165  	}
   166  }