Update to version 1.1.0

This commit is contained in:
chihyuwu
2022-04-25 11:10:19 +00:00
parent f0066b40ca
commit ebe7c1d97c
32 changed files with 2197 additions and 445 deletions

View File

@@ -108,6 +108,8 @@ func errCodeMapping(errCode int, oriErr error) error {
switch errCode {
case 18990002: // Out of free space
return utils.OutOfFreeSpaceError("")
case 18990531: // No such LUN
return utils.NoSuchLunError("")
case 18990538: // Duplicated LUN name
return utils.AlreadyExistError("")
case 18990541:
@@ -125,7 +127,7 @@ func errCodeMapping(errCode int, oriErr error) error {
}
if errCode > 18990000 {
return utils.IscsiDefaultError("")
return utils.IscsiDefaultError{errCode}
}
return oriErr
}
@@ -144,7 +146,7 @@ func (dsm *DSM) LunList() ([]LunInfo, error) {
resp, err := dsm.sendRequest("", &LunInfos{}, params, "webapi/entry.cgi")
if err != nil {
return nil, err
return nil, errCodeMapping(resp.ErrorCode, err)
}
lunInfos, ok := resp.Data.(*LunInfos)
@@ -175,9 +177,8 @@ func (dsm *DSM) LunCreate(spec LunCreateSpec) (string, error) {
}
resp, err := dsm.sendRequest("", &LunCreateResp{}, params, "webapi/entry.cgi")
err = errCodeMapping(resp.ErrorCode, err)
if err != nil {
return "", err
return "", errCodeMapping(resp.ErrorCode, err)
}
lunResp, ok := resp.Data.(*LunCreateResp)
@@ -196,9 +197,9 @@ func (dsm *DSM) LunUpdate(spec LunUpdateSpec) error {
params.Add("uuid", strconv.Quote(spec.Uuid))
params.Add("new_size", strconv.FormatInt(int64(spec.NewSize), 10))
_, err := dsm.sendRequest("", &struct{}{}, params, "webapi/entry.cgi")
resp, err := dsm.sendRequest("", &struct{}{}, params, "webapi/entry.cgi")
if err != nil {
return err
return errCodeMapping(resp.ErrorCode, err)
}
return nil
@@ -217,9 +218,9 @@ func (dsm *DSM) LunGet(uuid string) (LunInfo, error) {
}
info := Info{}
_, err := dsm.sendRequest("", &info, params, "webapi/entry.cgi")
resp, err := dsm.sendRequest("", &info, params, "webapi/entry.cgi")
if err != nil {
return LunInfo{}, err
return LunInfo{}, errCodeMapping(resp.ErrorCode, err)
}
return info.Lun, nil
@@ -239,9 +240,8 @@ func (dsm *DSM) LunClone(spec LunCloneSpec) (string, error) {
}
resp, err := dsm.sendRequest("", &LunCloneResp{}, params, "webapi/entry.cgi")
err = errCodeMapping(resp.ErrorCode, err)
if err != nil {
return "", err
return "", errCodeMapping(resp.ErrorCode, err)
}
cloneLunResp, ok := resp.Data.(*LunCloneResp)
@@ -265,7 +265,7 @@ func (dsm *DSM) TargetList() ([]TargetInfo, error) {
resp, err := dsm.sendRequest("", &TargetInfos{}, params, "webapi/entry.cgi")
if err != nil {
return nil, err
return nil, errCodeMapping(resp.ErrorCode, err)
}
trgInfos, ok := resp.Data.(*TargetInfos)
@@ -288,9 +288,9 @@ func (dsm *DSM) TargetGet(targetId string) (TargetInfo, error) {
}
info := Info{}
_, err := dsm.sendRequest("", &info, params, "webapi/entry.cgi")
resp, err := dsm.sendRequest("", &info, params, "webapi/entry.cgi")
if err != nil {
return TargetInfo{}, err
return TargetInfo{}, errCodeMapping(resp.ErrorCode, err)
}
return info.Target, nil
@@ -305,9 +305,9 @@ func (dsm *DSM) TargetSet(targetId string, maxSession int) error {
params.Add("target_id", strconv.Quote(targetId))
params.Add("max_sessions", strconv.Itoa(maxSession))
_, err := dsm.sendRequest("", &struct{}{}, params, "webapi/entry.cgi")
resp, err := dsm.sendRequest("", &struct{}{}, params, "webapi/entry.cgi")
if err != nil {
return err
return errCodeMapping(resp.ErrorCode, err)
}
return nil
@@ -327,9 +327,8 @@ func (dsm *DSM) TargetCreate(spec TargetCreateSpec) (string, error) {
}
resp, err := dsm.sendRequest("", &TrgCreateResp{}, params, "webapi/entry.cgi")
err = errCodeMapping(resp.ErrorCode, err)
if err != nil {
return "", err
return "", errCodeMapping(resp.ErrorCode, err)
}
trgResp, ok := resp.Data.(*TrgCreateResp)
@@ -352,9 +351,9 @@ func (dsm *DSM) LunMapTarget(targetIds []string, lunUuid string) error {
log.Debugln(params)
}
_, err := dsm.sendRequest("", &struct{}{}, params, "webapi/entry.cgi")
resp, err := dsm.sendRequest("", &struct{}{}, params, "webapi/entry.cgi")
if err != nil {
return err
return errCodeMapping(resp.ErrorCode, err)
}
return nil
}
@@ -366,9 +365,9 @@ func (dsm *DSM) LunDelete(lunUuid string) error {
params.Add("version", "1")
params.Add("uuid", strconv.Quote(lunUuid))
_, err := dsm.sendRequest("", &struct{}{}, params, "webapi/entry.cgi")
resp, err := dsm.sendRequest("", &struct{}{}, params, "webapi/entry.cgi")
if err != nil {
return err
return errCodeMapping(resp.ErrorCode, err)
}
return nil
}
@@ -380,9 +379,9 @@ func (dsm *DSM) TargetDelete(targetName string) error {
params.Add("version", "1")
params.Add("target_id", strconv.Quote(targetName))
_, err := dsm.sendRequest("", &struct{}{}, params, "webapi/entry.cgi")
resp, err := dsm.sendRequest("", &struct{}{}, params, "webapi/entry.cgi")
if err != nil {
return err
return errCodeMapping(resp.ErrorCode, err)
}
return nil
}

View File

@@ -7,21 +7,109 @@ import (
"fmt"
"net/url"
"strconv"
log "github.com/sirupsen/logrus"
"github.com/SynologyOpenSource/synology-csi/pkg/utils"
"github.com/SynologyOpenSource/synology-csi/pkg/logger"
)
type ShareInfo struct {
Name string `json:"name"`
VolPath string `json:"vol_path"`
Name string `json:"name"` // required
VolPath string `json:"vol_path"` // required
Desc string `json:"desc"`
EnableShareCow bool `json:"enable_share_cow"`
EnableShareCow bool `json:"enable_share_cow"` // field for create
EnableRecycleBin bool `json:"enable_recycle_bin"`
RecycleBinAdminOnly bool `json:"recycle_bin_admin_only"`
Encryption int `json:"encryption"`
Encryption int `json:"encryption"` // field for create
QuotaForCreate *int64 `json:"share_quota,omitempty"`
QuotaValueInMB int64 `json:"quota_value"` // field for get
SupportSnapshot bool `json:"support_snapshot"` // field for get
Uuid string `json:"uuid"` // field for get
NameOrg string `json:"name_org"` // required for clone
}
type ShareUpdateInfo struct {
Name string `json:"name"` // required
VolPath string `json:"vol_path"` // required
QuotaForCreate *int64 `json:"share_quota,omitempty"`
// Add properties you want to update to shares here
}
type ShareSnapshotInfo struct {
Uuid string `json:"ruuid"`
Time string `json:"time"`
Desc string `json:"desc"`
SnapSize string `json:"snap_size"` // the complete size of the snapshot
Lock bool `json:"lock"`
ScheduleSnapshot bool `json:"schedule_snapshot"`
}
type ShareCreateSpec struct {
Name string `json:"name"`
ShareInfo ShareInfo `json:"shareinfo"`
Name string
ShareInfo ShareInfo
}
type ShareCloneSpec struct {
Name string
Snapshot string
ShareInfo ShareInfo
}
type ShareSnapshotCreateSpec struct {
ShareName string
Desc string
IsLocked bool
}
type SharePermissionSetSpec struct {
Name string
UserGroupType string // "local_user"/"local_group"/"system"
Permissions []*SharePermission
}
type SharePermission struct {
Name string `json:"name"`
IsReadonly bool `json:"is_readonly"`
IsWritable bool `json:"is_writable"`
IsDeny bool `json:"is_deny"`
IsCustom bool `json:"is_custom,omitempty"`
IsAdmin bool `json:"is_admin,omitempty"` // field for list
}
func shareErrCodeMapping(errCode int, oriErr error) error {
switch errCode {
case 402: // No such share
return utils.NoSuchShareError("")
case 403: // Invalid input value
return utils.BadParametersError("")
case 3301: // already exists
return utils.AlreadyExistError("")
case 3309:
return utils.ShareReachMaxCountError("")
case 3328:
return utils.ShareSystemBusyError("")
}
if errCode >= 3300 {
return utils.ShareDefaultError{errCode}
}
return oriErr
}
// ----------------------- Share APIs -----------------------
func (dsm *DSM) ShareGet(shareName string) (ShareInfo, error) {
params := url.Values{}
params.Add("api", "SYNO.Core.Share")
params.Add("method", "get")
params.Add("version", "1")
params.Add("additional", "[\"encryption\", \"enable_share_cow\", \"recyclebin\", \"support_snapshot\", \"share_quota\"]")
params.Add("name", strconv.Quote(shareName))
info := ShareInfo{}
resp, err := dsm.sendRequest("", &info, params, "webapi/entry.cgi")
return info, shareErrCodeMapping(resp.ErrorCode, err)
}
func (dsm *DSM) ShareList() ([]ShareInfo, error) {
@@ -29,7 +117,7 @@ func (dsm *DSM) ShareList() ([]ShareInfo, error) {
params.Add("api", "SYNO.Core.Share")
params.Add("method", "list")
params.Add("version", "1")
params.Add("additional", "[\"encryption\"]")
params.Add("additional", "[\"encryption\", \"enable_share_cow\", \"recyclebin\", \"support_snapshot\", \"share_quota\"]")
type ShareInfos struct {
Shares []ShareInfo `json:"shares"`
@@ -37,7 +125,7 @@ func (dsm *DSM) ShareList() ([]ShareInfo, error) {
resp, err := dsm.sendRequest("", &ShareInfos{}, params, "webapi/entry.cgi")
if err != nil {
return nil, err
return nil, shareErrCodeMapping(resp.ErrorCode, err)
}
infos, ok := resp.Data.(*ShareInfos)
@@ -61,13 +149,49 @@ func (dsm *DSM) ShareCreate(spec ShareCreateSpec) error {
}
params.Add("shareinfo", string(js))
// response : {"data":{"name":"Share-2"},"success":true}
_, err = dsm.sendRequest("", &struct{}{}, params, "webapi/entry.cgi")
if err != nil {
return err
resp, err := dsm.sendRequest("", &struct{}{}, params, "webapi/entry.cgi")
return shareErrCodeMapping(resp.ErrorCode, err)
}
func (dsm *DSM) ShareClone(spec ShareCloneSpec) (string, error) {
params := url.Values{}
params.Add("api", "SYNO.Core.Share")
params.Add("method", "clone")
params.Add("version", "1")
params.Add("name", strconv.Quote(spec.Name))
// if clone from snapshot, the NameOrg must be the parent of the snapshot, or the webapi will return 3300
// if the snapshot doesn't exist, it will return 3300 too.
if spec.ShareInfo.NameOrg == "" {
return "", fmt.Errorf("Clone failed. The source name can't be empty.")
}
return nil
if spec.Snapshot != "" {
params.Add("snapshot", strconv.Quote(spec.Snapshot))
}
js, err := json.Marshal(spec.ShareInfo)
if err != nil {
return "", err
}
params.Add("shareinfo", string(js))
type ShareCreateResp struct {
Name string `json:"name"`
}
resp, err := dsm.sendRequest("", &ShareCreateResp{}, params, "webapi/entry.cgi")
if err != nil {
return "", shareErrCodeMapping(resp.ErrorCode, err)
}
shareResp, ok := resp.Data.(*ShareCreateResp)
if !ok {
return "", fmt.Errorf("Failed to assert response to %T", &ShareCreateResp{})
}
return shareResp.Name, nil
}
func (dsm *DSM) ShareDelete(shareName string) error {
@@ -75,13 +199,165 @@ func (dsm *DSM) ShareDelete(shareName string) error {
params.Add("api", "SYNO.Core.Share")
params.Add("method", "delete")
params.Add("version", "1")
params.Add("name", fmt.Sprintf("[%s]", strconv.Quote(shareName)))
resp, err := dsm.sendRequest("", &struct{}{}, params, "webapi/entry.cgi")
return shareErrCodeMapping(resp.ErrorCode, err)
}
func (dsm *DSM) ShareSet(shareName string, updateInfo ShareUpdateInfo) error {
params := url.Values{}
params.Add("api", "SYNO.Core.Share")
params.Add("method", "set")
params.Add("version", "1")
params.Add("name", strconv.Quote(shareName))
// response : {"success":true}
_, err := dsm.sendRequest("", &struct{}{}, params, "webapi/entry.cgi")
js, err := json.Marshal(updateInfo)
if err != nil {
return err
}
params.Add("shareinfo", string(js))
if logger.WebapiDebug {
log.Debugln(params)
}
resp, err := dsm.sendRequest("", &struct{}{}, params, "webapi/entry.cgi")
return shareErrCodeMapping(resp.ErrorCode, err)
}
func (dsm *DSM) SetShareQuota(shareInfo ShareInfo, newSizeInMB int64) error {
updateInfo := ShareUpdateInfo{
Name: shareInfo.Name,
VolPath: shareInfo.VolPath,
QuotaForCreate: &newSizeInMB,
}
return dsm.ShareSet(shareInfo.Name, updateInfo)
}
// ----------------------- Share Snapshot APIs -----------------------
func (dsm *DSM) ShareSnapshotCreate(spec ShareSnapshotCreateSpec) (string, error) {
params := url.Values{}
params.Add("api", "SYNO.Core.Share.Snapshot")
params.Add("method", "create")
params.Add("version", "1")
params.Add("name", strconv.Quote(spec.ShareName))
type SnapInfo struct {
Desc string `json:"desc"`
IsLocked bool `json:"lock"` // default true
}
snapinfo := SnapInfo{
Desc: spec.Desc,
IsLocked: spec.IsLocked,
}
js, err := json.Marshal(snapinfo)
if err != nil {
return "", err
}
params.Add("snapinfo", string(js))
var snapTime string
resp, err := dsm.sendRequest("", &snapTime, params, "webapi/entry.cgi")
if err != nil {
return "", shareErrCodeMapping(resp.ErrorCode, err)
}
return snapTime, nil // "GMT+08-2022.01.14-19.18.29"
}
func (dsm *DSM) ShareSnapshotList(name string) ([]ShareSnapshotInfo, error) {
params := url.Values{}
params.Add("api", "SYNO.Core.Share.Snapshot")
params.Add("method", "list")
params.Add("version", "2")
params.Add("name", strconv.Quote(name))
params.Add("additional", "[\"desc\", \"lock\", \"schedule_snapshot\", \"ruuid\", \"snap_size\"]")
type Infos struct {
Snapshots []ShareSnapshotInfo `json:"snapshots"`
Total int `json:"total"`
}
resp, err := dsm.sendRequest("", &Infos{}, params, "webapi/entry.cgi")
if err != nil {
return nil, shareErrCodeMapping(resp.ErrorCode, err)
}
infos, ok := resp.Data.(*Infos)
if !ok {
return nil, fmt.Errorf("Failed to assert response to %T", &Infos{})
}
return infos.Snapshots, nil
}
func (dsm *DSM) ShareSnapshotDelete(snapTime string, shareName string) error {
params := url.Values{}
params.Add("api", "SYNO.Core.Share.Snapshot")
params.Add("method", "delete")
params.Add("version", "1")
params.Add("name", strconv.Quote(shareName))
params.Add("snapshots", fmt.Sprintf("[%s]", strconv.Quote(snapTime))) // ["GMT+08-2022.01.14-19.18.29"]
var objmap []map[string]interface{}
resp, err := dsm.sendRequest("", &objmap, params, "webapi/entry.cgi")
if err != nil {
return shareErrCodeMapping(resp.ErrorCode, err)
}
if len(objmap) > 0 {
return fmt.Errorf("Failed to delete snapshot, API common error. snapshot: %s", snapTime)
}
return nil
}
// ----------------------- Share Permission APIs -----------------------
func (dsm *DSM) SharePermissionSet(spec SharePermissionSetSpec) error {
params := url.Values{}
params.Add("api", "SYNO.Core.Share.Permission")
params.Add("method", "set")
params.Add("version", "1")
params.Add("name", strconv.Quote(spec.Name))
params.Add("user_group_type", strconv.Quote(spec.UserGroupType))
js, err := json.Marshal(spec.Permissions)
if err != nil {
return err
}
params.Add("permissions", string(js))
resp, err := dsm.sendRequest("", &struct{}{}, params, "webapi/entry.cgi")
return shareErrCodeMapping(resp.ErrorCode, err)
}
func (dsm *DSM) SharePermissionList(shareName string, userGroupType string) ([]SharePermission, error) {
params := url.Values{}
params.Add("api", "SYNO.Core.Share.Permission")
params.Add("method", "list")
params.Add("version", "1")
params.Add("name", strconv.Quote(shareName))
params.Add("user_group_type", strconv.Quote(userGroupType))
type SharePermissions struct {
Permissions []SharePermission `json:"items"`
}
resp, err := dsm.sendRequest("", &SharePermissions{}, params, "webapi/entry.cgi")
if err != nil {
return nil, shareErrCodeMapping(resp.ErrorCode, err)
}
infos, ok := resp.Data.(*SharePermissions)
if !ok {
return nil, fmt.Errorf("Failed to assert response to %T", &SharePermissions{})
}
return infos.Permissions, nil
}