package virtigoxml /* validate / sanity check / consistancy check the data here is some code to do smart things like: * check mac addresses are unique * check uuid's are unique * double check filenames are unique * return a unique mac address * return a unique uuid */ import ( "errors" "os" "path/filepath" "github.com/google/uuid" pb "go.wit.com/lib/protobuf/virtbuf" "go.wit.com/log" ) // will make sure the mac address is unique func CheckUniqueMac(cluster *pb.Cluster, mac string) bool { for _, d := range cluster.Droplets { for _, n := range d.Networks { if n.Mac == mac { log.Info("duplicate MAC", n.Mac, "in droplet", d.Hostname) return false } } } return true } // records all the known paths. this should go in the protobuf func addClusterFilepath(cluster *pb.Cluster, dir string) *pb.Event { var found bool = false var e *pb.Event for _, d := range cluster.Dirs { if d == dir { // found dir found = true break } } if !found { if dir != "." { // make a new Add Event e = pb.NewAddEvent(nil, "Add Cluster Directory", dir) cluster.Dirs = append(cluster.Dirs, dir) } } return e } // returns the droplet using a filename func lookupFilename(cluster *pb.Cluster, filename string) *pb.Droplet { filebase := filepath.Base(filename) for _, d := range cluster.Droplets { for _, disk := range d.Disks { if filebase == disk.Filename { return d } } } return nil } func InsertFilename(cluster *pb.Cluster, d *pb.Droplet, filename string) (*pb.Event, error) { dupd := lookupFilename(cluster, filename) if dupd != nil { log.Info("file", filename, "already on droplet", dupd.Hostname) log.Info("file", filename, "on new droplet", d.Hostname) if os.Getenv("VIRTIGO_IGNORE_DISKDUP") == "" { log.Info("duplicate disk names (--xml-ignore-disk to ignore)") return nil, errors.New("duplicate disk names") } else { log.Info("ignore duplicate disk names (--xml-ignore-disk=true)") } } filebase := filepath.Base(filename) dir := filepath.Dir(filename) for _, disk := range d.Disks { if disk.Filename == filebase { log.Info("already have disk", filename) return nil, nil } } // make a new Add Event e := d.NewChangeEvent("Add Disk", "", filename) // add the disk protobuf entry var disk *pb.Disk disk = new(pb.Disk) disk.Filename = filebase disk.Filepath = dir d.Disks = append(d.Disks, disk) log.Info("New filename", filebase, dir) return e, nil } func CheckUniqueFilenames(cluster *pb.Cluster) bool { var ok bool = true var disks map[string]string disks = make(map[string]string) for _, d := range cluster.Droplets { for _, disk := range d.Disks { filename := disk.Filename addClusterFilepath(cluster, disk.Filepath) if _, ok := disks[filename]; ok { /* if argv.IgnDisk { log.Info("ignore dup disk", filename, disks[filename], d.Hostname) } else { } */ log.Info("file", filename, "on droplet", disks[filename]) log.Info("file", filename, "on droplet", d.Hostname) log.Info("duplicate disk names (--xml-ignore-disk to ignore)") ok = false } disks[filename] = d.Hostname } } if ok { log.Println("validated okay: no duplicate disk images") } return ok } func CheckDiskFilenames(cluster *pb.Cluster) []*pb.Event { var alle []*pb.Event for _, d := range cluster.Droplets { for _, disk := range d.Disks { filename := disk.Filename filebase := filepath.Base(filename) dir := filepath.Dir(filename) addClusterFilepath(cluster, dir) if disk.Filename != filebase { // update filename e := d.NewChangeEvent("Disk.Filename", disk.Filename, filebase) alle = append(alle, e) disk.Filename = filebase } if dir == "." { continue } if dir == "" { continue } if disk.Filepath != dir { // update filename e := d.NewChangeEvent("Disk.Filepath", disk.Filepath, dir) alle = append(alle, e) disk.Filepath = dir } } } return alle } func CheckDroplets(cluster *pb.Cluster, dump bool) bool { // uuid map to check for duplicates var umap map[string]string umap = make(map[string]string) // mac address map to check for duplicates var macs map[string]string macs = make(map[string]string) for _, d := range cluster.Droplets { // Generate a new UUID if d.Uuid == "" { u := uuid.New() d.Uuid = u.String() } // seconds, ok := timeZone[tz]; ok { if _, ok := umap[d.Uuid]; ok { // UUID already exists log.Info("duplicate UUID", d.Uuid, umap[d.Uuid]) log.Info("duplicate UUID", d.Uuid, d.Hostname) os.Exit(-1) } umap[d.Uuid] = d.Hostname for _, n := range d.Networks { // log.Println("network:", n.Mac, d.Uuid, d.Hostname) if _, ok := macs[n.Mac]; ok { // UUID already exists log.Info("duplicate MAC", n.Mac, macs[n.Mac], umap[macs[n.Mac]]) log.Info("duplicate MAC", n.Mac, d.Hostname) os.Exit(-1) } macs[n.Mac] = d.Uuid } } log.Println("validated okay: no duplicate MAC addr") log.Println("validated okay: no duplicate UUID") if dump { for u, hostname := range umap { log.Println("uuid:", u, "hostname:", hostname) } for mac, uuid := range macs { log.Println("mac:", mac, "uuid", uuid, "hostname:", umap[uuid]) } } return false }