// Reboot requests that a given server reboot. // Two methods exist for rebooting a server: // // HardReboot (aka PowerCycle) restarts the server instance by physically cutting power to the machine, or if a VM, // terminating it at the hypervisor level. // It's done. Caput. Full stop. // Then, after a brief while, power is restored or the VM instance restarted. // // SoftReboot (aka OSReboot) simply tells the OS to restart under its own procedures. // E.g., in Linux, asking it to enter runlevel 6, or executing "sudo shutdown -r now", or by asking Windows to restart the machine. func Reboot(client *gophercloud.ServiceClient, id string, how RebootMethod) ActionResult { var res ActionResult if (how != SoftReboot) && (how != HardReboot) { res.Err = &ErrInvalidHowParameterProvided{ &gophercloud.InvalidInputError{ BaseError: gophercloud.BaseError{ Function: "servers.Reboot", }, Argument: "how", Value: how, }, } return res } reqBody := struct { C map[string]string `json:"reboot"` }{ map[string]string{"type": string(how)}, } _, res.Err = client.Post(actionURL(client, id), reqBody, nil, &gophercloud.RequestOpts{ ErrorContext: &ServerError{id: id}, }) return res }
// Create requests a server to be provisioned to the user in the current tenant. func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { var res CreateResult reqBody, err := opts.ToServerCreateMap() if err != nil { res.Err = err return res } // If ImageRef isn't provided, use ImageName to ascertain the image ID. if reqBody["server"].(map[string]interface{})["imageRef"].(string) == "" { imageName := reqBody["server"].(map[string]interface{})["imageName"].(string) if imageName == "" { res.Err = &ErrNeitherImageIDNorImageNameProvided{ &gophercloud.InvalidInputError{ BaseError: gophercloud.BaseError{ Function: "servers.Create", }, Argument: "ImageRef/ImageName", }, } return res } imageID, err := images.IDFromName(client, imageName) if err != nil { res.Err = err return res } reqBody["server"].(map[string]interface{})["imageRef"] = imageID } delete(reqBody["server"].(map[string]interface{}), "imageName") // If FlavorRef isn't provided, use FlavorName to ascertain the flavor ID. if reqBody["server"].(map[string]interface{})["flavorRef"].(string) == "" { flavorName := reqBody["server"].(map[string]interface{})["flavorName"].(string) if flavorName == "" { res.Err = &ErrNeitherFlavorIDNorFlavorNameProvided{ &gophercloud.InvalidInputError{ BaseError: gophercloud.BaseError{ Function: "servers.Create", }, Argument: "FlavorRef/FlavorName", }, } return res } flavorID, err := flavors.IDFromName(client, flavorName) if err != nil { res.Err = err return res } reqBody["server"].(map[string]interface{})["flavorRef"] = flavorID } delete(reqBody["server"].(map[string]interface{}), "flavorName") _, res.Err = client.Post(listURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{ ErrorContext: &ServerError{}, }) return res }
// Rescue instructs the provider to place the server into RESCUE mode. func Rescue(client *gophercloud.ServiceClient, id string, opts RescueOptsBuilder) RescueResult { var result RescueResult if id == "" { result.Err = &ErrNoIDProvided{ &gophercloud.InvalidInputError{ BaseError: gophercloud.BaseError{ Function: "servers.Rescue", }, Argument: "id", }, } return result } reqBody, err := opts.ToServerRescueMap() if err != nil { result.Err = err return result } _, result.Err = client.Post(actionURL(client, id), reqBody, &result.Body, &gophercloud.RequestOpts{ OkCodes: []int{200}, ErrorContext: &ServerError{id: id}, }) return result }
// Create is an operation which provisions a new security group with default // security group rules for the IPv4 and IPv6 ether types. func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult { var res CreateResult // Validate required opts if opts.Name == "" { res.Err = errNameRequired return res } type secgroup struct { Name string `json:"name"` Description string `json:"description,omitempty"` } type request struct { SecGroup secgroup `json:"security_group"` } reqBody := request{SecGroup: secgroup{ Name: opts.Name, Description: opts.Description, }} _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil) return res }
// RevertResize cancels a previous resize operation on a server. // See Resize() for more details. func RevertResize(client *gophercloud.ServiceClient, id string) ActionResult { var res ActionResult reqBody := map[string]interface{}{"revertResize": nil} _, res.Err = client.Post(actionURL(client, id), reqBody, nil, &gophercloud.RequestOpts{ ErrorContext: &ServerError{id: id}, }) return res }
// ConfirmResize confirms a previous resize operation on a server. // See Resize() for more details. func ConfirmResize(client *gophercloud.ServiceClient, id string) ActionResult { var res ActionResult reqBody := map[string]interface{}{"confirmResize": nil} _, res.Err = client.Post(actionURL(client, id), reqBody, nil, &gophercloud.RequestOpts{ OkCodes: []int{201, 202, 204}, }) return res }
// Resize instructs the provider to change the flavor of the server. // Note that this implies rebuilding it. // Unfortunately, one cannot pass rebuild parameters to the resize function. // When the resize completes, the server will be in RESIZE_VERIFY state. // While in this state, you can explore the use of the new server's configuration. // If you like it, call ConfirmResize() to commit the resize permanently. // Otherwise, call RevertResize() to restore the old configuration. func Resize(client *gophercloud.ServiceClient, id string, opts ResizeOptsBuilder) ActionResult { var res ActionResult reqBody, err := opts.ToServerResizeMap() if err != nil { res.Err = err return res } _, res.Err = client.Post(actionURL(client, id), reqBody, nil, nil) return res }
// Create accepts a CreateOpts struct and creates a new network using the values // provided. You must remember to provide a NetworkID value. func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { var res CreateResult reqBody, err := opts.ToPortCreateMap() if err != nil { res.Err = err return res } _, res.Err = c.Post(createURL(c), reqBody, &res.Body, nil) return res }
// Create authenticates to the identity service and attempts to acquire a Token. // If successful, the CreateResult // Generally, rather than interact with this call directly, end users should call openstack.AuthenticatedClient(), // which abstracts all of the gory details about navigating service catalogs and such. func Create(client *gophercloud.ServiceClient, auth AuthOptionsBuilder) CreateResult { request, err := auth.ToTokenCreateMap() if err != nil { return CreateResult{gophercloud.Result{Err: err}} } var result CreateResult _, result.Err = client.Post(CreateURL(client), request, &result.Body, &gophercloud.RequestOpts{ OkCodes: []int{200, 203}, }) return result }
// UpdateMetadata updates (or creates) all the metadata specified by opts for the given server ID. // This operation does not affect already-existing metadata that is not specified // by opts. func UpdateMetadata(client *gophercloud.ServiceClient, id string, opts UpdateMetadataOptsBuilder) UpdateMetadataResult { var res UpdateMetadataResult metadata, err := opts.ToMetadataUpdateMap() if err != nil { res.Err = err return res } _, res.Err = client.Post(metadataURL(client, id), metadata, &res.Body, &gophercloud.RequestOpts{ OkCodes: []int{200}, }) return res }
// ChangeAdminPassword alters the administrator or root password for a specified server. func ChangeAdminPassword(client *gophercloud.ServiceClient, id, newPassword string) ActionResult { var req struct { ChangePassword struct { AdminPass string `json:"adminPass"` } `json:"changePassword"` } req.ChangePassword.AdminPass = newPassword var res ActionResult _, res.Err = client.Post(actionURL(client, id), req, nil, nil) return res }
// Resize instructs the provider to change the flavor of the server. // Note that this implies rebuilding it. // Unfortunately, one cannot pass rebuild parameters to the resize function. // When the resize completes, the server will be in RESIZE_VERIFY state. // While in this state, you can explore the use of the new server's configuration. // If you like it, call ConfirmResize() to commit the resize permanently. // Otherwise, call RevertResize() to restore the old configuration. func Resize(client *gophercloud.ServiceClient, id string, opts ResizeOptsBuilder) ActionResult { var res ActionResult reqBody, err := opts.ToServerResizeMap() if err != nil { res.Err = err return res } _, res.Err = client.Post(actionURL(client, id), reqBody, nil, &gophercloud.RequestOpts{ ErrorContext: &ServerError{id: id}, }) return res }
// CreateImage makes a request against the nova API to schedule an image to be created of the server func CreateImage(client *gophercloud.ServiceClient, serverId string, opts CreateImageOptsBuilder) CreateImageResult { var res CreateImageResult reqBody, err := opts.ToServerCreateImageMap() if err != nil { res.Err = err return res } response, err := client.Post(actionURL(client, serverId), reqBody, nil, &gophercloud.RequestOpts{ OkCodes: []int{202}, }) res.Err = err res.Header = response.Header return res }
// Create requests the creation of a new volume attachment on the server func Create(client *gophercloud.ServiceClient, serverId string, opts CreateOptsBuilder) CreateResult { var res CreateResult reqBody, err := opts.ToVolumeAttachmentCreateMap() if err != nil { res.Err = err return res } _, res.Err = client.Post(createURL(client, serverId), reqBody, &res.Body, &gophercloud.RequestOpts{ OkCodes: []int{200}, }) return res }
// Create requests the creation of a server from the given block device mapping. func Create(client *gophercloud.ServiceClient, opts servers.CreateOptsBuilder) servers.CreateResult { var res servers.CreateResult reqBody, err := opts.ToServerCreateMap() if err != nil { res.Err = err return res } _, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{ OkCodes: []int{200, 202}, }) return res }
// Create is an operation which provisions a new security group with default // security group rules for the IPv4 and IPv6 ether types. func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult { var res CreateResult // Validate required opts if opts.Direction != DirIngress && opts.Direction != DirEgress { res.Err = errValidDirectionRequired return res } if opts.EtherType != Ether4 && opts.EtherType != Ether6 { res.Err = errValidEtherTypeRequired return res } if opts.SecGroupID == "" { res.Err = errSecGroupIDRequired return res } if opts.Protocol != "" && opts.Protocol != ProtocolTCP && opts.Protocol != ProtocolUDP && opts.Protocol != ProtocolICMP { res.Err = errValidProtocolRequired return res } type secrule struct { Direction string `json:"direction"` EtherType string `json:"ethertype"` SecGroupID string `json:"security_group_id"` PortRangeMax int `json:"port_range_max,omitempty"` PortRangeMin int `json:"port_range_min,omitempty"` Protocol string `json:"protocol,omitempty"` RemoteGroupID string `json:"remote_group_id,omitempty"` RemoteIPPrefix string `json:"remote_ip_prefix,omitempty"` } type request struct { SecRule secrule `json:"security_group_rule"` } reqBody := request{SecRule: secrule{ Direction: opts.Direction, EtherType: opts.EtherType, SecGroupID: opts.SecGroupID, PortRangeMax: opts.PortRangeMax, PortRangeMin: opts.PortRangeMin, Protocol: opts.Protocol, RemoteGroupID: opts.RemoteGroupID, RemoteIPPrefix: opts.RemoteIPPrefix, }} _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil) return res }
// ChangeAdminPassword alters the administrator or root password for a specified server. func ChangeAdminPassword(client *gophercloud.ServiceClient, id, newPassword string) ActionResult { var req struct { ChangePassword struct { AdminPass string `json:"adminPass"` } `json:"changePassword"` } req.ChangePassword.AdminPass = newPassword var res ActionResult _, res.Err = client.Post(actionURL(client, id), req, nil, &gophercloud.RequestOpts{ ErrorContext: &ServerError{id: id}, }) return res }
// Rebuild will reprovision the server according to the configuration options // provided in the RebuildOpts struct. func Rebuild(client *gophercloud.ServiceClient, id string, opts RebuildOptsBuilder) RebuildResult { var result RebuildResult if id == "" { result.Err = fmt.Errorf("ID is required") return result } reqBody, err := opts.ToServerRebuildMap() if err != nil { result.Err = err return result } _, result.Err = client.Post(actionURL(client, id), reqBody, &result.Body, nil) return result }
// Create requests a server to be provisioned to the user in the current tenant. func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult { var res CreateResult reqBody, err := opts.ToServerCreateMap() if err != nil { res.Err = err return res } // If ImageRef isn't provided, use ImageName to ascertain the image ID. if reqBody["server"].(map[string]interface{})["imageRef"].(string) == "" { imageName := reqBody["server"].(map[string]interface{})["imageName"].(string) if imageName == "" { res.Err = errors.New("One and only one of ImageRef and ImageName must be provided.") return res } imageID, err := images.IDFromName(client, imageName) if err != nil { res.Err = err return res } reqBody["server"].(map[string]interface{})["imageRef"] = imageID } delete(reqBody["server"].(map[string]interface{}), "imageName") // If FlavorRef isn't provided, use FlavorName to ascertain the flavor ID. if reqBody["server"].(map[string]interface{})["flavorRef"].(string) == "" { flavorName := reqBody["server"].(map[string]interface{})["flavorName"].(string) if flavorName == "" { res.Err = errors.New("One and only one of FlavorRef and FlavorName must be provided.") return res } flavorID, err := flavors.IDFromName(client, flavorName) if err != nil { res.Err = err return res } reqBody["server"].(map[string]interface{})["flavorRef"] = flavorID } delete(reqBody["server"].(map[string]interface{}), "flavorName") _, res.Err = client.Post(listURL(client), reqBody, &res.Body, nil) return res }
// Rescue instructs the provider to place the server into RESCUE mode. func Rescue(client *gophercloud.ServiceClient, id string, opts RescueOptsBuilder) RescueResult { var result RescueResult if id == "" { result.Err = fmt.Errorf("ID is required") return result } reqBody, err := opts.ToServerRescueMap() if err != nil { result.Err = err return result } _, result.Err = client.Post(actionURL(client, id), reqBody, &result.Body, &gophercloud.RequestOpts{ OkCodes: []int{200}, }) return result }
// Reboot requests that a given server reboot. // Two methods exist for rebooting a server: // // HardReboot (aka PowerCycle) restarts the server instance by physically cutting power to the machine, or if a VM, // terminating it at the hypervisor level. // It's done. Caput. Full stop. // Then, after a brief while, power is restored or the VM instance restarted. // // SoftReboot (aka OSReboot) simply tells the OS to restart under its own procedures. // E.g., in Linux, asking it to enter runlevel 6, or executing "sudo shutdown -r now", or by asking Windows to restart the machine. func Reboot(client *gophercloud.ServiceClient, id string, how RebootMethod) ActionResult { var res ActionResult if (how != SoftReboot) && (how != HardReboot) { res.Err = &ErrArgument{ Function: "Reboot", Argument: "how", Value: how, } return res } reqBody := struct { C map[string]string `json:"reboot"` }{ map[string]string{"type": string(how)}, } _, res.Err = client.Post(actionURL(client, id), reqBody, nil, nil) return res }
// RevertResize cancels a previous resize operation on a server. // See Resize() for more details. func RevertResize(client *gophercloud.ServiceClient, id string) ActionResult { var res ActionResult reqBody := map[string]interface{}{"revertResize": nil} _, res.Err = client.Post(actionURL(client, id), reqBody, nil, nil) return res }
// Create authenticates and either generates a new token, or changes the Scope of an existing token. func Create(c *gophercloud.ServiceClient, options gophercloud.AuthOptions, scope *Scope) CreateResult { type domainReq struct { ID *string `json:"id,omitempty"` Name *string `json:"name,omitempty"` } type projectReq struct { Domain *domainReq `json:"domain,omitempty"` Name *string `json:"name,omitempty"` ID *string `json:"id,omitempty"` } type userReq struct { ID *string `json:"id,omitempty"` Name *string `json:"name,omitempty"` Password string `json:"password"` Domain *domainReq `json:"domain,omitempty"` } type passwordReq struct { User userReq `json:"user"` } type tokenReq struct { ID string `json:"id"` } type identityReq struct { Methods []string `json:"methods"` Password *passwordReq `json:"password,omitempty"` Token *tokenReq `json:"token,omitempty"` } type scopeReq struct { Domain *domainReq `json:"domain,omitempty"` Project *projectReq `json:"project,omitempty"` } type authReq struct { Identity identityReq `json:"identity"` Scope *scopeReq `json:"scope,omitempty"` } type request struct { Auth authReq `json:"auth"` } // Populate the request structure based on the provided arguments. Create and return an error // if insufficient or incompatible information is present. var req request // Test first for unrecognized arguments. if options.APIKey != "" { return createErr(ErrAPIKeyProvided) } if options.TenantID != "" { return createErr(ErrTenantIDProvided) } if options.TenantName != "" { return createErr(ErrTenantNameProvided) } if options.Password == "" { if c.TokenID != "" { // Because we aren't using password authentication, it's an error to also provide any of the user-based authentication // parameters. if options.Username != "" { return createErr(ErrUsernameWithToken) } if options.UserID != "" { return createErr(ErrUserIDWithToken) } if options.DomainID != "" { return createErr(ErrDomainIDWithToken) } if options.DomainName != "" { return createErr(ErrDomainNameWithToken) } // Configure the request for Token authentication. req.Auth.Identity.Methods = []string{"token"} req.Auth.Identity.Token = &tokenReq{ ID: c.TokenID, } } else { // If no password or token ID are available, authentication can't continue. return createErr(ErrMissingPassword) } } else { // Password authentication. req.Auth.Identity.Methods = []string{"password"} // At least one of Username and UserID must be specified. if options.Username == "" && options.UserID == "" { return createErr(ErrUsernameOrUserID) } if options.Username != "" { // If Username is provided, UserID may not be provided. if options.UserID != "" { return createErr(ErrUsernameOrUserID) } // Either DomainID or DomainName must also be specified. if options.DomainID == "" && options.DomainName == "" { return createErr(ErrDomainIDOrDomainName) } if options.DomainID != "" { if options.DomainName != "" { return createErr(ErrDomainIDOrDomainName) } // Configure the request for Username and Password authentication with a DomainID. req.Auth.Identity.Password = &passwordReq{ User: userReq{ Name: &options.Username, Password: options.Password, Domain: &domainReq{ID: &options.DomainID}, }, } } if options.DomainName != "" { // Configure the request for Username and Password authentication with a DomainName. req.Auth.Identity.Password = &passwordReq{ User: userReq{ Name: &options.Username, Password: options.Password, Domain: &domainReq{Name: &options.DomainName}, }, } } } if options.UserID != "" { // If UserID is specified, neither DomainID nor DomainName may be. if options.DomainID != "" { return createErr(ErrDomainIDWithUserID) } if options.DomainName != "" { return createErr(ErrDomainNameWithUserID) } // Configure the request for UserID and Password authentication. req.Auth.Identity.Password = &passwordReq{ User: userReq{ID: &options.UserID, Password: options.Password}, } } } // Add a "scope" element if a Scope has been provided. if scope != nil { if scope.ProjectName != "" { // ProjectName provided: either DomainID or DomainName must also be supplied. // ProjectID may not be supplied. if scope.DomainID == "" && scope.DomainName == "" { return createErr(ErrScopeDomainIDOrDomainName) } if scope.ProjectID != "" { return createErr(ErrScopeProjectIDOrProjectName) } if scope.DomainID != "" { // ProjectName + DomainID req.Auth.Scope = &scopeReq{ Project: &projectReq{ Name: &scope.ProjectName, Domain: &domainReq{ID: &scope.DomainID}, }, } } if scope.DomainName != "" { // ProjectName + DomainName req.Auth.Scope = &scopeReq{ Project: &projectReq{ Name: &scope.ProjectName, Domain: &domainReq{Name: &scope.DomainName}, }, } } } else if scope.ProjectID != "" { // ProjectID provided. ProjectName, DomainID, and DomainName may not be provided. if scope.DomainID != "" { return createErr(ErrScopeProjectIDAlone) } if scope.DomainName != "" { return createErr(ErrScopeProjectIDAlone) } // ProjectID req.Auth.Scope = &scopeReq{ Project: &projectReq{ID: &scope.ProjectID}, } } else if scope.DomainID != "" { // DomainID provided. ProjectID, ProjectName, and DomainName may not be provided. if scope.DomainName != "" { return createErr(ErrScopeDomainIDOrDomainName) } // DomainID req.Auth.Scope = &scopeReq{ Domain: &domainReq{ID: &scope.DomainID}, } } else if scope.DomainName != "" { return createErr(ErrScopeDomainName) } else { return createErr(ErrScopeEmpty) } } var result CreateResult var response *http.Response response, result.Err = c.Post(tokenURL(c), req, &result.Body, nil) if result.Err != nil { return result } result.Header = response.Header return result }