func (s Server) Find(ctx context.Context, req *pb.FindRequest) (*pb.VM, error) {
	if req.FindBy == pb.FindRequest_UNSPECIFIED {
		return nil, grpc.Errorf(codes.InvalidArgument, "search criteria not specified")
	}
	domains, err := traceListAllDomains(ctx, s.conn)
	if err != nil {
		return nil, err
	}
	for _, d := range domains {
		name, err := traceDomainGetName(ctx, d)
		if err != nil {
			continue
		}
		domXML, err := traceDomainGetXMLDesc(ctx, d)
		if err != nil {
			continue
		}
		dom := libvirtDomain{}
		err = xml.Unmarshal([]byte(domXML), &dom)
		if err != nil {
			continue
		}
		macs := extractMACs(dom)
		if len(macs) != 1 {
			glog.Warningf("strange mac count on %s: %v", name, macs)
		}
		mac := macs[0]
		ip := extractIP(dom)
		repl := &pb.VM{
			Name: name,
			Ip:   ip,
			Mac:  mac,
		}
		if req.FindBy == pb.FindRequest_IP && ip == req.Value {
			return repl, nil
		}
		if req.FindBy == pb.FindRequest_MAC && mac == req.Value {
			return repl, nil
		}
	}
	return nil, grpc.Errorf(codes.NotFound, "ip not found")
}
Find is GRPC handler for Find API.
package server
import (
	"bytes"
	"encoding/xml"
	"html/template"
	"net"
	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	pb "github.com/google/vmregistry/api"
	"github.com/golang/glog"
	libvirt "github.com/libvirt/libvirt-go"
)
func extractMACs(dom libvirtDomain) []string {
	macs := []string{}
	for _, i := range dom.Devices.Interface {
		macs = append(macs, i.Mac.Address)
	}
	return macs
}
func extractIP(dom libvirtDomain) string {
	return dom.Metadata.VMRegistry.IP
}
type StorageManager interface {
	CreateStorage(ctx context.Context, name string, size uint64, sourceImage string) error
	RemoveStorage(ctx context.Context, name string) error
	StorageBlockDevice(name string) string
}
type Server struct {
	conn    *libvirt.Connect
	storage StorageManager
	vmNet   *net.IPNet
	dnsCli  *DnsClient
	xmlTemplate *template.Template
}
func NewServer(conn *libvirt.Connect, storage StorageManager, vmNet *net.IPNet, dnsCli *DnsClient, xmlTemplate *template.Template) Server {
	return Server{
		conn:        conn,
		storage:     storage,
		vmNet:       vmNet,
		dnsCli:      dnsCli,
		xmlTemplate: xmlTemplate,
	}
}
func (s Server) List(ctx context.Context, req *pb.ListVMRequest) (*pb.ListVMReply, error) {
	domains, err := traceListAllDomains(ctx, s.conn)
	if err != nil {
		return nil, err
	}
	repl := &pb.ListVMReply{}
	repl.Vms = make([]*pb.VM, len(domains))
	for i, d := range domains {
		name, err := traceDomainGetName(ctx, d)
		if err != nil {
			return nil, err
		}
		domXML, err := traceDomainGetXMLDesc(ctx, d)
		if err != nil {
			return nil, err
		}
		dom := libvirtDomain{}
		err = xml.Unmarshal([]byte(domXML), &dom)
		if err != nil {
			return nil, grpc.Errorf(codes.Internal, "failed to parse domain xml: %v", err)
		}
		macs := extractMACs(dom)
		if len(macs) != 1 {
			glog.Warningf("strange mac count on %s: %v", name, macs)
		}
		mac := macs[0]
		ip := extractIP(dom)
		if ip == "" {
			glog.Warningf("failed to get ip for node %s", name)
		}
		repl.Vms[i] = &pb.VM{
			Name: name,
			Ip:   ip,
			Mac:  mac,
		}
	}
	return repl, nil
}