func LinuxDistribution() (string, error) {
	linuxDistrib := execCommand("lsb_release", "-cs")
	var out bytes.Buffer
	linuxDistrib.Stdout = &out
	if err := linuxDistrib.Run(); err != nil {
		return "", fmt.Errorf("l3afd/nf : Failed to run command with error: %w", err)
	}
	return strings.TrimSpace(string(out.Bytes())), nil
}
This method get the Linux distribution Codename. This logic works on ubuntu
Here assumption is all edge nodes are running with lsb modules.
It returns empty string in case of error
package kf
import (
	"archive/tar"
	"bytes"
	"compress/gzip"
	"container/ring"
	"context"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strconv"
	"strings"
	"sync"
	"syscall"
	"time"
	"unsafe"
	"github.com/l3af-project/l3afd/config"
	"github.com/l3af-project/l3afd/models"
	"github.com/l3af-project/l3afd/stats"
	"github.com/cilium/ebpf"
	ps "github.com/mitchellh/go-ps"
	"github.com/rs/zerolog/log"
	"golang.org/x/sys/unix"
)
var (
	execCommand           = exec.Command
	copyBufPool sync.Pool = sync.Pool{New: func() interface{} { return make([]byte, 32*1024) }}
)
const executePerm uint32 = 0111
const bpfStatus string = "RUNNING"
type BPF struct {
	Program        models.BPFProgram
	Cmd            *exec.Cmd
	FilePath       string                     
	RestartCount   int                        
	LogDir         string                     
	PrevMapName    string                     
	ProgID         int                        
	BpfMaps        map[string]BPFMap          
	MetricsBpfMaps map[string]*MetricsBPFMap  
	Ctx            context.Context
	Done           chan bool `json:"-"`
	DataCenter     string
}
func NewBpfProgram(ctx context.Context, program models.BPFProgram, logDir, dataCenter string) *BPF {
	bpf := &BPF{
		Program:        program,
		RestartCount:   0,
		Cmd:            nil,
		FilePath:       "",
		LogDir:         logDir,
		BpfMaps:        make(map[string]BPFMap, 0),
		MetricsBpfMaps: make(map[string]*MetricsBPFMap, 0),
		Ctx:            ctx,
		Done:           nil,
		DataCenter:     dataCenter,
	}
	return bpf
}
func LoadRootProgram(ifaceName string, direction string, eBPFType string, conf *config.Config) (*BPF, error) {
	log.Info().Msgf("LoadRootProgram iface %s direction %s ebpfType %s", ifaceName, direction, eBPFType)
	var rootProgBPF *BPF
	switch eBPFType {
	case models.XDPType:
		rootProgBPF = &BPF{
			Program: models.BPFProgram{
				Name:          conf.XDPRootProgramName,
				Artifact:      conf.XDPRootProgramArtifact,
				MapName:       conf.XDPRootProgramMapName,
				Version:       conf.XDPRootProgramVersion,
				IsUserProgram: conf.XDPRootProgramIsUserProgram,
				CmdStart:      conf.XDPRootProgramCommand,
				CmdStop:       conf.XDPRootProgramCommand,
				CmdStatus:     "",
				AdminStatus:   models.Enabled,
				SeqID:         0,
			},
			RestartCount: 0,
			Cmd:          nil,
			FilePath:     "",
			LogDir:       "",
			PrevMapName:  "",
		}
	case models.TCType:
		rootProgBPF = &BPF{
			Program: models.BPFProgram{
				Name:          conf.TCRootProgramName,
				Artifact:      conf.TCRootProgramArtifact,
				Version:       conf.TCRootProgramVersion,
				IsUserProgram: conf.TCRootProgramIsUserProgram,
				CmdStart:      conf.TCRootProgramCommand,
				CmdStop:       conf.TCRootProgramCommand,
				CmdStatus:     "",
				AdminStatus:   models.Enabled,
			},
			RestartCount: 0,
			Cmd:          nil,
			FilePath:     "",
			LogDir:       "",
			PrevMapName:  "",
		}
		if direction == models.IngressType {
			rootProgBPF.Program.MapName = conf.TCRootProgramIngressMapName
		} else if direction == models.EgressType {
			rootProgBPF.Program.MapName = conf.TCRootProgramEgressMapName
		}
	default:
		return nil, fmt.Errorf("unknown direction %s for root program in iface %s", direction, ifaceName)
	}
	rootProgBPF.Program.AddStartArgs(models.L3afDNFArgs{Key: "cmd", Value: models.StartType})
	rootProgBPF.Program.AddStopArgs(models.L3afDNFArgs{Key: "cmd", Value: models.StopType})
	if err := rootProgBPF.VerifyAndGetArtifacts(conf); err != nil {
		log.Error().Err(err).Msg("failed to get root artifacts")
		return nil, err
	}
	if fileExists(rootProgBPF.Program.MapName) {
		log.Warn().Msgf("previous instance of root program %s is running, stopping it ", rootProgBPF.Program.Name)
		if err := rootProgBPF.Stop(ifaceName, direction, conf.BpfChainingEnabled); err != nil {
			return nil, fmt.Errorf("failed to stop root program on iface %s name %s direction %s", ifaceName, rootProgBPF.Program.Name, direction)
		}
	}
	if err := rootProgBPF.Start(ifaceName, direction, conf.BpfChainingEnabled); err != nil {
		return nil, fmt.Errorf("failed to start root program on interface %s", ifaceName)
	}
	return rootProgBPF, nil
}