func DeleteDisk(c config.Cpi, extInput bosh.MethodArguments) error { var diskCID string if reflect.TypeOf(extInput[0]) != reflect.TypeOf(diskCID) { return errors.New("Received unexpected type for disk cid") } diskCID = extInput[0].(string) nodes, err := rackhdapi.GetNodes(c) if err != nil { return err } for _, node := range nodes { if node.PersistentDisk.DiskCID == diskCID { if node.PersistentDisk.IsAttached { return fmt.Errorf("Disk: %s is attached\n", diskCID) } container := rackhdapi.PersistentDiskSettingsContainer{ PersistentDisk: rackhdapi.PersistentDiskSettings{}, } bodyBytes, err := json.Marshal(container) if err != nil { return err } rackhdapi.PatchNode(c, node.ID, bodyBytes) return nil } } return fmt.Errorf("Disk: %s not found\n", diskCID) }
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 DetachDisk(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) nodes, err := rackhdapi.GetNodes(c) if err != nil { return err } for _, node := range nodes { if node.PersistentDisk.DiskCID == diskCID { if !node.PersistentDisk.IsAttached { return fmt.Errorf("Disk: %s is detached\n", diskCID) } if node.CID != vmCID { return fmt.Errorf("Disk %s does not belong to VM %s\n", diskCID, vmCID) } container := rackhdapi.PersistentDiskSettingsContainer{ PersistentDisk: node.PersistentDisk, } container.PersistentDisk.IsAttached = false bodyBytes, err := json.Marshal(container) if err != nil { return err } rackhdapi.PatchNode(c, node.ID, bodyBytes) return nil } } return fmt.Errorf("Disk: %s not found\n", diskCID) }
func CreateVM(c config.Cpi, extInput bosh.MethodArguments) (string, error) { agentID, stemcellCID, publicKey, boshNetworks, nodeID, err := parseCreateVMInput(extInput) if err != nil { return "", err } nodeID, err = TryReservation(c, nodeID, SelectNodeFromRackHD, ReserveNodeFromRackHD) if err != nil { return "", err } var netSpec bosh.Network var netName string for k, v := range boshNetworks { netName = k netSpec = v } nodeCatalog, err := rackhdapi.GetNodeCatalog(c, nodeID) if err != nil { return "", err } if netSpec.NetworkType == bosh.ManualNetworkType { netSpec, err = attachMAC(nodeCatalog.Data.NetworkData.Networks, netSpec) if err != nil { return "", err } } node, err := rackhdapi.GetNode(c, nodeID) if err != nil { return "", err } var diskCID string if node.PersistentDisk.DiskCID == "" { diskCID = fmt.Sprintf("%s-%s", nodeID, c.RequestID) container := rackhdapi.PersistentDiskSettingsContainer{ PersistentDisk: rackhdapi.PersistentDiskSettings{ PregeneratedDiskCID: diskCID, }, } bodyBytes, err := json.Marshal(container) if err != nil { return "", fmt.Errorf("error marshalling persistent disk information for agent %s", agentID) } err = rackhdapi.PatchNode(c, node.ID, bodyBytes) if err != nil { return "", err } } else { diskCID = node.PersistentDisk.DiskCID } persistentMetadata := map[string]interface{}{} if _, sdbFound := nodeCatalog.Data.BlockDevices["sdb"]; sdbFound { persistentMetadata = map[string]interface{}{ diskCID: map[string]string{ "path": "/dev/sdb", }, } } env := bosh.AgentEnv{ AgentID: agentID, Blobstore: c.Agent.Blobstore, Disks: map[string]interface{}{ "system": "/dev/sda", "persistent": persistentMetadata, }, Mbus: c.Agent.Mbus, Networks: map[string]bosh.Network{netName: netSpec}, NTP: c.Agent.Ntp, VM: map[string]string{ "id": nodeID, "name": nodeID, }, PublicKey: publicKey, } envBytes, err := json.Marshal(env) if err != nil { return "", fmt.Errorf("error marshalling agent env %s", err) } envReader := bytes.NewReader(envBytes) vmCID, err := rackhdapi.UploadFile(c, nodeID, envReader, int64(len(envBytes))) if err != nil { return "", err } defer rackhdapi.DeleteFile(c, nodeID) workflowName, err := workflows.PublishProvisionNodeWorkflow(c) if err != nil { return "", fmt.Errorf("error publishing provision workflow: %s", err) } wipeDisk := (nodeID == "") err = workflows.RunProvisionNodeWorkflow(c, nodeID, workflowName, vmCID, stemcellCID, wipeDisk) if err != nil { return "", fmt.Errorf("error running provision workflow: %s", err) } return vmCID, nil }