github.com/vmware/govmomi@v0.43.0/govc/vm/console.go (about)

     1  /*
     2  Copyright (c) 2017 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 vm
    18  
    19  import (
    20  	"context"
    21  	"flag"
    22  	"fmt"
    23  	"io"
    24  	"net/url"
    25  	"os"
    26  
    27  	"github.com/vmware/govmomi/govc/cli"
    28  	"github.com/vmware/govmomi/govc/flags"
    29  	"github.com/vmware/govmomi/object"
    30  	"github.com/vmware/govmomi/session"
    31  	"github.com/vmware/govmomi/vim25/soap"
    32  	"github.com/vmware/govmomi/vim25/types"
    33  )
    34  
    35  type console struct {
    36  	*flags.VirtualMachineFlag
    37  
    38  	h5      bool
    39  	wss     bool
    40  	capture string
    41  }
    42  
    43  func init() {
    44  	cli.Register("vm.console", &console{})
    45  }
    46  
    47  func (cmd *console) Register(ctx context.Context, f *flag.FlagSet) {
    48  	cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
    49  	cmd.VirtualMachineFlag.Register(ctx, f)
    50  
    51  	f.BoolVar(&cmd.h5, "h5", false, "Generate HTML5 UI console link")
    52  	f.BoolVar(&cmd.wss, "wss", false, "Generate WebSocket console link")
    53  	f.StringVar(&cmd.capture, "capture", "", "Capture console screen shot to file")
    54  }
    55  
    56  func (cmd *console) Process(ctx context.Context) error {
    57  	if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
    58  		return err
    59  	}
    60  	return nil
    61  }
    62  
    63  func (cmd *console) Usage() string {
    64  	return "VM"
    65  }
    66  
    67  func (cmd *console) Description() string {
    68  	return `Generate console URL or screen capture for VM.
    69  
    70  One of VMRC, VMware Player, VMware Fusion or VMware Workstation must be installed to
    71  open VMRC console URLs.
    72  
    73  Examples:
    74    govc vm.console my-vm
    75    govc vm.console -capture screen.png my-vm  # screen capture
    76    govc vm.console -capture - my-vm | display # screen capture to stdout
    77    open $(govc vm.console my-vm)              # MacOSX VMRC
    78    open $(govc vm.console -h5 my-vm)          # MacOSX H5
    79    xdg-open $(govc vm.console my-vm)          # Linux VMRC
    80    xdg-open $(govc vm.console -h5 my-vm)      # Linux H5`
    81  }
    82  
    83  func (cmd *console) Run(ctx context.Context, f *flag.FlagSet) error {
    84  	vms, err := cmd.VirtualMachines(f.Args())
    85  	if err != nil {
    86  		return err
    87  	}
    88  
    89  	if len(vms) != 1 {
    90  		return flag.ErrHelp
    91  	}
    92  
    93  	vm := vms[0]
    94  
    95  	state, err := vm.PowerState(ctx)
    96  	if err != nil {
    97  		return err
    98  	}
    99  
   100  	if (cmd.capture != "" || cmd.wss) && state != types.VirtualMachinePowerStatePoweredOn {
   101  		return fmt.Errorf("vm is not powered on (%s)", state)
   102  	}
   103  
   104  	c := vm.Client()
   105  
   106  	u := c.URL()
   107  
   108  	if cmd.capture != "" {
   109  		u.Path = "/screen"
   110  		query := url.Values{"id": []string{vm.Reference().Value}}
   111  		u.RawQuery = query.Encode()
   112  
   113  		param := soap.DefaultDownload
   114  
   115  		if cmd.capture == "-" {
   116  			w, _, derr := c.Download(ctx, u, &param)
   117  			if derr != nil {
   118  				return derr
   119  			}
   120  
   121  			_, err = io.Copy(os.Stdout, w)
   122  			if err != nil {
   123  				return err
   124  			}
   125  
   126  			return w.Close()
   127  		}
   128  
   129  		return c.DownloadFile(ctx, cmd.capture, u, &param)
   130  	}
   131  
   132  	if cmd.wss {
   133  		ticket, err := vm.AcquireTicket(ctx, string(types.VirtualMachineTicketTypeWebmks))
   134  		if err != nil {
   135  			return err
   136  		}
   137  
   138  		link := fmt.Sprintf("wss://%s:%d/ticket/%s", ticket.Host, ticket.Port, ticket.Ticket)
   139  		fmt.Fprintln(cmd.Out, link)
   140  		return nil
   141  	}
   142  
   143  	m := session.NewManager(c)
   144  	ticket, err := m.AcquireCloneTicket(ctx)
   145  	if err != nil {
   146  		return err
   147  	}
   148  
   149  	var link string
   150  
   151  	if cmd.h5 {
   152  		m := object.NewOptionManager(c, *c.ServiceContent.Setting)
   153  
   154  		opt, err := m.Query(ctx, "VirtualCenter.FQDN")
   155  		if err != nil {
   156  			return err
   157  		}
   158  
   159  		fqdn := opt[0].GetOptionValue().Value.(string)
   160  
   161  		var info object.HostCertificateInfo
   162  		err = info.FromURL(u, nil)
   163  		if err != nil {
   164  			return err
   165  		}
   166  
   167  		u.Path = "/ui/webconsole.html"
   168  
   169  		u.RawQuery = url.Values{
   170  			"vmId":          []string{vm.Reference().Value},
   171  			"vmName":        []string{vm.Name()},
   172  			"serverGuid":    []string{c.ServiceContent.About.InstanceUuid},
   173  			"host":          []string{fqdn},
   174  			"sessionTicket": []string{ticket},
   175  			"thumbprint":    []string{info.ThumbprintSHA1},
   176  		}.Encode()
   177  
   178  		link = u.String()
   179  	} else {
   180  		link = fmt.Sprintf("vmrc://clone:%s@%s/?moid=%s", ticket, u.Hostname(), vm.Reference().Value)
   181  	}
   182  
   183  	fmt.Fprintln(cmd.Out, link)
   184  
   185  	return nil
   186  }