Beispiel #1
0
func main() {
	var parentUUID string
	var parentGroup = flag.String("g", "", "UUID or Name (if unique and -l present) of the parent Hardware Group")
	var location = flag.String("l", "", "Data centre location to use for resolving -g <Group-Name>")
	var desc = flag.String("t", "", "Textual description of the new group")
	var acctAlias = flag.String("a", "", "Account alias to use")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options]  <New Group Name>\n", path.Base(os.Args[0]))
		flag.PrintDefaults()
	}
	flag.Parse()
	if flag.NArg() != 1 || *parentGroup == "" {
		flag.Usage()
		os.Exit(1)
	}

	/* parentGroup may be hex uuid or group name */
	if _, err := hex.DecodeString(*parentGroup); err == nil {
		parentUUID = *parentGroup
	} else if *location == "" {
		exit.Errorf("Using -g <Group-Name> requires -l <Location> to be set")
	}

	client, err := clcv1.NewClient(log.New(os.Stdout, "", log.LstdFlags|log.Ltime))
	if err != nil {
		exit.Fatal(err.Error())
	} else if err := client.Logon("", ""); err != nil {
		exit.Fatalf("Login failed: %s", err)
	}

	if parentUUID == "" {
		if group, err := client.GetGroupByName(*parentGroup, *location, *acctAlias); err != nil {
			exit.Errorf("Failed to resolve group name %q: %s", *parentGroup, err)
		} else if group == nil {
			exit.Errorf("No group named %q was found on %s", *parentGroup, *location)
		} else {
			parentUUID = group.UUID
		}
	}

	g, err := client.CreateHardwareGroup(*acctAlias, parentUUID, flag.Arg(0), *desc)
	if err != nil {
		exit.Fatalf("Failed to create hardware group %q: %s", flag.Arg(0), err)
	}

	fmt.Println("New Group: ", g.Name)
	fmt.Println("UUID:      ", g.UUID)
}
Beispiel #2
0
func main() {
	var location = flag.String("l", "", "The location of the deployment to retrieve status for (required)")
	var pollIntvl = flag.Int("i", 1, "Poll interval in seconds (to monitor progress")
	var acctAlias = flag.String("a", "", "Account alias to use")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options]  <Request-ID>\n", path.Base(os.Args[0]))
		flag.PrintDefaults()
	}

	flag.Parse()
	if flag.NArg() != 1 || *location == "" {
		flag.Usage()
		os.Exit(1)
	}

	reqId, err := strconv.ParseUint(flag.Arg(0), 10, 32)
	if err != nil {
		exit.Errorf("Invalid Request ID %q: %s", flag.Arg(0), err)
	}

	client, err := clcv1.NewClient(log.New(os.Stdout, "", log.LstdFlags|log.Ltime))
	if err != nil {
		exit.Fatal(err.Error())
	} else if err := client.Logon("", ""); err != nil {
		exit.Fatalf("Login failed: %s", err)
	}

	err = client.PollDeploymentStatus(int(reqId), *location, *acctAlias, *pollIntvl)
	if err != nil {
		exit.Fatalf("Failed to poll status of request ID %d: %s", reqId, err)
	}
}
Beispiel #3
0
func main() {
	var location = flag.String("l", "", "Alias of the data centre the server resides in")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options]  <IP Address>\n", path.Base(os.Args[0]))
		flag.PrintDefaults()
	}

	flag.Parse()
	if flag.NArg() != 1 || *location == "" {
		flag.Usage()
		os.Exit(1)
	}

	client, err := clcv2.NewCLIClient()
	if err != nil {
		exit.Fatal(err.Error())
	}

	iad, err := client.GetNetworkDetailsByIp(flag.Arg(0), *location)
	if err != nil {
		exit.Fatalf("failed to look up %s: %s", flag.Arg(0), err)
	} else if iad == nil {
		exit.Errorf("No match found for %s in %s", flag.Arg(0), *location)
	}

	// The 'Server' field is not necessarily filled in, hence we need to test here.
	if iad.Server != "" {
		fmt.Printf("%s is used by %s.\n", iad.Address, iad.Server)
	} else {
		fmt.Printf("%s is in %s use in %s, but the server name is not disclosed.\n", iad.Address, iad.Type, *location)
	}
}
Beispiel #4
0
func main() {
	var size = flag.Uint("size", 0, "New size of the disk in GB")
	// Allow the same ID types as in disk_remove.go
	var reMajMin = regexp.MustCompile(`^\d+:\d+$`)
	var reMin = regexp.MustCompile(`^\d+$`)
	var id string

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options]  <Server-Name>  <Disk-ID>\n", path.Base(os.Args[0]))
		flag.PrintDefaults()
	}

	flag.Parse()
	if flag.NArg() != 2 || *size == 0 {
		flag.Usage()
		os.Exit(1)
	} else if reMajMin.MatchString(flag.Arg(1)) {
		id = flag.Arg(1)
	} else if reMin.MatchString(flag.Arg(1)) {
		id = fmt.Sprintf("0:%s", flag.Arg(1))
	} else {
		exit.Errorf("invalid disk ID %q", flag.Arg(1))
	}

	client, err := clcv2.NewCLIClient()
	if err != nil {
		exit.Fatal(err.Error())
	}

	server, err := client.GetServer(flag.Arg(0))
	if err != nil {
		exit.Fatalf("failed to list details of server %q: %s", flag.Arg(0), err)
	}

	disks := make([]clcv2.ServerAdditionalDisk, len(server.Details.Disks))
	for i := range server.Details.Disks {
		disks[i] = clcv2.ServerAdditionalDisk{
			Id:     server.Details.Disks[i].Id,
			SizeGB: server.Details.Disks[i].SizeGB,
		}
		if disks[i].Id == id {
			// The API does not allow to reduce the size of an existing disk.
			if uint32(*size) <= disks[i].SizeGB {
				fmt.Printf("Disk %s size is already at %d GB.\n", id, disks[i].SizeGB)
				os.Exit(0)
			}
			fmt.Printf("Changing disk %s size from %d to %d GB ...\n",
				id, disks[i].SizeGB, *size)
			disks[i].SizeGB = uint32(*size)
		}
	}

	reqID, err := client.ServerSetDisks(flag.Arg(0), disks)
	if err != nil {
		exit.Fatalf("failed to update the disk configuration on %q: %s", flag.Arg(0), err)
	}

	log.Printf("Status Id for resizing the disk on %s: %s", flag.Arg(0), reqID)
	client.PollStatus(reqID, 10*time.Second)
}
Beispiel #5
0
func main() {
	var parentGroup = flag.String("g", "", "UUID or Name (if unique and -l present) of the parent Hardware Group")
	var location = flag.String("l", "", "Data centre location to use for resolving -g <Group-Name>")
	var desc = flag.String("t", "", "Textual description of the new group")
	var parentUUID string

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options]  <New Group Name>\n", path.Base(os.Args[0]))
		flag.PrintDefaults()
	}
	flag.Parse()
	if flag.NArg() != 1 || *parentGroup == "" {
		flag.Usage()
		os.Exit(1)
	}

	/* parentGroup may be hex uuid or group name */
	if _, err := hex.DecodeString(*parentGroup); err == nil {
		parentUUID = *parentGroup
	} else if *location == "" {
		exit.Errorf("Using -g <Group-Name> requires -l <Location> to be set")
	}

	client, err := clcv2.NewCLIClient()
	if err != nil {
		exit.Fatal(err.Error())
	}

	if parentUUID == "" { /* resolve group name */
		if group, err := client.GetGroupByName(*parentGroup, *location); err != nil {
			exit.Errorf("failed to resolve group name %q: %s", *parentGroup, err)
		} else if group == nil {
			exit.Errorf("No group named %q was found in %s", *parentGroup, *location)
		} else {
			parentUUID = group.Id
		}
	}

	g, err := client.CreateGroup(flag.Arg(0), parentUUID, *desc, []clcv2.SimpleCustomField{})
	if err != nil {
		exit.Fatalf("failed to create hardware group %q: %s", flag.Arg(0), err)
	}

	fmt.Println("New Group: ", g.Name)
	fmt.Println("UUID:      ", g.Id)
}
Beispiel #6
0
func main() {
	// Allow two types of ID: (a) <major>:<minor> syntax, (b) <minor> syntax
	var reMajMin = regexp.MustCompile(`^\d+:\d+$`)
	var reMin = regexp.MustCompile(`^\d+$`)
	var ids []string

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options]  <Server Name> <diskId> [<diskId> ...]\n", path.Base(os.Args[0]))
		flag.PrintDefaults()
	}

	flag.Parse()
	if flag.NArg() < 2 {
		flag.Usage()
		os.Exit(1)
	}

	for i := 1; i < flag.NArg(); i++ {
		if reMajMin.MatchString(flag.Arg(i)) {
			ids = append(ids, flag.Arg(i))
		} else if reMin.MatchString(flag.Arg(i)) {
			ids = append(ids, fmt.Sprintf("0:%s", flag.Arg(i)))
		} else {
			exit.Errorf("invalid disk ID %q", flag.Arg(i))
		}
	}

	client, err := clcv2.NewCLIClient()
	if err != nil {
		exit.Fatal(err.Error())
	}

	server, err := client.GetServer(flag.Arg(0))
	if err != nil {
		exit.Fatalf("failed to list details of server %q: %s", flag.Arg(0), err)
	}

	disks := make([]clcv2.ServerAdditionalDisk, 0)
	for i := range server.Details.Disks {
		if inStringArray(server.Details.Disks[i].Id, ids...) {
			fmt.Printf("Deleting disk %s (%d GB) ...\n", server.Details.Disks[i].Id, server.Details.Disks[i].SizeGB)
		} else {
			disks = append(disks, clcv2.ServerAdditionalDisk{
				Id:     server.Details.Disks[i].Id,
				SizeGB: server.Details.Disks[i].SizeGB,
			})
		}
	}

	reqID, err := client.ServerSetDisks(flag.Arg(0), disks)
	if err != nil {
		exit.Fatalf("failed to update the disk configuration on %q: %s", flag.Arg(0), err)
	}

	log.Printf("Status Id for updating the disks on %s: %s", flag.Arg(0), reqID)
	client.PollStatus(reqID, 5*time.Second)
}
Beispiel #7
0
func main() {
	var hwGroup = flag.String("g", "", "UUID or name (if unique) of the HW group to restore this group to")
	var location = flag.String("l", "", "Data centre alias (to resolve group and/or network ID)")
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options]  <HW Group UUID>\n", path.Base(os.Args[0]))
		flag.PrintDefaults()
	}

	flag.Parse()
	if flag.NArg() != 1 || *hwGroup == "" {
		flag.Usage()
		os.Exit(1)
	}

	client, err := clcv2.NewCLIClient()
	if err != nil {
		exit.Fatal(err.Error())
	}

	/* hwGroup may be hex uuid or group name */
	if _, err := hex.DecodeString(*hwGroup); err == nil {
		/* already looks like a HEX ID */
	} else if *location == "" {
		exit.Errorf("Need a location argument (-l) if not using a HW Group UUID (%s)", *hwGroup)
	} else {
		fmt.Printf("Resolving ID of Hardware Group %q ...\n", *hwGroup)

		if group, err := client.GetGroupByName(*hwGroup, *location); err != nil {
			exit.Errorf("failed to resolve group name %q: %s", *hwGroup, err)
		} else if group == nil {
			exit.Errorf("No group named %q was found in %s", *hwGroup, *location)
		} else {
			*hwGroup = group.Id
		}
	}

	statusId, err := client.RestoreGroup(flag.Arg(0), *hwGroup)
	if err != nil {
		exit.Fatalf("failed to restore group %s: %s", flag.Arg(0), err)
	}

	fmt.Println("Request ID for restoring group:", statusId)
}
Beispiel #8
0
func main() {
	var uuid string /* UUID of the HW group to delete */
	var location = flag.String("l", "", "Data center location if using HW Group-Name")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options]  <HW Group-Name or UUID>\n", path.Base(os.Args[0]))
		flag.PrintDefaults()
	}
	flag.Parse()
	if flag.NArg() != 1 {
		flag.Usage()
		os.Exit(1)
	}

	client, err := clcv2.NewCLIClient()
	if err != nil {
		exit.Fatal(err.Error())
	}

	/* If the first argument decodes as a hex value, assume it is a Hardware Group UUID */
	if _, err := hex.DecodeString(flag.Arg(0)); err == nil {
		uuid = flag.Arg(0)
	} else if *location == "" {
		exit.Errorf("Need a location (-l argument) when not using a HW Group UUID")
	} else {
		fmt.Printf("Resolving group UUID of %s in %s ...\n", flag.Arg(0), *location)
		if grp, err := client.GetGroupByName(flag.Arg(0), *location); err != nil {
			exit.Errorf("failed to resolve group name %q: %s", flag.Arg(0), err)
		} else if grp == nil {
			exit.Errorf("No group named %q was found in %s", flag.Arg(0), *location)
		} else {
			uuid = grp.Id
		}
	}

	reqId, err := client.DeleteGroup(uuid)
	if err != nil {
		exit.Fatalf("failed to delete hardware group: %s", err)
	}

	fmt.Printf("Status ID for group deletion: %s\n", reqId)
}
Beispiel #9
0
func main() {
	var (
		query    = flag.String("q", "none", "Filter IP addresses; one of 'none', 'claimed', 'free', or 'all'")
		location = flag.String("l", os.Getenv("CLC_LOCATION"), "Data centre alias (needed to resolve IDs)")
		simple   = flag.Bool("simple", false, "Use simple (debugging) output format")
	)

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options] -l <Location>  <Network-ID (hex)>\n", path.Base(os.Args[0]))
		flag.PrintDefaults()
	}

	flag.Parse()
	/* Location is required (despite hex id), an empty location leads to a "404 Not Found" response. */
	if flag.NArg() != 1 || *location == "" {
		flag.Usage()
		os.Exit(1)
	} else if !inStringArray(*query, "none", "claimed", "free", "all") {
		exit.Errorf("Invalid IP query %q. Try -h")
	}

	client, err := clcv2.NewCLIClient()
	if err != nil {
		exit.Fatal(err.Error())
	}

	details, err := client.GetNetworkDetails(*location, flag.Arg(0), *query)
	if err != nil {
		exit.Fatalf("failed to query network details of %s: %s", flag.Arg(0), err)
	}

	if *simple {
		pretty.Println(details)
	} else {
		fmt.Printf("Details of %s (%s):\n", details.Name, details.Description)
		fmt.Printf("CIDR:    %s\n", details.Cidr)
		fmt.Printf("Gateway: %s\n", details.Gateway)
		fmt.Printf("Type:    %s\n", details.Type)
		fmt.Printf("VLAN:    %d\n", details.Vlan)

		if len(details.IpAddresses) > 0 {
			table := tablewriter.NewWriter(os.Stdout)
			table.SetAutoFormatHeaders(false)
			table.SetAlignment(tablewriter.ALIGN_RIGHT)
			table.SetAutoWrapText(false)

			table.SetHeader([]string{"Address", "Claimed", "Server", "Type"})
			for _, i := range details.IpAddresses {
				table.Append([]string{i.Address, fmt.Sprint(i.Claimed), i.Server, i.Type})
			}
			table.Render()
		}
	}
}
Beispiel #10
0
func main() {
	var group = flag.String("g", "", "UUID or name of the new parent group")
	var location = flag.String("l", "", "Location to use if -g refers to a Group-Name")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options]  <server-name>\n", path.Base(os.Args[0]))
		flag.PrintDefaults()
	}

	flag.Parse()
	if flag.NArg() != 1 || *group == "" {
		flag.Usage()
		os.Exit(1)
	}

	client, err := clcv2.NewCLIClient()
	if err != nil {
		exit.Fatal(err.Error())
	}

	if _, err := hex.DecodeString(*group); err == nil {
		/* Looks like a Group UUID */
	} else if *location == "" {
		exit.Errorf("Need a location argument (-l) if -g (%s) is not a UUID", *group)
	} else {
		if grp, err := client.GetGroupByName(*group, *location); err != nil {
			exit.Errorf("failed to resolve group name %q: %s", *group, err)
		} else if grp == nil {
			exit.Errorf("No group named %q was found in %s", *group, *location)
		} else {
			*group = grp.Id
		}
	}

	err = client.ServerSetGroup(flag.Arg(0), *group)
	if err != nil {
		exit.Fatalf("failed to change the parent group on %q: %s", flag.Arg(0), err)
	}

	fmt.Printf("Successfully changed the parent group of %s to %s.\n", flag.Arg(0), *group)
}
Beispiel #11
0
func main() {
	var location = flag.String("l", "", "Location to use if using a Group-Name instead of a UUID")
	var uuid string

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options]  <Group Name or UUID>\n", path.Base(os.Args[0]))
		flag.PrintDefaults()
	}

	flag.Parse()
	if flag.NArg() != 1 {
		flag.Usage()
		os.Exit(1)
	}

	client, err := clcv2.NewCLIClient()
	if err != nil {
		exit.Fatal(err.Error())
	}

	if _, err := hex.DecodeString(flag.Arg(0)); err == nil {
		uuid = flag.Arg(0)
	} else if *location == "" {
		exit.Errorf("Need a location argument (-l) if not using Group UUID (%s)", flag.Arg(0))
	} else {
		if grp, err := client.GetGroupByName(flag.Arg(0), *location); err != nil {
			exit.Errorf("failed to resolve group name %q: %s", flag.Arg(0), err)
		} else if grp == nil {
			exit.Errorf("No group named %q was found in %s", flag.Arg(0), *location)
		} else {
			uuid = grp.Id
		}
	}

	statusId, err := client.ArchiveGroup(uuid)
	if err != nil {
		exit.Fatalf("failed to archive group %s: %s", flag.Arg(0), err)
	}

	fmt.Println("Request ID for archiving group:", statusId)
}
Beispiel #12
0
func main() {
	var group string /* UUID of the group to change */
	var newName = flag.String("n", "", "New name for the group")
	var location = flag.String("l", "", "Location to use if using a Group-Name instead of a UUID")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options]  <Group Name or UUID>\n", path.Base(os.Args[0]))
		flag.PrintDefaults()
	}

	flag.Parse()
	if flag.NArg() != 1 || *newName == "" {
		flag.Usage()
		os.Exit(1)
	}

	client, err := clcv2.NewCLIClient()
	if err != nil {
		exit.Fatal(err.Error())
	}

	if _, err := hex.DecodeString(flag.Arg(0)); err == nil {
		group = flag.Arg(0)
	} else if *location == "" {
		exit.Errorf("Need a location argument (-l) if not using Group UUID (%s)", flag.Arg(0))
	} else {
		if grp, err := client.GetGroupByName(flag.Arg(0), *location); err != nil {
			exit.Errorf("failed to resolve group name %q: %s", flag.Arg(0), err)
		} else if grp == nil {
			exit.Errorf("No group named %q was found in %s", flag.Arg(0), *location)
		} else {
			group = grp.Id
		}
	}

	if err = client.GroupSetName(group, *newName); err != nil {
		exit.Fatalf("failed to change the name of %q: %s", flag.Arg(0), err)
	}

	fmt.Printf("Successfully changed the name of %s to %q.\n", flag.Arg(0), *newName)
}
Beispiel #13
0
// Collapse an unsorted array @in of IPv4 addresses into sorted ranges in @out.
func CollapseIpRanges(in []string) (out []string) {
	var start, end, prev net.IP
	var ips []net.IP

	for _, ip_string := range in {
		ip := net.ParseIP(ip_string)
		if ip == nil {
			exit.Errorf("Invalid IP address %q", ip_string)
		}
		ip = ip.To4()
		if ip == nil {
			exit.Errorf("Not an IPv4 address: %q", ip_string)
		}
		ips = append(ips, ip)
	}
	sort.Stable(byIPv4Address(ips))

	for _, ip := range ips {
		if prev != nil && reflect.DeepEqual(ip[:3], prev[:3]) && ip[3] == prev[3]+1 {
			end = ip
		} else {
			if end != nil {
				out = append(out, fmt.Sprintf("%s-%d", start, end[3]))
				end = nil
			} else if prev != nil {
				out = append(out, prev.String())
			}
			start = ip
		}
		prev = ip
	}
	if end != nil {
		out = append(out, fmt.Sprintf("%s-%d", start, end[3]))
	}

	return out
}
Beispiel #14
0
func main() {
	var child string /* UUID of the group to relocate */
	var parent = flag.String("g", "", "UUID or name of the new parent group")
	var location = flag.String("l", "", "Location to use if using Group Name instead of UUID")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options]  <Group Name or UUID>\n", path.Base(os.Args[0]))
		flag.PrintDefaults()
	}

	flag.Parse()
	if flag.NArg() != 1 || *parent == "" {
		flag.Usage()
		os.Exit(1)
	}

	client, err := clcv2.NewCLIClient()
	if err != nil {
		exit.Fatal(err.Error())
	}

	if _, err := hex.DecodeString(flag.Arg(0)); err == nil {
		child = flag.Arg(0)
	} else if *location == "" {
		exit.Errorf("Need a location argument (-l) if not using Group UUID (%s)", flag.Arg(0))
	} else {
		if grp, err := client.GetGroupByName(flag.Arg(0), *location); err != nil {
			exit.Errorf("failed to resolve group name %q: %s", flag.Arg(0), err)
		} else if grp == nil {
			exit.Errorf("No group named %q was found in %s", flag.Arg(0), *location)
		} else {
			child = grp.Id
		}
	}

	if _, err := hex.DecodeString(*parent); err == nil {
		/* Looks like a Group UUID */
	} else if *location == "" {
		exit.Errorf("Need a location argument (-l) if parent (-g %s) is not a UUID", *parent)
	} else {
		if grp, err := client.GetGroupByName(*parent, *location); err != nil {
			exit.Errorf("failed to resolve group name %q: %s", *parent, err)
		} else if grp == nil {
			exit.Errorf("No group named %q was found in %s", *parent, *location)
		} else {
			*parent = grp.Id
		}
	}

	err = client.GroupSetParent(child, *parent)
	if err != nil {
		exit.Fatalf("failed to change the parent group of %q: %s", flag.Arg(0), err)
	}

	fmt.Printf("Successfully changed the parent group of %s to %s.\n", flag.Arg(0), *parent)
}
Beispiel #15
0
func main() {
	var acctAlias = flag.String("a", "", "Account alias of the account in question")
	var location = flag.String("l", "", "Data center location of @Group-Name")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options]  <Group-Name>\n", path.Base(os.Args[0]))
		flag.PrintDefaults()
	}
	flag.Parse()

	if flag.NArg() != 1 || *location == "" {
		flag.Usage()
		os.Exit(1)
	}

	client, err := clcv1.NewClient(log.New(os.Stdout, "", log.LstdFlags|log.Ltime))
	if err != nil {
		exit.Fatal(err.Error())
	} else if err := client.Logon("", ""); err != nil {
		exit.Fatalf("Login failed: %s", err)
	}

	groups, err := client.GetGroups(*location, *acctAlias)
	if err != nil {
		exit.Fatalf("Failed to obtain hardware groups: %s", err)
	}

	if len(groups) == 0 {
		exit.Errorf("Empty result.")
	}

	table := tablewriter.NewWriter(os.Stdout)
	table.SetAutoFormatHeaders(false)
	table.SetAlignment(tablewriter.ALIGN_LEFT)
	table.SetAutoWrapText(true)
	table.SetHeader([]string{"Name", "UUID", "Parent UUID", "System Group?"})
	for _, g := range groups {
		if g.Name == flag.Arg(0) {
			table.Append([]string{g.Name, g.UUID, g.ParentUUID, fmt.Sprint(g.IsSystemGroup)})
		}
	}

	table.Render()
}
Beispiel #16
0
// Show group details
// @client:    authenticated CLCv1 Client
// @uuid:      hardware group UUID to use
// @acctAlias: account alias to use (leave blank to use default)
// @location:  data centre location (needed to resolve @uuid)
func showGroup(client *clcv1.Client, uuid, acctAlias, location string) {
	if location == "" {
		exit.Errorf("Location is required in order to show the group hierarchy starting at %s", uuid)
	}
	root, err := client.GetGroupHierarchy(location, acctAlias, true)
	if err != nil {
		exit.Fatalf("Failed to look up groups at %s: %s", location, err)
	}
	start := root
	if uuid != "" {
		start = clcv1.FindGroupNode(root, func(g *clcv1.GroupNode) bool {
			return g.UUID == uuid
		})
		if start == nil {
			exit.Fatalf("Failed to look up UUID %s at %s", uuid, location)
		}
	}
	clcv1.PrintGroupHierarchy(start, "")
}
Beispiel #17
0
func main() {
	var uuid string
	var simple = flag.Bool("simple", false, "Use simple (debugging) output format")
	var location = flag.String("l", "", "Location to use if using a Group-Name instead of a UUID")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options]  <Group Name or UUID>\n", path.Base(os.Args[0]))
		flag.PrintDefaults()
	}
	flag.Parse()

	if flag.NArg() != 1 {
		flag.Usage()
		os.Exit(1)
	}

	client, err := clcv2.NewCLIClient()
	if err != nil {
		exit.Fatal(err.Error())
	}

	if _, err := hex.DecodeString(flag.Arg(0)); err == nil {
		uuid = flag.Arg(0)
	} else if *location == "" {
		exit.Errorf("Need a location argument (-l) if not using Group UUID (%s)", flag.Arg(0))
	} else {
		if grp, err := client.GetGroupByName(flag.Arg(0), *location); err != nil {
			exit.Errorf("failed to resolve group name %q: %s", flag.Arg(0), err)
		} else if grp == nil {
			exit.Errorf("No group named %q was found in %s", flag.Arg(0), *location)
		} else {
			uuid = grp.Id
		}
	}

	bd, err := client.GetGroupBillingDetails(uuid)
	if err != nil {
		exit.Fatalf("failed to query billing details of group %s: %s", flag.Arg(0), err)
	}

	if *simple {
		pretty.Println(bd)
	} else {
		var totalMonthTod, totalMonthEst float64

		if rootGroup, ok := bd.Groups[uuid]; !ok {
			exit.Fatalf("Query result does not contain queried group %s", uuid)
		} else {
			fmt.Printf("Billing details of %s as of %s:\n", rootGroup.Name,
				bd.Date.Format("Monday, 2 Jan 2006, 15:04 MST"))
		}

		for k, v := range bd.Groups {
			if k == uuid || len(v.Servers) == 0 {
				continue
			}
			fmt.Printf("\nServer details of %q (%s):\n", v.Name, k)

			table := tablewriter.NewWriter(os.Stdout)
			table.SetAutoFormatHeaders(false)
			table.SetAlignment(tablewriter.ALIGN_RIGHT)
			table.SetAutoWrapText(true)

			table.SetHeader([]string{"Server", "Template Cost", "Archive Cost", "Current Hour",
				"Month to Date", "Monthly Estimate"})

			for s, sbd := range v.Servers {
				table.Append([]string{strings.ToUpper(s),
					fmt.Sprintf("$%.2f", sbd.TemplateCost),
					fmt.Sprintf("$%.2f", sbd.ArchiveCost),
					fmt.Sprintf("$%.2f", sbd.CurrentHour),
					fmt.Sprintf("$%.2f", sbd.MonthToDate),
					fmt.Sprintf("$%.2f", sbd.MonthlyEstimate),
				})
				totalMonthTod += sbd.MonthToDate
				totalMonthEst += sbd.MonthlyEstimate
			}
			table.Render()
		}

		fmt.Printf("\nTotal month to date:    $%.2f\n", totalMonthTod)
		fmt.Printf("Total monthly estimate: $%.2f\n", totalMonthEst)
	}
}
Beispiel #18
0
func main() {
	var uuid string
	var simple = flag.Bool("simple", false, "Use simple (debugging) output format")
	var location = flag.String("l", "", "Location to use if using a Group-Name instead of a UUID")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options]  <Group Name or UUID>\n", path.Base(os.Args[0]))
		flag.PrintDefaults()
	}
	flag.Parse()

	if flag.NArg() != 1 {
		flag.Usage()
		os.Exit(1)
	}

	client, err := clcv2.NewCLIClient()
	if err != nil {
		exit.Fatal(err.Error())
	}

	if _, err := hex.DecodeString(flag.Arg(0)); err == nil {
		uuid = flag.Arg(0)
	} else if *location == "" {
		exit.Errorf("Need a location argument (-l) if not using Group UUID (%s)", flag.Arg(0))
	} else {
		if grp, err := client.GetGroupByName(flag.Arg(0), *location); err != nil {
			exit.Errorf("failed to resolve group name %q: %s", flag.Arg(0), err)
		} else if grp == nil {
			exit.Errorf("No group named %q was found in %s", flag.Arg(0), *location)
		} else {
			uuid = grp.Id
		}
	}

	rootNode, err := client.GetGroup(uuid)
	if err != nil {
		exit.Fatalf("failed to query HW group %s: %s", flag.Arg(0), err)
	}

	if *simple {
		pretty.Println(rootNode)
	} else {
		fmt.Printf("Group %q in %s:\n", rootNode.Name, rootNode.LocationId)
		fmt.Printf("ID:            %s\n", rootNode.Id)
		fmt.Printf("Description:   %s\n", rootNode.Description)
		fmt.Printf("Type:          %s\n", rootNode.Type)
		fmt.Printf("Status:        %s\n", rootNode.Status)

		if len(rootNode.CustomFields) > 0 {
			fmt.Println("Custom fields:", rootNode.CustomFields)
		}

		// ChangeInfo
		createdStr := humanize.Time(rootNode.ChangeInfo.CreatedDate)
		/* The CreatedBy field can be an email address, or an API Key (hex string) */
		if _, err := hex.DecodeString(rootNode.ChangeInfo.CreatedBy); err == nil {
			createdStr += " via API Key"
		} else {
			createdStr += " by " + rootNode.ChangeInfo.CreatedBy
		}
		fmt.Printf("Created:       %s\n", createdStr)

		modifiedStr := humanize.Time(rootNode.ChangeInfo.ModifiedDate)
		/* The ModifiedBy field can be an email address, or an API Key (hex string) */
		if _, err := hex.DecodeString(rootNode.ChangeInfo.ModifiedBy); err == nil {
			modifiedStr += " via API Key"
		} else {
			modifiedStr += " by " + rootNode.ChangeInfo.ModifiedBy
		}
		fmt.Printf("Modified:      %s\n", modifiedStr)

		// Servers
		fmt.Printf("#Servers:      %d\n", rootNode.Serverscount)
		if rootNode.Serverscount > 0 {
			var servers []string

			if sl := clcv2.ExtractLinks(rootNode.Links, "server"); len(sl) > 0 {
				for _, s := range sl {
					servers = append(servers, s.Id)
				}
				fmt.Printf("Servers:       %s\n", strings.Join(servers, ", "))
			}
		}

		// Sub-groups
		if len(rootNode.Groups) > 0 {
			fmt.Printf("\nGroups of %s:\n", rootNode.Name)
			table := tablewriter.NewWriter(os.Stdout)
			table.SetAutoFormatHeaders(false)
			table.SetAlignment(tablewriter.ALIGN_LEFT)
			table.SetAutoWrapText(true)

			table.SetHeader([]string{"Name", "UUID", "Description", "#Servers", "Type"})
			for _, g := range rootNode.Groups {
				table.Append([]string{g.Name, g.Id, g.Description, fmt.Sprint(g.Serverscount), g.Type})
			}
			table.Render()
		} else {
			fmt.Printf("Sub-groups:    none\n")
		}

	}
}
Beispiel #19
0
func main() {
	var net = flag.String("net", "", "ID or name of the Network to use (if different from source)")
	var hwGroup = flag.String("g", "", "UUID or name (if unique) of the HW group to clone this server into")
	var primDNS = flag.String("dns1", "8.8.8.8", "Primary DNS to use")
	var secDNS = flag.String("dns2", "8.8.4.4", "Secondary DNS to use")
	var numCpu = flag.Int("cpu", 0, "Number of Cpus to use (if different from source VM)")
	var memGB = flag.Int("memory", 0, "Amount of memory in GB (if different from source VM")
	var seed = flag.String("name", "", "The 4-6 character seed for the name of the cloned server")
	var desc = flag.String("desc", "", "Description of the cloned server")
	var ttl = flag.Duration("ttl", 0, "Time span (counting from time of creation) until server gets deleted")
	var extraDrv = flag.Int("drive", 0, "Extra storage (in GB) to add to server as a raw disk")
	var wasStopped bool
	var maxAttempts = 1
	var url, reqID string

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options] <Source-Server-Name>\n", path.Base(os.Args[0]))
		flag.PrintDefaults()
	}

	flag.Parse()
	if flag.NArg() != 1 {
		flag.Usage()
		os.Exit(0)
	}

	client, err := clcv2.NewCLIClient()
	if err != nil {
		exit.Fatal(err.Error())
	}

	// First get the details of the source server
	log.Printf("Obtaining details of source server %s ...", flag.Arg(0))
	src, err := client.GetServer(flag.Arg(0))
	if err != nil {
		exit.Fatalf("failed to list details of source server %q: %s", flag.Arg(0), err)
	}

	if wasStopped = src.Details.PowerState == "stopped"; wasStopped {
		// The source server must be powered on
		log.Printf("%s is powered-off - powering on ...", src.Name)
		reqID, err := client.PowerOnServer(src.Name)
		if err != nil {
			exit.Fatalf("failed to power on source server %s: %s", src.Name, err)
		}
		log.Printf("Waiting for %s to power on (status ID: %s) ...", src.Name, reqID)
		if _, err = client.AwaitCompletion(reqID); err != nil {
			exit.Fatalf("failed to await completion of %s: %s", reqID, err)
		}
		// When the server is being powered on, it can take up to 5 minutes until
		// the backend is able to clone it; it requires the server to be fully booted.
		maxAttempts = 5
		time.Sleep(1 * time.Minute)
	}

	// We need the credentials, too
	log.Printf("Obtaining %s credentials ...", src.Name)
	credentials, err := client.GetServerCredentials(src.Name)
	if err != nil {
		exit.Fatalf("failed to obtain the credentials of server %q: %s", src.Name, err)
	}

	req := clcv2.CreateServerReq{
		Name:                 *seed,
		Cpu:                  src.Details.Cpu,
		MemoryGB:             src.Details.MemoryMb >> 10,
		GroupId:              src.GroupId,
		SourceServerId:       src.Name,
		PrimaryDns:           *primDNS,
		SecondaryDns:         *secDNS,
		Password:             credentials.Password,
		SourceServerPassword: credentials.Password,

		Type: src.Type,
	}

	if *seed == "" {
		if l := len(src.Name); l > 10 { // use same naming as original by default
			req.Name = src.Name[7 : l-1]
		} else {
			req.Name = "CLONE"
		}
	}

	if *numCpu != 0 {
		req.Cpu = *numCpu
	}
	if *memGB != 0 {
		req.MemoryGB = *memGB
	}

	if *desc != "" {
		req.Description = *desc
	} else if src.Description == "" {
		req.Description = fmt.Sprintf("Clone of %s", src.Name)
	} else {
		req.Description = fmt.Sprintf("%s (cloned from %s)", src.Description, src.Name)
	}

	if *extraDrv != 0 {
		req.AdditionalDisks = append(req.AdditionalDisks,
			clcv2.ServerAdditionalDisk{SizeGB: uint32(*extraDrv), Type: "raw"})
	}
	if *ttl != 0 { /* Date/time that the server should be deleted. */
		req.Ttl = new(time.Time)
		*req.Ttl = time.Now().Add(*ttl)
	}

	/* hwGroup may be hex uuid or group name */
	if *hwGroup != "" {
		req.GroupId = *hwGroup

		if _, err := hex.DecodeString(*hwGroup); err != nil {
			log.Printf("Resolving ID of Hardware Group %q in %s ...", *hwGroup, src.LocationId)

			if group, err := client.GetGroupByName(*hwGroup, src.LocationId); err != nil {
				exit.Fatalf("failed to resolve group name %q: %s", *hwGroup, err)
			} else if group == nil {
				exit.Errorf("No group named %q was found in %s", *hwGroup, src.LocationId)
			} else {
				req.GroupId = group.Id
			}
		}
	}

	/* net is supposed to be a (hex) ID, but allow network names, too */
	if *net == "" {
		log.Printf("Determining network ID used by %s ...", src.Name)

		if nets, err := client.GetServerNets(src); err != nil {
			exit.Fatalf("failed to query networks of %s: %s", src.Name, err)
		} else if len(nets) == 0 {
			// No network information found for the server, even though it has an IP.
			// This can happen when the server is owned by a sub-account, and uses a
			// network that is owned by the parent account. In this case, the sub-account
			// is prevented from querying details of the parent account, due to insufficient
			// permission.
			log.Printf("Unable to determine network details - querying %s deployable networks ...", src.LocationId)
			capa, err := client.GetDeploymentCapabilities(src.LocationId)
			if err != nil {
				exit.Fatalf("failed to determine %s Deployment Capabilities: %s", src.LocationId, err)
			}
			fmt.Println("Please specify the network ID for the clone manually via -net, using this information:")
			table := tablewriter.NewWriter(os.Stdout)
			table.SetAutoFormatHeaders(false)
			table.SetAlignment(tablewriter.ALIGN_LEFT)
			table.SetAutoWrapText(false)

			table.SetHeader([]string{"Name", "Type", "Account", "Network ID"})
			for _, net := range capa.DeployableNetworks {
				table.Append([]string{net.Name, net.Type, net.AccountID, net.NetworkId})
			}

			table.Render()
			os.Exit(0)
		} else if len(nets) != 1 {
			// FIXME: print server networks
			exit.Errorf("please specify which network to use (%s uses %d)", src.Name, len(nets))
		} else {
			req.NetworkId = nets[0].Id
		}
	} else if _, err := hex.DecodeString(*net); err != nil { // not a HEX ID, treat as group name
		log.Printf("Resolving network ID of %q in %s ...", *net, src.LocationId)

		if netw, err := client.GetNetworkIdByName(*net, src.LocationId); err != nil {
			exit.Fatalf("failed to resolve network name %q: %s", *net, err)
		} else if netw == nil {
			exit.Fatalf("unable to resolve network name %q in %s - maybe use hex ID?", *net, src.LocationId)
		} else {
			req.NetworkId = netw.Id
		}
	} else { // HEX ID, use directoy
		req.NetworkId = *net
	}

	log.Printf("Cloning %s ...", src.Name)
	for i := 1; ; i++ {
		url, reqID, err = client.CreateServer(&req)
		if err == nil || i == maxAttempts || strings.Index(err.Error(), "body.sourceServerId") > 0 {
			break
		}
		log.Printf("attempt %d/%d failed (%s) - retrying ...", i, maxAttempts, strings.TrimSpace(err.Error()))
		time.Sleep(1 * time.Minute)
	}
	if err != nil {
		exit.Fatalf("failed to create server: %s", err)
	}

	log.Printf("Status Id: %s\n", reqID)
	status, err := client.PollStatus(reqID, 5*time.Second)
	if err != nil {
		exit.Fatalf("failed to poll %s status: %s", reqID, err)
	}

	server, err := client.GetServerByURI(url)
	if err != nil {
		log.Fatalf("failed to query server details at %s: %s", url, err)
	} else if status == clcv2.Failed {
		exit.Fatalf("failed to clone %s (will show up as 'under construction')", server.Name)
	}
	log.Printf("New server name: %s\n", server.Name)
	log.Printf("Server Password: \"%s\"\n", credentials.Password)
}
Beispiel #20
0
func main() {
	var net = flag.String("net", "", "ID or name of the Network to use (required)")
	var location = flag.String("l", "", "Data centre alias (to resolve network name if not using hex ID)")
	var ip = flag.String("ip", "", "IP address on -net (optional, default is automatic assignment)")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options] <Server-Name>\n", path.Base(os.Args[0]))
		flag.PrintDefaults()
	}

	flag.Parse()
	if flag.NArg() != 1 {
		flag.Usage()
		os.Exit(0)
	}

	client, err := clcv2.NewCLIClient()
	if err != nil {
		exit.Fatal(err.Error())
	}

	/* net is supposed to be a (hex) ID, but allow network names, too */
	if *net != "" {
		if _, err := hex.DecodeString(*net); err == nil {
			/* already looks like a HEX ID */
		} else {
			fmt.Printf("Resolving network id of %q ...\n", *net)
			if *location == "" {
				fmt.Printf("Querying location details of %s ...\n", flag.Arg(0))
				src, err := client.GetServer(flag.Arg(0))
				if err != nil {
					exit.Fatalf("failed to list details of server %q: %s", flag.Arg(0), err)
				}
				*location = src.LocationId
			}
			if netw, err := client.GetNetworkIdByName(*net, *location); err != nil {
				exit.Errorf("failed to resolve network name %q: %s", *net, err)
			} else if netw == nil {
				exit.Errorf("no network named %q was found in %s", *net, *location)
			} else {
				*net = netw.Id
			}
		}
	} else { /* Network ID is mandatory for this request to complete. */
		var IPs []string

		fmt.Println("This request requires a network ID via -net:")

		fmt.Printf("Querying details of %s ...\n", flag.Arg(0))
		src, err := client.GetServer(flag.Arg(0))
		if err != nil {
			exit.Fatalf("failed to list details of server %q: %s", flag.Arg(0), err)
		}
		*location = src.LocationId

		for _, ip := range src.Details.IpAddresses {
			if ip.Internal != "" {
				IPs = append(IPs, ip.Internal)
			}
		}
		fmt.Printf("%s current IP configuration: %s\n", flag.Arg(0), strings.Join(IPs, ", "))

		fmt.Printf("Querying available networks in %s ...\n", *location)
		capa, err := client.GetDeploymentCapabilities(*location)
		if err != nil {
			exit.Fatalf("failed to determine deployable networks in %s: %s", *location, err)
		}
		fmt.Printf("These are the networks deployable in %s:\n", *location)

		table := tablewriter.NewWriter(os.Stdout)
		table.SetAutoFormatHeaders(false)
		table.SetAlignment(tablewriter.ALIGN_LEFT)
		table.SetAutoWrapText(false)

		table.SetHeader([]string{"Name", "Type", "Account", "Network ID"})
		for _, net := range capa.DeployableNetworks {
			table.Append([]string{net.Name, net.Type, net.AccountID, net.NetworkId})
		}

		table.Render()
		exit.Errorf("please specify a network ID via -net (using the selection above).")
	}

	if err = client.ServerAddNic(flag.Arg(0), *net, *ip); err != nil {
		exit.Fatalf("failed to add NIC to %s: %s", flag.Arg(0), err)
	}

	fmt.Printf("Successfully added a secondary NIC to %s.\n", flag.Arg(0))
}
Beispiel #21
0
func main() {
	var group string /* UUID of the group to set defaults of */
	var location = flag.String("l", "", "Location to use if using a Group-Name instead of a UUID")
	var template = flag.String("t", "", "Name of the template to use as the source")
	var numCpu = flag.Int("cpu", 1, "Number of Cpus to use (1-16)")
	var memGB = flag.Int("mem", 4, "Amount of memory in GB (1-128)")
	var net = flag.String("net", "", "Name of the Network to use")
	var primDNS = flag.String("dns1", "8.8.8.8", "Primary DNS to use")
	var secDNS = flag.String("dns2", "8.8.4.4", "Secondary DNS to use")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options]  <Group Name or UUID>\n", path.Base(os.Args[0]))
		flag.PrintDefaults()
	}

	flag.Parse()
	if flag.NArg() != 1 {
		flag.Usage()
		os.Exit(0)
	}

	client, err := clcv2.NewCLIClient()
	if err != nil {
		exit.Fatal(err.Error())
	}

	if _, err := hex.DecodeString(flag.Arg(0)); err == nil {
		group = flag.Arg(0)
	} else if *location == "" {
		exit.Errorf("Need a location argument (-l) if not using Group UUID (%s)", flag.Arg(0))
	} else {
		fmt.Printf("Resolving group id of %q ...\n", flag.Arg(0))
		if grp, err := client.GetGroupByName(flag.Arg(0), *location); err != nil {
			exit.Errorf("failed to resolve group name %q: %s", flag.Arg(0), err)
		} else if grp == nil {
			exit.Errorf("No group named %q was found in %s", flag.Arg(0), *location)
		} else {
			group = grp.Id
		}
	}
	if *net != "" {
		if _, err := hex.DecodeString(*net); err == nil {
			/* already looks like a HEX ID */
		} else if *location == "" {
			exit.Errorf("Need a location argument (-l) if not using a network ID (%s)", *net)
		} else {
			fmt.Printf("Resolving network id of %q ...\n", *net)

			if netw, err := client.GetNetworkIdByName(*net, *location); err != nil {
				exit.Errorf("failed to resolve network name %q: %s", *net, err)
			} else if netw == nil {
				exit.Errorf("No network named %q was found in %s", *net, *location)
			} else {
				*net = netw.Id
			}
		}
	}

	req := clcv2.GroupDefaults{
		Cpu:          *numCpu,
		MemoryGB:     *memGB,
		NetworkId:    *net,
		PrimaryDns:   *primDNS,
		SecondaryDns: *secDNS,
		TemplateName: *template,
	}

	settings, err := client.SetGroupDefaults(group, &req)
	if err != nil {
		exit.Fatalf("failed to set group defaults of %s: %s", flag.Arg(0), err)
	}

	table := tablewriter.NewWriter(os.Stdout)
	table.SetAutoFormatHeaders(false)
	table.SetAlignment(tablewriter.ALIGN_RIGHT)
	table.SetAutoWrapText(false)

	table.SetHeader([]string{"Default", "Value", "Inherited"})
	for k, v := range settings {
		table.Append([]string{strings.Title(k), fmt.Sprint(v.Value), fmt.Sprint(v.Inherited)})
	}
	table.Render()
}
Beispiel #22
0
func main() {
	var hwGroup = flag.String("g", "", "UUID or name (if unique) of the HW group to add this server to")
	var location = flag.String("l", "", "Data centre alias")
	var acctAlias = flag.String("a", "", "Account alias to use")
	var template = flag.String("t", "", "The name of the template to create the server from")
	var seed = flag.String("s", "AUTO", "The seed for the server name (max 6 characters)")
	var desc = flag.String("D", "", "Description of the server")

	var net = flag.String("net", "", "Name of the Network to use")
	var primDNS = flag.String("dns1", "8.8.8.8", "Primary DNS to use")
	var secDNS = flag.String("dns2", "8.8.4.4", "Secondary DNS to use")
	var password = flag.String("pass", "", "Desired password. Leave blank to auto-generate")

	var extraDrv = flag.Int("drive", 0, "Extra drive (in GB) to add to server. Set to 0 to leave out")
	var numCpu = flag.Int("cpu", 1, "Number of Cpus to use")
	var memGB = flag.Int("memory", 4, "Amount of memory in GB")
	var serverType = flag.Int("type", 1, "The type of server to create (1: Standard, 2: Enterprise)")
	var servLevel = flag.Int("level", 2, "Data storage service level (1: Premium, 2: Standard)")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options]\n", path.Base(os.Args[0]))
		flag.PrintDefaults()
	}

	flag.Parse()
	if *hwGroup == "" || *location == "" || *template == "" || *seed == "" || *net == "" {
		flag.Usage()
		os.Exit(0)
	}

	client, err := clcv1.NewClient(log.New(os.Stdout, "", log.LstdFlags|log.Ltime))
	if err != nil {
		exit.Fatal(err.Error())
	} else if err := client.Logon("", ""); err != nil {
		exit.Fatalf("Login failed: %s", err)
	}

	req := clcv1.CreateServerReq{
		// The alias of the account to own the server.
		// If not provided it will assume the account to which the API user is mapped.
		// Providing this value gives you the ability to create servers in your sub accounts. (optional)
		AccountAlias: *acctAlias,

		// The alias of the data center in which to create the server.
		// If not provided, will default to the API user's default data center.
		// NOTE: empty value can cause error if location is not the same as HWUUID's
		LocationAlias: *location,

		// The name of the template to create the server from (required)
		Template: *template,

		// The alias for the server. Limit 6 charcters (required)
		Alias: *seed,

		// An optional description for the server. If none is supplied the server name will be used. (optional)
		Description: *desc,

		// The unique identifier of the Hardware Group to add this server to (required)
		HardwareGroupUUID: *hwGroup,

		//The type of server to create (required)
		ServerType: *serverType,

		// The service level/performance for the underlying data store (required)
		ServiceLevel: *servLevel,

		// The number of processors to configure the server with (required)
		Cpu: *numCpu,

		// The number of GB of memory to configure the server with (required)
		MemoryGB: *memGB,

		// The size in GB of an additional drive to add to the server (required).
		// If no additional drive is needed, pass in a 0 value.
		ExtraDriveGB: *extraDrv,

		// The primary DNS to set on the server (optional)
		// If not supplied the default value set on the account will be used.
		PrimaryDns: *primDNS,

		// The secondary DNS to set on the server (optional)
		// If not supplied the default value set on the account will be used.
		SecondaryDns: *secDNS,

		// The name of the network to which to deploy the server.
		// If your account has not yet been assigned a network, leave this blank and one will be assigned automatically.
		// If one or more networks are available, the network name is required.
		Network: *net,

		// The desired Admin/Root password (optional).
		// Please note the password must meet the password strength policy.
		// Leave blank to have the system generate a password
		Password: *password,

		// A list of Custom Fields associated to this server
		// FIXME: not supported yet
		CustomFields: nil,
	}

	/* hwGroup may be hex uuid or group name */
	if _, err := hex.DecodeString(*hwGroup); err != nil {
		if group, err := client.GetGroupByName(*hwGroup, *location, *acctAlias); err != nil {
			exit.Errorf("Failed to resolve group name %q: %s", *hwGroup, err)
		} else if group == nil {
			exit.Errorf("No group named %q was found on %s", *hwGroup, *location)
		} else {
			req.HardwareGroupUUID = group.UUID
		}
	}

	reqId, err := client.CreateServer(&req)
	if err != nil {
		exit.Fatalf("Failed to create server: %s", err)
	}

	fmt.Println("Request ID for server creation:", reqId)
}
Beispiel #23
0
func main() {
	var (
		location       = flag.String("l", os.Getenv("CLC_LOCATION"), "Data centre alias (needed to resolve IDs)")
		intvl          = flag.Duration("i", 1*time.Second, "Poll interval for status updates (use 0 to disable)")
		handlingServer bool   // what to act on
		action, where  string // what to do and where
		reqID          string // request ID of the action
	)

	/*
	 * Argument Validation
	 */
	flag.Usage = usage
	flag.Parse()

	if flag.NArg() >= 1 {
		action = flag.Arg(0)
		if flag.NArg() > 1 {
			where = flag.Arg(1)
		}
	} else {
		usage()
	}

	switch action {
	case "help":
		usage()
	case "networks", "templates", "show":
		// Omit location warning here, will be displayed after client is initialized.
	case "credentials":
		handlingServer = true
	case "memory":
		handlingServer = true
		if flag.NArg() != 3 {
			exit.Errorf("usage: password <serverName> <memoryGB>")
		}
	case "password":
		handlingServer = true
		if flag.NArg() < 2 {
			exit.Errorf("usage: password <serverName> [<new-password>]")
		}
	case "description":
		handlingServer = true
		if flag.NArg() < 2 {
			exit.Errorf("usage: description <serverName> <descriptive-text")
		}
	case "rawdisk":
		handlingServer = true
		if flag.NArg() != 3 {
			exit.Errorf("usage: rawdisk <serverName> <diskGB>")
		}
	case "mv":
		if flag.NArg() != 3 {
			exit.Errorf("usage: mv <server|group> <new-Group>")
		}
	case "mkdir":
		if flag.NArg() != 3 {
			exit.Errorf("usage: mkdir <parentGroup> <newGroupName>")
		}
	case "rename":
		if flag.NArg() != 3 {
			exit.Errorf("usage: rename <oldGroupName> <newGroupName>")
		}
	case "ip", "on", "start", "off", "shutdown", "stop", "pause", "reset", "reboot", "snapshot",
		"delsnapshot", "revert", "archive", "delete", "remove", "wait":
		/* FIXME: use map for usage, and use keys here, i.e. _, ok := map[action] */
		if where == "" {
			exit.Errorf("Action %q requires an argument (try -h).", action)
		}
	default:
		exit.Errorf("Unsupported action %q", action)
	}

	client, err := clcv2.NewCLIClient()
	if err != nil {
		exit.Fatal(err.Error())
	}

	if *location == "" {
		if action == "networks" || action == "show" || action == "templates" {
			fmt.Fprintf(os.Stderr, "Note: no location argument (-l) given, defaulting to %s.\n", client.LocationAlias)
		}
		*location = client.LocationAlias
	}

	if !handlingServer && action != "wait" {
		/*
		 * Decide if arguments refer to a server or a hardware group.
		 */
		if _, err := hex.DecodeString(where); err == nil {
			/* If the first argument decodes as a hex value, assume it is a Hardware Group UUID */
		} else if utils.LooksLikeServerName(where) { /* Starts with a location identifier and is not hex ... */
			where = strings.ToUpper(where)
			handlingServer = true
		} else if *location != "" && where != "" {
			if group, err := client.GetGroupByName(where, *location); err != nil {
				exit.Errorf("failed to resolve group name %q: %s", where, err)
			} else if group == nil {
				exit.Errorf("No group named %q was found in %s", where, *location)
			} else {
				where = group.Id
			}
		} else if *location == "" {
			exit.Errorf("%q looks like a group name - need a location (-l argument) to resolve it.", where)
		} else {
			exit.Errorf("Unable to determine whether %q is a server or a group", where)
		}
	}

	if action == "templates" { /* where="" - neither server nor group action; print regional templates */
		showTemplates(client, *location)
		os.Exit(0)
	} else if action == "networks" { /* similar, neither server nor group action; print regional networks */
		showNetworks(client, *location)
		os.Exit(0)
	} else if action == "wait" {
		reqID = flag.Arg(1)
	} else if handlingServer { /* Server Action */
		switch action {
		case "ip":
			printServerIP(client, where)
			os.Exit(0)
		case "show":
			// FIXME: deal with multiple servers
			if flag.NArg() == 2 {
				showServer(client, where)
			} else {
				showServers(client, flag.Args()[1:]...)
			}
			os.Exit(0)
		case "mv":
			var newParent = flag.Arg(2)

			if _, err := hex.DecodeString(newParent); err == nil {
				/* Looks like a Group UUID */
			} else if *location == "" {
				exit.Errorf("Need a location argument (-l) if destination group (%s) is not a UUID", newParent)
			} else {
				if grp, err := client.GetGroupByName(newParent, *location); err != nil {
					exit.Errorf("failed to resolve group name %q: %s", newParent, err)
				} else if grp == nil {
					exit.Errorf("No group named %q was found in %s", newParent, *location)
				} else {
					newParent = grp.Id
				}
			}

			if err = client.ServerSetGroup(where, newParent); err != nil {
				exit.Fatalf("failed to change the parent group on %q: %s", where, err)
			}

			fmt.Printf("Successfully changed the parent group of %s to %s.\n", where, flag.Arg(2))
			os.Exit(0)
		case "memory":
			fmt.Printf("Setting %s memory to %s GB ...\n", where, flag.Arg(2))

			reqID, err = client.ServerSetMemory(where, flag.Arg(2))
			if err != nil {
				exit.Fatalf("failed to change the amount of Memory on %q: %s", where, err)
			}
		case "description":
			fmt.Printf("Setting %s description to to %q.\n", where, flag.Arg(2))

			if err = client.ServerSetDescription(where, flag.Arg(2)); err != nil {
				exit.Fatalf("failed to change the description of %q: %s", where, err)
			}
		case "password":
			var newPassword string

			log.Printf("Looking up existing password of %s", where)

			credentials, err := client.GetServerCredentials(where)
			if err != nil {
				exit.Fatalf("failed to obtain the credentials of %q: %s", where, err)
			}
			log.Printf("Existing %s password: %q", where, credentials.Password)

			if flag.NArg() == 3 {
				newPassword = flag.Arg(2)
			} else if newPassword, err = garbler.NewPassword(&garbler.Paranoid); err != nil {
				exit.Fatalf("failed to generate new 'garbler' password: %s", err)
			} else {
				// The 'Paranoid' mode in garbler more than satisfies CLC requirements.
				// However, the symbols may contain unsupported characters.
				newPassword = strings.Map(func(r rune) rune {
					if strings.Index(clcv2.InvalidPasswordCharacters, string(r)) > -1 {
						return '@'
					}
					return r
				}, newPassword)
				log.Printf("New paranoid 'garbler' password: %q", newPassword)
			}

			if newPassword == credentials.Password {
				log.Printf("%s password is already set to %q", where, newPassword)
				os.Exit(0)
			}

			reqID, err = client.ServerChangePassword(where, credentials.Password, newPassword)
			if err != nil {
				exit.Fatalf("failed to change the password on %q: %s", where, err)
			}
		case "credentials":
			credentials, err := client.GetServerCredentials(where)
			if err != nil {
				exit.Fatalf("failed to obtain the credentials of server %q: %s", where, err)
			}

			fmt.Printf("Credentials for %s:\n", where)
			fmt.Printf("User:     %s\n", credentials.Username)
			fmt.Printf("Password: \"%s\"\n", credentials.Password)
			os.Exit(0)
		case "rawdisk":
			diskGB, err := strconv.ParseUint(flag.Arg(2), 10, 32)
			if err != nil {
				exit.Errorf("rawdisk: invalid disk size in GB %q for %s", flag.Arg(2), where)
			}
			reqID = addRawDisk(client, where, uint32(diskGB))
		default:
			var serverAction = map[string]func(string) (string, error){
				"on":          client.PowerOnServer,
				"start":       client.PowerOnServer, // Alias
				"off":         client.PowerOffServer,
				"pause":       client.PauseServer,
				"reset":       client.ResetServer,
				"reboot":      client.RebootServer,
				"shutdown":    client.ShutdownServer,
				"stop":        client.ShutdownServer, // Alias
				"archive":     client.ArchiveServer,
				"delete":      client.DeleteServer,
				"remove":      client.DeleteServer, // Alias
				"snapshot":    client.SnapshotServer,
				"delsnapshot": client.DeleteSnapshot,
				"revert":      client.RevertToSnapshot,
			}

			/* Long-running commands that return a RequestID */
			handler, ok := serverAction[action]
			if !ok {
				exit.Fatalf("Unsupported server action %s", action)
			}

			reqID, err = handler(where)
			if err != nil {
				exit.Fatalf("Server command %q failed: %s", action, err)
			}
		}
	} else if action == "show" || action == "ip" {
		/* Printing group trees: requires to resolve the root first. */
		var start *clcv2.Group

		if *location == "" {
			exit.Errorf("Location argument (-l) is required in order to traverse nested groups.")
		}

		root, err := client.GetGroups(*location)
		if err != nil {
			exit.Fatalf("failed to look up groups at %s: %s", *location, err)
		}

		start = &root
		if where != "" {
			start = clcv2.FindGroupNode(start, func(g *clcv2.Group) bool {
				return g.Id == where
			})
			if start == nil {
				exit.Fatalf("failed to look up UUID %s in %s - is this the correct value?", where, *location)
			}
		}

		switch action {
		case "show":
			showGroup(client, start)
		case "ip":
			printGroupIPs(client, start)
		}
		os.Exit(0)
	} else {
		/* Other Group Action */
		switch action {
		case "archive":
			reqID, err = client.ArchiveGroup(where)
		case "mkdir":
			g, err := client.CreateGroup(flag.Arg(2), where, flag.Arg(2), nil)
			if err == nil {
				fmt.Printf("New subfolder of %s: %q (UUID: %s)\n", flag.Arg(1), g.Name, g.Id)
			}
		case "delete", "remove":
			reqID, err = client.DeleteGroup(where)
		case "mv":
			var newParent = flag.Arg(2)

			if _, err := hex.DecodeString(newParent); err == nil {
				/* Looks like a Group UUID */
			} else if *location == "" {
				exit.Errorf("Need a location argument (-l) if destination group (%s) is not a UUID", newParent)
			} else {
				if grp, err := client.GetGroupByName(newParent, *location); err != nil {
					exit.Errorf("failed to resolve group name %q: %s", newParent, err)
				} else if grp == nil {
					exit.Errorf("No group named %q was found in %s", newParent, *location)
				} else {
					newParent = grp.Id
				}
			}

			if err = client.GroupSetParent(where, newParent); err != nil {
				exit.Fatalf("failed to change the parent group on %q: %s", where, err)
			}

			fmt.Printf("Successfully changed the parent group of %s to %s.\n", where, flag.Arg(2))
			os.Exit(0)
		case "rename":
			if err = client.GroupSetName(where, flag.Arg(2)); err == nil {
				fmt.Println("OK")
			}
		default:
			exit.Errorf("Unsupported group action %q", action)
		}
		if err != nil {
			exit.Fatalf("Group command %q failed: %s", action, err)
		}
	}

	if reqID != "" {
		client.PollStatus(reqID, *intvl)
	}
}
Beispiel #24
0
func main() {
	var location = flag.String("l", "", "Location to use for <Group-Name>")
	var acctAlias = flag.String("a", "", "Account alias to use (to override default)")
	var serverAction bool
	var action, where string

	flag.Usage = usage
	flag.Parse()

	if flag.NArg() == 2 {
		action, where = flag.Arg(0), flag.Arg(1)
	} else if flag.NArg() == 1 && flag.Arg(0) == "show" {
		if *location == "" {
			exit.Errorf("Showing group details requires location (-l) argument.")
		}
		action = flag.Arg(0)
	} else {
		usage()
	}

	client, err := clcv1.NewClient(log.New(os.Stdout, "", log.LstdFlags|log.Ltime))
	if err != nil {
		exit.Fatal(err.Error())
	} else if err := client.Logon("", ""); err != nil {
		exit.Fatalf("Login failed: %s", err)
	}

	/* If the first argument decodes as a hex value, assume it is a Hardware Group UUID */
	if _, err := hex.DecodeString(where); err == nil {
		serverAction = false
	} else if utils.LooksLikeServerName(where) {
		serverAction = true
		if *location != "" {
			fmt.Fprintf(os.Stderr, "WARNING: location (%s) ignored for %s\n", *location, where)
		}
	} else if *location != "" && where != "" {
		if group, err := client.GetGroupByName(where, *location, *acctAlias); err != nil {
			exit.Errorf("Failed to resolve group name %q: %s", where, err)
		} else if group == nil {
			exit.Errorf("No group named %q was found on %s", where, *location)
		} else {
			where = group.UUID
		}
	} else {
		serverAction = true
	}

	switch action {
	case "show":
		if serverAction {
			showServer(client, where, *acctAlias)
		} else {
			showGroup(client, where, *acctAlias, *location)
		}
		os.Exit(0)
	case "help":
		usage()
	}

	/* Long-running commands that return a RequestID */
	handler, ok := actionMap(serverAction, client)[action]
	if !ok {
		exit.Fatalf("Unsupported action %s", action)
	}

	reqID, err := handler(where, *acctAlias)
	if err != nil {
		exit.Fatalf("Command %q failed: %s", action, err)
	}

	fmt.Printf("Request ID for %q action: %d\n", action, reqID)

	locationStr := *location
	if serverAction {
		locationStr = utils.ExtractLocationFromServerName(where)
	}
	client.PollDeploymentStatus(reqID, locationStr, *acctAlias, 1)
}
Beispiel #25
0
func main() {
	var uuid string
	var simple = flag.Bool("simple", false, "Use simple (debugging) output format")
	var location = flag.String("l", "", "Location to use if using a Group-Name instead of a UUID")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options]  <Group Name or UUID>\n", path.Base(os.Args[0]))
		flag.PrintDefaults()
	}
	flag.Parse()

	if flag.NArg() != 1 {
		flag.Usage()
		os.Exit(1)
	}

	client, err := clcv2.NewCLIClient()
	if err != nil {
		exit.Fatal(err.Error())
	}

	if _, err := hex.DecodeString(flag.Arg(0)); err == nil {
		uuid = flag.Arg(0)
	} else if *location == "" {
		exit.Errorf("Need a location argument (-l) if not using Group UUID (%s)", flag.Arg(0))
	} else {
		if grp, err := client.GetGroupByName(flag.Arg(0), *location); err != nil {
			exit.Errorf("failed to resolve group name %q: %s", flag.Arg(0), err)
		} else if grp == nil {
			exit.Errorf("No group named %q was found in %s", flag.Arg(0), *location)
		} else {
			uuid = grp.Id
		}
	}

	sa, err := client.GetGroupScheduledActivities(uuid)
	if err != nil {
		exit.Fatalf("failed to query billing details of group %s: %s", flag.Arg(0), err)
	}

	if *simple {
		pretty.Println(sa)
	} else {

		table := tablewriter.NewWriter(os.Stdout)
		table.SetAutoFormatHeaders(false)
		table.SetAlignment(tablewriter.ALIGN_RIGHT)
		table.SetAutoWrapText(false)

		table.SetHeader([]string{"Type", "On?", "Exp?",
			"Repeat", "Expire", "Begin", "Next", "#Count", "Days", "Modified",
		})

		for _, s := range sa {
			var beginStr, nextStr string

			modifiedStr := humanize.Time(s.ChangeInfo.ModifiedDate)
			/* The ModifiedBy field can be an email address, or an API Key (hex string) */
			if _, err := hex.DecodeString(s.ChangeInfo.ModifiedBy); err == nil {
				modifiedStr += " via API Key"
			} else {
				modifiedStr += " by " + s.ChangeInfo.ModifiedBy
			}

			if s.BeginDateUtc.IsZero() {
				beginStr = "never"
			} else {
				beginStr = s.BeginDateUtc.In(time.Local).Format("Mon 2 Jan 15:04 MST")
			}
			if s.NextOccurrenceDateUtc.IsZero() {
				nextStr = "never"
			} else {
				nextStr = s.NextOccurrenceDateUtc.In(time.Local).Format("Mon 2 Jan 15:04 MST")
			}
			table.Append([]string{
				s.Type, s.Status, fmt.Sprint(s.IsExpired),
				s.Repeat, s.Expire, beginStr, nextStr,
				fmt.Sprint(s.OccurrenceCount),
				strings.Join(s.CustomWeeklyDays, "/"), modifiedStr,
			})

		}
		table.Render()
	}
}
Beispiel #26
0
func main() {
	var netw string /* The network ID, name or CIDR to query */
	var query = flag.String("q", "free", "Filter IP addresses; one of 'claimed', 'free', or 'all'")
	var location = flag.String("l", "", "Data centre alias of the network (required)")
	var simple = flag.Bool("simple", false, "Use simple (debugging) output format")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options]  <Network-ID|Network-Name|Network-CIDR>)>\n", path.Base(os.Args[0]))
		flag.PrintDefaults()
	}

	flag.Parse()
	/* It seems that Location is always required, even if using the hex ID of the network. */
	if flag.NArg() != 1 || *location == "" {
		flag.Usage()
		os.Exit(1)
	} else if !inStringArray(*query, "claimed", "free", "all") {
		exit.Errorf("Invalid IP query %q. Try -h")
	}

	client, err := clcv2.NewCLIClient()
	if err != nil {
		exit.Fatal(err.Error())
	}

	/* Allow argument to be one of hex-ID, CIDR, or network name. */
	if _, err := hex.DecodeString(flag.Arg(0)); err == nil {
		netw = flag.Arg(0)
	} else if *location == "" {
		exit.Errorf("Need a location argument (-l) if not using a network ID (%s)", flag.Arg(0))
	} else if _, _, err := net.ParseCIDR(flag.Arg(0)); err == nil {
		if network, err := client.GetNetworkIdByCIDR(flag.Arg(0), *location); err != nil {
			exit.Errorf("failed to resolve network %s: %s", flag.Arg(0), err)
		} else if network == nil {
			exit.Errorf("No network of type %s was found in %s", flag.Arg(0), *location)
		} else {
			netw = network.Id
		}
	} else {
		if network, err := client.GetNetworkIdByName(flag.Arg(0), *location); err != nil {
			exit.Errorf("failed to resolve network name %q: %s", flag.Arg(0), err)
		} else if network == nil {
			exit.Errorf("No network named %q was found in %s", flag.Arg(0), *location)
		} else {
			netw = network.Id
		}
	}

	// Note: re-using the 'Get Network' call here. There seems to be no dedicated 'Get IP Address List' call.
	details, err := client.GetNetworkDetails(*location, netw, *query)
	if err != nil {
		exit.Fatalf("failed to query network details of %s: %s", netw, err)
	}

	if len(details.IpAddresses) == 0 {
		println("Empty result.")
	} else if *simple {
		pretty.Println(details)
	} else if *query == "free" {
		var freeIPs = clcv2.ExtractIPs(details.IpAddresses)

		fmt.Printf("%d free IP addresses on %s:\n", len(freeIPs), details.Cidr)
		for _, rng := range utils.CollapseIpRanges(freeIPs) {
			fmt.Println(rng)
		}
	} else {
		table := tablewriter.NewWriter(os.Stdout)
		table.SetAutoFormatHeaders(false)
		table.SetAlignment(tablewriter.ALIGN_RIGHT)
		table.SetAutoWrapText(false)

		switch *query {
		case "claimed":
			table.SetAlignment(tablewriter.ALIGN_LEFT)
			table.SetHeader([]string{"Address", "Server"})
			for _, i := range details.IpAddresses {
				table.Append([]string{i.Address, i.Server})
			}
		case "all":
			table.SetHeader([]string{"Address", "Claimed", "Server", "Type"})
			for _, i := range details.IpAddresses {
				table.Append([]string{i.Address, fmt.Sprint(i.Claimed), i.Server, i.Type})
			}
		}
		table.Render()
	}
}