Exemple #1
0
// 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
}
Exemple #2
0
// 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
}
Exemple #3
0
// 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
}
Exemple #4
0
// 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
}
Exemple #5
0
// 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
}
Exemple #6
0
// 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
}
Exemple #7
0
// 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
}
Exemple #8
0
// 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
}
Exemple #9
0
// 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
}
Exemple #10
0
// 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
}
Exemple #11
0
// 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
}
Exemple #12
0
// 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
}
Exemple #13
0
// 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
}
Exemple #14
0
// 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
}
Exemple #15
0
// 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
}
Exemple #16
0
// 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
}
Exemple #17
0
// 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
}
Exemple #18
0
// 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
}
Exemple #19
0
// 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
}
Exemple #20
0
// 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
}
Exemple #21
0
// 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
}
Exemple #22
0
// 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
}
Exemple #23
0
// 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
}