func DeleteVM(c config.Cpi, extInput bosh.MethodArguments) error { var cid string if reflect.TypeOf(extInput[0]) != reflect.TypeOf(cid) { return errors.New("Received unexpected type for vm cid") } cid = extInput[0].(string) node, err := rackhdapi.GetNodeByVMCID(c, cid) if err != nil { return err } nodeID := node.ID workflowName, err := workflows.PublishDeprovisionNodeWorkflow(c, cid) if err != nil { return err } err = workflows.RunDeprovisionNodeWorkflow(c, nodeID, workflowName) if err != nil { return err } err = rackhdapi.ReleaseNode(c, nodeID) if err != nil { return err } return nil }
func SetVMMetadata(c config.Cpi, extInput bosh.MethodArguments) error { var cid string if reflect.TypeOf(extInput[0]) != reflect.TypeOf(cid) { return fmt.Errorf("Cannot set VM metadata: received unexpected value for vm cid: %s", cid) } cid = extInput[0].(string) metadata, err := json.Marshal(extInput[1]) if err != nil { return fmt.Errorf("Cannot set VM metadata: metadata is not valid JSON") } else { for _, v := range extInput[1].(map[string]interface{}) { switch v.(type) { case string, int: default: fmt.Println("Cannot set VM metadata: metadata must be a hash with string or integer values") } } } node, err := rackhdapi.GetNodeByVMCID(c, cid) nodeID := node.ID if err != nil { return err } return rackhdapi.SetNodeMetadata(c, nodeID, string(metadata)) }
func CreateDisk(c config.Cpi, extInput bosh.MethodArguments) (string, error) { diskSizeInMB, vmCID, err := parseCreateDiskInput(extInput) if err != nil { return "", err } filter := Filter{ data: diskSizeInMB, method: FilterBasedOnSizeMethod, } var diskCID string var node rackhdapi.Node if vmCID != "" { node, err = rackhdapi.GetNodeByVMCID(c, vmCID) if err != nil { return "", err } if node.PersistentDisk.DiskCID != "" { return "", fmt.Errorf("error creating disk: VM %s already has a persistent disk", vmCID) } valid, err := filter.Run(c, node) if !valid || err != nil { return "", fmt.Errorf("error creating disk: %v", err) } if node.PersistentDisk.PregeneratedDiskCID == "" { return "", fmt.Errorf("error creating disk: can not find pregenerated disk cid for VM %s", vmCID) } diskCID = node.PersistentDisk.PregeneratedDiskCID } else { node.ID, err = TryReservationWithFilter(c, "", filter, SelectNodeFromRackHD, ReserveNodeFromRackHD) if err != nil { return "", err } diskCID = fmt.Sprintf("%s-%s", node.ID, c.RequestID) } container := rackhdapi.PersistentDiskSettingsContainer{ PersistentDisk: rackhdapi.PersistentDiskSettings{ DiskCID: diskCID, Location: fmt.Sprintf("/dev/%s", rackhdapi.PersistentDiskLocation), IsAttached: false, }, } bodyBytes, err := json.Marshal(container) if err != nil { return "", fmt.Errorf("error marshalling persistent disk information for VM %s", vmCID) } err = rackhdapi.PatchNode(c, node.ID, bodyBytes) if err != nil { return "", err } return container.PersistentDisk.DiskCID, nil }
func CreateDisk(c config.Cpi, extInput bosh.MethodArguments) (string, error) { diskSizeInMB, vmCID, err := parseCreateDiskInput(extInput) if err != nil { return "", err } var node rackhdapi.Node if vmCID != "" { node, err = rackhdapi.GetNodeByVMCID(c, vmCID) if err != nil { return "", err } if node.PersistentDisk.DiskCID != "" { return "", fmt.Errorf("error creating disk: VM %s already has a persistent disk", vmCID) } } else { nodeID, err := SelectNodeFromRackHD(c, "") if err != nil { return "", err } node.ID = nodeID } catalog, err := rackhdapi.GetNodeCatalog(c, node.ID) if err != nil { return "", fmt.Errorf("error getting catalog of VM: %s", vmCID) } availableSpaceInKB, err := strconv.Atoi(catalog.Data.BlockDevices[rackhdapi.PersistentDiskLocation].Size) if err != nil { return "", fmt.Errorf("error creating disk for VM %s: disk not found", vmCID) } if availableSpaceInKB < diskSizeInMB*1024 { return "", fmt.Errorf("error creating disk with size %vMB for VM %s: insufficient available disk space", diskSizeInMB, vmCID) } container := rackhdapi.PersistentDiskSettingsContainer{ PersistentDisk: rackhdapi.PersistentDiskSettings{ DiskCID: node.ID, Location: fmt.Sprintf("/dev/%s", rackhdapi.PersistentDiskLocation), IsAttached: false, }, } bodyBytes, err := json.Marshal(container) if err != nil { return "", fmt.Errorf("error marshalling persistent disk information for VM %s", vmCID) } err = rackhdapi.PatchNode(c, node.ID, bodyBytes) if err != nil { return "", err } return node.ID, nil }
func AttachDisk(c config.Cpi, extInput bosh.MethodArguments) error { var vmCID string var diskCID string if reflect.TypeOf(extInput[0]) != reflect.TypeOf(vmCID) { return errors.New("Received unexpected type for vm cid") } if reflect.TypeOf(extInput[1]) != reflect.TypeOf(diskCID) { return errors.New("Received unexpected type for disk cid") } vmCID = extInput[0].(string) diskCID = extInput[1].(string) node, err := rackhdapi.GetNodeByVMCID(c, vmCID) if err != nil { return fmt.Errorf("VM: %s not found\n", vmCID) } if node.PersistentDisk.DiskCID == "" { return fmt.Errorf("Disk: %s not found on VM: %s", diskCID, vmCID) } if node.PersistentDisk.DiskCID != diskCID { if node.PersistentDisk.IsAttached { return fmt.Errorf("Node %s has persistent disk %s attached. Cannot attach additional disk %s.", vmCID, node.PersistentDisk.DiskCID, diskCID) } else { return fmt.Errorf("Node %s has persistent disk %s, but detached. Cannot attach disk %s.", vmCID, node.PersistentDisk.DiskCID, diskCID) } } if node.CID != vmCID { return fmt.Errorf("Disk: %s does not belong to VM: %s\n", diskCID, vmCID) } if !node.PersistentDisk.IsAttached { container := rackhdapi.PersistentDiskSettingsContainer{ PersistentDisk: node.PersistentDisk, } container.PersistentDisk.IsAttached = true bodyBytes, err := json.Marshal(container) if err != nil { return err } err = rackhdapi.PatchNode(c, node.ID, bodyBytes) if err != nil { return err } } return nil }
func GetDisks(c config.Cpi, extInput bosh.MethodArguments) ([]string, error) { var vmCID string if reflect.TypeOf(extInput[0]) != reflect.TypeOf(vmCID) { return nil, errors.New("Received unexpected type for vm cid") } vmCID = extInput[0].(string) node, err := rackhdapi.GetNodeByVMCID(c, vmCID) if err != nil { return nil, err } if node.PersistentDisk.DiskCID != "" { result := make([]string, 1) result[0] = node.PersistentDisk.DiskCID return result, nil } else { return make([]string, 0), nil } }
func DeleteVM(c config.Cpi, extInput bosh.MethodArguments) error { var cid string if reflect.TypeOf(extInput[0]) != reflect.TypeOf(cid) { return errors.New("Received unexpected type for vm cid") } cid = extInput[0].(string) node, err := rackhdapi.GetNodeByVMCID(c, cid) if err != nil { return err } if node.PersistentDisk.IsAttached { err = rackhdapi.MakeDiskRequest(c, node, false) if err != nil { return err } } workflowName, err := workflows.PublishDeprovisionNodeWorkflow(c) if err != nil { return err } err = workflows.RunDeprovisionNodeWorkflow(c, node.ID, workflowName) if err != nil { return err } if node.PersistentDisk.DiskCID == "" { err = rackhdapi.ReleaseNode(c, node.ID) if err != nil { return err } } return nil }
}) }) Describe("Getting a single node by CID", func() { It("returns expected node's fields", func() { expectedNodes := helpers.LoadNodes("../spec_assets/dummy_all_nodes_are_vms.json") expectedNodesData, err := json.Marshal(expectedNodes) Expect(err).ToNot(HaveOccurred()) server.AppendHandlers( ghttp.CombineHandlers( ghttp.VerifyRequest("GET", "/api/common/nodes"), ghttp.RespondWith(http.StatusOK, expectedNodesData), ), ) node, err := rackhdapi.GetNodeByVMCID(cpiConfig, "vm-5678") Expect(err).ToNot(HaveOccurred()) Expect(node).To(Equal(expectedNodes[0])) }) }) Describe("Getting a single node by disk CID", func() { It("returns node with the disk specified", func() { expectedNodes := helpers.LoadNodes("../spec_assets/dummy_create_vm_with_disk_response.json") expectedNodesData, err := json.Marshal(expectedNodes) Expect(err).ToNot(HaveOccurred()) server.AppendHandlers( ghttp.CombineHandlers( ghttp.VerifyRequest("GET", "/api/common/nodes"), ghttp.RespondWith(http.StatusOK, expectedNodesData),