1/*
2Copyright (c) 2015 VMware, Inc. All Rights Reserved.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package logs
18
19import (
20	"context"
21	"flag"
22	"fmt"
23	"path"
24
25	"github.com/vmware/govmomi/govc/cli"
26	"github.com/vmware/govmomi/govc/flags"
27	"github.com/vmware/govmomi/object"
28	"github.com/vmware/govmomi/vim25"
29	"github.com/vmware/govmomi/vim25/soap"
30	"github.com/vmware/govmomi/vim25/types"
31)
32
33type download struct {
34	*flags.DatacenterFlag
35
36	IncludeDefault bool
37}
38
39func init() {
40	cli.Register("logs.download", &download{})
41}
42
43func (cmd *download) Register(ctx context.Context, f *flag.FlagSet) {
44	cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
45	cmd.DatacenterFlag.Register(ctx, f)
46
47	f.BoolVar(&cmd.IncludeDefault, "default", true, "Specifies if the bundle should include the default server")
48}
49
50func (cmd *download) Process(ctx context.Context) error {
51	if err := cmd.DatacenterFlag.Process(ctx); err != nil {
52		return err
53	}
54	return nil
55}
56
57func (cmd *download) Usage() string {
58	return "[PATH]..."
59}
60
61func (cmd *download) Description() string {
62	return `Generate diagnostic bundles.
63
64A diagnostic bundle includes log files and other configuration information.
65
66Use PATH to include a specific set of hosts to include.
67
68Examples:
69  govc logs.download
70  govc logs.download host-a host-b`
71}
72
73func (cmd *download) DownloadFile(c *vim25.Client, b string) error {
74	u, err := c.Client.ParseURL(b)
75	if err != nil {
76		return err
77	}
78
79	dst := path.Base(u.Path)
80	p := soap.DefaultDownload
81	if cmd.OutputFlag.TTY {
82		logger := cmd.ProgressLogger(fmt.Sprintf("Downloading %s... ", dst))
83		defer logger.Wait()
84		p.Progress = logger
85	}
86
87	return c.Client.DownloadFile(context.Background(), dst, u, &p)
88}
89
90func (cmd *download) GenerateLogBundles(m *object.DiagnosticManager, host []*object.HostSystem) ([]types.DiagnosticManagerBundleInfo, error) {
91	ctx := context.TODO()
92	logger := cmd.ProgressLogger("Generating log bundles... ")
93	defer logger.Wait()
94
95	task, err := m.GenerateLogBundles(ctx, cmd.IncludeDefault, host)
96	if err != nil {
97		return nil, err
98	}
99
100	r, err := task.WaitForResult(ctx, logger)
101	if err != nil {
102		return nil, err
103	}
104
105	return r.Result.(types.ArrayOfDiagnosticManagerBundleInfo).DiagnosticManagerBundleInfo, nil
106}
107
108func (cmd *download) Run(ctx context.Context, f *flag.FlagSet) error {
109	finder, err := cmd.Finder()
110	if err != nil {
111		return err
112	}
113
114	var host []*object.HostSystem
115
116	for _, arg := range f.Args() {
117		hs, err := finder.HostSystemList(ctx, arg)
118		if err != nil {
119			return err
120		}
121
122		host = append(host, hs...)
123	}
124
125	c, err := cmd.Client()
126	if err != nil {
127		return err
128	}
129
130	m := object.NewDiagnosticManager(c)
131
132	bundles, err := cmd.GenerateLogBundles(m, host)
133	if err != nil {
134		return err
135	}
136
137	for _, bundle := range bundles {
138		err := cmd.DownloadFile(c, bundle.Url)
139		if err != nil {
140			return err
141		}
142	}
143
144	return nil
145}
146