diff --git a/client/lxd_certificates.go b/client/lxd_certificates.go index 32b0276eaaf2..2b5127a69986 100644 --- a/client/lxd_certificates.go +++ b/client/lxd_certificates.go @@ -62,12 +62,13 @@ func (r *ProtocolLXD) CreateCertificate(certificate api.CertificatesPost) error // UpdateCertificate updates the certificate definition. func (r *ProtocolLXD) UpdateCertificate(fingerprint string, certificate api.CertificatePut, ETag string) error { - if !r.HasExtension("certificate_update") { - return fmt.Errorf("The server is missing the required \"certificate_update\" API extension") + err := r.CheckExtension("certificate_update") + if err != nil { + return err } // Send the request - _, _, err := r.query("PUT", fmt.Sprintf("/certificates/%s", url.PathEscape(fingerprint)), certificate, ETag) + _, _, err = r.query("PUT", fmt.Sprintf("/certificates/%s", url.PathEscape(fingerprint)), certificate, ETag) if err != nil { return err } @@ -88,8 +89,9 @@ func (r *ProtocolLXD) DeleteCertificate(fingerprint string) error { // CreateCertificateToken requests a certificate add token. func (r *ProtocolLXD) CreateCertificateToken(certificate api.CertificatesPost) (Operation, error) { - if !r.HasExtension("certificate_token") { - return nil, fmt.Errorf("The server is missing the required \"certificate_token\" API extension") + err := r.CheckExtension("certificate_token") + if err != nil { + return nil, err } if !certificate.Token { diff --git a/client/lxd_cluster.go b/client/lxd_cluster.go index 2bb0470b8686..6beb9f74fe3a 100644 --- a/client/lxd_cluster.go +++ b/client/lxd_cluster.go @@ -10,8 +10,9 @@ import ( // // If this client is not trusted, the password must be supplied. func (r *ProtocolLXD) GetCluster() (*api.Cluster, string, error) { - if !r.HasExtension("clustering") { - return nil, "", fmt.Errorf("The server is missing the required \"clustering\" API extension") + err := r.CheckExtension("clustering") + if err != nil { + return nil, "", err } cluster := &api.Cluster{} @@ -25,13 +26,15 @@ func (r *ProtocolLXD) GetCluster() (*api.Cluster, string, error) { // UpdateCluster requests to bootstrap a new cluster or join an existing one. func (r *ProtocolLXD) UpdateCluster(cluster api.ClusterPut, ETag string) (Operation, error) { - if !r.HasExtension("clustering") { - return nil, fmt.Errorf("The server is missing the required \"clustering\" API extension") + err := r.CheckExtension("clustering") + if err != nil { + return nil, err } if cluster.ServerAddress != "" || cluster.ClusterPassword != "" || len(cluster.MemberConfig) > 0 { - if !r.HasExtension("clustering_join") { - return nil, fmt.Errorf("The server is missing the required \"clustering_join\" API extension") + err := r.CheckExtension("clustering_join") + if err != nil { + return nil, err } } @@ -46,8 +49,9 @@ func (r *ProtocolLXD) UpdateCluster(cluster api.ClusterPut, ETag string) (Operat // DeleteClusterMember makes the given member leave the cluster (gracefully or not, // depending on the force flag). func (r *ProtocolLXD) DeleteClusterMember(name string, force bool) error { - if !r.HasExtension("clustering") { - return fmt.Errorf("The server is missing the required \"clustering\" API extension") + err := r.CheckExtension("clustering") + if err != nil { + return err } params := "" @@ -55,7 +59,7 @@ func (r *ProtocolLXD) DeleteClusterMember(name string, force bool) error { params += "?force=1" } - _, _, err := r.query("DELETE", fmt.Sprintf("/cluster/members/%s%s", name, params), nil, "") + _, _, err = r.query("DELETE", fmt.Sprintf("/cluster/members/%s%s", name, params), nil, "") if err != nil { return err } @@ -65,14 +69,15 @@ func (r *ProtocolLXD) DeleteClusterMember(name string, force bool) error { // GetClusterMemberNames returns the URLs of the current members in the cluster. func (r *ProtocolLXD) GetClusterMemberNames() ([]string, error) { - if !r.HasExtension("clustering") { - return nil, fmt.Errorf("The server is missing the required \"clustering\" API extension") + err := r.CheckExtension("clustering") + if err != nil { + return nil, err } // Fetch the raw URL values. urls := []string{} baseURL := "/cluster/members" - _, err := r.queryStruct("GET", baseURL, nil, "", &urls) + _, err = r.queryStruct("GET", baseURL, nil, "", &urls) if err != nil { return nil, err } @@ -83,12 +88,13 @@ func (r *ProtocolLXD) GetClusterMemberNames() ([]string, error) { // GetClusterMembers returns the current members of the cluster. func (r *ProtocolLXD) GetClusterMembers() ([]api.ClusterMember, error) { - if !r.HasExtension("clustering") { - return nil, fmt.Errorf("The server is missing the required \"clustering\" API extension") + err := r.CheckExtension("clustering") + if err != nil { + return nil, err } members := []api.ClusterMember{} - _, err := r.queryStruct("GET", "/cluster/members?recursion=1", nil, "", &members) + _, err = r.queryStruct("GET", "/cluster/members?recursion=1", nil, "", &members) if err != nil { return nil, err } @@ -98,8 +104,9 @@ func (r *ProtocolLXD) GetClusterMembers() ([]api.ClusterMember, error) { // GetClusterMember returns information about the given member. func (r *ProtocolLXD) GetClusterMember(name string) (*api.ClusterMember, string, error) { - if !r.HasExtension("clustering") { - return nil, "", fmt.Errorf("The server is missing the required \"clustering\" API extension") + err := r.CheckExtension("clustering") + if err != nil { + return nil, "", err } member := api.ClusterMember{} @@ -113,18 +120,20 @@ func (r *ProtocolLXD) GetClusterMember(name string) (*api.ClusterMember, string, // UpdateClusterMember updates information about the given member. func (r *ProtocolLXD) UpdateClusterMember(name string, member api.ClusterMemberPut, ETag string) error { - if !r.HasExtension("clustering_edit_roles") { - return fmt.Errorf("The server is missing the required \"clustering_edit_roles\" API extension") + err := r.CheckExtension("clustering_edit_roles") + if err != nil { + return err } if member.FailureDomain != "" { - if !r.HasExtension("clustering_failure_domains") { - return fmt.Errorf("The server is missing the required \"clustering_failure_domains\" API extension") + err := r.CheckExtension("clustering_failure_domains") + if err != nil { + return err } } // Send the request - _, _, err := r.query("PUT", fmt.Sprintf("/cluster/members/%s", name), member, ETag) + _, _, err = r.query("PUT", fmt.Sprintf("/cluster/members/%s", name), member, ETag) if err != nil { return err } @@ -134,11 +143,12 @@ func (r *ProtocolLXD) UpdateClusterMember(name string, member api.ClusterMemberP // RenameClusterMember changes the name of an existing member. func (r *ProtocolLXD) RenameClusterMember(name string, member api.ClusterMemberPost) error { - if !r.HasExtension("clustering") { - return fmt.Errorf("The server is missing the required \"clustering\" API extension") + err := r.CheckExtension("clustering") + if err != nil { + return err } - _, _, err := r.query("POST", fmt.Sprintf("/cluster/members/%s", name), member, "") + _, _, err = r.query("POST", fmt.Sprintf("/cluster/members/%s", name), member, "") if err != nil { return err } @@ -148,8 +158,9 @@ func (r *ProtocolLXD) RenameClusterMember(name string, member api.ClusterMemberP // CreateClusterMember generates a join token to add a cluster member. func (r *ProtocolLXD) CreateClusterMember(member api.ClusterMembersPost) (Operation, error) { - if !r.HasExtension("clustering_join_token") { - return nil, fmt.Errorf("The server is missing the required \"clustering_join_token\" API extension") + err := r.CheckExtension("clustering_join_token") + if err != nil { + return nil, err } op, _, err := r.queryOperation("POST", "/cluster/members", member, "", true) @@ -162,11 +173,12 @@ func (r *ProtocolLXD) CreateClusterMember(member api.ClusterMembersPost) (Operat // UpdateClusterCertificate updates the cluster certificate for every node in the cluster. func (r *ProtocolLXD) UpdateClusterCertificate(certs api.ClusterCertificatePut, ETag string) error { - if !r.HasExtension("clustering_update_cert") { - return fmt.Errorf("The server is missing the required \"clustering_update_cert\" API extension") + err := r.CheckExtension("clustering_update_cert") + if err != nil { + return err } - _, _, err := r.query("PUT", "/cluster/certificate", certs, ETag) + _, _, err = r.query("PUT", "/cluster/certificate", certs, ETag) if err != nil { return err } @@ -193,8 +205,9 @@ func (r *ProtocolLXD) GetClusterMemberState(name string) (*api.ClusterMemberStat // UpdateClusterMemberState evacuates or restores a cluster member. func (r *ProtocolLXD) UpdateClusterMemberState(name string, state api.ClusterMemberStatePost) (Operation, error) { - if !r.HasExtension("clustering_evacuation") { - return nil, fmt.Errorf("The server is missing the required \"clustering_evacuation\" API extension") + err := r.CheckExtension("clustering_evacuation") + if err != nil { + return nil, err } op, _, err := r.queryOperation("POST", fmt.Sprintf("/cluster/members/%s/state", name), state, "", true) @@ -207,13 +220,14 @@ func (r *ProtocolLXD) UpdateClusterMemberState(name string, state api.ClusterMem // GetClusterGroups returns the cluster groups. func (r *ProtocolLXD) GetClusterGroups() ([]api.ClusterGroup, error) { - if !r.HasExtension("clustering_groups") { - return nil, fmt.Errorf("The server is missing the required \"clustering_groups\" API extension") + err := r.CheckExtension("clustering_groups") + if err != nil { + return nil, err } groups := []api.ClusterGroup{} - _, err := r.queryStruct("GET", "/cluster/groups?recursion=1", nil, "", &groups) + _, err = r.queryStruct("GET", "/cluster/groups?recursion=1", nil, "", &groups) if err != nil { return nil, err } @@ -223,13 +237,14 @@ func (r *ProtocolLXD) GetClusterGroups() ([]api.ClusterGroup, error) { // GetClusterGroupNames returns the cluster group names. func (r *ProtocolLXD) GetClusterGroupNames() ([]string, error) { - if !r.HasExtension("clustering_groups") { - return nil, fmt.Errorf("The server is missing the required \"clustering_groups\" API extension") + err := r.CheckExtension("clustering_groups") + if err != nil { + return nil, err } urls := []string{} - _, err := r.queryStruct("GET", "/cluster/groups", nil, "", &urls) + _, err = r.queryStruct("GET", "/cluster/groups", nil, "", &urls) if err != nil { return nil, err } @@ -240,11 +255,12 @@ func (r *ProtocolLXD) GetClusterGroupNames() ([]string, error) { // RenameClusterGroup changes the name of an existing cluster group. func (r *ProtocolLXD) RenameClusterGroup(name string, group api.ClusterGroupPost) error { - if !r.HasExtension("clustering_groups") { - return fmt.Errorf("The server is missing the required \"clustering_groups\" API extension") + err := r.CheckExtension("clustering_groups") + if err != nil { + return err } - _, _, err := r.query("POST", fmt.Sprintf("/cluster/groups/%s", name), group, "") + _, _, err = r.query("POST", fmt.Sprintf("/cluster/groups/%s", name), group, "") if err != nil { return err } @@ -254,11 +270,12 @@ func (r *ProtocolLXD) RenameClusterGroup(name string, group api.ClusterGroupPost // CreateClusterGroup creates a new cluster group. func (r *ProtocolLXD) CreateClusterGroup(group api.ClusterGroupsPost) error { - if !r.HasExtension("clustering_groups") { - return fmt.Errorf("The server is missing the required \"clustering_groups\" API extension") + err := r.CheckExtension("clustering_groups") + if err != nil { + return err } - _, _, err := r.query("POST", "/cluster/groups", group, "") + _, _, err = r.query("POST", "/cluster/groups", group, "") if err != nil { return err } @@ -268,11 +285,12 @@ func (r *ProtocolLXD) CreateClusterGroup(group api.ClusterGroupsPost) error { // DeleteClusterGroup deletes an existing cluster group. func (r *ProtocolLXD) DeleteClusterGroup(name string) error { - if !r.HasExtension("clustering_groups") { - return fmt.Errorf("The server is missing the required \"clustering_groups\" API extension") + err := r.CheckExtension("clustering_groups") + if err != nil { + return err } - _, _, err := r.query("DELETE", fmt.Sprintf("/cluster/groups/%s", name), nil, "") + _, _, err = r.query("DELETE", fmt.Sprintf("/cluster/groups/%s", name), nil, "") if err != nil { return err } @@ -282,12 +300,13 @@ func (r *ProtocolLXD) DeleteClusterGroup(name string) error { // UpdateClusterGroup updates information about the given cluster group. func (r *ProtocolLXD) UpdateClusterGroup(name string, group api.ClusterGroupPut, ETag string) error { - if !r.HasExtension("clustering_groups") { - return fmt.Errorf("The server is missing the required \"clustering_groups\" API extension") + err := r.CheckExtension("clustering_groups") + if err != nil { + return err } // Send the request - _, _, err := r.query("PUT", fmt.Sprintf("/cluster/groups/%s", name), group, ETag) + _, _, err = r.query("PUT", fmt.Sprintf("/cluster/groups/%s", name), group, ETag) if err != nil { return err } @@ -297,8 +316,9 @@ func (r *ProtocolLXD) UpdateClusterGroup(name string, group api.ClusterGroupPut, // GetClusterGroup returns information about the given cluster group. func (r *ProtocolLXD) GetClusterGroup(name string) (*api.ClusterGroup, string, error) { - if !r.HasExtension("clustering_groups") { - return nil, "", fmt.Errorf("The server is missing the required \"clustering_groups\" API extension") + err := r.CheckExtension("clustering_groups") + if err != nil { + return nil, "", err } group := api.ClusterGroup{} diff --git a/client/lxd_containers.go b/client/lxd_containers.go index dfa281809a00..aaf19f3958c8 100644 --- a/client/lxd_containers.go +++ b/client/lxd_containers.go @@ -54,12 +54,13 @@ func (r *ProtocolLXD) GetContainers() ([]api.Container, error) { func (r *ProtocolLXD) GetContainersFull() ([]api.ContainerFull, error) { containers := []api.ContainerFull{} - if !r.HasExtension("container_full") { - return nil, fmt.Errorf("The server is missing the required \"container_full\" API extension") + err := r.CheckExtension("container_full") + if err != nil { + return nil, err } // Fetch the raw value - _, err := r.queryStruct("GET", "/containers?recursion=2", nil, "", &containers) + _, err = r.queryStruct("GET", "/containers?recursion=2", nil, "", &containers) if err != nil { return nil, err } @@ -83,8 +84,9 @@ func (r *ProtocolLXD) GetContainer(name string) (*api.Container, string, error) // CreateContainerFromBackup is a convenience function to make it easier to // create a container from a backup. func (r *ProtocolLXD) CreateContainerFromBackup(args ContainerBackupArgs) (Operation, error) { - if !r.HasExtension("container_backup") { - return nil, fmt.Errorf("The server is missing the required \"container_backup\" API extension") + err := r.CheckExtension("container_backup") + if err != nil { + return nil, err } if args.PoolName == "" { @@ -97,8 +99,9 @@ func (r *ProtocolLXD) CreateContainerFromBackup(args ContainerBackupArgs) (Opera return op, nil } - if !r.HasExtension("container_backup_override_pool") { - return nil, fmt.Errorf("The server is missing the required \"container_backup_override_pool\" API extension") + err = r.CheckExtension("container_backup_override_pool") + if err != nil { + return nil, err } // Prepare the HTTP request @@ -148,8 +151,9 @@ func (r *ProtocolLXD) CreateContainerFromBackup(args ContainerBackupArgs) (Opera // CreateContainer requests that LXD creates a new container. func (r *ProtocolLXD) CreateContainer(container api.ContainersPost) (Operation, error) { if container.Source.ContainerOnly { - if !r.HasExtension("container_only_migration") { - return nil, fmt.Errorf("The server is missing the required \"container_only_migration\" API extension") + err := r.CheckExtension("container_only_migration") + if err != nil { + return nil, err } } @@ -356,11 +360,12 @@ func (r *ProtocolLXD) CopyContainer(source InstanceServer, container api.Contain } // Optimization for the local copy case - if destInfo.URL == sourceInfo.URL && destInfo.SocketPath == sourceInfo.SocketPath && (!r.IsClustered() || container.Location == r.clusterTarget || r.HasExtension("cluster_internal_copy")) { + if destInfo.URL == sourceInfo.URL && destInfo.SocketPath == sourceInfo.SocketPath && (!r.IsClustered() || container.Location == r.clusterTarget || r.CheckExtension("cluster_internal_copy") == nil) { // Project handling if destInfo.Project != sourceInfo.Project { - if !r.HasExtension("container_copy_project") { - return nil, fmt.Errorf("The server is missing the required \"container_copy_project\" API extension") + err := r.CheckExtension("container_copy_project") + if err != nil { + return nil, err } req.Source.Project = sourceInfo.Project @@ -586,8 +591,9 @@ func (r *ProtocolLXD) tryMigrateContainer(source InstanceServer, name string, re // MigrateContainer requests that LXD prepares for a container migration. func (r *ProtocolLXD) MigrateContainer(name string, container api.ContainerPost) (Operation, error) { if container.ContainerOnly { - if !r.HasExtension("container_only_migration") { - return nil, fmt.Errorf("The server is missing the required \"container_only_migration\" API extension") + err := r.CheckExtension("container_only_migration") + if err != nil { + return nil, err } } @@ -619,14 +625,16 @@ func (r *ProtocolLXD) DeleteContainer(name string) (Operation, error) { // ExecContainer requests that LXD spawns a command inside the container. func (r *ProtocolLXD) ExecContainer(containerName string, exec api.ContainerExecPost, args *ContainerExecArgs) (Operation, error) { if exec.RecordOutput { - if !r.HasExtension("container_exec_recording") { - return nil, fmt.Errorf("The server is missing the required \"container_exec_recording\" API extension") + err := r.CheckExtension("container_exec_recording") + if err != nil { + return nil, err } } if exec.User > 0 || exec.Group > 0 || exec.Cwd != "" { - if !r.HasExtension("container_exec_user_group_cwd") { - return nil, fmt.Errorf("The server is missing the required \"container_exec_user_group_cwd\" API extension") + err := r.CheckExtension("container_exec_user_group_cwd") + if err != nil { + return nil, err } } @@ -837,20 +845,23 @@ func (r *ProtocolLXD) GetContainerFile(containerName string, path string) (io.Re // CreateContainerFile tells LXD to create a file in the container. func (r *ProtocolLXD) CreateContainerFile(containerName string, path string, args ContainerFileArgs) error { if args.Type == "directory" { - if !r.HasExtension("directory_manipulation") { - return fmt.Errorf("The server is missing the required \"directory_manipulation\" API extension") + err := r.CheckExtension("directory_manipulation") + if err != nil { + return err } } if args.Type == "symlink" { - if !r.HasExtension("file_symlinks") { - return fmt.Errorf("The server is missing the required \"file_symlinks\" API extension") + err := r.CheckExtension("file_symlinks") + if err != nil { + return err } } if args.WriteMode == "append" { - if !r.HasExtension("file_append") { - return fmt.Errorf("The server is missing the required \"file_append\" API extension") + err := r.CheckExtension("file_append") + if err != nil { + return err } } @@ -905,12 +916,13 @@ func (r *ProtocolLXD) CreateContainerFile(containerName string, path string, arg // DeleteContainerFile deletes a file in the container. func (r *ProtocolLXD) DeleteContainerFile(containerName string, path string) error { - if !r.HasExtension("file_delete") { - return fmt.Errorf("The server is missing the required \"file_delete\" API extension") + err := r.CheckExtension("file_delete") + if err != nil { + return err } // Send the request - _, _, err := r.query("DELETE", fmt.Sprintf("/containers/%s/files?path=%s", url.PathEscape(containerName), url.QueryEscape(path)), nil, "") + _, _, err = r.query("DELETE", fmt.Sprintf("/containers/%s/files?path=%s", url.PathEscape(containerName), url.QueryEscape(path)), nil, "") if err != nil { return err } @@ -961,8 +973,11 @@ func (r *ProtocolLXD) GetContainerSnapshot(containerName string, name string) (* // CreateContainerSnapshot requests that LXD creates a new snapshot for the container. func (r *ProtocolLXD) CreateContainerSnapshot(containerName string, snapshot api.ContainerSnapshotsPost) (Operation, error) { // Validate the request - if snapshot.ExpiresAt != nil && !r.HasExtension("snapshot_expiry_creation") { - return nil, fmt.Errorf("The server is missing the required \"snapshot_expiry_creation\" API extension") + if snapshot.ExpiresAt != nil { + err := r.CheckExtension("snapshot_expiry_creation") + if err != nil { + return nil, err + } } // Send the request @@ -994,8 +1009,9 @@ func (r *ProtocolLXD) CopyContainerSnapshot(source InstanceServer, containerName } if snapshot.Stateful && args.Live { - if !r.HasExtension("container_snapshot_stateful_migration") { - return nil, fmt.Errorf("The server is missing the required \"container_snapshot_stateful_migration\" API extension") + err := r.CheckExtension("container_snapshot_stateful_migration") + if err != nil { + return nil, err } req.ContainerPut.Stateful = snapshot.Stateful @@ -1043,11 +1059,12 @@ func (r *ProtocolLXD) CopyContainerSnapshot(source InstanceServer, containerName } // Optimization for the local copy case - if destInfo.URL == sourceInfo.URL && destInfo.SocketPath == sourceInfo.SocketPath && (!r.IsClustered() || container.Location == r.clusterTarget || r.HasExtension("cluster_internal_copy")) { + if destInfo.URL == sourceInfo.URL && destInfo.SocketPath == sourceInfo.SocketPath && (!r.IsClustered() || container.Location == r.clusterTarget || r.CheckExtension("cluster_internal_copy") == nil) { // Project handling if destInfo.Project != sourceInfo.Project { - if !r.HasExtension("container_copy_project") { - return nil, fmt.Errorf("The server is missing the required \"container_copy_project\" API extension") + err := r.CheckExtension("container_copy_project") + if err != nil { + return nil, err } req.Source.Project = sourceInfo.Project @@ -1292,8 +1309,9 @@ func (r *ProtocolLXD) DeleteContainerSnapshot(containerName string, name string) // UpdateContainerSnapshot requests that LXD updates the container snapshot. func (r *ProtocolLXD) UpdateContainerSnapshot(containerName string, name string, container api.ContainerSnapshotPut, ETag string) (Operation, error) { - if !r.HasExtension("snapshot_expiry") { - return nil, fmt.Errorf("The server is missing the required \"snapshot_expiry\" API extension") + err := r.CheckExtension("snapshot_expiry") + if err != nil { + return nil, err } // Send the request @@ -1391,8 +1409,9 @@ func (r *ProtocolLXD) DeleteContainerLogfile(name string, filename string) error // GetContainerMetadata returns container metadata. func (r *ProtocolLXD) GetContainerMetadata(name string) (*api.ImageMetadata, string, error) { - if !r.HasExtension("container_edit_metadata") { - return nil, "", fmt.Errorf("The server is missing the required \"container_edit_metadata\" API extension") + err := r.CheckExtension("container_edit_metadata") + if err != nil { + return nil, "", err } metadata := api.ImageMetadata{} @@ -1408,12 +1427,13 @@ func (r *ProtocolLXD) GetContainerMetadata(name string) (*api.ImageMetadata, str // SetContainerMetadata sets the content of the container metadata file. func (r *ProtocolLXD) SetContainerMetadata(name string, metadata api.ImageMetadata, ETag string) error { - if !r.HasExtension("container_edit_metadata") { - return fmt.Errorf("The server is missing the required \"container_edit_metadata\" API extension") + err := r.CheckExtension("container_edit_metadata") + if err != nil { + return err } url := fmt.Sprintf("/containers/%s/metadata", url.PathEscape(name)) - _, _, err := r.query("PUT", url, metadata, ETag) + _, _, err = r.query("PUT", url, metadata, ETag) if err != nil { return err } @@ -1423,14 +1443,15 @@ func (r *ProtocolLXD) SetContainerMetadata(name string, metadata api.ImageMetada // GetContainerTemplateFiles returns the list of names of template files for a container. func (r *ProtocolLXD) GetContainerTemplateFiles(containerName string) ([]string, error) { - if !r.HasExtension("container_edit_metadata") { - return nil, fmt.Errorf("The server is missing the required \"container_edit_metadata\" API extension") + err := r.CheckExtension("container_edit_metadata") + if err != nil { + return nil, err } templates := []string{} url := fmt.Sprintf("/containers/%s/metadata/templates", url.PathEscape(containerName)) - _, err := r.queryStruct("GET", url, nil, "", &templates) + _, err = r.queryStruct("GET", url, nil, "", &templates) if err != nil { return nil, err } @@ -1440,13 +1461,14 @@ func (r *ProtocolLXD) GetContainerTemplateFiles(containerName string) ([]string, // GetContainerTemplateFile returns the content of a template file for a container. func (r *ProtocolLXD) GetContainerTemplateFile(containerName string, templateName string) (io.ReadCloser, error) { - if !r.HasExtension("container_edit_metadata") { - return nil, fmt.Errorf("The server is missing the required \"container_edit_metadata\" API extension") + err := r.CheckExtension("container_edit_metadata") + if err != nil { + return nil, err } url := fmt.Sprintf("%s/1.0/containers/%s/metadata/templates?path=%s", r.httpBaseURL.String(), url.PathEscape(containerName), url.QueryEscape(templateName)) - url, err := r.setQueryAttributes(url) + url, err = r.setQueryAttributes(url) if err != nil { return nil, err } @@ -1475,13 +1497,14 @@ func (r *ProtocolLXD) GetContainerTemplateFile(containerName string, templateNam // CreateContainerTemplateFile creates an a template for a container. func (r *ProtocolLXD) CreateContainerTemplateFile(containerName string, templateName string, content io.ReadSeeker) error { - if !r.HasExtension("container_edit_metadata") { - return fmt.Errorf("The server is missing the required \"container_edit_metadata\" API extension") + err := r.CheckExtension("container_edit_metadata") + if err != nil { + return err } url := fmt.Sprintf("%s/1.0/containers/%s/metadata/templates?path=%s", r.httpBaseURL.String(), url.PathEscape(containerName), url.QueryEscape(templateName)) - url, err := r.setQueryAttributes(url) + url, err = r.setQueryAttributes(url) if err != nil { return err } @@ -1512,18 +1535,20 @@ func (r *ProtocolLXD) UpdateContainerTemplateFile(containerName string, template // DeleteContainerTemplateFile deletes a template file for a container. func (r *ProtocolLXD) DeleteContainerTemplateFile(name string, templateName string) error { - if !r.HasExtension("container_edit_metadata") { - return fmt.Errorf("The server is missing the required \"container_edit_metadata\" API extension") + err := r.CheckExtension("container_edit_metadata") + if err != nil { + return err } - _, _, err := r.query("DELETE", fmt.Sprintf("/containers/%s/metadata/templates?path=%s", url.PathEscape(name), url.QueryEscape(templateName)), nil, "") + _, _, err = r.query("DELETE", fmt.Sprintf("/containers/%s/metadata/templates?path=%s", url.PathEscape(name), url.QueryEscape(templateName)), nil, "") return err } // ConsoleContainer requests that LXD attaches to the console device of a container. func (r *ProtocolLXD) ConsoleContainer(containerName string, console api.ContainerConsolePost, args *ContainerConsoleArgs) (Operation, error) { - if !r.HasExtension("console") { - return nil, fmt.Errorf("The server is missing the required \"console\" API extension") + err := r.CheckExtension("console") + if err != nil { + return nil, err } // Send the request @@ -1595,14 +1620,15 @@ func (r *ProtocolLXD) ConsoleContainer(containerName string, console api.Contain // // Note that it's the caller's responsibility to close the returned ReadCloser. func (r *ProtocolLXD) GetContainerConsoleLog(containerName string, args *ContainerConsoleLogArgs) (io.ReadCloser, error) { - if !r.HasExtension("console") { - return nil, fmt.Errorf("The server is missing the required \"console\" API extension") + err := r.CheckExtension("console") + if err != nil { + return nil, err } // Prepare the HTTP request url := fmt.Sprintf("%s/1.0/containers/%s/console", r.httpBaseURL.String(), url.PathEscape(containerName)) - url, err := r.setQueryAttributes(url) + url, err = r.setQueryAttributes(url) if err != nil { return nil, err } @@ -1631,12 +1657,13 @@ func (r *ProtocolLXD) GetContainerConsoleLog(containerName string, args *Contain // DeleteContainerConsoleLog deletes the requested container's console log. func (r *ProtocolLXD) DeleteContainerConsoleLog(containerName string, args *ContainerConsoleLogArgs) error { - if !r.HasExtension("console") { - return fmt.Errorf("The server is missing the required \"console\" API extension") + err := r.CheckExtension("console") + if err != nil { + return err } // Send the request - _, _, err := r.query("DELETE", fmt.Sprintf("/containers/%s/console", url.PathEscape(containerName)), nil, "") + _, _, err = r.query("DELETE", fmt.Sprintf("/containers/%s/console", url.PathEscape(containerName)), nil, "") if err != nil { return err } @@ -1646,14 +1673,15 @@ func (r *ProtocolLXD) DeleteContainerConsoleLog(containerName string, args *Cont // GetContainerBackupNames returns a list of backup names for the container. func (r *ProtocolLXD) GetContainerBackupNames(containerName string) ([]string, error) { - if !r.HasExtension("container_backup") { - return nil, fmt.Errorf("The server is missing the required \"container_backup\" API extension") + err := r.CheckExtension("container_backup") + if err != nil { + return nil, err } // Fetch the raw URL values. urls := []string{} baseURL := fmt.Sprintf("/containers/%s/backups", url.PathEscape(containerName)) - _, err := r.queryStruct("GET", baseURL, nil, "", &urls) + _, err = r.queryStruct("GET", baseURL, nil, "", &urls) if err != nil { return nil, err } @@ -1664,14 +1692,15 @@ func (r *ProtocolLXD) GetContainerBackupNames(containerName string) ([]string, e // GetContainerBackups returns a list of backups for the container. func (r *ProtocolLXD) GetContainerBackups(containerName string) ([]api.ContainerBackup, error) { - if !r.HasExtension("container_backup") { - return nil, fmt.Errorf("The server is missing the required \"container_backup\" API extension") + err := r.CheckExtension("container_backup") + if err != nil { + return nil, err } // Fetch the raw value backups := []api.ContainerBackup{} - _, err := r.queryStruct("GET", fmt.Sprintf("/containers/%s/backups?recursion=1", url.PathEscape(containerName)), nil, "", &backups) + _, err = r.queryStruct("GET", fmt.Sprintf("/containers/%s/backups?recursion=1", url.PathEscape(containerName)), nil, "", &backups) if err != nil { return nil, err } @@ -1681,8 +1710,9 @@ func (r *ProtocolLXD) GetContainerBackups(containerName string) ([]api.Container // GetContainerBackup returns a Backup struct for the provided container and backup names. func (r *ProtocolLXD) GetContainerBackup(containerName string, name string) (*api.ContainerBackup, string, error) { - if !r.HasExtension("container_backup") { - return nil, "", fmt.Errorf("The server is missing the required \"container_backup\" API extension") + err := r.CheckExtension("container_backup") + if err != nil { + return nil, "", err } // Fetch the raw value @@ -1697,8 +1727,9 @@ func (r *ProtocolLXD) GetContainerBackup(containerName string, name string) (*ap // CreateContainerBackup requests that LXD creates a new backup for the container. func (r *ProtocolLXD) CreateContainerBackup(containerName string, backup api.ContainerBackupsPost) (Operation, error) { - if !r.HasExtension("container_backup") { - return nil, fmt.Errorf("The server is missing the required \"container_backup\" API extension") + err := r.CheckExtension("container_backup") + if err != nil { + return nil, err } // Send the request @@ -1713,8 +1744,9 @@ func (r *ProtocolLXD) CreateContainerBackup(containerName string, backup api.Con // RenameContainerBackup requests that LXD renames the backup. func (r *ProtocolLXD) RenameContainerBackup(containerName string, name string, backup api.ContainerBackupPost) (Operation, error) { - if !r.HasExtension("container_backup") { - return nil, fmt.Errorf("The server is missing the required \"container_backup\" API extension") + err := r.CheckExtension("container_backup") + if err != nil { + return nil, err } // Send the request @@ -1729,8 +1761,9 @@ func (r *ProtocolLXD) RenameContainerBackup(containerName string, name string, b // DeleteContainerBackup requests that LXD deletes the container backup. func (r *ProtocolLXD) DeleteContainerBackup(containerName string, name string) (Operation, error) { - if !r.HasExtension("container_backup") { - return nil, fmt.Errorf("The server is missing the required \"container_backup\" API extension") + err := r.CheckExtension("container_backup") + if err != nil { + return nil, err } // Send the request @@ -1745,8 +1778,9 @@ func (r *ProtocolLXD) DeleteContainerBackup(containerName string, name string) ( // GetContainerBackupFile requests the container backup content. func (r *ProtocolLXD) GetContainerBackupFile(containerName string, name string, req *BackupFileRequest) (*BackupFileResponse, error) { - if !r.HasExtension("container_backup") { - return nil, fmt.Errorf("The server is missing the required \"container_backup\" API extension") + err := r.CheckExtension("container_backup") + if err != nil { + return nil, err } // Build the URL diff --git a/client/lxd_images.go b/client/lxd_images.go index 5360b40f1594..b6c7b9288828 100644 --- a/client/lxd_images.go +++ b/client/lxd_images.go @@ -35,8 +35,9 @@ func (r *ProtocolLXD) GetImages() ([]api.Image, error) { // GetImagesWithFilter returns a filtered list of available images as Image structs. func (r *ProtocolLXD) GetImagesWithFilter(filters []string) ([]api.Image, error) { - if !r.HasExtension("api_filtering") { - return nil, fmt.Errorf("The server is missing the required \"api_filtering\" API extension") + err := r.CheckExtension("api_filtering") + if err != nil { + return nil, err } images := []api.Image{} @@ -45,7 +46,7 @@ func (r *ProtocolLXD) GetImagesWithFilter(filters []string) ([]api.Image, error) v.Set("recursion", "1") v.Set("filter", parseFilters(filters)) - _, err := r.queryStruct("GET", fmt.Sprintf("/images?%s", v.Encode()), nil, "", &images) + _, err = r.queryStruct("GET", fmt.Sprintf("/images?%s", v.Encode()), nil, "", &images) if err != nil { return nil, err } @@ -386,8 +387,9 @@ func (r *ProtocolLXD) GetImageAliasArchitectures(imageType string, name string) // CreateImage requests that LXD creates, copies or import a new image. func (r *ProtocolLXD) CreateImage(image api.ImagesPost, args *ImageCreateArgs) (Operation, error) { if image.CompressionAlgorithm != "" { - if !r.HasExtension("image_compression_algorithm") { - return nil, fmt.Errorf("The server is missing the required \"image_compression_algorithm\" API extension") + err := r.CheckExtension("image_compression_algorithm") + if err != nil { + return nil, err } } @@ -582,7 +584,7 @@ func (r *ProtocolLXD) tryCopyImage(req api.ImagesPost, urls []string) (RemoteOpe } // For older servers, apply the aliases after copy - if !r.HasExtension("image_create_aliases") && req.Aliases != nil { + if r.CheckExtension("image_create_aliases") != nil && req.Aliases != nil { rop.chPost = make(chan bool) go func() { @@ -678,8 +680,9 @@ func (r *ProtocolLXD) CopyImage(source ImageServer, image api.Image, args *Image // Handle profile list overrides. if args != nil && args.Profiles != nil { - if !r.HasExtension("image_copy_profile") { - return nil, fmt.Errorf("The server is missing the required \"image_copy_profile\" API extension") + err := r.CheckExtension("image_copy_profile") + if err != nil { + return nil, err } image.Profiles = args.Profiles @@ -926,8 +929,9 @@ func (r *ProtocolLXD) DeleteImage(fingerprint string) (Operation, error) { // RefreshImage requests that LXD issues an image refresh. func (r *ProtocolLXD) RefreshImage(fingerprint string) (Operation, error) { - if !r.HasExtension("image_force_refresh") { - return nil, fmt.Errorf("The server is missing the required \"image_force_refresh\" API extension") + err := r.CheckExtension("image_force_refresh") + if err != nil { + return nil, err } // Send the request @@ -996,8 +1000,9 @@ func (r *ProtocolLXD) DeleteImageAlias(name string) error { // ExportImage exports (copies) an image to a remote server. func (r *ProtocolLXD) ExportImage(fingerprint string, image api.ImageExportPost) (Operation, error) { - if !r.HasExtension("images_push_relay") { - return nil, fmt.Errorf("The server is missing the required \"images_push_relay\" API extension") + err := r.CheckExtension("images_push_relay") + if err != nil { + return nil, err } // Send the request diff --git a/client/lxd_instances.go b/client/lxd_instances.go index 6495ab7a8840..53105cdde699 100644 --- a/client/lxd_instances.go +++ b/client/lxd_instances.go @@ -34,7 +34,7 @@ func (r *ProtocolLXD) instanceTypeToPath(instanceType api.InstanceType) (string, // If the remote server doesn't support instances extension, check that only containers // or any type has been requested and then fallback to using the old /containers endpoint. - if !r.HasExtension("instances") { + if r.CheckExtension("instances") != nil { if instanceType == api.InstanceTypeContainer || instanceType == api.InstanceTypeAny { return "/containers", v, nil } @@ -118,8 +118,9 @@ func (r *ProtocolLXD) GetInstances(instanceType api.InstanceType) ([]api.Instanc // GetInstancesWithFilter returns a filtered list of instances. func (r *ProtocolLXD) GetInstancesWithFilter(instanceType api.InstanceType, filters []string) ([]api.Instance, error) { - if !r.HasExtension("api_filtering") { - return nil, fmt.Errorf("The server is missing the required \"api_filtering\" API extension") + err := r.CheckExtension("api_filtering") + if err != nil { + return nil, err } instances := []api.Instance{} @@ -153,8 +154,9 @@ func (r *ProtocolLXD) GetInstancesAllProjects(instanceType api.InstanceType) ([] v.Set("recursion", "1") v.Set("all-projects", "true") - if !r.HasExtension("instance_all_projects") { - return nil, fmt.Errorf("The server is missing the required \"instance_all_projects\" API extension") + err = r.CheckExtension("instance_all_projects") + if err != nil { + return nil, err } // Fetch the raw value @@ -168,8 +170,9 @@ func (r *ProtocolLXD) GetInstancesAllProjects(instanceType api.InstanceType) ([] // GetInstancesAllProjectsWithFilter returns a filtered list of instances from all projects. func (r *ProtocolLXD) GetInstancesAllProjectsWithFilter(instanceType api.InstanceType, filters []string) ([]api.Instance, error) { - if !r.HasExtension("api_filtering") { - return nil, fmt.Errorf("The server is missing the required \"api_filtering\" API extension") + err := r.CheckExtension("api_filtering") + if err != nil { + return nil, err } instances := []api.Instance{} @@ -183,8 +186,9 @@ func (r *ProtocolLXD) GetInstancesAllProjectsWithFilter(instanceType api.Instanc v.Set("all-projects", "true") v.Set("filter", parseFilters(filters)) - if !r.HasExtension("instance_all_projects") { - return nil, fmt.Errorf("The server is missing the required \"instance_all_projects\" API extension") + err = r.CheckExtension("instance_all_projects") + if err != nil { + return nil, err } // Fetch the raw value @@ -349,8 +353,9 @@ func (r *ProtocolLXD) GetInstancesFull(instanceType api.InstanceType) ([]api.Ins v.Set("recursion", "2") - if !r.HasExtension("container_full") { - return nil, fmt.Errorf("The server is missing the required \"container_full\" API extension") + err = r.CheckExtension("container_full") + if err != nil { + return nil, err } // Fetch the raw value @@ -364,8 +369,9 @@ func (r *ProtocolLXD) GetInstancesFull(instanceType api.InstanceType) ([]api.Ins // GetInstancesFullWithFilter returns a filtered list of instances including snapshots, backups and state. func (r *ProtocolLXD) GetInstancesFullWithFilter(instanceType api.InstanceType, filters []string) ([]api.InstanceFull, error) { - if !r.HasExtension("api_filtering") { - return nil, fmt.Errorf("The server is missing the required \"api_filtering\" API extension") + err := r.CheckExtension("api_filtering") + if err != nil { + return nil, err } instances := []api.InstanceFull{} @@ -378,8 +384,9 @@ func (r *ProtocolLXD) GetInstancesFullWithFilter(instanceType api.InstanceType, v.Set("recursion", "2") v.Set("filter", parseFilters(filters)) - if !r.HasExtension("container_full") { - return nil, fmt.Errorf("The server is missing the required \"container_full\" API extension") + err = r.CheckExtension("container_full") + if err != nil { + return nil, err } // Fetch the raw value @@ -403,12 +410,14 @@ func (r *ProtocolLXD) GetInstancesFullAllProjects(instanceType api.InstanceType) v.Set("recursion", "2") v.Set("all-projects", "true") - if !r.HasExtension("container_full") { - return nil, fmt.Errorf("The server is missing the required \"container_full\" API extension") + err = r.CheckExtension("container_full") + if err != nil { + return nil, err } - if !r.HasExtension("instance_all_projects") { - return nil, fmt.Errorf("The server is missing the required \"instance_all_projects\" API extension") + err = r.CheckExtension("instance_all_projects") + if err != nil { + return nil, err } // Fetch the raw value @@ -422,8 +431,9 @@ func (r *ProtocolLXD) GetInstancesFullAllProjects(instanceType api.InstanceType) // GetInstancesFullAllProjectsWithFilter returns a filtered list of instances including snapshots, backups and state from all projects. func (r *ProtocolLXD) GetInstancesFullAllProjectsWithFilter(instanceType api.InstanceType, filters []string) ([]api.InstanceFull, error) { - if !r.HasExtension("api_filtering") { - return nil, fmt.Errorf("The server is missing the required \"api_filtering\" API extension") + err := r.CheckExtension("api_filtering") + if err != nil { + return nil, err } instances := []api.InstanceFull{} @@ -437,12 +447,14 @@ func (r *ProtocolLXD) GetInstancesFullAllProjectsWithFilter(instanceType api.Ins v.Set("all-projects", "true") v.Set("filter", parseFilters(filters)) - if !r.HasExtension("container_full") { - return nil, fmt.Errorf("The server is missing the required \"container_full\" API extension") + err = r.CheckExtension("container_full") + if err != nil { + return nil, err } - if !r.HasExtension("instance_all_projects") { - return nil, fmt.Errorf("The server is missing the required \"instance_all_projects\" API extension") + err = r.CheckExtension("instance_all_projects") + if err != nil { + return nil, err } // Fetch the raw value @@ -476,7 +488,7 @@ func (r *ProtocolLXD) GetInstance(name string) (*api.Instance, string, error) { func (r *ProtocolLXD) GetInstanceFull(name string) (*api.InstanceFull, string, error) { instance := api.InstanceFull{} - if !r.HasExtension("instance_get_full") { + if r.CheckExtension("instance_get_full") != nil { // Backware compatibility. ct, _, err := r.GetInstance(name) if err != nil { @@ -523,8 +535,9 @@ func (r *ProtocolLXD) GetInstanceFull(name string) (*api.InstanceFull, string, e // CreateInstanceFromBackup is a convenience function to make it easier to // create a instance from a backup. func (r *ProtocolLXD) CreateInstanceFromBackup(args InstanceBackupArgs) (Operation, error) { - if !r.HasExtension("container_backup") { - return nil, fmt.Errorf("The server is missing the required \"container_backup\" API extension") + err := r.CheckExtension("container_backup") + if err != nil { + return nil, err } path, _, err := r.instanceTypeToPath(api.InstanceTypeAny) @@ -542,12 +555,18 @@ func (r *ProtocolLXD) CreateInstanceFromBackup(args InstanceBackupArgs) (Operati return op, nil } - if args.PoolName != "" && !r.HasExtension("container_backup_override_pool") { - return nil, fmt.Errorf(`The server is missing the required "container_backup_override_pool" API extension`) + if args.PoolName != "" { + err := r.CheckExtension("container_backup_override_pool") + if err != nil { + return nil, err + } } - if args.Name != "" && !r.HasExtension("backup_override_name") { - return nil, fmt.Errorf(`The server is missing the required "backup_override_name" API extension`) + if args.Name != "" { + err := r.CheckExtension("backup_override_name") + if err != nil { + return nil, err + } } // Prepare the HTTP request @@ -609,8 +628,9 @@ func (r *ProtocolLXD) CreateInstance(instance api.InstancesPost) (Operation, err } if instance.Source.InstanceOnly || instance.Source.ContainerOnly { - if !r.HasExtension("container_only_migration") { - return nil, fmt.Errorf("The server is missing the required \"container_only_migration\" API extension") + err := r.CheckExtension("container_only_migration") + if err != nil { + return nil, err } } @@ -770,7 +790,7 @@ func (r *ProtocolLXD) CopyInstance(source InstanceServer, instance api.Instance, if args.AllowInconsistent { if !r.HasExtension("instance_allow_inconsistent_copy") { - return nil, fmt.Errorf("The source server is missing the required \"instance_allow_inconsistent_copy\" API extension") + return nil, fmt.Errorf("The target server is missing the required \"instance_allow_inconsistent_copy\" API extension") } } @@ -801,11 +821,12 @@ func (r *ProtocolLXD) CopyInstance(source InstanceServer, instance api.Instance, } // Optimization for the local copy case - if destInfo.URL == sourceInfo.URL && destInfo.SocketPath == sourceInfo.SocketPath && (!r.IsClustered() || instance.Location == r.clusterTarget || r.HasExtension("cluster_internal_copy")) { + if destInfo.URL == sourceInfo.URL && destInfo.SocketPath == sourceInfo.SocketPath && (!r.IsClustered() || instance.Location == r.clusterTarget || r.CheckExtension("cluster_internal_copy") == nil) { // Project handling if destInfo.Project != sourceInfo.Project { - if !r.HasExtension("container_copy_project") { - return nil, fmt.Errorf("The server is missing the required \"container_copy_project\" API extension") + err := r.CheckExtension("container_copy_project") + if err != nil { + return nil, err } req.Source.Project = sourceInfo.Project @@ -1050,21 +1071,31 @@ func (r *ProtocolLXD) MigrateInstance(name string, instance api.InstancePost) (O } if instance.InstanceOnly || instance.ContainerOnly { - if !r.HasExtension("container_only_migration") { - return nil, fmt.Errorf("The server is missing the required \"container_only_migration\" API extension") + err := r.CheckExtension("container_only_migration") + if err != nil { + return nil, err } } - if instance.Pool != "" && !r.HasExtension("instance_pool_move") { - return nil, fmt.Errorf("The server is missing the required \"instance_pool_move\" API extension") + if instance.Pool != "" { + err := r.CheckExtension("instance_pool_move") + if err != nil { + return nil, err + } } - if instance.Project != "" && !r.HasExtension("instance_project_move") { - return nil, fmt.Errorf("The server is missing the required \"instance_project_move\" API extension") + if instance.Project != "" { + err := r.CheckExtension("instance_project_move") + if err != nil { + return nil, err + } } - if instance.AllowInconsistent && !r.HasExtension("cluster_migration_inconsistent_copy") { - return nil, fmt.Errorf("The server is missing the required \"cluster_migration_inconsistent_copy\" API extension") + if instance.AllowInconsistent { + err := r.CheckExtension("cluster_migration_inconsistent_copy") + if err != nil { + return nil, err + } } // Quick check. @@ -1105,14 +1136,16 @@ func (r *ProtocolLXD) ExecInstance(instanceName string, exec api.InstanceExecPos } if exec.RecordOutput { - if !r.HasExtension("container_exec_recording") { - return nil, fmt.Errorf("The server is missing the required \"container_exec_recording\" API extension") + err := r.CheckExtension("container_exec_recording") + if err != nil { + return nil, err } } if exec.User > 0 || exec.Group > 0 || exec.Cwd != "" { - if !r.HasExtension("container_exec_user_group_cwd") { - return nil, fmt.Errorf("The server is missing the required \"container_exec_user_group_cwd\" API extension") + err := r.CheckExtension("container_exec_user_group_cwd") + if err != nil { + return nil, err } } @@ -1429,20 +1462,23 @@ func (r *ProtocolLXD) GetInstanceFile(instanceName string, filePath string) (io. // CreateInstanceFile tells LXD to create a file in the instance. func (r *ProtocolLXD) CreateInstanceFile(instanceName string, filePath string, args InstanceFileArgs) error { if args.Type == "directory" { - if !r.HasExtension("directory_manipulation") { - return fmt.Errorf("The server is missing the required \"directory_manipulation\" API extension") + err := r.CheckExtension("directory_manipulation") + if err != nil { + return err } } if args.Type == "symlink" { - if !r.HasExtension("file_symlinks") { - return fmt.Errorf("The server is missing the required \"file_symlinks\" API extension") + err := r.CheckExtension("file_symlinks") + if err != nil { + return err } } if args.WriteMode == "append" { - if !r.HasExtension("file_append") { - return fmt.Errorf("The server is missing the required \"file_append\" API extension") + err := r.CheckExtension("file_append") + if err != nil { + return err } } @@ -1508,8 +1544,9 @@ func (r *ProtocolLXD) CreateInstanceFile(instanceName string, filePath string, a // DeleteInstanceFile deletes a file in the instance. func (r *ProtocolLXD) DeleteInstanceFile(instanceName string, filePath string) error { - if !r.HasExtension("file_delete") { - return fmt.Errorf("The server is missing the required \"file_delete\" API extension") + err := r.CheckExtension("file_delete") + if err != nil { + return err } var requestURL string @@ -1526,7 +1563,7 @@ func (r *ProtocolLXD) DeleteInstanceFile(instanceName string, filePath string) e requestURL = fmt.Sprintf("%s/%s/files?path=%s", path, url.PathEscape(instanceName), url.QueryEscape(filePath)) } - requestURL, err := r.setQueryAttributes(requestURL) + requestURL, err = r.setQueryAttributes(requestURL) if err != nil { return err } @@ -1704,8 +1741,11 @@ func (r *ProtocolLXD) CreateInstanceSnapshot(instanceName string, snapshot api.I } // Validate the request - if snapshot.ExpiresAt != nil && !r.HasExtension("snapshot_expiry_creation") { - return nil, fmt.Errorf("The server is missing the required \"snapshot_expiry_creation\" API extension") + if snapshot.ExpiresAt != nil { + err := r.CheckExtension("snapshot_expiry_creation") + if err != nil { + return nil, err + } } // Send the request @@ -1737,8 +1777,9 @@ func (r *ProtocolLXD) CopyInstanceSnapshot(source InstanceServer, instanceName s } if snapshot.Stateful && args.Live { - if !r.HasExtension("container_snapshot_stateful_migration") { - return nil, fmt.Errorf("The server is missing the required \"container_snapshot_stateful_migration\" API extension") + err := r.CheckExtension("container_snapshot_stateful_migration") + if err != nil { + return nil, err } req.InstancePut.Stateful = snapshot.Stateful @@ -1751,8 +1792,9 @@ func (r *ProtocolLXD) CopyInstanceSnapshot(source InstanceServer, instanceName s if args != nil { // Quick checks. if shared.ValueInSlice(args.Mode, []string{"push", "relay"}) { - if !r.HasExtension("container_push") { - return nil, fmt.Errorf("The target server is missing the required \"container_push\" API extension") + err := r.CheckExtension("container_push") + if err != nil { + return nil, err } if !source.HasExtension("container_push") { @@ -1786,11 +1828,12 @@ func (r *ProtocolLXD) CopyInstanceSnapshot(source InstanceServer, instanceName s } // Optimization for the local copy case - if destInfo.URL == sourceInfo.URL && destInfo.SocketPath == sourceInfo.SocketPath && (!r.IsClustered() || instance.Location == r.clusterTarget || r.HasExtension("cluster_internal_copy")) { + if destInfo.URL == sourceInfo.URL && destInfo.SocketPath == sourceInfo.SocketPath && (!r.IsClustered() || instance.Location == r.clusterTarget || r.CheckExtension("cluster_internal_copy") == nil) { // Project handling if destInfo.Project != sourceInfo.Project { - if !r.HasExtension("container_copy_project") { - return nil, fmt.Errorf("The server is missing the required \"container_copy_project\" API extension") + err := r.CheckExtension("container_copy_project") + if err != nil { + return nil, err } req.Source.Project = sourceInfo.Project @@ -2063,8 +2106,9 @@ func (r *ProtocolLXD) UpdateInstanceSnapshot(instanceName string, name string, i return nil, err } - if !r.HasExtension("snapshot_expiry") { - return nil, fmt.Errorf("The server is missing the required \"snapshot_expiry\" API extension") + err = r.CheckExtension("snapshot_expiry") + if err != nil { + return nil, err } // Send the request @@ -2264,8 +2308,9 @@ func (r *ProtocolLXD) GetInstanceMetadata(name string) (*api.ImageMetadata, stri return nil, "", err } - if !r.HasExtension("container_edit_metadata") { - return nil, "", fmt.Errorf("The server is missing the required \"container_edit_metadata\" API extension") + err = r.CheckExtension("container_edit_metadata") + if err != nil { + return nil, "", err } metadata := api.ImageMetadata{} @@ -2286,8 +2331,9 @@ func (r *ProtocolLXD) UpdateInstanceMetadata(name string, metadata api.ImageMeta return err } - if !r.HasExtension("container_edit_metadata") { - return fmt.Errorf("The server is missing the required \"container_edit_metadata\" API extension") + err = r.CheckExtension("container_edit_metadata") + if err != nil { + return err } url := fmt.Sprintf("%s/%s/metadata", path, url.PathEscape(name)) @@ -2306,8 +2352,9 @@ func (r *ProtocolLXD) GetInstanceTemplateFiles(instanceName string) ([]string, e return nil, err } - if !r.HasExtension("container_edit_metadata") { - return nil, fmt.Errorf("The server is missing the required \"container_edit_metadata\" API extension") + err = r.CheckExtension("container_edit_metadata") + if err != nil { + return nil, err } templates := []string{} @@ -2328,8 +2375,9 @@ func (r *ProtocolLXD) GetInstanceTemplateFile(instanceName string, templateName return nil, err } - if !r.HasExtension("container_edit_metadata") { - return nil, fmt.Errorf("The server is missing the required \"container_edit_metadata\" API extension") + err = r.CheckExtension("container_edit_metadata") + if err != nil { + return nil, err } url := fmt.Sprintf("%s/1.0%s/%s/metadata/templates?path=%s", r.httpBaseURL.String(), path, url.PathEscape(instanceName), url.QueryEscape(templateName)) @@ -2368,8 +2416,9 @@ func (r *ProtocolLXD) CreateInstanceTemplateFile(instanceName string, templateNa return err } - if !r.HasExtension("container_edit_metadata") { - return fmt.Errorf("The server is missing the required \"container_edit_metadata\" API extension") + err = r.CheckExtension("container_edit_metadata") + if err != nil { + return err } url := fmt.Sprintf("%s/1.0%s/%s/metadata/templates?path=%s", r.httpBaseURL.String(), path, url.PathEscape(instanceName), url.QueryEscape(templateName)) @@ -2405,8 +2454,9 @@ func (r *ProtocolLXD) DeleteInstanceTemplateFile(name string, templateName strin return err } - if !r.HasExtension("container_edit_metadata") { - return fmt.Errorf("The server is missing the required \"container_edit_metadata\" API extension") + err = r.CheckExtension("container_edit_metadata") + if err != nil { + return err } _, _, err = r.query("DELETE", fmt.Sprintf("%s/%s/metadata/templates?path=%s", path, url.PathEscape(name), url.QueryEscape(templateName)), nil, "") @@ -2420,16 +2470,20 @@ func (r *ProtocolLXD) ConsoleInstance(instanceName string, console api.InstanceC return nil, err } - if !r.HasExtension("console") { - return nil, fmt.Errorf("The server is missing the required \"console\" API extension") + err = r.CheckExtension("console") + if err != nil { + return nil, err } if console.Type == "" { console.Type = "console" } - if console.Type == "vga" && !r.HasExtension("console_vga_type") { - return nil, fmt.Errorf("The server is missing the required \"console_vga_type\" API extension") + if console.Type == "vga" { + err = r.CheckExtension("console_vga_type") + if err != nil { + return nil, err + } } // Send the request @@ -2509,16 +2563,20 @@ func (r *ProtocolLXD) ConsoleInstanceDynamic(instanceName string, console api.In return nil, nil, err } - if !r.HasExtension("console") { - return nil, nil, fmt.Errorf("The server is missing the required \"console\" API extension") + err = r.CheckExtension("console") + if err != nil { + return nil, nil, err } if console.Type == "" { console.Type = "console" } - if console.Type == "vga" && !r.HasExtension("console_vga_type") { - return nil, nil, fmt.Errorf("The server is missing the required \"console_vga_type\" API extension") + if console.Type == "vga" { + err = r.CheckExtension("console_vga_type") + if err != nil { + return nil, nil, err + } } // Send the request. @@ -2596,8 +2654,9 @@ func (r *ProtocolLXD) GetInstanceConsoleLog(instanceName string, args *InstanceC return nil, err } - if !r.HasExtension("console") { - return nil, fmt.Errorf("The server is missing the required \"console\" API extension") + err = r.CheckExtension("console") + if err != nil { + return nil, err } // Prepare the HTTP request @@ -2637,8 +2696,9 @@ func (r *ProtocolLXD) DeleteInstanceConsoleLog(instanceName string, args *Instan return err } - if !r.HasExtension("console") { - return fmt.Errorf("The server is missing the required \"console\" API extension") + err = r.CheckExtension("console") + if err != nil { + return err } // Send the request @@ -2652,8 +2712,9 @@ func (r *ProtocolLXD) DeleteInstanceConsoleLog(instanceName string, args *Instan // GetInstanceBackupNames returns a list of backup names for the instance. func (r *ProtocolLXD) GetInstanceBackupNames(instanceName string) ([]string, error) { - if !r.HasExtension("container_backup") { - return nil, fmt.Errorf("The server is missing the required \"container_backup\" API extension") + err := r.CheckExtension("container_backup") + if err != nil { + return nil, err } path, _, err := r.instanceTypeToPath(api.InstanceTypeAny) @@ -2680,8 +2741,9 @@ func (r *ProtocolLXD) GetInstanceBackups(instanceName string) ([]api.InstanceBac return nil, err } - if !r.HasExtension("container_backup") { - return nil, fmt.Errorf("The server is missing the required \"container_backup\" API extension") + err = r.CheckExtension("container_backup") + if err != nil { + return nil, err } // Fetch the raw value @@ -2702,8 +2764,9 @@ func (r *ProtocolLXD) GetInstanceBackup(instanceName string, name string) (*api. return nil, "", err } - if !r.HasExtension("container_backup") { - return nil, "", fmt.Errorf("The server is missing the required \"container_backup\" API extension") + err = r.CheckExtension("container_backup") + if err != nil { + return nil, "", err } // Fetch the raw value @@ -2723,8 +2786,9 @@ func (r *ProtocolLXD) CreateInstanceBackup(instanceName string, backup api.Insta return nil, err } - if !r.HasExtension("container_backup") { - return nil, fmt.Errorf("The server is missing the required \"container_backup\" API extension") + err = r.CheckExtension("container_backup") + if err != nil { + return nil, err } // Send the request @@ -2743,8 +2807,9 @@ func (r *ProtocolLXD) RenameInstanceBackup(instanceName string, name string, bac return nil, err } - if !r.HasExtension("container_backup") { - return nil, fmt.Errorf("The server is missing the required \"container_backup\" API extension") + err = r.CheckExtension("container_backup") + if err != nil { + return nil, err } // Send the request @@ -2763,8 +2828,9 @@ func (r *ProtocolLXD) DeleteInstanceBackup(instanceName string, name string) (Op return nil, err } - if !r.HasExtension("container_backup") { - return nil, fmt.Errorf("The server is missing the required \"container_backup\" API extension") + err = r.CheckExtension("container_backup") + if err != nil { + return nil, err } // Send the request @@ -2783,8 +2849,9 @@ func (r *ProtocolLXD) GetInstanceBackupFile(instanceName string, name string, re return nil, err } - if !r.HasExtension("container_backup") { - return nil, fmt.Errorf("The server is missing the required \"container_backup\" API extension") + err = r.CheckExtension("container_backup") + if err != nil { + return nil, err } // Build the URL diff --git a/client/lxd_network_acls.go b/client/lxd_network_acls.go index 62122c12d336..011a9baf4ddf 100644 --- a/client/lxd_network_acls.go +++ b/client/lxd_network_acls.go @@ -11,14 +11,15 @@ import ( // GetNetworkACLNames returns a list of network ACL names. func (r *ProtocolLXD) GetNetworkACLNames() ([]string, error) { - if !r.HasExtension("network_acl") { - return nil, fmt.Errorf(`The server is missing the required "network_acl" API extension`) + err := r.CheckExtension("network_acl") + if err != nil { + return nil, err } // Fetch the raw URL values. urls := []string{} baseURL := "/network-acls" - _, err := r.queryStruct("GET", baseURL, nil, "", &urls) + _, err = r.queryStruct("GET", baseURL, nil, "", &urls) if err != nil { return nil, err } @@ -29,14 +30,15 @@ func (r *ProtocolLXD) GetNetworkACLNames() ([]string, error) { // GetNetworkACLs returns a list of Network ACL structs. func (r *ProtocolLXD) GetNetworkACLs() ([]api.NetworkACL, error) { - if !r.HasExtension("network_acl") { - return nil, fmt.Errorf(`The server is missing the required "network_acl" API extension`) + err := r.CheckExtension("network_acl") + if err != nil { + return nil, err } acls := []api.NetworkACL{} // Fetch the raw value. - _, err := r.queryStruct("GET", "/network-acls?recursion=1", nil, "", &acls) + _, err = r.queryStruct("GET", "/network-acls?recursion=1", nil, "", &acls) if err != nil { return nil, err } @@ -46,8 +48,9 @@ func (r *ProtocolLXD) GetNetworkACLs() ([]api.NetworkACL, error) { // GetNetworkACL returns a Network ACL entry for the provided name. func (r *ProtocolLXD) GetNetworkACL(name string) (*api.NetworkACL, string, error) { - if !r.HasExtension("network_acl") { - return nil, "", fmt.Errorf(`The server is missing the required "network_acl" API extension`) + err := r.CheckExtension("network_acl") + if err != nil { + return nil, "", err } acl := api.NetworkACL{} @@ -65,13 +68,14 @@ func (r *ProtocolLXD) GetNetworkACL(name string) (*api.NetworkACL, string, error // // Note that it's the caller's responsibility to close the returned ReadCloser. func (r *ProtocolLXD) GetNetworkACLLogfile(name string) (io.ReadCloser, error) { - if !r.HasExtension("network_acl_log") { - return nil, fmt.Errorf(`The server is missing the required "network_acl_log" API extension`) + err := r.CheckExtension("network_acl_log") + if err != nil { + return nil, err } // Prepare the HTTP request url := fmt.Sprintf("%s/1.0/network-acls/%s/log", r.httpBaseURL.String(), url.PathEscape(name)) - url, err := r.setQueryAttributes(url) + url, err = r.setQueryAttributes(url) if err != nil { return nil, err } @@ -100,12 +104,13 @@ func (r *ProtocolLXD) GetNetworkACLLogfile(name string) (io.ReadCloser, error) { // CreateNetworkACL defines a new network ACL using the provided struct. func (r *ProtocolLXD) CreateNetworkACL(acl api.NetworkACLsPost) error { - if !r.HasExtension("network_acl") { - return fmt.Errorf(`The server is missing the required "network_acl" API extension`) + err := r.CheckExtension("network_acl") + if err != nil { + return err } // Send the request. - _, _, err := r.query("POST", "/network-acls", acl, "") + _, _, err = r.query("POST", "/network-acls", acl, "") if err != nil { return err } @@ -115,12 +120,13 @@ func (r *ProtocolLXD) CreateNetworkACL(acl api.NetworkACLsPost) error { // UpdateNetworkACL updates the network ACL to match the provided struct. func (r *ProtocolLXD) UpdateNetworkACL(name string, acl api.NetworkACLPut, ETag string) error { - if !r.HasExtension("network_acl") { - return fmt.Errorf(`The server is missing the required "network_acl" API extension`) + err := r.CheckExtension("network_acl") + if err != nil { + return err } // Send the request. - _, _, err := r.query("PUT", fmt.Sprintf("/network-acls/%s", url.PathEscape(name)), acl, ETag) + _, _, err = r.query("PUT", fmt.Sprintf("/network-acls/%s", url.PathEscape(name)), acl, ETag) if err != nil { return err } @@ -130,12 +136,13 @@ func (r *ProtocolLXD) UpdateNetworkACL(name string, acl api.NetworkACLPut, ETag // RenameNetworkACL renames an existing network ACL entry. func (r *ProtocolLXD) RenameNetworkACL(name string, acl api.NetworkACLPost) error { - if !r.HasExtension("network_acl") { - return fmt.Errorf(`The server is missing the required "network_acl" API extension`) + err := r.CheckExtension("network_acl") + if err != nil { + return err } // Send the request. - _, _, err := r.query("POST", fmt.Sprintf("/network-acls/%s", url.PathEscape(name)), acl, "") + _, _, err = r.query("POST", fmt.Sprintf("/network-acls/%s", url.PathEscape(name)), acl, "") if err != nil { return err } @@ -145,12 +152,13 @@ func (r *ProtocolLXD) RenameNetworkACL(name string, acl api.NetworkACLPost) erro // DeleteNetworkACL deletes an existing network ACL. func (r *ProtocolLXD) DeleteNetworkACL(name string) error { - if !r.HasExtension("network_acl") { - return fmt.Errorf(`The server is missing the required "network_acl" API extension`) + err := r.CheckExtension("network_acl") + if err != nil { + return err } // Send the request. - _, _, err := r.query("DELETE", fmt.Sprintf("/network-acls/%s", url.PathEscape(name)), nil, "") + _, _, err = r.query("DELETE", fmt.Sprintf("/network-acls/%s", url.PathEscape(name)), nil, "") if err != nil { return err } diff --git a/client/lxd_network_forwards.go b/client/lxd_network_forwards.go index 5efa7098885a..2953c79a6385 100644 --- a/client/lxd_network_forwards.go +++ b/client/lxd_network_forwards.go @@ -9,14 +9,15 @@ import ( // GetNetworkForwardAddresses returns a list of network forward listen addresses. func (r *ProtocolLXD) GetNetworkForwardAddresses(networkName string) ([]string, error) { - if !r.HasExtension("network_forward") { - return nil, fmt.Errorf(`The server is missing the required "network_forward" API extension`) + err := r.CheckExtension("network_forward") + if err != nil { + return nil, err } // Fetch the raw URL values. urls := []string{} baseURL := fmt.Sprintf("/networks/%s/forwards", url.PathEscape(networkName)) - _, err := r.queryStruct("GET", baseURL, nil, "", &urls) + _, err = r.queryStruct("GET", baseURL, nil, "", &urls) if err != nil { return nil, err } @@ -27,14 +28,15 @@ func (r *ProtocolLXD) GetNetworkForwardAddresses(networkName string) ([]string, // GetNetworkForwards returns a list of Network forward structs. func (r *ProtocolLXD) GetNetworkForwards(networkName string) ([]api.NetworkForward, error) { - if !r.HasExtension("network_forward") { - return nil, fmt.Errorf(`The server is missing the required "network_forward" API extension`) + err := r.CheckExtension("network_forward") + if err != nil { + return nil, err } forwards := []api.NetworkForward{} // Fetch the raw value. - _, err := r.queryStruct("GET", fmt.Sprintf("/networks/%s/forwards?recursion=1", url.PathEscape(networkName)), nil, "", &forwards) + _, err = r.queryStruct("GET", fmt.Sprintf("/networks/%s/forwards?recursion=1", url.PathEscape(networkName)), nil, "", &forwards) if err != nil { return nil, err } @@ -44,8 +46,9 @@ func (r *ProtocolLXD) GetNetworkForwards(networkName string) ([]api.NetworkForwa // GetNetworkForward returns a Network forward entry for the provided network and listen address. func (r *ProtocolLXD) GetNetworkForward(networkName string, listenAddress string) (*api.NetworkForward, string, error) { - if !r.HasExtension("network_forward") { - return nil, "", fmt.Errorf(`The server is missing the required "network_forward" API extension`) + err := r.CheckExtension("network_forward") + if err != nil { + return nil, "", err } forward := api.NetworkForward{} @@ -61,12 +64,13 @@ func (r *ProtocolLXD) GetNetworkForward(networkName string, listenAddress string // CreateNetworkForward defines a new network forward using the provided struct. func (r *ProtocolLXD) CreateNetworkForward(networkName string, forward api.NetworkForwardsPost) error { - if !r.HasExtension("network_forward") { - return fmt.Errorf(`The server is missing the required "network_forward" API extension`) + err := r.CheckExtension("network_forward") + if err != nil { + return err } // Send the request. - _, _, err := r.query("POST", fmt.Sprintf("/networks/%s/forwards", url.PathEscape(networkName)), forward, "") + _, _, err = r.query("POST", fmt.Sprintf("/networks/%s/forwards", url.PathEscape(networkName)), forward, "") if err != nil { return err } @@ -76,12 +80,13 @@ func (r *ProtocolLXD) CreateNetworkForward(networkName string, forward api.Netwo // UpdateNetworkForward updates the network forward to match the provided struct. func (r *ProtocolLXD) UpdateNetworkForward(networkName string, listenAddress string, forward api.NetworkForwardPut, ETag string) error { - if !r.HasExtension("network_forward") { - return fmt.Errorf(`The server is missing the required "network_forward" API extension`) + err := r.CheckExtension("network_forward") + if err != nil { + return err } // Send the request. - _, _, err := r.query("PUT", fmt.Sprintf("/networks/%s/forwards/%s", url.PathEscape(networkName), url.PathEscape(listenAddress)), forward, ETag) + _, _, err = r.query("PUT", fmt.Sprintf("/networks/%s/forwards/%s", url.PathEscape(networkName), url.PathEscape(listenAddress)), forward, ETag) if err != nil { return err } @@ -91,12 +96,13 @@ func (r *ProtocolLXD) UpdateNetworkForward(networkName string, listenAddress str // DeleteNetworkForward deletes an existing network forward. func (r *ProtocolLXD) DeleteNetworkForward(networkName string, listenAddress string) error { - if !r.HasExtension("network_forward") { - return fmt.Errorf(`The server is missing the required "network_forward" API extension`) + err := r.CheckExtension("network_forward") + if err != nil { + return err } // Send the request. - _, _, err := r.query("DELETE", fmt.Sprintf("/networks/%s/forwards/%s", url.PathEscape(networkName), url.PathEscape(listenAddress)), nil, "") + _, _, err = r.query("DELETE", fmt.Sprintf("/networks/%s/forwards/%s", url.PathEscape(networkName), url.PathEscape(listenAddress)), nil, "") if err != nil { return err } diff --git a/client/lxd_network_peer.go b/client/lxd_network_peer.go index 386bab464c3f..8145d5f770ff 100644 --- a/client/lxd_network_peer.go +++ b/client/lxd_network_peer.go @@ -9,14 +9,15 @@ import ( // GetNetworkPeerNames returns a list of network peer names. func (r *ProtocolLXD) GetNetworkPeerNames(networkName string) ([]string, error) { - if !r.HasExtension("network_peer") { - return nil, fmt.Errorf(`The server is missing the required "network_peer" API extension`) + err := r.CheckExtension("network_peer") + if err != nil { + return nil, err } // Fetch the raw URL values. urls := []string{} baseURL := fmt.Sprintf("/networks/%s/peers", url.PathEscape(networkName)) - _, err := r.queryStruct("GET", baseURL, nil, "", &urls) + _, err = r.queryStruct("GET", baseURL, nil, "", &urls) if err != nil { return nil, err } @@ -27,14 +28,15 @@ func (r *ProtocolLXD) GetNetworkPeerNames(networkName string) ([]string, error) // GetNetworkPeers returns a list of network peer structs. func (r *ProtocolLXD) GetNetworkPeers(networkName string) ([]api.NetworkPeer, error) { - if !r.HasExtension("network_peer") { - return nil, fmt.Errorf(`The server is missing the required "network_peer" API extension`) + err := r.CheckExtension("network_peer") + if err != nil { + return nil, err } peers := []api.NetworkPeer{} // Fetch the raw value. - _, err := r.queryStruct("GET", fmt.Sprintf("/networks/%s/peers?recursion=1", url.PathEscape(networkName)), nil, "", &peers) + _, err = r.queryStruct("GET", fmt.Sprintf("/networks/%s/peers?recursion=1", url.PathEscape(networkName)), nil, "", &peers) if err != nil { return nil, err } @@ -44,8 +46,9 @@ func (r *ProtocolLXD) GetNetworkPeers(networkName string) ([]api.NetworkPeer, er // GetNetworkPeer returns a network peer entry for the provided network and peer name. func (r *ProtocolLXD) GetNetworkPeer(networkName string, peerName string) (*api.NetworkPeer, string, error) { - if !r.HasExtension("network_peer") { - return nil, "", fmt.Errorf(`The server is missing the required "network_peer" API extension`) + err := r.CheckExtension("network_peer") + if err != nil { + return nil, "", err } peer := api.NetworkPeer{} @@ -62,12 +65,13 @@ func (r *ProtocolLXD) GetNetworkPeer(networkName string, peerName string) (*api. // CreateNetworkPeer defines a new network peer using the provided struct. // Returns true if the peer connection has been mutually created. Returns false if peering has been only initiated. func (r *ProtocolLXD) CreateNetworkPeer(networkName string, peer api.NetworkPeersPost) error { - if !r.HasExtension("network_peer") { - return fmt.Errorf(`The server is missing the required "network_peer" API extension`) + err := r.CheckExtension("network_peer") + if err != nil { + return err } // Send the request. - _, _, err := r.query("POST", fmt.Sprintf("/networks/%s/peers", url.PathEscape(networkName)), peer, "") + _, _, err = r.query("POST", fmt.Sprintf("/networks/%s/peers", url.PathEscape(networkName)), peer, "") if err != nil { return err } @@ -77,12 +81,13 @@ func (r *ProtocolLXD) CreateNetworkPeer(networkName string, peer api.NetworkPeer // UpdateNetworkPeer updates the network peer to match the provided struct. func (r *ProtocolLXD) UpdateNetworkPeer(networkName string, peerName string, peer api.NetworkPeerPut, ETag string) error { - if !r.HasExtension("network_peer") { - return fmt.Errorf(`The server is missing the required "network_peer" API extension`) + err := r.CheckExtension("network_peer") + if err != nil { + return err } // Send the request. - _, _, err := r.query("PUT", fmt.Sprintf("/networks/%s/peers/%s", url.PathEscape(networkName), url.PathEscape(peerName)), peer, ETag) + _, _, err = r.query("PUT", fmt.Sprintf("/networks/%s/peers/%s", url.PathEscape(networkName), url.PathEscape(peerName)), peer, ETag) if err != nil { return err } @@ -92,12 +97,13 @@ func (r *ProtocolLXD) UpdateNetworkPeer(networkName string, peerName string, pee // DeleteNetworkPeer deletes an existing network peer. func (r *ProtocolLXD) DeleteNetworkPeer(networkName string, peerName string) error { - if !r.HasExtension("network_peer") { - return fmt.Errorf(`The server is missing the required "network_peer" API extension`) + err := r.CheckExtension("network_peer") + if err != nil { + return err } // Send the request. - _, _, err := r.query("DELETE", fmt.Sprintf("/networks/%s/peers/%s", url.PathEscape(networkName), url.PathEscape(peerName)), nil, "") + _, _, err = r.query("DELETE", fmt.Sprintf("/networks/%s/peers/%s", url.PathEscape(networkName), url.PathEscape(peerName)), nil, "") if err != nil { return err } diff --git a/client/lxd_network_zones.go b/client/lxd_network_zones.go index 708ea046b05c..a12676ef32bc 100644 --- a/client/lxd_network_zones.go +++ b/client/lxd_network_zones.go @@ -9,14 +9,15 @@ import ( // GetNetworkZoneNames returns a list of network zone names. func (r *ProtocolLXD) GetNetworkZoneNames() ([]string, error) { - if !r.HasExtension("network_dns") { - return nil, fmt.Errorf(`The server is missing the required "network_dns" API extension`) + err := r.CheckExtension("network_dns") + if err != nil { + return nil, err } // Fetch the raw URL values. urls := []string{} baseURL := "/network-zones" - _, err := r.queryStruct("GET", baseURL, nil, "", &urls) + _, err = r.queryStruct("GET", baseURL, nil, "", &urls) if err != nil { return nil, err } @@ -27,14 +28,15 @@ func (r *ProtocolLXD) GetNetworkZoneNames() ([]string, error) { // GetNetworkZones returns a list of Network zone structs. func (r *ProtocolLXD) GetNetworkZones() ([]api.NetworkZone, error) { - if !r.HasExtension("network_dns") { - return nil, fmt.Errorf(`The server is missing the required "network_dns" API extension`) + err := r.CheckExtension("network_dns") + if err != nil { + return nil, err } zones := []api.NetworkZone{} // Fetch the raw value. - _, err := r.queryStruct("GET", "/network-zones?recursion=1", nil, "", &zones) + _, err = r.queryStruct("GET", "/network-zones?recursion=1", nil, "", &zones) if err != nil { return nil, err } @@ -44,8 +46,9 @@ func (r *ProtocolLXD) GetNetworkZones() ([]api.NetworkZone, error) { // GetNetworkZone returns a Network zone entry for the provided name. func (r *ProtocolLXD) GetNetworkZone(name string) (*api.NetworkZone, string, error) { - if !r.HasExtension("network_dns") { - return nil, "", fmt.Errorf(`The server is missing the required "network_dns" API extension`) + err := r.CheckExtension("network_dns") + if err != nil { + return nil, "", err } zone := api.NetworkZone{} @@ -61,12 +64,13 @@ func (r *ProtocolLXD) GetNetworkZone(name string) (*api.NetworkZone, string, err // CreateNetworkZone defines a new Network zone using the provided struct. func (r *ProtocolLXD) CreateNetworkZone(zone api.NetworkZonesPost) error { - if !r.HasExtension("network_dns") { - return fmt.Errorf(`The server is missing the required "network_dns" API extension`) + err := r.CheckExtension("network_dns") + if err != nil { + return err } // Send the request. - _, _, err := r.query("POST", "/network-zones", zone, "") + _, _, err = r.query("POST", "/network-zones", zone, "") if err != nil { return err } @@ -76,12 +80,13 @@ func (r *ProtocolLXD) CreateNetworkZone(zone api.NetworkZonesPost) error { // UpdateNetworkZone updates the network zone to match the provided struct. func (r *ProtocolLXD) UpdateNetworkZone(name string, zone api.NetworkZonePut, ETag string) error { - if !r.HasExtension("network_dns") { - return fmt.Errorf(`The server is missing the required "network_dns" API extension`) + err := r.CheckExtension("network_dns") + if err != nil { + return err } // Send the request. - _, _, err := r.query("PUT", fmt.Sprintf("/network-zones/%s", url.PathEscape(name)), zone, ETag) + _, _, err = r.query("PUT", fmt.Sprintf("/network-zones/%s", url.PathEscape(name)), zone, ETag) if err != nil { return err } @@ -91,12 +96,13 @@ func (r *ProtocolLXD) UpdateNetworkZone(name string, zone api.NetworkZonePut, ET // DeleteNetworkZone deletes an existing network zone. func (r *ProtocolLXD) DeleteNetworkZone(name string) error { - if !r.HasExtension("network_dns") { - return fmt.Errorf(`The server is missing the required "network_dns" API extension`) + err := r.CheckExtension("network_dns") + if err != nil { + return err } // Send the request. - _, _, err := r.query("DELETE", fmt.Sprintf("/network-zones/%s", url.PathEscape(name)), nil, "") + _, _, err = r.query("DELETE", fmt.Sprintf("/network-zones/%s", url.PathEscape(name)), nil, "") if err != nil { return err } @@ -106,14 +112,15 @@ func (r *ProtocolLXD) DeleteNetworkZone(name string) error { // GetNetworkZoneRecordNames returns a list of network zone record names. func (r *ProtocolLXD) GetNetworkZoneRecordNames(zone string) ([]string, error) { - if !r.HasExtension("network_dns_records") { - return nil, fmt.Errorf(`The server is missing the required "network_dns_records" API extension`) + err := r.CheckExtension("network_dns_records") + if err != nil { + return nil, err } // Fetch the raw URL values. urls := []string{} baseURL := fmt.Sprintf("/network-zones/%s/records", url.PathEscape(zone)) - _, err := r.queryStruct("GET", baseURL, nil, "", &urls) + _, err = r.queryStruct("GET", baseURL, nil, "", &urls) if err != nil { return nil, err } @@ -124,14 +131,15 @@ func (r *ProtocolLXD) GetNetworkZoneRecordNames(zone string) ([]string, error) { // GetNetworkZoneRecords returns a list of Network zone record structs. func (r *ProtocolLXD) GetNetworkZoneRecords(zone string) ([]api.NetworkZoneRecord, error) { - if !r.HasExtension("network_dns_records") { - return nil, fmt.Errorf(`The server is missing the required "network_dns_records" API extension`) + err := r.CheckExtension("network_dns_records") + if err != nil { + return nil, err } records := []api.NetworkZoneRecord{} // Fetch the raw value. - _, err := r.queryStruct("GET", fmt.Sprintf("/network-zones/%s/records?recursion=1", url.PathEscape(zone)), nil, "", &records) + _, err = r.queryStruct("GET", fmt.Sprintf("/network-zones/%s/records?recursion=1", url.PathEscape(zone)), nil, "", &records) if err != nil { return nil, err } @@ -141,8 +149,9 @@ func (r *ProtocolLXD) GetNetworkZoneRecords(zone string) ([]api.NetworkZoneRecor // GetNetworkZoneRecord returns a Network zone record entry for the provided zone and name. func (r *ProtocolLXD) GetNetworkZoneRecord(zone string, name string) (*api.NetworkZoneRecord, string, error) { - if !r.HasExtension("network_dns_records") { - return nil, "", fmt.Errorf(`The server is missing the required "network_dns_records" API extension`) + err := r.CheckExtension("network_dns_records") + if err != nil { + return nil, "", err } record := api.NetworkZoneRecord{} @@ -158,12 +167,13 @@ func (r *ProtocolLXD) GetNetworkZoneRecord(zone string, name string) (*api.Netwo // CreateNetworkZoneRecord defines a new Network zone record using the provided struct. func (r *ProtocolLXD) CreateNetworkZoneRecord(zone string, record api.NetworkZoneRecordsPost) error { - if !r.HasExtension("network_dns_records") { - return fmt.Errorf(`The server is missing the required "network_dns_records" API extension`) + err := r.CheckExtension("network_dns_records") + if err != nil { + return err } // Send the request. - _, _, err := r.query("POST", fmt.Sprintf("/network-zones/%s/records", url.PathEscape(zone)), record, "") + _, _, err = r.query("POST", fmt.Sprintf("/network-zones/%s/records", url.PathEscape(zone)), record, "") if err != nil { return err } @@ -173,12 +183,13 @@ func (r *ProtocolLXD) CreateNetworkZoneRecord(zone string, record api.NetworkZon // UpdateNetworkZoneRecord updates the network zone record to match the provided struct. func (r *ProtocolLXD) UpdateNetworkZoneRecord(zone string, name string, record api.NetworkZoneRecordPut, ETag string) error { - if !r.HasExtension("network_dns_records") { - return fmt.Errorf(`The server is missing the required "network_dns_records" API extension`) + err := r.CheckExtension("network_dns_records") + if err != nil { + return err } // Send the request. - _, _, err := r.query("PUT", fmt.Sprintf("/network-zones/%s/records/%s", url.PathEscape(zone), url.PathEscape(name)), record, ETag) + _, _, err = r.query("PUT", fmt.Sprintf("/network-zones/%s/records/%s", url.PathEscape(zone), url.PathEscape(name)), record, ETag) if err != nil { return err } @@ -188,12 +199,13 @@ func (r *ProtocolLXD) UpdateNetworkZoneRecord(zone string, name string, record a // DeleteNetworkZoneRecord deletes an existing network zone record. func (r *ProtocolLXD) DeleteNetworkZoneRecord(zone string, name string) error { - if !r.HasExtension("network_dns_records") { - return fmt.Errorf(`The server is missing the required "network_dns_records" API extension`) + err := r.CheckExtension("network_dns_records") + if err != nil { + return err } // Send the request. - _, _, err := r.query("DELETE", fmt.Sprintf("/network-zones/%s/records/%s", url.PathEscape(zone), url.PathEscape(name)), nil, "") + _, _, err = r.query("DELETE", fmt.Sprintf("/network-zones/%s/records/%s", url.PathEscape(zone), url.PathEscape(name)), nil, "") if err != nil { return err } diff --git a/client/lxd_networks.go b/client/lxd_networks.go index d459fa76457c..64a9e4f666d6 100644 --- a/client/lxd_networks.go +++ b/client/lxd_networks.go @@ -9,14 +9,15 @@ import ( // GetNetworkNames returns a list of network names. func (r *ProtocolLXD) GetNetworkNames() ([]string, error) { - if !r.HasExtension("network") { - return nil, fmt.Errorf("The server is missing the required \"network\" API extension") + err := r.CheckExtension("network") + if err != nil { + return nil, err } // Fetch the raw values. urls := []string{} baseURL := "/networks" - _, err := r.queryStruct("GET", baseURL, nil, "", &urls) + _, err = r.queryStruct("GET", baseURL, nil, "", &urls) if err != nil { return nil, err } @@ -27,14 +28,15 @@ func (r *ProtocolLXD) GetNetworkNames() ([]string, error) { // GetNetworks returns a list of Network struct. func (r *ProtocolLXD) GetNetworks() ([]api.Network, error) { - if !r.HasExtension("network") { - return nil, fmt.Errorf("The server is missing the required \"network\" API extension") + err := r.CheckExtension("network") + if err != nil { + return nil, err } networks := []api.Network{} // Fetch the raw value - _, err := r.queryStruct("GET", "/networks?recursion=1", nil, "", &networks) + _, err = r.queryStruct("GET", "/networks?recursion=1", nil, "", &networks) if err != nil { return nil, err } @@ -44,8 +46,9 @@ func (r *ProtocolLXD) GetNetworks() ([]api.Network, error) { // GetNetwork returns a Network entry for the provided name. func (r *ProtocolLXD) GetNetwork(name string) (*api.Network, string, error) { - if !r.HasExtension("network") { - return nil, "", fmt.Errorf("The server is missing the required \"network\" API extension") + err := r.CheckExtension("network") + if err != nil { + return nil, "", err } network := api.Network{} @@ -61,14 +64,15 @@ func (r *ProtocolLXD) GetNetwork(name string) (*api.Network, string, error) { // GetNetworkLeases returns a list of Network struct. func (r *ProtocolLXD) GetNetworkLeases(name string) ([]api.NetworkLease, error) { - if !r.HasExtension("network_leases") { - return nil, fmt.Errorf("The server is missing the required \"network_leases\" API extension") + err := r.CheckExtension("network_leases") + if err != nil { + return nil, err } leases := []api.NetworkLease{} // Fetch the raw value - _, err := r.queryStruct("GET", fmt.Sprintf("/networks/%s/leases", url.PathEscape(name)), nil, "", &leases) + _, err = r.queryStruct("GET", fmt.Sprintf("/networks/%s/leases", url.PathEscape(name)), nil, "", &leases) if err != nil { return nil, err } @@ -78,14 +82,15 @@ func (r *ProtocolLXD) GetNetworkLeases(name string) ([]api.NetworkLease, error) // GetNetworkState returns metrics and information on the running network. func (r *ProtocolLXD) GetNetworkState(name string) (*api.NetworkState, error) { - if !r.HasExtension("network_state") { - return nil, fmt.Errorf("The server is missing the required \"network_state\" API extension") + err := r.CheckExtension("network_state") + if err != nil { + return nil, err } state := api.NetworkState{} // Fetch the raw value - _, err := r.queryStruct("GET", fmt.Sprintf("/networks/%s/state", url.PathEscape(name)), nil, "", &state) + _, err = r.queryStruct("GET", fmt.Sprintf("/networks/%s/state", url.PathEscape(name)), nil, "", &state) if err != nil { return nil, err } @@ -95,12 +100,13 @@ func (r *ProtocolLXD) GetNetworkState(name string) (*api.NetworkState, error) { // CreateNetwork defines a new network using the provided Network struct. func (r *ProtocolLXD) CreateNetwork(network api.NetworksPost) error { - if !r.HasExtension("network") { - return fmt.Errorf("The server is missing the required \"network\" API extension") + err := r.CheckExtension("network") + if err != nil { + return err } // Send the request - _, _, err := r.query("POST", "/networks", network, "") + _, _, err = r.query("POST", "/networks", network, "") if err != nil { return err } @@ -110,12 +116,13 @@ func (r *ProtocolLXD) CreateNetwork(network api.NetworksPost) error { // UpdateNetwork updates the network to match the provided Network struct. func (r *ProtocolLXD) UpdateNetwork(name string, network api.NetworkPut, ETag string) error { - if !r.HasExtension("network") { - return fmt.Errorf("The server is missing the required \"network\" API extension") + err := r.CheckExtension("network") + if err != nil { + return err } // Send the request - _, _, err := r.query("PUT", fmt.Sprintf("/networks/%s", url.PathEscape(name)), network, ETag) + _, _, err = r.query("PUT", fmt.Sprintf("/networks/%s", url.PathEscape(name)), network, ETag) if err != nil { return err } @@ -125,12 +132,13 @@ func (r *ProtocolLXD) UpdateNetwork(name string, network api.NetworkPut, ETag st // RenameNetwork renames an existing network entry. func (r *ProtocolLXD) RenameNetwork(name string, network api.NetworkPost) error { - if !r.HasExtension("network") { - return fmt.Errorf("The server is missing the required \"network\" API extension") + err := r.CheckExtension("network") + if err != nil { + return err } // Send the request - _, _, err := r.query("POST", fmt.Sprintf("/networks/%s", url.PathEscape(name)), network, "") + _, _, err = r.query("POST", fmt.Sprintf("/networks/%s", url.PathEscape(name)), network, "") if err != nil { return err } @@ -140,12 +148,13 @@ func (r *ProtocolLXD) RenameNetwork(name string, network api.NetworkPost) error // DeleteNetwork deletes an existing network. func (r *ProtocolLXD) DeleteNetwork(name string) error { - if !r.HasExtension("network") { - return fmt.Errorf("The server is missing the required \"network\" API extension") + err := r.CheckExtension("network") + if err != nil { + return err } // Send the request - _, _, err := r.query("DELETE", fmt.Sprintf("/networks/%s", url.PathEscape(name)), nil, "") + _, _, err = r.query("DELETE", fmt.Sprintf("/networks/%s", url.PathEscape(name)), nil, "") if err != nil { return err } diff --git a/client/lxd_projects.go b/client/lxd_projects.go index 3dcf69f875a1..a05a1b6d7bf2 100644 --- a/client/lxd_projects.go +++ b/client/lxd_projects.go @@ -11,14 +11,15 @@ import ( // GetProjectNames returns a list of available project names. func (r *ProtocolLXD) GetProjectNames() ([]string, error) { - if !r.HasExtension("projects") { - return nil, fmt.Errorf("The server is missing the required \"projects\" API extension") + err := r.CheckExtension("projects") + if err != nil { + return nil, err } // Fetch the raw URL values. urls := []string{} baseURL := "/projects" - _, err := r.queryStruct("GET", baseURL, nil, "", &urls) + _, err = r.queryStruct("GET", baseURL, nil, "", &urls) if err != nil { return nil, err } @@ -29,14 +30,15 @@ func (r *ProtocolLXD) GetProjectNames() ([]string, error) { // GetProjects returns a list of available Project structs. func (r *ProtocolLXD) GetProjects() ([]api.Project, error) { - if !r.HasExtension("projects") { - return nil, fmt.Errorf("The server is missing the required \"projects\" API extension") + err := r.CheckExtension("projects") + if err != nil { + return nil, err } projects := []api.Project{} // Fetch the raw value - _, err := r.queryStruct("GET", "/projects?recursion=1", nil, "", &projects) + _, err = r.queryStruct("GET", "/projects?recursion=1", nil, "", &projects) if err != nil { return nil, err } @@ -46,8 +48,9 @@ func (r *ProtocolLXD) GetProjects() ([]api.Project, error) { // GetProject returns a Project entry for the provided name. func (r *ProtocolLXD) GetProject(name string) (*api.Project, string, error) { - if !r.HasExtension("projects") { - return nil, "", fmt.Errorf("The server is missing the required \"projects\" API extension") + err := r.CheckExtension("projects") + if err != nil { + return nil, "", err } project := api.Project{} @@ -63,14 +66,15 @@ func (r *ProtocolLXD) GetProject(name string) (*api.Project, string, error) { // GetProjectState returns a Project state for the provided name. func (r *ProtocolLXD) GetProjectState(name string) (*api.ProjectState, error) { - if !r.HasExtension("project_usage") { - return nil, fmt.Errorf("The server is missing the required \"project_usage\" API extension") + err := r.CheckExtension("project_usage") + if err != nil { + return nil, err } projectState := api.ProjectState{} // Fetch the raw value - _, err := r.queryStruct("GET", fmt.Sprintf("/projects/%s/state", url.PathEscape(name)), nil, "", &projectState) + _, err = r.queryStruct("GET", fmt.Sprintf("/projects/%s/state", url.PathEscape(name)), nil, "", &projectState) if err != nil { return nil, err } @@ -80,12 +84,13 @@ func (r *ProtocolLXD) GetProjectState(name string) (*api.ProjectState, error) { // CreateProject defines a new container project. func (r *ProtocolLXD) CreateProject(project api.ProjectsPost) error { - if !r.HasExtension("projects") { - return fmt.Errorf("The server is missing the required \"projects\" API extension") + err := r.CheckExtension("projects") + if err != nil { + return err } // Send the request - _, _, err := r.query("POST", "/projects", project, "") + _, _, err = r.query("POST", "/projects", project, "") if err != nil { return err } @@ -95,12 +100,13 @@ func (r *ProtocolLXD) CreateProject(project api.ProjectsPost) error { // UpdateProject updates the project to match the provided Project struct. func (r *ProtocolLXD) UpdateProject(name string, project api.ProjectPut, ETag string) error { - if !r.HasExtension("projects") { - return fmt.Errorf("The server is missing the required \"projects\" API extension") + err := r.CheckExtension("projects") + if err != nil { + return err } // Send the request - _, _, err := r.query("PUT", fmt.Sprintf("/projects/%s", url.PathEscape(name)), project, ETag) + _, _, err = r.query("PUT", fmt.Sprintf("/projects/%s", url.PathEscape(name)), project, ETag) if err != nil { return err } @@ -110,8 +116,9 @@ func (r *ProtocolLXD) UpdateProject(name string, project api.ProjectPut, ETag st // RenameProject renames an existing project entry. func (r *ProtocolLXD) RenameProject(name string, project api.ProjectPost) (Operation, error) { - if !r.HasExtension("projects") { - return nil, fmt.Errorf("The server is missing the required \"projects\" API extension") + err := r.CheckExtension("projects") + if err != nil { + return nil, err } // Send the request @@ -125,12 +132,13 @@ func (r *ProtocolLXD) RenameProject(name string, project api.ProjectPost) (Opera // DeleteProject deletes a project. func (r *ProtocolLXD) DeleteProject(name string) error { - if !r.HasExtension("projects") { - return fmt.Errorf("The server is missing the required \"projects\" API extension") + err := r.CheckExtension("projects") + if err != nil { + return err } // Send the request - _, _, err := r.query("DELETE", fmt.Sprintf("/projects/%s", url.PathEscape(name)), nil, "") + _, _, err = r.query("DELETE", fmt.Sprintf("/projects/%s", url.PathEscape(name)), nil, "") if err != nil { return err } diff --git a/client/lxd_server.go b/client/lxd_server.go index 7f9f71fb2725..141c72e21d8d 100644 --- a/client/lxd_server.go +++ b/client/lxd_server.go @@ -82,14 +82,15 @@ func (r *ProtocolLXD) IsClustered() bool { // GetServerResources returns the resources available to a given LXD server. func (r *ProtocolLXD) GetServerResources() (*api.Resources, error) { - if !r.HasExtension("resources") { - return nil, fmt.Errorf("The server is missing the required \"resources\" API extension") + err := r.CheckExtension("resources") + if err != nil { + return nil, err } resources := api.Resources{} // Fetch the raw value - _, err := r.queryStruct("GET", "/resources", nil, "", &resources) + _, err = r.queryStruct("GET", "/resources", nil, "", &resources) if err != nil { return nil, err } @@ -153,8 +154,9 @@ func (r *ProtocolLXD) IsAgent() bool { // GetMetrics returns the text OpenMetrics data. func (r *ProtocolLXD) GetMetrics() (string, error) { // Check that the server supports it. - if !r.HasExtension("metrics") { - return "", fmt.Errorf("The server is missing the required \"metrics\" API extension") + err := r.CheckExtension("metrics") + if err != nil { + return "", err } // Prepare the request. diff --git a/client/lxd_storage_buckets.go b/client/lxd_storage_buckets.go index 428452f58abf..db325c6dbcf4 100644 --- a/client/lxd_storage_buckets.go +++ b/client/lxd_storage_buckets.go @@ -73,7 +73,7 @@ func (r *ProtocolLXD) CreateStoragePoolBucket(poolName string, bucket api.Storag u := api.NewURL().Path("storage-pools", poolName, "buckets") // Send the request and get the resulting key info (including generated keys). - if r.HasExtension("storage_buckets_create_credentials") { + if r.CheckExtension("storage_buckets_create_credentials") == nil { var newKey api.StorageBucketKey _, err = r.queryStruct("POST", u.String(), bucket, "", &newKey) if err != nil { diff --git a/client/lxd_storage_pools.go b/client/lxd_storage_pools.go index 129c18d452df..66d13c9dd415 100644 --- a/client/lxd_storage_pools.go +++ b/client/lxd_storage_pools.go @@ -11,14 +11,15 @@ import ( // GetStoragePoolNames returns the names of all storage pools. func (r *ProtocolLXD) GetStoragePoolNames() ([]string, error) { - if !r.HasExtension("storage") { - return nil, fmt.Errorf("The server is missing the required \"storage\" API extension") + err := r.CheckExtension("storage") + if err != nil { + return nil, err } // Fetch the raw URL values. urls := []string{} baseURL := "/storage-pools" - _, err := r.queryStruct("GET", baseURL, nil, "", &urls) + _, err = r.queryStruct("GET", baseURL, nil, "", &urls) if err != nil { return nil, err } @@ -29,14 +30,15 @@ func (r *ProtocolLXD) GetStoragePoolNames() ([]string, error) { // GetStoragePools returns a list of StoragePool entries. func (r *ProtocolLXD) GetStoragePools() ([]api.StoragePool, error) { - if !r.HasExtension("storage") { - return nil, fmt.Errorf("The server is missing the required \"storage\" API extension") + err := r.CheckExtension("storage") + if err != nil { + return nil, err } pools := []api.StoragePool{} // Fetch the raw value - _, err := r.queryStruct("GET", "/storage-pools?recursion=1", nil, "", &pools) + _, err = r.queryStruct("GET", "/storage-pools?recursion=1", nil, "", &pools) if err != nil { return nil, err } @@ -46,8 +48,9 @@ func (r *ProtocolLXD) GetStoragePools() ([]api.StoragePool, error) { // GetStoragePool returns a StoragePool entry for the provided pool name. func (r *ProtocolLXD) GetStoragePool(name string) (*api.StoragePool, string, error) { - if !r.HasExtension("storage") { - return nil, "", fmt.Errorf("The server is missing the required \"storage\" API extension") + err := r.CheckExtension("storage") + if err != nil { + return nil, "", err } pool := api.StoragePool{} @@ -63,16 +66,20 @@ func (r *ProtocolLXD) GetStoragePool(name string) (*api.StoragePool, string, err // CreateStoragePool defines a new storage pool using the provided StoragePool struct. func (r *ProtocolLXD) CreateStoragePool(pool api.StoragePoolsPost) error { - if !r.HasExtension("storage") { - return fmt.Errorf("The server is missing the required \"storage\" API extension") + err := r.CheckExtension("storage") + if err != nil { + return err } - if pool.Driver == "ceph" && !r.HasExtension("storage_driver_ceph") { - return fmt.Errorf("The server is missing the required \"storage_driver_ceph\" API extension") + if pool.Driver == "ceph" { + err := r.CheckExtension("storage_driver_ceph") + if err != nil { + return err + } } // Send the request - _, _, err := r.query("POST", "/storage-pools", pool, "") + _, _, err = r.query("POST", "/storage-pools", pool, "") if err != nil { return err } @@ -82,12 +89,13 @@ func (r *ProtocolLXD) CreateStoragePool(pool api.StoragePoolsPost) error { // UpdateStoragePool updates the pool to match the provided StoragePool struct. func (r *ProtocolLXD) UpdateStoragePool(name string, pool api.StoragePoolPut, ETag string) error { - if !r.HasExtension("storage") { - return fmt.Errorf("The server is missing the required \"storage\" API extension") + err := r.CheckExtension("storage") + if err != nil { + return err } // Send the request - _, _, err := r.query("PUT", fmt.Sprintf("/storage-pools/%s", url.PathEscape(name)), pool, ETag) + _, _, err = r.query("PUT", fmt.Sprintf("/storage-pools/%s", url.PathEscape(name)), pool, ETag) if err != nil { return err } @@ -97,12 +105,13 @@ func (r *ProtocolLXD) UpdateStoragePool(name string, pool api.StoragePoolPut, ET // DeleteStoragePool deletes a storage pool. func (r *ProtocolLXD) DeleteStoragePool(name string) error { - if !r.HasExtension("storage") { - return fmt.Errorf("The server is missing the required \"storage\" API extension") + err := r.CheckExtension("storage") + if err != nil { + return err } // Send the request - _, _, err := r.query("DELETE", fmt.Sprintf("/storage-pools/%s", url.PathEscape(name)), nil, "") + _, _, err = r.query("DELETE", fmt.Sprintf("/storage-pools/%s", url.PathEscape(name)), nil, "") if err != nil { return err } @@ -112,14 +121,15 @@ func (r *ProtocolLXD) DeleteStoragePool(name string) error { // GetStoragePoolResources gets the resources available to a given storage pool. func (r *ProtocolLXD) GetStoragePoolResources(name string) (*api.ResourcesStoragePool, error) { - if !r.HasExtension("resources") { - return nil, fmt.Errorf("The server is missing the required \"resources\" API extension") + err := r.CheckExtension("resources") + if err != nil { + return nil, err } res := api.ResourcesStoragePool{} // Fetch the raw value - _, err := r.queryStruct("GET", fmt.Sprintf("/storage-pools/%s/resources", url.PathEscape(name)), nil, "", &res) + _, err = r.queryStruct("GET", fmt.Sprintf("/storage-pools/%s/resources", url.PathEscape(name)), nil, "", &res) if err != nil { return nil, err } diff --git a/client/lxd_storage_volumes.go b/client/lxd_storage_volumes.go index 5367358ba388..b7c93bb582a5 100644 --- a/client/lxd_storage_volumes.go +++ b/client/lxd_storage_volumes.go @@ -18,14 +18,15 @@ import ( // GetStoragePoolVolumeNames returns the names of all volumes in a pool. func (r *ProtocolLXD) GetStoragePoolVolumeNames(pool string) ([]string, error) { - if !r.HasExtension("storage") { - return nil, fmt.Errorf("The server is missing the required \"storage\" API extension") + err := r.CheckExtension("storage") + if err != nil { + return nil, err } // Fetch the raw URL values. urls := []string{} baseURL := fmt.Sprintf("/storage-pools/%s/volumes", url.PathEscape(pool)) - _, err := r.queryStruct("GET", baseURL, nil, "", &urls) + _, err = r.queryStruct("GET", baseURL, nil, "", &urls) if err != nil { return nil, err } @@ -79,14 +80,15 @@ func (r *ProtocolLXD) GetStoragePoolVolumeNamesAllProjects(pool string) (map[str // GetStoragePoolVolumes returns a list of StorageVolume entries for the provided pool. func (r *ProtocolLXD) GetStoragePoolVolumes(pool string) ([]api.StorageVolume, error) { - if !r.HasExtension("storage") { - return nil, fmt.Errorf("The server is missing the required \"storage\" API extension") + err := r.CheckExtension("storage") + if err != nil { + return nil, err } volumes := []api.StorageVolume{} // Fetch the raw value - _, err := r.queryStruct("GET", fmt.Sprintf("/storage-pools/%s/volumes?recursion=1", url.PathEscape(pool)), nil, "", &volumes) + _, err = r.queryStruct("GET", fmt.Sprintf("/storage-pools/%s/volumes?recursion=1", url.PathEscape(pool)), nil, "", &volumes) if err != nil { return nil, err } @@ -123,8 +125,9 @@ func (r *ProtocolLXD) GetStoragePoolVolumesAllProjects(pool string) ([]api.Stora // GetStoragePoolVolumesWithFilter returns a filtered list of StorageVolume entries for the provided pool. func (r *ProtocolLXD) GetStoragePoolVolumesWithFilter(pool string, filters []string) ([]api.StorageVolume, error) { - if !r.HasExtension("storage") { - return nil, fmt.Errorf("The server is missing the required \"storage\" API extension") + err := r.CheckExtension("storage") + if err != nil { + return nil, err } volumes := []api.StorageVolume{} @@ -133,7 +136,7 @@ func (r *ProtocolLXD) GetStoragePoolVolumesWithFilter(pool string, filters []str v.Set("recursion", "1") v.Set("filter", parseFilters(filters)) // Fetch the raw value - _, err := r.queryStruct("GET", fmt.Sprintf("/storage-pools/%s/volumes?%s", url.PathEscape(pool), v.Encode()), nil, "", &volumes) + _, err = r.queryStruct("GET", fmt.Sprintf("/storage-pools/%s/volumes?%s", url.PathEscape(pool), v.Encode()), nil, "", &volumes) if err != nil { return nil, err } @@ -171,8 +174,9 @@ func (r *ProtocolLXD) GetStoragePoolVolumesWithFilterAllProjects(pool string, fi // GetStoragePoolVolume returns a StorageVolume entry for the provided pool and volume name. func (r *ProtocolLXD) GetStoragePoolVolume(pool string, volType string, name string) (*api.StorageVolume, string, error) { - if !r.HasExtension("storage") { - return nil, "", fmt.Errorf("The server is missing the required \"storage\" API extension") + err := r.CheckExtension("storage") + if err != nil { + return nil, "", err } volume := api.StorageVolume{} @@ -189,14 +193,15 @@ func (r *ProtocolLXD) GetStoragePoolVolume(pool string, volType string, name str // GetStoragePoolVolumeState returns a StorageVolumeState entry for the provided pool and volume name. func (r *ProtocolLXD) GetStoragePoolVolumeState(pool string, volType string, name string) (*api.StorageVolumeState, error) { - if !r.HasExtension("storage_volume_state") { - return nil, fmt.Errorf("The server is missing the required \"storage_volume_state\" API extension") + err := r.CheckExtension("storage_volume_state") + if err != nil { + return nil, err } // Fetch the raw value state := api.StorageVolumeState{} path := fmt.Sprintf("/storage-pools/%s/volumes/%s/%s/state", url.PathEscape(pool), url.PathEscape(volType), url.PathEscape(name)) - _, err := r.queryStruct("GET", path, nil, "", &state) + _, err = r.queryStruct("GET", path, nil, "", &state) if err != nil { return nil, err } @@ -206,13 +211,14 @@ func (r *ProtocolLXD) GetStoragePoolVolumeState(pool string, volType string, nam // CreateStoragePoolVolume defines a new storage volume. func (r *ProtocolLXD) CreateStoragePoolVolume(pool string, volume api.StorageVolumesPost) error { - if !r.HasExtension("storage") { - return fmt.Errorf("The server is missing the required \"storage\" API extension") + err := r.CheckExtension("storage") + if err != nil { + return err } // Send the request path := fmt.Sprintf("/storage-pools/%s/volumes/%s", url.PathEscape(pool), url.PathEscape(volume.Type)) - _, _, err := r.query("POST", path, volume, "") + _, _, err = r.query("POST", path, volume, "") if err != nil { return err } @@ -222,8 +228,9 @@ func (r *ProtocolLXD) CreateStoragePoolVolume(pool string, volume api.StorageVol // CreateStoragePoolVolumeSnapshot defines a new storage volume. func (r *ProtocolLXD) CreateStoragePoolVolumeSnapshot(pool string, volumeType string, volumeName string, snapshot api.StorageVolumeSnapshotsPost) (Operation, error) { - if !r.HasExtension("storage_api_volume_snapshots") { - return nil, fmt.Errorf("The server is missing the required \"storage_api_volume_snapshots\" API extension") + err := r.CheckExtension("storage_api_volume_snapshots") + if err != nil { + return nil, err } // Send the request @@ -242,14 +249,15 @@ func (r *ProtocolLXD) CreateStoragePoolVolumeSnapshot(pool string, volumeType st // GetStoragePoolVolumeSnapshotNames returns a list of snapshot names for the // storage volume. func (r *ProtocolLXD) GetStoragePoolVolumeSnapshotNames(pool string, volumeType string, volumeName string) ([]string, error) { - if !r.HasExtension("storage_api_volume_snapshots") { - return nil, fmt.Errorf("The server is missing the required \"storage_api_volume_snapshots\" API extension") + err := r.CheckExtension("storage_api_volume_snapshots") + if err != nil { + return nil, err } // Fetch the raw URL values. urls := []string{} baseURL := fmt.Sprintf("/storage-pools/%s/volumes/%s/%s/snapshots", url.PathEscape(pool), url.PathEscape(volumeType), url.PathEscape(volumeName)) - _, err := r.queryStruct("GET", baseURL, nil, "", &urls) + _, err = r.queryStruct("GET", baseURL, nil, "", &urls) if err != nil { return nil, err } @@ -261,8 +269,9 @@ func (r *ProtocolLXD) GetStoragePoolVolumeSnapshotNames(pool string, volumeType // GetStoragePoolVolumeSnapshots returns a list of snapshots for the storage // volume. func (r *ProtocolLXD) GetStoragePoolVolumeSnapshots(pool string, volumeType string, volumeName string) ([]api.StorageVolumeSnapshot, error) { - if !r.HasExtension("storage_api_volume_snapshots") { - return nil, fmt.Errorf("The server is missing the required \"storage_api_volume_snapshots\" API extension") + err := r.CheckExtension("storage_api_volume_snapshots") + if err != nil { + return nil, err } snapshots := []api.StorageVolumeSnapshot{} @@ -271,7 +280,7 @@ func (r *ProtocolLXD) GetStoragePoolVolumeSnapshots(pool string, volumeType stri url.PathEscape(pool), url.PathEscape(volumeType), url.PathEscape(volumeName)) - _, err := r.queryStruct("GET", path, nil, "", &snapshots) + _, err = r.queryStruct("GET", path, nil, "", &snapshots) if err != nil { return nil, err } @@ -281,8 +290,9 @@ func (r *ProtocolLXD) GetStoragePoolVolumeSnapshots(pool string, volumeType stri // GetStoragePoolVolumeSnapshot returns a snapshots for the storage volume. func (r *ProtocolLXD) GetStoragePoolVolumeSnapshot(pool string, volumeType string, volumeName string, snapshotName string) (*api.StorageVolumeSnapshot, string, error) { - if !r.HasExtension("storage_api_volume_snapshots") { - return nil, "", fmt.Errorf("The server is missing the required \"storage_api_volume_snapshots\" API extension") + err := r.CheckExtension("storage_api_volume_snapshots") + if err != nil { + return nil, "", err } snapshot := api.StorageVolumeSnapshot{} @@ -302,8 +312,9 @@ func (r *ProtocolLXD) GetStoragePoolVolumeSnapshot(pool string, volumeType strin // RenameStoragePoolVolumeSnapshot renames a storage volume snapshot. func (r *ProtocolLXD) RenameStoragePoolVolumeSnapshot(pool string, volumeType string, volumeName string, snapshotName string, snapshot api.StorageVolumeSnapshotPost) (Operation, error) { - if !r.HasExtension("storage_api_volume_snapshots") { - return nil, fmt.Errorf("The server is missing the required \"storage_api_volume_snapshots\" API extension") + err := r.CheckExtension("storage_api_volume_snapshots") + if err != nil { + return nil, err } path := fmt.Sprintf("/storage-pools/%s/volumes/%s/%s/snapshots/%s", url.PathEscape(pool), url.PathEscape(volumeType), url.PathEscape(volumeName), url.PathEscape(snapshotName)) @@ -318,8 +329,9 @@ func (r *ProtocolLXD) RenameStoragePoolVolumeSnapshot(pool string, volumeType st // DeleteStoragePoolVolumeSnapshot deletes a storage volume snapshot. func (r *ProtocolLXD) DeleteStoragePoolVolumeSnapshot(pool string, volumeType string, volumeName string, snapshotName string) (Operation, error) { - if !r.HasExtension("storage_api_volume_snapshots") { - return nil, fmt.Errorf("The server is missing the required \"storage_api_volume_snapshots\" API extension") + err := r.CheckExtension("storage_api_volume_snapshots") + if err != nil { + return nil, err } // Send the request @@ -337,13 +349,14 @@ func (r *ProtocolLXD) DeleteStoragePoolVolumeSnapshot(pool string, volumeType st // UpdateStoragePoolVolumeSnapshot updates the volume to match the provided StoragePoolVolume struct. func (r *ProtocolLXD) UpdateStoragePoolVolumeSnapshot(pool string, volumeType string, volumeName string, snapshotName string, volume api.StorageVolumeSnapshotPut, ETag string) error { - if !r.HasExtension("storage_api_volume_snapshots") { - return fmt.Errorf("The server is missing the required \"storage_api_volume_snapshots\" API extension") + err := r.CheckExtension("storage_api_volume_snapshots") + if err != nil { + return err } // Send the request path := fmt.Sprintf("/storage-pools/%s/volumes/%s/%s/snapshots/%s", url.PathEscape(pool), url.PathEscape(volumeType), url.PathEscape(volumeName), url.PathEscape(snapshotName)) - _, _, err := r.queryOperation("PUT", path, volume, ETag, true) + _, _, err = r.queryOperation("PUT", path, volume, ETag, true) if err != nil { return err } @@ -353,8 +366,9 @@ func (r *ProtocolLXD) UpdateStoragePoolVolumeSnapshot(pool string, volumeType st // MigrateStoragePoolVolume requests that LXD prepares for a storage volume migration. func (r *ProtocolLXD) MigrateStoragePoolVolume(pool string, volume api.StorageVolumePost) (Operation, error) { - if !r.HasExtension("storage_api_remote_volume_handling") { - return nil, fmt.Errorf("The server is missing the required \"storage_api_remote_volume_handling\" API extension") + err := r.CheckExtension("storage_api_remote_volume_handling") + if err != nil { + return nil, err } // Quick check. @@ -517,15 +531,16 @@ func (r *ProtocolLXD) tryCreateStoragePoolVolume(pool string, req api.StorageVol // CopyStoragePoolVolume copies an existing storage volume. func (r *ProtocolLXD) CopyStoragePoolVolume(pool string, source InstanceServer, sourcePool string, volume api.StorageVolume, args *StoragePoolVolumeCopyArgs) (RemoteOperation, error) { - if !r.HasExtension("storage_api_local_volume_handling") { - return nil, fmt.Errorf("The server is missing the required \"storage_api_local_volume_handling\" API extension") + err := r.CheckExtension("storage_api_local_volume_handling") + if err != nil { + return nil, err } - if args != nil && args.VolumeOnly && !r.HasExtension("storage_api_volume_snapshots") { + if args != nil && args.VolumeOnly && r.CheckExtension("storage_api_volume_snapshots") != nil { return nil, fmt.Errorf("The target server is missing the required \"storage_api_volume_snapshots\" API extension") } - if args != nil && args.Refresh && !r.HasExtension("custom_volume_refresh") { + if args != nil && args.Refresh && r.CheckExtension("custom_volume_refresh") != nil { return nil, fmt.Errorf("The target server is missing the required \"custom_volume_refresh\" API extension") } @@ -561,8 +576,9 @@ func (r *ProtocolLXD) CopyStoragePoolVolume(pool string, source InstanceServer, if destInfo.URL == sourceInfo.URL && destInfo.SocketPath == sourceInfo.SocketPath && (volume.Location == r.clusterTarget || (volume.Location == "none" && r.clusterTarget == "") || clusterInternalVolumeCopy) { // Project handling if destInfo.Project != sourceInfo.Project { - if !r.HasExtension("storage_api_project") { - return nil, fmt.Errorf("The server is missing the required \"storage_api_project\" API extension") + err := r.CheckExtension("storage_api_project") + if err != nil { + return nil, err } req.Source.Project = sourceInfo.Project @@ -592,8 +608,9 @@ func (r *ProtocolLXD) CopyStoragePoolVolume(pool string, source InstanceServer, return &rop, nil } - if !r.HasExtension("storage_api_remote_volume_handling") { - return nil, fmt.Errorf("The server is missing the required \"storage_api_remote_volume_handling\" API extension") + err = r.CheckExtension("storage_api_remote_volume_handling") + if err != nil { + return nil, err } sourceReq := api.StorageVolumePost{ @@ -720,8 +737,9 @@ func (r *ProtocolLXD) CopyStoragePoolVolume(pool string, source InstanceServer, // MoveStoragePoolVolume renames or moves an existing storage volume. func (r *ProtocolLXD) MoveStoragePoolVolume(pool string, source InstanceServer, sourcePool string, volume api.StorageVolume, args *StoragePoolVolumeMoveArgs) (RemoteOperation, error) { - if !r.HasExtension("storage_api_local_volume_handling") { - return nil, fmt.Errorf("The server is missing the required \"storage_api_local_volume_handling\" API extension") + err := r.CheckExtension("storage_api_local_volume_handling") + if err != nil { + return nil, err } if r != source { @@ -734,8 +752,9 @@ func (r *ProtocolLXD) MoveStoragePoolVolume(pool string, source InstanceServer, } if args.Project != "" { - if !r.HasExtension("storage_volume_project_move") { - return nil, fmt.Errorf("The server is missing the required \"storage_volume_project_move\" API extension") + err := r.CheckExtension("storage_volume_project_move") + if err != nil { + return nil, err } req.Project = args.Project @@ -763,17 +782,21 @@ func (r *ProtocolLXD) MoveStoragePoolVolume(pool string, source InstanceServer, // UpdateStoragePoolVolume updates the volume to match the provided StoragePoolVolume struct. func (r *ProtocolLXD) UpdateStoragePoolVolume(pool string, volType string, name string, volume api.StorageVolumePut, ETag string) error { - if !r.HasExtension("storage") { - return fmt.Errorf("The server is missing the required \"storage\" API extension") + err := r.CheckExtension("storage") + if err != nil { + return err } - if volume.Restore != "" && !r.HasExtension("storage_api_volume_snapshots") { - return fmt.Errorf("The server is missing the required \"storage_api_volume_snapshots\" API extension") + if volume.Restore != "" { + err := r.CheckExtension("storage_api_volume_snapshots") + if err != nil { + return err + } } // Send the request path := fmt.Sprintf("/storage-pools/%s/volumes/%s/%s", url.PathEscape(pool), url.PathEscape(volType), url.PathEscape(name)) - _, _, err := r.query("PUT", path, volume, ETag) + _, _, err = r.query("PUT", path, volume, ETag) if err != nil { return err } @@ -783,13 +806,14 @@ func (r *ProtocolLXD) UpdateStoragePoolVolume(pool string, volType string, name // DeleteStoragePoolVolume deletes a storage pool. func (r *ProtocolLXD) DeleteStoragePoolVolume(pool string, volType string, name string) error { - if !r.HasExtension("storage") { - return fmt.Errorf("The server is missing the required \"storage\" API extension") + err := r.CheckExtension("storage") + if err != nil { + return err } // Send the request path := fmt.Sprintf("/storage-pools/%s/volumes/%s/%s", url.PathEscape(pool), url.PathEscape(volType), url.PathEscape(name)) - _, _, err := r.query("DELETE", path, nil, "") + _, _, err = r.query("DELETE", path, nil, "") if err != nil { return err } @@ -799,14 +823,15 @@ func (r *ProtocolLXD) DeleteStoragePoolVolume(pool string, volType string, name // RenameStoragePoolVolume renames a storage volume. func (r *ProtocolLXD) RenameStoragePoolVolume(pool string, volType string, name string, volume api.StorageVolumePost) error { - if !r.HasExtension("storage_api_volume_rename") { - return fmt.Errorf("The server is missing the required \"storage_api_volume_rename\" API extension") + err := r.CheckExtension("storage_api_volume_rename") + if err != nil { + return err } path := fmt.Sprintf("/storage-pools/%s/volumes/%s/%s", url.PathEscape(pool), url.PathEscape(volType), url.PathEscape(name)) // Send the request - _, _, err := r.query("POST", path, volume, "") + _, _, err = r.query("POST", path, volume, "") if err != nil { return err } @@ -816,14 +841,15 @@ func (r *ProtocolLXD) RenameStoragePoolVolume(pool string, volType string, name // GetStoragePoolVolumeBackupNames returns a list of volume backup names. func (r *ProtocolLXD) GetStoragePoolVolumeBackupNames(pool string, volName string) ([]string, error) { - if !r.HasExtension("custom_volume_backup") { - return nil, fmt.Errorf("The server is missing the required \"custom_volume_backup\" API extension") + err := r.CheckExtension("custom_volume_backup") + if err != nil { + return nil, err } // Fetch the raw URL values. urls := []string{} baseURL := fmt.Sprintf("/storage-pools/%s/volumes/custom/%s/backups", url.PathEscape(pool), url.PathEscape(volName)) - _, err := r.queryStruct("GET", baseURL, nil, "", &urls) + _, err = r.queryStruct("GET", baseURL, nil, "", &urls) if err != nil { return nil, err } @@ -834,14 +860,15 @@ func (r *ProtocolLXD) GetStoragePoolVolumeBackupNames(pool string, volName strin // GetStoragePoolVolumeBackups returns a list of custom volume backups. func (r *ProtocolLXD) GetStoragePoolVolumeBackups(pool string, volName string) ([]api.StoragePoolVolumeBackup, error) { - if !r.HasExtension("custom_volume_backup") { - return nil, fmt.Errorf("The server is missing the required \"custom_volume_backup\" API extension") + err := r.CheckExtension("custom_volume_backup") + if err != nil { + return nil, err } // Fetch the raw value backups := []api.StoragePoolVolumeBackup{} - _, err := r.queryStruct("GET", fmt.Sprintf("/storage-pools/%s/volumes/custom/%s/backups?recursion=1", url.PathEscape(pool), url.PathEscape(volName)), nil, "", &backups) + _, err = r.queryStruct("GET", fmt.Sprintf("/storage-pools/%s/volumes/custom/%s/backups?recursion=1", url.PathEscape(pool), url.PathEscape(volName)), nil, "", &backups) if err != nil { return nil, err } @@ -851,8 +878,9 @@ func (r *ProtocolLXD) GetStoragePoolVolumeBackups(pool string, volName string) ( // GetStoragePoolVolumeBackup returns a custom volume backup. func (r *ProtocolLXD) GetStoragePoolVolumeBackup(pool string, volName string, name string) (*api.StoragePoolVolumeBackup, string, error) { - if !r.HasExtension("custom_volume_backup") { - return nil, "", fmt.Errorf("The server is missing the required \"custom_volume_backup\" API extension") + err := r.CheckExtension("custom_volume_backup") + if err != nil { + return nil, "", err } // Fetch the raw value @@ -867,8 +895,9 @@ func (r *ProtocolLXD) GetStoragePoolVolumeBackup(pool string, volName string, na // CreateStoragePoolVolumeBackup creates new custom volume backup. func (r *ProtocolLXD) CreateStoragePoolVolumeBackup(pool string, volName string, backup api.StoragePoolVolumeBackupsPost) (Operation, error) { - if !r.HasExtension("custom_volume_backup") { - return nil, fmt.Errorf("The server is missing the required \"custom_volume_backup\" API extension") + err := r.CheckExtension("custom_volume_backup") + if err != nil { + return nil, err } // Send the request @@ -882,8 +911,9 @@ func (r *ProtocolLXD) CreateStoragePoolVolumeBackup(pool string, volName string, // RenameStoragePoolVolumeBackup renames a custom volume backup. func (r *ProtocolLXD) RenameStoragePoolVolumeBackup(pool string, volName string, name string, backup api.StoragePoolVolumeBackupPost) (Operation, error) { - if !r.HasExtension("custom_volume_backup") { - return nil, fmt.Errorf("The server is missing the required \"custom_volume_backup\" API extension") + err := r.CheckExtension("custom_volume_backup") + if err != nil { + return nil, err } // Send the request @@ -897,8 +927,9 @@ func (r *ProtocolLXD) RenameStoragePoolVolumeBackup(pool string, volName string, // DeleteStoragePoolVolumeBackup deletes a custom volume backup. func (r *ProtocolLXD) DeleteStoragePoolVolumeBackup(pool string, volName string, name string) (Operation, error) { - if !r.HasExtension("custom_volume_backup") { - return nil, fmt.Errorf("The server is missing the required \"custom_volume_backup\" API extension") + err := r.CheckExtension("custom_volume_backup") + if err != nil { + return nil, err } // Send the request @@ -912,8 +943,9 @@ func (r *ProtocolLXD) DeleteStoragePoolVolumeBackup(pool string, volName string, // GetStoragePoolVolumeBackupFile requests the custom volume backup content. func (r *ProtocolLXD) GetStoragePoolVolumeBackupFile(pool string, volName string, name string, req *BackupFileRequest) (*BackupFileResponse, error) { - if !r.HasExtension("custom_volume_backup") { - return nil, fmt.Errorf("The server is missing the required \"custom_volume_backup\" API extension") + err := r.CheckExtension("custom_volume_backup") + if err != nil { + return nil, err } // Build the URL @@ -1034,12 +1066,16 @@ func (r *ProtocolLXD) CreateStoragePoolVolumeFromISO(pool string, args StoragePo // CreateStoragePoolVolumeFromBackup creates a custom volume from a backup file. func (r *ProtocolLXD) CreateStoragePoolVolumeFromBackup(pool string, args StoragePoolVolumeBackupArgs) (Operation, error) { - if !r.HasExtension("custom_volume_backup") { - return nil, fmt.Errorf(`The server is missing the required "custom_volume_backup" API extension`) + err := r.CheckExtension("custom_volume_backup") + if err != nil { + return nil, err } - if args.Name != "" && !r.HasExtension("backup_override_name") { - return nil, fmt.Errorf(`The server is missing the required "backup_override_name" API extension`) + if args.Name != "" { + err := r.CheckExtension("backup_override_name") + if err != nil { + return nil, err + } } path := fmt.Sprintf("/storage-pools/%s/volumes/custom", url.PathEscape(pool)) diff --git a/client/lxd_warnings.go b/client/lxd_warnings.go index 677d522de05e..cdd644038e81 100644 --- a/client/lxd_warnings.go +++ b/client/lxd_warnings.go @@ -11,14 +11,15 @@ import ( // GetWarningUUIDs returns a list of operation uuids. func (r *ProtocolLXD) GetWarningUUIDs() ([]string, error) { - if !r.HasExtension("warnings") { - return nil, fmt.Errorf("The server is missing the required \"warnings\" API extension") + err := r.CheckExtension("warnings") + if err != nil { + return nil, err } // Fetch the raw values. urls := []string{} baseURL := "/warnings" - _, err := r.queryStruct("GET", baseURL, nil, "", &urls) + _, err = r.queryStruct("GET", baseURL, nil, "", &urls) if err != nil { return nil, err } @@ -29,13 +30,14 @@ func (r *ProtocolLXD) GetWarningUUIDs() ([]string, error) { // GetWarnings returns a list of warnings. func (r *ProtocolLXD) GetWarnings() ([]api.Warning, error) { - if !r.HasExtension("warnings") { - return nil, fmt.Errorf("The server is missing the required \"warnings\" API extension") + err := r.CheckExtension("warnings") + if err != nil { + return nil, err } warnings := []api.Warning{} - _, err := r.queryStruct("GET", "/warnings?recursion=1", nil, "", &warnings) + _, err = r.queryStruct("GET", "/warnings?recursion=1", nil, "", &warnings) if err != nil { return nil, err } @@ -45,8 +47,9 @@ func (r *ProtocolLXD) GetWarnings() ([]api.Warning, error) { // GetWarning returns the warning with the given UUID. func (r *ProtocolLXD) GetWarning(UUID string) (*api.Warning, string, error) { - if !r.HasExtension("warnings") { - return nil, "", fmt.Errorf("The server is missing the required \"warnings\" API extension") + err := r.CheckExtension("warnings") + if err != nil { + return nil, "", err } warning := api.Warning{} @@ -61,12 +64,13 @@ func (r *ProtocolLXD) GetWarning(UUID string) (*api.Warning, string, error) { // UpdateWarning updates the warning with the given UUID. func (r *ProtocolLXD) UpdateWarning(UUID string, warning api.WarningPut, ETag string) error { - if !r.HasExtension("warnings") { - return fmt.Errorf("The server is missing the required \"warnings\" API extension") + err := r.CheckExtension("warnings") + if err != nil { + return err } // Send the request - _, _, err := r.query("PUT", fmt.Sprintf("/warnings/%s", url.PathEscape(UUID)), warning, "") + _, _, err = r.query("PUT", fmt.Sprintf("/warnings/%s", url.PathEscape(UUID)), warning, "") if err != nil { return err } @@ -76,12 +80,13 @@ func (r *ProtocolLXD) UpdateWarning(UUID string, warning api.WarningPut, ETag st // DeleteWarning deletes the provided warning. func (r *ProtocolLXD) DeleteWarning(UUID string) error { - if !r.HasExtension("warnings") { - return fmt.Errorf("The server is missing the required \"warnings\" API extension") + err := r.CheckExtension("warnings") + if err != nil { + return err } // Send the request - _, _, err := r.query("DELETE", fmt.Sprintf("/warnings/%s", url.PathEscape(UUID)), nil, "") + _, _, err = r.query("DELETE", fmt.Sprintf("/warnings/%s", url.PathEscape(UUID)), nil, "") if err != nil { return err }