From a64b1fa47336ddf8cfb8b50eb845fec427702c70 Mon Sep 17 00:00:00 2001 From: Hang Yan Date: Wed, 9 Aug 2023 18:07:18 +0800 Subject: [PATCH] update Signed-off-by: Hang Yan --- pkg/apis/system/v1beta1/types.go | 1 + .../registry/system/samplingpacket/agent.go | 101 ++++++++++++++++++ .../registry/system/samplingpacket/rest.go | 11 +- 3 files changed, 108 insertions(+), 5 deletions(-) create mode 100644 pkg/apiserver/registry/system/samplingpacket/agent.go diff --git a/pkg/apis/system/v1beta1/types.go b/pkg/apis/system/v1beta1/types.go index 988f9c86af2..8f6300cced1 100644 --- a/pkg/apis/system/v1beta1/types.go +++ b/pkg/apis/system/v1beta1/types.go @@ -57,6 +57,7 @@ type CapturedPacket struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` + Sum string `json:"sum,omitempty"` Status PacketStatus `json:"status,omitempty"` Size uint32 `json:"size,omitempty"` Filepath string `json:"-"` diff --git a/pkg/apiserver/registry/system/samplingpacket/agent.go b/pkg/apiserver/registry/system/samplingpacket/agent.go new file mode 100644 index 00000000000..411ee0b7da7 --- /dev/null +++ b/pkg/apiserver/registry/system/samplingpacket/agent.go @@ -0,0 +1,101 @@ +package samplingpacket + +import ( + "antrea.io/antrea/pkg/util/logdir" + "bufio" + "fmt" + "github.com/spf13/afero" + "io" + "k8s.io/utils/exec" + "os" + "path" + "strconv" + "strings" + "time" +) + +type agentDumper struct { + fs afero.Fs + executor exec.Interface + +} + +func NewAgentDumper(fs afero.Fs, executor exec.Interface) *agentDumper { + return &agentDumper{ + fs: fs, + executor: executor, + } +} + +func (d *agentDumper) DumpLog(basedir string) error { + logDir := logdir.GetLogDir() + return directoryCopy(d.fs, path.Join(basedir, "logs", "controller"), logDir, "antrea-controller", timestampFilter(d.since)) +} + +// directoryCopy copies files under the srcDir to the targetDir. Only files whose name matches +// the prefixFilter will be copied. If prefixFiler is "", no filter is performed. At the same time, if the timeFilter is set, +// only files whose modTime is later than the timeFilter will be copied. If a file contains both older logs and matched logs, only +// the matched logs will be copied. Copied files will be located under the same relative path. +func directoryCopy(fs afero.Fs, targetDir string, srcDir string, prefixFilter string, timeFilter *time.Time) error { + err := fs.MkdirAll(targetDir, os.ModePerm) + if err != nil { + return fmt.Errorf("error when creating target dir: %w", err) + } + return afero.Walk(fs, srcDir, func(filePath string, info os.FileInfo, err error) error { + if err != nil { + return nil + } + if !info.Mode().IsRegular() { + return nil + } + if prefixFilter != "" && !strings.HasPrefix(info.Name(), prefixFilter) { + return nil + } + + if timeFilter != nil && info.ModTime().Before(*timeFilter) { + return nil + } + + targetPath := path.Join(targetDir, info.Name()) + targetFile, err := fs.Create(targetPath) + if err != nil { + return fmt.Errorf("error when creating target file %s: %w", targetPath, err) + } + defer targetFile.Close() + + srcFile, err := fs.Open(filePath) + if err != nil { + return fmt.Errorf("error when opening source file %s: %w", filePath, err) + } + defer srcFile.Close() + + startTime, err := parseTimeFromFileName(info.Name()) + if timeFilter != nil { + // if name contains timestamp, use it to find the first matched file. If not, such as ovs log file, + // just parse the log file (usually there is only one log file for each component) + if err == nil && startTime.Before(*timeFilter) || err != nil { + data := "" + scanner := bufio.NewScanner(srcFile) + for scanner.Scan() { + // the size limit of single log line is 64k. marked it as known issue and fix it if + // error occurs + line := scanner.Text() + if data != "" { + data += line + "\n" + } else { + ts, err := parseTimeFromLogLine(line, strconv.Itoa(timeFilter.Year()), prefixFilter) + if err == nil { + if !ts.Before(*timeFilter) { + data += line + "\n" + } + } + } + } + _, err = targetFile.WriteString(data) + return err + } + } + _, err = io.Copy(targetFile, srcFile) + return err + }) +} \ No newline at end of file diff --git a/pkg/apiserver/registry/system/samplingpacket/rest.go b/pkg/apiserver/registry/system/samplingpacket/rest.go index 7c057119ef5..0de03adb907 100644 --- a/pkg/apiserver/registry/system/samplingpacket/rest.go +++ b/pkg/apiserver/registry/system/samplingpacket/rest.go @@ -194,8 +194,9 @@ func (r *samplingPacketsREST) NamespaceScoped() bool { return false } -func (r *samplingPacketsREST) collect(ctx context.Context, dumpers ...func(string) error) (*systemv1beta1.SupportBundle, error) { - basedir, err := afero.TempDir(defaultFS, "", "bundle_tmp_") +func (r *samplingPacketsREST) collect(ctx context.Context, dumpers ...func(string) error) (*systemv1beta1.CapturedPacket, error) { + // TODO: copy dir or refactor this + basedir, err := afero.TempDir(defaultFS, "", "packets_") if err != nil { return nil, fmt.Errorf("error when creating tempdir: %w", err) } @@ -205,7 +206,7 @@ func (r *samplingPacketsREST) collect(ctx context.Context, dumpers ...func(strin return nil, err } } - outputFile, err := afero.TempFile(defaultFS, "", "bundle_*.tar.gz") + outputFile, err := afero.TempFile(defaultFS, "", "packets_*.tar.gz") if err != nil { return nil, fmt.Errorf("error when creating output tarfile: %w", err) } @@ -228,13 +229,13 @@ func (r *samplingPacketsREST) collect(ctx context.Context, dumpers ...func(strin } creationTime := metav1.Now() deletionTime := metav1.NewTime(creationTime.Add(bundleExpireDuration)) - return &systemv1beta1.SupportBundle{ + return &systemv1beta1.CapturedPacket{ ObjectMeta: metav1.ObjectMeta{ Name: r.mode, CreationTimestamp: creationTime, DeletionTimestamp: &deletionTime, }, - Status: systemv1beta1.SupportBundleStatusCollected, + Status: systemv1beta1.SamplingPacketStatusCollected, Sum: fmt.Sprintf("%x", hashSum), Size: uint32(fileSize), Filepath: outputFile.Name(),