From bb139218fb275a04c261a6799125d7762efc4109 Mon Sep 17 00:00:00 2001 From: Muhamad Awad Date: Mon, 24 Oct 2022 10:04:01 +0200 Subject: [PATCH] Network usage report (#1815) * WIP: create a link from workload-id to network-id This will make it easy to find which nework reousrce belongs to which contract * build metrics collection of public interface of an nr Collect data on network reosurce for each NR (best effort) and report to chain * delete deadcode --- cmds/modules/provisiond/main.go | 52 +---------- cmds/modules/provisiond/migration.go | 132 +++++++++++++++++++++++++++ cmds/modules/provisiond/reporter.go | 37 +++++++- pkg/gridtypes/zos/network.go | 10 +- pkg/network.go | 9 +- pkg/network/networker.go | 131 ++++++++++++++++++++++---- pkg/primitives/network/network.go | 14 +-- pkg/stubs/network_stub.go | 24 ++++- 8 files changed, 321 insertions(+), 88 deletions(-) create mode 100644 cmds/modules/provisiond/migration.go diff --git a/cmds/modules/provisiond/main.go b/cmds/modules/provisiond/main.go index afb891148..aa303bedb 100644 --- a/cmds/modules/provisiond/main.go +++ b/cmds/modules/provisiond/main.go @@ -3,10 +3,8 @@ package provisiond import ( "context" "crypto/ed25519" - "fmt" "os" "path/filepath" - "sort" "time" "github.com/cenkalti/backoff/v3" @@ -205,6 +203,10 @@ func action(cli *cli.Context) error { } } + if err := netResourceMigration(active); err != nil { + log.Error().Err(err).Msg("failed to migrate network resources") + } + log.Debug().Msgf("current used capacity: %+v", current) // statistics collects information about workload statistics // also does some checks on capacity @@ -419,49 +421,3 @@ func getNodeReserved(cl zbus.Client, available gridtypes.Capacity) (counter prim return } - -func storageMigration(db *storage.BoltStorage, fs *fsStorage.Fs) error { - log.Info().Msg("starting storage migration") - twins, err := fs.Twins() - if err != nil { - return err - } - migration := db.Migration() - errorred := false - for _, twin := range twins { - dls, err := fs.ByTwin(twin) - if err != nil { - log.Error().Err(err).Uint32("twin", twin).Msg("failed to list twin deployments") - continue - } - - sort.Slice(dls, func(i, j int) bool { - return dls[i] < dls[j] - }) - - for _, dl := range dls { - log.Info().Uint32("twin", twin).Uint64("deployment", dl).Msg("processing deployment migration") - deployment, err := fs.Get(twin, dl) - if err != nil { - log.Error().Err(err).Uint32("twin", twin).Uint64("deployment", dl).Msg("failed to get deployment") - errorred = true - continue - } - if err := migration.Migrate(deployment); err != nil { - log.Error().Err(err).Uint32("twin", twin).Uint64("deployment", dl).Msg("failed to migrate deployment") - errorred = true - continue - } - if err := fs.Delete(deployment); err != nil { - log.Error().Err(err).Uint32("twin", twin).Uint64("deployment", dl).Msg("failed to delete migrated deployment") - continue - } - } - } - - if errorred { - return fmt.Errorf("not all deployments where migrated") - } - - return nil -} diff --git a/cmds/modules/provisiond/migration.go b/cmds/modules/provisiond/migration.go new file mode 100644 index 000000000..be351cf0e --- /dev/null +++ b/cmds/modules/provisiond/migration.go @@ -0,0 +1,132 @@ +package provisiond + +import ( + "fmt" + "os" + "path/filepath" + "sort" + + "github.com/pkg/errors" + "github.com/rs/zerolog/log" + "github.com/threefoldtech/zos/pkg/gridtypes" + "github.com/threefoldtech/zos/pkg/gridtypes/zos" + "github.com/threefoldtech/zos/pkg/provision/storage" + fsStorage "github.com/threefoldtech/zos/pkg/provision/storage.fs" +) + +func storageMigration(db *storage.BoltStorage, fs *fsStorage.Fs) error { + log.Info().Msg("starting storage migration") + twins, err := fs.Twins() + if err != nil { + return err + } + migration := db.Migration() + errorred := false + for _, twin := range twins { + dls, err := fs.ByTwin(twin) + if err != nil { + log.Error().Err(err).Uint32("twin", twin).Msg("failed to list twin deployments") + continue + } + + sort.Slice(dls, func(i, j int) bool { + return dls[i] < dls[j] + }) + + for _, dl := range dls { + log.Info().Uint32("twin", twin).Uint64("deployment", dl).Msg("processing deployment migration") + deployment, err := fs.Get(twin, dl) + if err != nil { + log.Error().Err(err).Uint32("twin", twin).Uint64("deployment", dl).Msg("failed to get deployment") + errorred = true + continue + } + if err := migration.Migrate(deployment); err != nil { + log.Error().Err(err).Uint32("twin", twin).Uint64("deployment", dl).Msg("failed to migrate deployment") + errorred = true + continue + } + if err := fs.Delete(deployment); err != nil { + log.Error().Err(err).Uint32("twin", twin).Uint64("deployment", dl).Msg("failed to delete migrated deployment") + continue + } + } + } + + if errorred { + return fmt.Errorf("not all deployments where migrated") + } + + return nil +} + +func netResourceMigration(active []gridtypes.Deployment) error { + /* + because of limit on the net devices names (length mainly) it was always needed to + name the devices with unique name that is derived from the actual user twin/deployment and network workload name + hence the zos.NetworkID function which takes into account all required inputs to make a unique network id. + + The problem now it's impossible for the system to map back network resources names to a unique reservation. + a bridge br-27xVrq9bva3vJ or a namespace n-27xVrq9bva3vJ means nothing and you can't tell which user owns this. + + Since networkd stores the network object anyway on disk (under /var/run/cache/networkd/networks) it's then possible to update those objects + to also contain the workload full id not only the network id. + + The first way to do this is to update all cached files on this volatile storage, update the file version and add the extra missing filed. but this + requires changes in multiple places (define a new type and track the version of the file). make sure the correct types are used and possibly support + of multiple versions of the structure in multiple places. + + The other "easier" approach is simply creating a symlink from the ID to the correct network file. this means only entities that need to find the network + by it's full workload name can use the link to find the NR bridge and namespace. + + Networkd will be modified to always create the symlink (if not exist already) to the persisted NR file. But for already created networks, it's not possible to + create them from within networkd because it does not know this information. + + Hence this migration code witch will go over all active deployments on start, and create the missing symlinks. Newer networks objects will be created with + their proper symlinks by networkd. + */ + + const volatile = "/var/run/cache/networkd/networks" + _, err := os.Stat(volatile) + if os.IsNotExist(err) { + // if this doesn't exist it means it's probably first start (after boot) and hence networkd + // will be called to create all NRs hence it will create the symlink and nothing we need to + // do now. + return nil + } else if err != nil { + return errors.Wrap(err, "failed to check networkd volatile cache") + } + + sym := filepath.Join(volatile, "link") + if err := os.MkdirAll(sym, 0755); err != nil { + return errors.Wrap(err, "failed to create network link directory") + } + + for _, dl := range active { + for _, wl := range dl.Workloads { + if wl.Type != zos.NetworkType || + !wl.Result.State.IsOkay() { + continue + } + id, err := gridtypes.NewWorkloadID(dl.TwinID, dl.ContractID, wl.Name) + if err != nil { + log.Error().Err(err).Msg("failed to build network workload id") + continue + } + + netId := zos.NetworkID(dl.TwinID, wl.Name) + if _, err := os.Stat(filepath.Join(volatile, netId.String())); os.IsNotExist(err) { + continue + } + + if err := os.Symlink( + filepath.Join("..", string(netId)), + filepath.Join(sym, string(id)), + ); err != nil && !os.IsExist(err) { + log.Error().Err(err).Msgf("failed to create network symlink for %s -> ../%s", id, netId) + } + } + } + + return nil +} diff --git a/cmds/modules/provisiond/reporter.go b/cmds/modules/provisiond/reporter.go index f088297ff..f93f3cc74 100644 --- a/cmds/modules/provisiond/reporter.go +++ b/cmds/modules/provisiond/reporter.go @@ -164,6 +164,29 @@ func (r *Reporter) getVmMetrics(ctx context.Context, slot rrd.Slot) error { return nil } +// getNetworkMetrics will collect network consumption for network resource and store it in the given slot +func (r *Reporter) getNetworkMetrics(ctx context.Context, slot rrd.Slot) error { + log.Debug().Msg("collecting networking metrics") + stub := stubs.NewNetworkerStub(r.cl) + + ctx, cancel := context.WithTimeout(ctx, 1*time.Minute) + defer cancel() + metrics, err := stub.Metrics(ctx) + if err != nil { + return err + } + + for wl, consumption := range metrics { + nu := consumption.Nu() + log.Debug().Str("network", wl).Uint64("computed", uint64(nu)).Msgf("consumption: %+v", consumption) + if err := slot.Counter(wl, float64(nu)); err != nil { + return errors.Wrapf(err, "failed to store metrics for '%s'", wl) + } + } + + return nil +} + // getVmMetrics will collect network consumption every 5 min and store // it in the rrd database. func (r *Reporter) getGwMetrics(ctx context.Context, slot rrd.Slot) error { @@ -205,8 +228,12 @@ func (r *Reporter) getMetrics(ctx context.Context) error { return err } + if err := r.getNetworkMetrics(ctx, slot); err != nil { + log.Error().Err(err).Msg("failed to get network resource consumption") + } + if err := r.getVmMetrics(ctx, slot); err != nil { - log.Error().Err(err).Msg("failed to get vm network consumption") + log.Error().Err(err).Msg("failed to get vm public ip consumption") } if err := r.getGwMetrics(ctx, slot); err != nil { @@ -327,23 +354,23 @@ func (r *Reporter) report(ctx context.Context, since time.Time) (time.Time, erro continue } - _, deploment, _, err := gridtypes.WorkloadID(key).Parts() + _, deployment, _, err := gridtypes.WorkloadID(key).Parts() if err != nil { log.Error().Err(err).Msgf("failed to parse metric key '%s'", key) continue } - rep, ok := reports[deploment] + rep, ok := reports[deployment] if !ok { rep = substrate.NruConsumption{ - ContractID: types.U64(deploment), + ContractID: types.U64(deployment), Timestamp: types.U64(now.Unix()), Window: types.U64(window / time.Second), } } rep.NRU += types.U64(value) - reports[deploment] = rep + reports[deployment] = rep } var report Report diff --git a/pkg/gridtypes/zos/network.go b/pkg/gridtypes/zos/network.go index 3696bc024..2256231ca 100644 --- a/pkg/gridtypes/zos/network.go +++ b/pkg/gridtypes/zos/network.go @@ -31,6 +31,14 @@ func NetworkID(twin uint32, network gridtypes.Name) NetID { return NetID(string(b)) } +func NetworkIDFromWorkloadID(wl gridtypes.WorkloadID) (NetID, error) { + twin, _, name, err := wl.Parts() + if err != nil { + return "", err + } + return NetworkID(twin, name), nil +} + // Network is the description of a part of a network local to a specific node. // A network workload defines a wireguard network that is usually spans multiple nodes. One of the nodes must work as an access node // in other words, it must be reachable from other nodes, hence it needs to have a `PublicConfig`. @@ -155,7 +163,7 @@ func (p *Peer) Valid() error { return nil } -//Challenge for peer +// Challenge for peer func (p Peer) Challenge(w io.Writer) error { if _, err := fmt.Fprintf(w, "%s", p.WGPublicKey); err != nil { return err diff --git a/pkg/network.go b/pkg/network.go index f7d0b22c2..58ec9be33 100644 --- a/pkg/network.go +++ b/pkg/network.go @@ -65,16 +65,18 @@ func (e *ExitDevice) String() string { return "unknown" } -//Networker is the interface for the network module +type NetResourceMetrics map[string]NetMetric + +// Networker is the interface for the network module type Networker interface { // Ready return nil is networkd is ready to operate // This function is used by other deamon to test if networkd is done booting Ready() error // Create a new network resource - CreateNR(Network) (string, error) + CreateNR(wl gridtypes.WorkloadID, network Network) (string, error) // Delete a network resource - DeleteNR(Network) error + DeleteNR(wl gridtypes.WorkloadID) error // Namespace returns the namespace name for given netid. // it doesn't check if network exists. @@ -202,6 +204,7 @@ type Networker interface { SetPublicExitDevice(iface string) error + Metrics() (NetResourceMetrics, error) // Monitoring methods // ZOSAddresses monitoring streams for ZOS bridge IPs diff --git a/pkg/network/networker.go b/pkg/network/networker.go index af506f91c..fbd77ef2f 100644 --- a/pkg/network/networker.go +++ b/pkg/network/networker.go @@ -17,6 +17,7 @@ import ( "github.com/blang/semver" "github.com/threefoldtech/zos/pkg/cache" + "github.com/threefoldtech/zos/pkg/gridtypes" "github.com/threefoldtech/zos/pkg/gridtypes/zos" "github.com/threefoldtech/zos/pkg/network/bootstrap" "github.com/threefoldtech/zos/pkg/network/ndmz" @@ -54,6 +55,7 @@ const ( ZDBYggIface = "ygg0" networkDir = "networks" + linkDir = "link" ipamLeaseDir = "ndmz-lease" zdbNamespacePrefix = "zdb-ns-" qsfsNamespacePrefix = "qfs-ns-" @@ -71,6 +73,7 @@ var ( type networker struct { identity *stubs.IdentityManagerStub networkDir string + linkDir string ipamLeaseDir string portSet *set.UIntSet @@ -88,9 +91,10 @@ func NewNetworker(identity *stubs.IdentityManagerStub, ndmz ndmz.DMZ, ygg *yggdr } runtimeDir := filepath.Join(vd, networkDir) + linkDir := filepath.Join(runtimeDir, linkDir) ipamLease := filepath.Join(vd, ipamLeaseDir) - for _, dir := range []string{runtimeDir, ipamLease} { + for _, dir := range []string{linkDir, ipamLease} { if err := os.MkdirAll(dir, 0755); err != nil { return nil, errors.Wrapf(err, "failed to create directory: '%s'", dir) } @@ -99,6 +103,7 @@ func NewNetworker(identity *stubs.IdentityManagerStub, ndmz ndmz.DMZ, ygg *yggdr nw := &networker{ identity: identity, networkDir: runtimeDir, + linkDir: linkDir, ipamLeaseDir: ipamLease, portSet: set.NewInt(), @@ -220,7 +225,7 @@ func (n *networker) destroy(ns string) error { return namespace.Delete(nSpace) } -//func (n *networker) NSPrepare(id string, ) +// func (n *networker) NSPrepare(id string, ) // ZDBPrepare sends a macvlan interface into the // network namespace of a ZDB container func (n *networker) ZDBPrepare(id string) (string, error) { @@ -270,7 +275,7 @@ func (n *networker) createMacVlan(iface string, master string, hw net.HardwareAd func (n *networker) SetupPrivTap(networkID pkg.NetID, name string) (ifc string, err error) { log.Info().Str("network-id", string(networkID)).Msg("Setting up tap interface") - localNR, err := n.networkOf(string(networkID)) + localNR, err := n.networkOf(networkID) if err != nil { return "", errors.Wrapf(err, "couldn't load network with id (%s)", networkID) } @@ -589,7 +594,7 @@ func (n *networker) GetPublicIPv6Subnet() (net.IPNet, error) { // GetSubnet of a local network resource identified by the network ID, ipv4 and ipv6 // subnet respectively func (n *networker) GetSubnet(networkID pkg.NetID) (net.IPNet, error) { - localNR, err := n.networkOf(string(networkID)) + localNR, err := n.networkOf(networkID) if err != nil { return net.IPNet{}, errors.Wrapf(err, "couldn't load network with id (%s)", networkID) } @@ -599,7 +604,7 @@ func (n *networker) GetSubnet(networkID pkg.NetID) (net.IPNet, error) { // GetNet of a network identified by the network ID func (n *networker) GetNet(networkID pkg.NetID) (net.IPNet, error) { - localNR, err := n.networkOf(string(networkID)) + localNR, err := n.networkOf(networkID) if err != nil { return net.IPNet{}, errors.Wrapf(err, "couldn't load network with id (%s)", networkID) } @@ -611,7 +616,7 @@ func (n *networker) GetNet(networkID pkg.NetID) (net.IPNet, error) { // resource identified by the network ID on the local node, for IPv4 and IPv6 // respectively func (n *networker) GetDefaultGwIP(networkID pkg.NetID) (net.IP, net.IP, error) { - localNR, err := n.networkOf(string(networkID)) + localNR, err := n.networkOf(networkID) if err != nil { return nil, nil, errors.Wrapf(err, "couldn't load network with id (%s)", networkID) } @@ -752,12 +757,12 @@ func (n *networker) Addrs(iface string, netns string) (ips []net.IP, mac string, } // CreateNR implements pkg.Networker interface -func (n *networker) CreateNR(netNR pkg.Network) (string, error) { +func (n *networker) CreateNR(wl gridtypes.WorkloadID, netNR pkg.Network) (string, error) { log.Info().Str("network", string(netNR.NetID)).Msg("create network resource") // check if there is a reserved wireguard port for this NR already // or if we need to update it - storedNR, err := n.networkOf(string(netNR.NetID)) + storedNR, err := n.networkOf(netNR.NetID) if err != nil && !os.IsNotExist(err) { return "", errors.Wrap(err, "failed to load previous network setup") } @@ -832,14 +837,34 @@ func (n *networker) CreateNR(netNR pkg.Network) (string, error) { return "", errors.Wrap(err, "failed to configure network resource") } - if err = n.storeNetwork(netNR); err != nil { + if err = n.storeNetwork(wl, netNR); err != nil { return "", errors.Wrap(err, "failed to store network object") } return netr.Namespace() } -func (n *networker) storeNetwork(network pkg.Network) error { +func (n *networker) rmNetwork(wl gridtypes.WorkloadID) error { + netID, err := zos.NetworkIDFromWorkloadID(wl) + if err != nil { + return err + } + + rm := []string{ + filepath.Join(n.networkDir, netID.String()), + filepath.Join(n.linkDir, wl.String()), + } + + for _, p := range rm { + if err := os.Remove(p); err != nil && !os.IsNotExist(err) { + log.Error().Err(err).Str("path", p).Msg("failed to delete file") + } + } + + return nil +} + +func (n *networker) storeNetwork(wl gridtypes.WorkloadID, network pkg.Network) error { // map the network ID to the network namespace path := filepath.Join(n.networkDir, string(network.NetID)) file, err := os.Create(path) @@ -857,12 +882,24 @@ func (n *networker) storeNetwork(network pkg.Network) error { if err := enc.Encode(&network); err != nil { return err } - + link := filepath.Join(n.linkDir, wl.String()) + if err := os.Symlink(filepath.Join("../", string(network.NetID)), link); err != nil { + return errors.Wrap(err, "failed to create network symlink") + } return nil } // DeleteNR implements pkg.Networker interface -func (n *networker) DeleteNR(netNR pkg.Network) error { +func (n *networker) DeleteNR(wl gridtypes.WorkloadID) error { + netID, err := zos.NetworkIDFromWorkloadID(wl) + if err != nil { + return err + } + netNR, err := n.networkOf(netID) + if err != nil { + return err + } + nr, err := nr.New(netNR) if err != nil { return errors.Wrap(err, "failed to load network resource") @@ -881,9 +918,7 @@ func (n *networker) DeleteNR(netNR pkg.Network) error { log.Error().Err(err).Msg("failed to detach network from ndmz") } - // map the network ID to the network namespace - path := filepath.Join(n.networkDir, string(netNR.NetID)) - if err := os.Remove(path); err != nil && !os.IsNotExist(err) { + if err := n.rmNetwork(wl); err != nil { log.Error().Err(err).Msg("failed to remove file mapping between network ID and namespace") } @@ -996,7 +1031,7 @@ func (n *networker) GetPublicConfig() (pkg.PublicConfig, error) { return cfg, nil } -func (n *networker) networkOf(id string) (nr pkg.Network, err error) { +func (n *networker) networkOf(id zos.NetID) (nr pkg.Network, err error) { path := filepath.Join(n.networkDir, string(id)) file, err := os.OpenFile(path, os.O_RDWR, 0660) if err != nil { @@ -1070,6 +1105,53 @@ func (n *networker) DMZAddresses(ctx context.Context) <-chan pkg.NetlinkAddresse return ch } +func (n *networker) Metrics() (pkg.NetResourceMetrics, error) { + links, err := os.ReadDir(n.linkDir) + if err != nil { + return nil, errors.Wrap(err, "failed to list networks") + } + + metrics := make(pkg.NetResourceMetrics) + for _, link := range links { + if link.IsDir() { + continue + } + + wl := link.Name() + logger := log.With().Str("workload", wl).Logger() + sym, err := os.Readlink(filepath.Join(n.linkDir, wl)) + if err != nil { + logger.Error().Err(err).Msg("failed to get network name from workload link") + continue + } + nsName := n.Namespace(zos.NetID(filepath.Base(sym))) + logger.Debug().Str("namespace", nsName).Msg("collecting namespace statistics") + nr, err := namespace.GetByName(nsName) + if err != nil { + logger.Error().Str("namespace", nsName).Err(err).Msg("failed to get network namespace from workload") + continue + } + + defer nr.Close() + err = nr.Do(func(_ ns.NetNS) error { + // get stats of public interface. + m, err := metricsForNics("public") + if err != nil { + return err + } + + metrics[wl] = m + return nil + }) + + if err != nil { + log.Error().Err(err).Msg("failed to collect metrics for network") + } + } + + return metrics, nil +} + func (n *networker) YggAddresses(ctx context.Context) <-chan pkg.NetlinkAddresses { ch := make(chan pkg.NetlinkAddresses) go func() { @@ -1264,3 +1346,20 @@ var yggPrefix = net.IPNet{ func isYgg(ip net.IP) bool { return yggPrefix.Contains(ip) } + +func metricsForNics(nics ...string) (m pkg.NetMetric, err error) { + for _, nic := range nics { + l, err := netlink.LinkByName(nic) + if err != nil { + return pkg.NetMetric{}, err + } + + stats := l.Attrs().Statistics + m.NetRxBytes += stats.RxBytes + m.NetTxBytes += stats.TxBytes + m.NetRxPackets += stats.RxPackets + m.NetTxPackets += stats.TxPackets + } + + return +} diff --git a/pkg/primitives/network/network.go b/pkg/primitives/network/network.go index 730fc4ace..df178c0a1 100644 --- a/pkg/primitives/network/network.go +++ b/pkg/primitives/network/network.go @@ -41,7 +41,7 @@ func (p *Manager) networkProvisionImpl(ctx context.Context, wl *gridtypes.Worklo mgr := stubs.NewNetworkerStub(p.zbus) log.Debug().Str("network", fmt.Sprintf("%+v", network)).Msg("provision network") - _, err := mgr.CreateNR(ctx, pkg.Network{ + _, err := mgr.CreateNR(ctx, wl.ID, pkg.Network{ Network: network, NetID: zos.NetworkID(twin, wl.Name), }) @@ -64,17 +64,7 @@ func (p *Manager) Update(ctx context.Context, wl *gridtypes.WorkloadWithID) (int func (p *Manager) Deprovision(ctx context.Context, wl *gridtypes.WorkloadWithID) error { mgr := stubs.NewNetworkerStub(p.zbus) - var network zos.Network - if err := json.Unmarshal(wl.Data, &network); err != nil { - return fmt.Errorf("failed to unmarshal network from reservation: %w", err) - } - - twin, _ := provision.GetDeploymentID(ctx) - - if err := mgr.DeleteNR(ctx, pkg.Network{ - Network: network, - NetID: zos.NetworkID(twin, wl.Name), - }); err != nil { + if err := mgr.DeleteNR(ctx, wl.ID); err != nil { return fmt.Errorf("failed to delete network resource: %w", err) } diff --git a/pkg/stubs/network_stub.go b/pkg/stubs/network_stub.go index 17360fb5a..3668f48c1 100644 --- a/pkg/stubs/network_stub.go +++ b/pkg/stubs/network_stub.go @@ -4,6 +4,7 @@ import ( "context" zbus "github.com/threefoldtech/zbus" pkg "github.com/threefoldtech/zos/pkg" + gridtypes "github.com/threefoldtech/zos/pkg/gridtypes" zos "github.com/threefoldtech/zos/pkg/gridtypes/zos" "net" ) @@ -43,8 +44,8 @@ func (s *NetworkerStub) Addrs(ctx context.Context, arg0 string, arg1 string) (re return } -func (s *NetworkerStub) CreateNR(ctx context.Context, arg0 pkg.Network) (ret0 string, ret1 error) { - args := []interface{}{arg0} +func (s *NetworkerStub) CreateNR(ctx context.Context, arg0 gridtypes.WorkloadID, arg1 pkg.Network) (ret0 string, ret1 error) { + args := []interface{}{arg0, arg1} result, err := s.client.RequestContext(ctx, s.module, s.object, "CreateNR", args...) if err != nil { panic(err) @@ -84,7 +85,7 @@ func (s *NetworkerStub) DMZAddresses(ctx context.Context) (<-chan pkg.NetlinkAdd return ch, nil } -func (s *NetworkerStub) DeleteNR(ctx context.Context, arg0 pkg.Network) (ret0 error) { +func (s *NetworkerStub) DeleteNR(ctx context.Context, arg0 gridtypes.WorkloadID) (ret0 error) { args := []interface{}{arg0} result, err := s.client.RequestContext(ctx, s.module, s.object, "DeleteNR", args...) if err != nil { @@ -251,6 +252,23 @@ func (s *NetworkerStub) Interfaces(ctx context.Context, arg0 string, arg1 string return } +func (s *NetworkerStub) Metrics(ctx context.Context) (ret0 pkg.NetResourceMetrics, ret1 error) { + args := []interface{}{} + result, err := s.client.RequestContext(ctx, s.module, s.object, "Metrics", args...) + if err != nil { + panic(err) + } + result.PanicOnError() + ret1 = result.CallError() + loader := zbus.Loader{ + &ret0, + } + if err := result.Unmarshal(&loader); err != nil { + panic(err) + } + return +} + func (s *NetworkerStub) Namespace(ctx context.Context, arg0 zos.NetID) (ret0 string) { args := []interface{}{arg0} result, err := s.client.RequestContext(ctx, s.module, s.object, "Namespace", args...)