github.com/vmware/govmomi@v0.37.1/govc/importx/spec.go (about)

     1  /*
     2  Copyright (c) 2015-2023 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 importx
    18  
    19  import (
    20  	"context"
    21  	"flag"
    22  	"fmt"
    23  	"io"
    24  	"path"
    25  	"strings"
    26  
    27  	"github.com/vmware/govmomi/govc/cli"
    28  	"github.com/vmware/govmomi/govc/flags"
    29  	"github.com/vmware/govmomi/ovf"
    30  	"github.com/vmware/govmomi/vim25/types"
    31  )
    32  
    33  var (
    34  	allDiskProvisioningOptions = []string{
    35  		string(types.OvfCreateImportSpecParamsDiskProvisioningTypeFlat),
    36  		string(types.OvfCreateImportSpecParamsDiskProvisioningTypeMonolithicSparse),
    37  		string(types.OvfCreateImportSpecParamsDiskProvisioningTypeMonolithicFlat),
    38  		string(types.OvfCreateImportSpecParamsDiskProvisioningTypeTwoGbMaxExtentSparse),
    39  		string(types.OvfCreateImportSpecParamsDiskProvisioningTypeTwoGbMaxExtentFlat),
    40  		string(types.OvfCreateImportSpecParamsDiskProvisioningTypeThin),
    41  		string(types.OvfCreateImportSpecParamsDiskProvisioningTypeThick),
    42  		string(types.OvfCreateImportSpecParamsDiskProvisioningTypeSeSparse),
    43  		string(types.OvfCreateImportSpecParamsDiskProvisioningTypeEagerZeroedThick),
    44  		string(types.OvfCreateImportSpecParamsDiskProvisioningTypeSparse),
    45  	}
    46  	allIPAllocationPolicyOptions = []string{
    47  		string(types.VAppIPAssignmentInfoIpAllocationPolicyDhcpPolicy),
    48  		string(types.VAppIPAssignmentInfoIpAllocationPolicyTransientPolicy),
    49  		string(types.VAppIPAssignmentInfoIpAllocationPolicyFixedPolicy),
    50  		string(types.VAppIPAssignmentInfoIpAllocationPolicyFixedAllocatedPolicy),
    51  	}
    52  	allIPProtocolOptions = []string{
    53  		string(types.VAppIPAssignmentInfoProtocolsIPv4),
    54  		string(types.VAppIPAssignmentInfoProtocolsIPv6),
    55  	}
    56  )
    57  
    58  type spec struct {
    59  	*ArchiveFlag
    60  	*flags.ClientFlag
    61  	*flags.OutputFlag
    62  
    63  	hidden bool
    64  }
    65  
    66  func init() {
    67  	cli.Register("import.spec", &spec{})
    68  }
    69  
    70  func (cmd *spec) Register(ctx context.Context, f *flag.FlagSet) {
    71  	cmd.ArchiveFlag, ctx = newArchiveFlag(ctx)
    72  	cmd.ArchiveFlag.Register(ctx, f)
    73  	cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
    74  	cmd.ClientFlag.Register(ctx, f)
    75  
    76  	cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
    77  	cmd.OutputFlag.Register(ctx, f)
    78  
    79  	f.BoolVar(&cmd.hidden, "hidden", false, "Enable hidden properties")
    80  }
    81  
    82  func (cmd *spec) Process(ctx context.Context) error {
    83  	if err := cmd.ArchiveFlag.Process(ctx); err != nil {
    84  		return err
    85  	}
    86  	if err := cmd.ClientFlag.Process(ctx); err != nil {
    87  		return err
    88  	}
    89  	return cmd.OutputFlag.Process(ctx)
    90  }
    91  
    92  func (cmd *spec) Usage() string {
    93  	return "PATH_TO_OVF_OR_OVA"
    94  }
    95  
    96  func (cmd *spec) Run(ctx context.Context, f *flag.FlagSet) error {
    97  	fpath := ""
    98  	args := f.Args()
    99  	if len(args) == 1 {
   100  		fpath = f.Arg(0)
   101  	}
   102  
   103  	if len(fpath) > 0 {
   104  		switch path.Ext(fpath) {
   105  		case ".ovf":
   106  			cmd.Archive = &FileArchive{Path: fpath}
   107  		case "", ".ova":
   108  			cmd.Archive = &TapeArchive{Path: fpath}
   109  			fpath = "*.ovf"
   110  		default:
   111  			return fmt.Errorf("invalid file extension %s", path.Ext(fpath))
   112  		}
   113  
   114  		if isRemotePath(f.Arg(0)) {
   115  			client, err := cmd.Client()
   116  			if err != nil {
   117  				return err
   118  			}
   119  			switch archive := cmd.Archive.(type) {
   120  			case *FileArchive:
   121  				archive.Client = client
   122  			case *TapeArchive:
   123  				archive.Client = client
   124  			}
   125  		}
   126  	}
   127  
   128  	env, err := cmd.Spec(fpath)
   129  	if err != nil {
   130  		return err
   131  	}
   132  
   133  	if !cmd.All() {
   134  		cmd.JSON = true
   135  	}
   136  	return cmd.WriteResult(&specResult{env})
   137  }
   138  
   139  type specResult struct {
   140  	*Options
   141  }
   142  
   143  func (*specResult) Write(w io.Writer) error {
   144  	return nil
   145  }
   146  
   147  func (cmd *spec) Map(e *ovf.Envelope) (res []Property) {
   148  	if e == nil || e.VirtualSystem == nil {
   149  		return nil
   150  	}
   151  
   152  	for _, p := range e.VirtualSystem.Product {
   153  		for i, v := range p.Property {
   154  			if v.UserConfigurable == nil {
   155  				continue
   156  			}
   157  			if !*v.UserConfigurable && !cmd.hidden {
   158  				continue
   159  			}
   160  
   161  			d := ""
   162  			if v.Default != nil {
   163  				d = *v.Default
   164  			}
   165  
   166  			// vSphere only accept True/False as boolean values for some reason
   167  			if v.Type == "boolean" {
   168  				d = strings.Title(d)
   169  			}
   170  
   171  			np := Property{KeyValue: KeyValue{Key: p.Key(v), Value: d}}
   172  
   173  			if cmd.Verbose() {
   174  				np.Spec = &p.Property[i]
   175  			}
   176  
   177  			res = append(res, np)
   178  		}
   179  	}
   180  
   181  	return
   182  }
   183  
   184  func (cmd *spec) Spec(fpath string) (*Options, error) {
   185  	e := &ovf.Envelope{}
   186  	if fpath != "" {
   187  		d, err := cmd.ReadOvf(fpath)
   188  		if err != nil {
   189  			return nil, err
   190  		}
   191  
   192  		if e, err = cmd.ReadEnvelope(d); err != nil {
   193  			return nil, err
   194  		}
   195  	}
   196  
   197  	var deploymentOptions []string
   198  	if e.DeploymentOption != nil && e.DeploymentOption.Configuration != nil {
   199  		// add default first
   200  		for _, c := range e.DeploymentOption.Configuration {
   201  			if c.Default != nil && *c.Default {
   202  				deploymentOptions = append(deploymentOptions, c.ID)
   203  			}
   204  		}
   205  
   206  		for _, c := range e.DeploymentOption.Configuration {
   207  			if c.Default == nil || !*c.Default {
   208  				deploymentOptions = append(deploymentOptions, c.ID)
   209  			}
   210  		}
   211  	}
   212  
   213  	o := Options{
   214  		DiskProvisioning:   allDiskProvisioningOptions[0],
   215  		IPAllocationPolicy: allIPAllocationPolicyOptions[0],
   216  		IPProtocol:         allIPProtocolOptions[0],
   217  		MarkAsTemplate:     false,
   218  		PowerOn:            false,
   219  		WaitForIP:          false,
   220  		InjectOvfEnv:       false,
   221  		PropertyMapping:    cmd.Map(e),
   222  	}
   223  
   224  	if deploymentOptions != nil {
   225  		o.Deployment = deploymentOptions[0]
   226  	}
   227  
   228  	if e.VirtualSystem != nil && e.VirtualSystem.Annotation != nil {
   229  		for _, a := range e.VirtualSystem.Annotation {
   230  			o.Annotation += a.Annotation
   231  		}
   232  	}
   233  
   234  	if e.Network != nil {
   235  		for _, net := range e.Network.Networks {
   236  			o.NetworkMapping = append(o.NetworkMapping, Network{net.Name, ""})
   237  		}
   238  	}
   239  
   240  	if cmd.Verbose() {
   241  		if deploymentOptions != nil {
   242  			o.AllDeploymentOptions = deploymentOptions
   243  		}
   244  		o.AllDiskProvisioningOptions = allDiskProvisioningOptions
   245  		o.AllIPAllocationPolicyOptions = allIPAllocationPolicyOptions
   246  		o.AllIPProtocolOptions = allIPProtocolOptions
   247  	}
   248  
   249  	return &o, nil
   250  }