Skip to content

Commit

Permalink
Implement supportbundle command on Windows node
Browse files Browse the repository at this point in the history
- Use internal queriers instead of antctl to
  retrieve networkpolicies and agentinfo.
- Change default output dir name because Windows
  does not support ':' in filename.

Signed-off-by: Weiqiang TANG <weiqiangt@vmware.com>
  • Loading branch information
weiqiangt committed Jun 11, 2020
1 parent 07d2484 commit bbf1115
Show file tree
Hide file tree
Showing 9 changed files with 221 additions and 167 deletions.
6 changes: 3 additions & 3 deletions pkg/agent/apiserver/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,10 @@ func installHandlers(aq agentquerier.AgentQuerier, npq querier.AgentNetworkPolic
s.Handler.NonGoRestfulMux.HandleFunc("/ovstracing", ovstracing.HandleFunc(aq))
}

func installAPIGroup(s *genericapiserver.GenericAPIServer, aq agentquerier.AgentQuerier) error {
func installAPIGroup(s *genericapiserver.GenericAPIServer, aq agentquerier.AgentQuerier, npq querier.AgentNetworkPolicyInfoQuerier) error {
systemGroup := genericapiserver.NewDefaultAPIGroupInfo(systemv1beta1.GroupName, scheme, metav1.ParameterCodec, codecs)
systemStorage := map[string]rest.Storage{}
supportBundleStorage := supportbundle.NewStorage("agent", ovsctl.NewClient(aq.GetNodeConfig().OVSBridge))
supportBundleStorage := supportbundle.NewAgentStorage(ovsctl.NewClient(aq.GetNodeConfig().OVSBridge), aq, npq)
systemStorage["supportbundles"] = supportBundleStorage.SupportBundle
systemStorage["supportbundles/download"] = supportBundleStorage.Download
systemGroup.VersionedResourcesStorageMap["v1beta1"] = systemStorage
Expand All @@ -98,7 +98,7 @@ func New(aq agentquerier.AgentQuerier, npq querier.AgentNetworkPolicyInfoQuerier
if err != nil {
return nil, err
}
if err := installAPIGroup(s, aq); err != nil {
if err := installAPIGroup(s, aq, npq); err != nil {
return nil, err
}
installHandlers(aq, npq, s)
Expand Down
2 changes: 1 addition & 1 deletion pkg/antctl/raw/supportbundle/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const (
barTmpl pb.ProgressBarTemplate = `{{string . "prefix"}}{{bar . }} {{percent . }} {{rtime . "ETA %s"}}` // Example: 'Prefix[-->______] 20%'
requestRate = 50
requestBurst = 100
timeFormat = "20060102T150405Z0700"
)

// Command is the support bundle command implementation.
Expand Down Expand Up @@ -428,7 +429,6 @@ func getClusterInfo(k8sClient kubernetes.Interface) (io.Reader, error) {
func controllerRemoteRunE(cmd *cobra.Command, args []string) error {
if option.dir == "" {
cwd, _ := os.Getwd()
const timeFormat = "Jan02-15-04-05"
option.dir = filepath.Join(cwd, "support-bundles_"+time.Now().Format(timeFormat))
}
dir, err := filepath.Abs(option.dir)
Expand Down
4 changes: 2 additions & 2 deletions pkg/apiserver/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
package apiserver

import (
"github.com/vmware-tanzu/antrea/pkg/apiserver/certificate"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
Expand All @@ -29,6 +28,7 @@ import (
networkinginstall "github.com/vmware-tanzu/antrea/pkg/apis/networking/install"
systeminstall "github.com/vmware-tanzu/antrea/pkg/apis/system/install"
system "github.com/vmware-tanzu/antrea/pkg/apis/system/v1beta1"
"github.com/vmware-tanzu/antrea/pkg/apiserver/certificate"
"github.com/vmware-tanzu/antrea/pkg/apiserver/registry/networkpolicy/addressgroup"
"github.com/vmware-tanzu/antrea/pkg/apiserver/registry/networkpolicy/appliedtogroup"
"github.com/vmware-tanzu/antrea/pkg/apiserver/registry/networkpolicy/networkpolicy"
Expand Down Expand Up @@ -132,7 +132,7 @@ func (c completedConfig) New() (*APIServer, error) {
systemGroup := genericapiserver.NewDefaultAPIGroupInfo(system.GroupName, Scheme, metav1.ParameterCodec, Codecs)
systemStorage := map[string]rest.Storage{}
systemStorage["controllerinfos"] = controllerinfo.NewREST(c.extraConfig.controllerQuerier)
bundleStorage := supportbundle.NewStorage("controller", nil)
bundleStorage := supportbundle.NewControllerStorage()
systemStorage["supportbundles"] = bundleStorage.SupportBundle
systemStorage["supportbundles/download"] = bundleStorage.Download
systemGroup.VersionedResourcesStorageMap["v1beta1"] = systemStorage
Expand Down
46 changes: 36 additions & 10 deletions pkg/apiserver/registry/system/supportbundle/rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,31 +37,54 @@ import (
"k8s.io/klog"
"k8s.io/utils/exec"

agentquerier "github.com/vmware-tanzu/antrea/pkg/agent/querier"
systemv1beta1 "github.com/vmware-tanzu/antrea/pkg/apis/system/v1beta1"
"github.com/vmware-tanzu/antrea/pkg/ovs/ovsctl"
"github.com/vmware-tanzu/antrea/pkg/querier"
"github.com/vmware-tanzu/antrea/pkg/support"
)

const bundleExpireDuration = time.Hour
const (
bundleExpireDuration = time.Hour
modeController = "controller"
modeAgent = "agent"
)

var (
defaultFS = afero.NewOsFs()
defaultExecutor = exec.New()
)

// NewStorage creates a support bundle storage. The mode should be either agent
// or controller. If the mode is agent, the client argument should not be nil.
func NewStorage(mode string, client ovsctl.OVSCtlClient) Storage {
// NewControllerStorage creates a support bundle storage for working on antrea controller.
func NewControllerStorage() Storage {
bundle := &supportBundleREST{
mode: mode,
mode: modeController,
cache: &systemv1beta1.SupportBundle{
ObjectMeta: metav1.ObjectMeta{Name: modeController},
Status: systemv1beta1.SupportBundleStatusNone,
},
}
return Storage{
Mode: modeController,
SupportBundle: bundle,
Download: &downloadREST{supportBundle: bundle},
}
}

// NewAgentStorage creates a support bundle storage for working on antrea agent.
func NewAgentStorage(client ovsctl.OVSCtlClient, aq agentquerier.AgentQuerier, npq querier.AgentNetworkPolicyInfoQuerier) Storage {
bundle := &supportBundleREST{
mode: modeAgent,
ovsCtlClient: client,
aq: aq,
npq: npq,
cache: &systemv1beta1.SupportBundle{
ObjectMeta: metav1.ObjectMeta{Name: mode},
ObjectMeta: metav1.ObjectMeta{Name: modeAgent},
Status: systemv1beta1.SupportBundleStatusNone,
},
}
return Storage{
Mode: mode,
Mode: modeAgent,
SupportBundle: bundle,
Download: &downloadREST{supportBundle: bundle},
}
Expand All @@ -88,7 +111,10 @@ type supportBundleREST struct {
statusLocker sync.RWMutex
cancelFunc context.CancelFunc
cache *systemv1beta1.SupportBundle

ovsCtlClient ovsctl.OVSCtlClient
aq agentquerier.AgentQuerier
npq querier.AgentNetworkPolicyInfoQuerier
}

// Create triggers a bundle generation. It only allows resource creation when
Expand All @@ -115,9 +141,9 @@ func (r *supportBundleREST) Create(ctx context.Context, obj runtime.Object, _ re
go func() {
var err error
var b *systemv1beta1.SupportBundle
if r.mode == "agent" {
if r.mode == modeAgent {
b, err = r.collectAgent(ctx)
} else if r.mode == "controller" {
} else if r.mode == modeController {
b, err = r.collectController(ctx)
}
func() {
Expand Down Expand Up @@ -225,7 +251,7 @@ func (r *supportBundleREST) collect(ctx context.Context, dumpers ...func(string)
}

func (r *supportBundleREST) collectAgent(ctx context.Context) (*systemv1beta1.SupportBundle, error) {
dumper := support.NewAgentDumper(defaultFS, defaultExecutor, r.ovsCtlClient)
dumper := support.NewAgentDumper(defaultFS, defaultExecutor, r.ovsCtlClient, r.aq, r.npq)
return r.collect(
ctx,
dumper.DumpLog,
Expand Down
2 changes: 1 addition & 1 deletion pkg/apiserver/registry/system/supportbundle/rest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func TestClean(t *testing.T) {
require.NoError(t, err)
defer defaultFS.Remove(f.Name())
require.NoError(t, f.Close())
storage := NewStorage("controller", nil)
storage := NewControllerStorage()
ctx, cancelFunc := context.WithCancel(context.Background())
if tc.needCancel {
cancelFunc()
Expand Down
85 changes: 84 additions & 1 deletion pkg/support/dump.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package support

import (
"encoding/json"
"flag"
"fmt"
"io"
"os"
Expand All @@ -10,8 +12,16 @@ import (

"github.com/spf13/afero"
"k8s.io/utils/exec"

agentquerier "github.com/vmware-tanzu/antrea/pkg/agent/querier"
clusterinformationv1beta1 "github.com/vmware-tanzu/antrea/pkg/apis/clusterinformation/v1beta1"
controllerquerier "github.com/vmware-tanzu/antrea/pkg/controller/querier"
"github.com/vmware-tanzu/antrea/pkg/ovs/ovsctl"
"github.com/vmware-tanzu/antrea/pkg/querier"
)

const antreaLinuxWellKnownLogDir = "/var/log/antrea"

// AgentDumper is the interface for dumping runtime information of the agent. Its
// functions should only work in an agent Pod or a Windows Node which has an agent
// installed.
Expand Down Expand Up @@ -106,6 +116,7 @@ func fileCopy(fs afero.Fs, targetDir string, srcDir string, prefixFilter string)
type controllerDumper struct {
fs afero.Fs
executor exec.Interface
cq controllerquerier.ControllerQuerier
}

func (d *controllerDumper) DumpControllerInfo(basedir string) error {
Expand All @@ -117,7 +128,16 @@ func (d *controllerDumper) DumpNetworkPolicyResources(basedir string) error {
}

func (d *controllerDumper) DumpLog(basedir string) error {
return fileCopy(d.fs, path.Join(basedir, "logs", "controller"), "/var/log/antrea", "antrea-controller")
logDirFlag := flag.CommandLine.Lookup("log_dir")
var logDir string
if logDirFlag == nil {
logDir = antreaLinuxWellKnownLogDir
} else if len(logDirFlag.Value.String()) == 0 {
logDir = logDirFlag.DefValue
} else {
logDir = logDirFlag.Value.String()
}
return fileCopy(d.fs, path.Join(basedir, "logs", "controller"), logDir, "antrea-controller")
}

func NewControllerDumper(fs afero.Fs, executor exec.Interface) ControllerDumper {
Expand All @@ -126,3 +146,66 @@ func NewControllerDumper(fs afero.Fs, executor exec.Interface) ControllerDumper
executor: executor,
}
}

type agentDumper struct {
fs afero.Fs
executor exec.Interface
ovsCtlClient ovsctl.OVSCtlClient
aq agentquerier.AgentQuerier
npq querier.AgentNetworkPolicyInfoQuerier
}

func (d *agentDumper) DumpAgentInfo(basedir string) error {
ci := new(clusterinformationv1beta1.AntreaAgentInfo)
d.aq.GetAgentInfo(ci, false)
f, err := d.fs.Create(filepath.Join(basedir, "agentinfo"))
if err != nil {
return err
}
defer f.Close()
encoder := json.NewEncoder(f)
encoder.SetIndent("", " ")
return encoder.Encode(ci)
}

func (d *agentDumper) DumpNetworkPolicyResources(basedir string) error {
dump := func(o interface{}, name string) error {
f, err := d.fs.Create(filepath.Join(basedir, "agentinfo"))
if err != nil {
return err
}
defer f.Close()
encoder := json.NewEncoder(f)
encoder.SetIndent("", " ")
return encoder.Encode(o)
}
if err := dump(d.npq.GetAddressGroups(), "addressgroups"); err != nil {
return err
}
if err := dump(d.npq.GetNetworkPolicies(""), "networkpolicies"); err != nil {
return err
}
return dump(d.npq.GetAppliedToGroups(), "appliedtogroups")
}

func (d *agentDumper) DumpFlows(basedir string) error {
flows, err := d.ovsCtlClient.DumpFlows()
if err != nil {
return fmt.Errorf("error when dumping flows: %w", err)
}
err = afero.WriteFile(d.fs, filepath.Join(basedir, "flows"), []byte(strings.Join(flows, "\n")), 0644)
if err != nil {
return fmt.Errorf("error when creating flows output file: %w", err)
}
return nil
}

func NewAgentDumper(fs afero.Fs, executor exec.Interface, ovsCtlClient ovsctl.OVSCtlClient, aq agentquerier.AgentQuerier, npq querier.AgentNetworkPolicyInfoQuerier) AgentDumper {
return &agentDumper{
fs: fs,
executor: executor,
ovsCtlClient: ovsCtlClient,
aq: aq,
npq: npq,
}
}
Loading

0 comments on commit bbf1115

Please sign in to comment.