github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/examples/fixmynetboot/main.go (about)

     1  // Copyright 2017-2019 the u-root Authors. All rights reserved
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package main
     6  
     7  import (
     8  	"flag"
     9  	"fmt"
    10  	"log"
    11  	"net"
    12  
    13  	"github.com/mvdan/u-root-coreutils/pkg/checker"
    14  )
    15  
    16  // fixmynetboot is a troubleshooting tool that can help you identify issues that
    17  // won't let your system boot over the network.
    18  // NOTE: this is a DEMO tool. It's here only to show you how to write your own
    19  // checks and remediations. Don't use it in production.
    20  
    21  var emergencyShellBanner = `
    22  **************************************************************************
    23  ** Interface checks failed, see the output above to debug the issue.     *
    24  ** Entering the emergency shell, where you can run "fixmynetboot" again, *
    25  ** or any other LinuxBoot command.                                       *
    26  **************************************************************************
    27  `
    28  
    29  var doEmergencyShell = flag.Bool("shell", false, "Run emergency shell if checks fail")
    30  
    31  func checkInterface(ifname string) error {
    32  	checklist := []checker.Check{
    33  		{
    34  			Name:        fmt.Sprintf("%s exists", ifname),
    35  			Run:         checker.InterfaceExists(ifname),
    36  			Remediate:   checker.InterfaceRemediate(ifname),
    37  			StopOnError: true,
    38  		},
    39  		{
    40  			Name:        fmt.Sprintf("%s link speed", ifname),
    41  			Run:         checker.LinkSpeed(ifname, 400000),
    42  			Remediate:   nil,
    43  			StopOnError: false,
    44  		},
    45  		{
    46  			Name:        fmt.Sprintf("%s link autoneg", ifname),
    47  			Run:         checker.LinkAutoneg(ifname, true),
    48  			Remediate:   nil,
    49  			StopOnError: false,
    50  		},
    51  		{
    52  			Name:        fmt.Sprintf("%s has link-local", ifname),
    53  			Run:         checker.InterfaceHasLinkLocalAddress(ifname),
    54  			Remediate:   nil,
    55  			StopOnError: true,
    56  		},
    57  		{
    58  			Name:        fmt.Sprintf("%s has global addresses", ifname),
    59  			Run:         checker.InterfaceHasGlobalAddresses("eth0"),
    60  			Remediate:   nil,
    61  			StopOnError: true,
    62  		},
    63  	}
    64  
    65  	return checker.Run(checklist)
    66  }
    67  
    68  func getNonLoopbackInterfaces() ([]string, error) {
    69  	var interfaces []string
    70  	allInterfaces, err := net.Interfaces()
    71  	if err != nil {
    72  		return nil, err
    73  	}
    74  	for _, iface := range allInterfaces {
    75  		if iface.Flags&net.FlagLoopback == 0 {
    76  			interfaces = append(interfaces, iface.Name)
    77  		}
    78  	}
    79  	return interfaces, nil
    80  }
    81  
    82  func main() {
    83  	flag.Parse()
    84  	var (
    85  		interfaces []string
    86  		err        error
    87  	)
    88  	ifname := flag.Arg(0)
    89  	if ifname == "" {
    90  		interfaces, err = getNonLoopbackInterfaces()
    91  		if err != nil {
    92  			log.Fatal(err)
    93  		}
    94  	} else {
    95  		interfaces = []string{ifname}
    96  	}
    97  
    98  	for _, ifname := range interfaces {
    99  		if err := checkInterface(ifname); err != nil {
   100  			if !*doEmergencyShell {
   101  				log.Fatal(err)
   102  			}
   103  			if err := checker.EmergencyShell(emergencyShellBanner)(); err != nil {
   104  				log.Fatal(err)
   105  			}
   106  		}
   107  	}
   108  }