// Copyright (C) LINBIT HA-Solutions GmbH // All Rights Reserved. // Author: Roland Kammerer // // Licensed under the Apache License, Version 2.0 (the "License"); you may // not use this file except in compliance with the License. You may obtain // a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations // under the License. package client import ( "context" "net" "github.com/LINBIT/golinstor/devicelayerkind" ) // copy & paste from generated code // Node represents a node in LINSTOR type Node struct { Name string `json:"name"` Type string `json:"type"` Flags []string `json:"flags,omitempty"` // A string to string property map. Props map[string]string `json:"props,omitempty"` NetInterfaces []NetInterface `json:"net_interfaces,omitempty"` // Enum describing the current connection status. ConnectionStatus string `json:"connection_status,omitempty"` // unique object id Uuid string `json:"uuid,omitempty"` StorageProviders []ProviderKind `json:"storage_providers,omitempty"` ResourceLayers []devicelayerkind.DeviceLayerKind `json:"resource_layers,omitempty"` UnsupportedProviders map[ProviderKind][]string `json:"unsupported_providers,omitempty"` UnsupportedLayers map[devicelayerkind.DeviceLayerKind][]string `json:"unsupported_layers,omitempty"` // milliseconds since unix epoch in UTC EvictionTimestamp *TimeStampMs `json:"eviction_timestamp,omitempty"` } type NodeModify struct { NodeType string `json:"node_type,omitempty"` // A string to string property map. GenericPropsModify } type NodeRestore struct { DeleteResources *bool `json:"delete_resources,omitempty"` DeleteSnapshots *bool `json:"delete_snapshots,omitempty"` } // NetInterface represents a node's network interface. type NetInterface struct { Name string `json:"name"` Address net.IP `json:"address"` SatellitePort int32 `json:"satellite_port,omitempty"` SatelliteEncryptionType string `json:"satellite_encryption_type,omitempty"` // Defines if this netinterface should be used for the satellite connection IsActive bool `json:"is_active,omitempty"` // unique object id Uuid string `json:"uuid,omitempty"` } // StoragePool represents a nodes storage pool as defined in LINSTOR. type StoragePool struct { StoragePoolName string `json:"storage_pool_name"` NodeName string `json:"node_name,omitempty"` ProviderKind ProviderKind `json:"provider_kind"` // A string to string property map. Props map[string]string `json:"props,omitempty"` // read only map of static storage pool traits StaticTraits map[string]string `json:"static_traits,omitempty"` // Kibi - read only FreeCapacity int64 `json:"free_capacity,omitempty"` // Kibi - read only TotalCapacity int64 `json:"total_capacity,omitempty"` // read only FreeSpaceMgrName string `json:"free_space_mgr_name,omitempty"` // unique object id Uuid string `json:"uuid,omitempty"` // Currently known report messages for this storage pool Reports []ApiCallRc `json:"reports,omitempty"` // true if the storage pool supports snapshots. false otherwise SupportsSnapshots bool `json:"supports_snapshots,omitempty"` // name of the shared space or null if none given SharedSpace string `json:"shared_space,omitempty"` // true if a shared storage pool uses linstor-external locking, like cLVM ExternalLocking bool `json:"external_locking,omitempty"` } // ProviderKind is a type that represents various types of storage. type ProviderKind string // List of ProviderKind const ( DISKLESS ProviderKind = "DISKLESS" LVM ProviderKind = "LVM" LVM_THIN ProviderKind = "LVM_THIN" ZFS ProviderKind = "ZFS" ZFS_THIN ProviderKind = "ZFS_THIN" FILE ProviderKind = "FILE" FILE_THIN ProviderKind = "FILE_THIN" SPDK ProviderKind = "SPDK" EBS_TARGET ProviderKind = "EBS_TARGET" EBS_INIT ProviderKind = "EBS_INIT" ) // custom code // NodeProvider acts as an abstraction for a NodeService. It can be swapped out // for another NodeService implementation, for example for testing. type NodeProvider interface { // GetAll gets information for all registered nodes. GetAll(ctx context.Context, opts ...*ListOpts) ([]Node, error) // Get gets information for a particular node. Get(ctx context.Context, nodeName string, opts ...*ListOpts) (Node, error) // Create creates a new node object. Create(ctx context.Context, node Node) error // CreateEbsNode creates a special virtual satellite for interacting with EBS. CreateEbsNode(ctx context.Context, name string, remoteName string) error // Modify modifies the given node and sets/deletes the given properties. Modify(ctx context.Context, nodeName string, props NodeModify) error // Delete deletes the given node. Delete(ctx context.Context, nodeName string) error // Lost marks the given node as lost to delete an unrecoverable node. Lost(ctx context.Context, nodeName string) error // Reconnect reconnects a node to the controller. Reconnect(ctx context.Context, nodeName string) error // GetNetInterfaces gets information about all network interfaces of a given node. GetNetInterfaces(ctx context.Context, nodeName string, opts ...*ListOpts) ([]NetInterface, error) // GetNetInterface gets information about a particular network interface on a given node. GetNetInterface(ctx context.Context, nodeName, nifName string, opts ...*ListOpts) (NetInterface, error) // CreateNetInterface creates the given network interface on a given node. CreateNetInterface(ctx context.Context, nodeName string, nif NetInterface) error // ModifyNetInterface modifies the given network interface on a given node. ModifyNetInterface(ctx context.Context, nodeName, nifName string, nif NetInterface) error // DeleteNetinterface deletes the given network interface on a given node. DeleteNetinterface(ctx context.Context, nodeName, nifName string) error // GetStoragePoolView gets information about all storage pools in the cluster. GetStoragePoolView(ctx context.Context, opts ...*ListOpts) ([]StoragePool, error) // GetStoragePools gets information about all storage pools on a given node. GetStoragePools(ctx context.Context, nodeName string, opts ...*ListOpts) ([]StoragePool, error) // GetStoragePool gets information about a specific storage pool on a given node. GetStoragePool(ctx context.Context, nodeName, spName string, opts ...*ListOpts) (StoragePool, error) // CreateStoragePool creates a storage pool on a given node. CreateStoragePool(ctx context.Context, nodeName string, sp StoragePool) error // ModifyStoragePool modifies a storage pool on a given node. ModifyStoragePool(ctx context.Context, nodeName, spName string, genericProps GenericPropsModify) error // DeleteStoragePool deletes a storage pool on a given node. DeleteStoragePool(ctx context.Context, nodeName, spName string) error // CreateDevicePool creates an LVM, LVM-thin or ZFS pool, optional VDO under it on a given node. CreateDevicePool(ctx context.Context, nodeName string, psc PhysicalStorageCreate) error // GetPhysicalStorageView gets a grouped list of physical storage that can be turned into a LINSTOR storage-pool GetPhysicalStorageView(ctx context.Context, opts ...*ListOpts) ([]PhysicalStorageViewItem, error) // GetPhysicalStorage gets a list of unconfigured physical storage on a node. GetPhysicalStorage(ctx context.Context, nodeName string) ([]PhysicalStorageNode, error) // GetStoragePoolPropsInfos gets meta information about the properties // that can be set on a storage pool on a particular node. GetStoragePoolPropsInfos(ctx context.Context, nodeName string, opts ...*ListOpts) ([]PropsInfo, error) // GetPropsInfos gets meta information about the properties that can be // set on a node. GetPropsInfos(ctx context.Context, opts ...*ListOpts) ([]PropsInfo, error) // Evict the given node, migrating resources to the remaining nodes, if possible. This is meant for offline nodes. Evict(ctx context.Context, nodeName string) error // Restore an evicted node, optionally keeping existing resources. Restore(ctx context.Context, nodeName string, restore NodeRestore) error // Evacuate the given node, migrating resources to remaining nodes. While Evict works only on offline nodes, this // is meant for online nodes. Evacuate(ctx context.Context, nodeName string) error } // NodeService is the service that deals with node related tasks. type NodeService struct { client *Client } var _ NodeProvider = &NodeService{} // GetAll gets information for all registered nodes. func (n *NodeService) GetAll(ctx context.Context, opts ...*ListOpts) ([]Node, error) { var nodes []Node _, err := n.client.doGET(ctx, "/v1/nodes", &nodes, opts...) return nodes, err } // Get gets information for a particular node. func (n *NodeService) Get(ctx context.Context, nodeName string, opts ...*ListOpts) (Node, error) { var node Node _, err := n.client.doGET(ctx, "/v1/nodes/"+nodeName, &node, opts...) return node, err } // Create creates a new node object. func (n *NodeService) Create(ctx context.Context, node Node) error { _, err := n.client.doPOST(ctx, "/v1/nodes", node) return err } func (n *NodeService) CreateEbsNode(ctx context.Context, name, remoteName string) error { _, err := n.client.doPOST(ctx, "/v1/nodes/ebs", struct { Name string `json:"name"` EbsRemoteName string `json:"ebs_remote_name"` }{ Name: name, EbsRemoteName: remoteName, }) return err } // Modify modifies the given node and sets/deletes the given properties. func (n *NodeService) Modify(ctx context.Context, nodeName string, props NodeModify) error { _, err := n.client.doPUT(ctx, "/v1/nodes/"+nodeName, props) return err } // Delete deletes the given node. func (n *NodeService) Delete(ctx context.Context, nodeName string) error { _, err := n.client.doDELETE(ctx, "/v1/nodes/"+nodeName, nil) return err } // Lost marks the given node as lost to delete an unrecoverable node. func (n *NodeService) Lost(ctx context.Context, nodeName string) error { _, err := n.client.doDELETE(ctx, "/v1/nodes/"+nodeName+"/lost", nil) return err } // Reconnect reconnects a node to the controller. func (n *NodeService) Reconnect(ctx context.Context, nodeName string) error { _, err := n.client.doPUT(ctx, "/v1/nodes/"+nodeName+"/reconnect", nil) return err } // GetNetInterfaces gets information about all network interfaces of a given node. func (n *NodeService) GetNetInterfaces(ctx context.Context, nodeName string, opts ...*ListOpts) ([]NetInterface, error) { var nifs []NetInterface _, err := n.client.doGET(ctx, "/v1/nodes/"+nodeName+"/net-interfaces", &nifs, opts...) return nifs, err } // GetNetInterface gets information about a particular network interface on a given node. func (n *NodeService) GetNetInterface(ctx context.Context, nodeName, nifName string, opts ...*ListOpts) (NetInterface, error) { var nif NetInterface _, err := n.client.doGET(ctx, "/v1/nodes/"+nodeName+"/net-interfaces/"+nifName, &nif, opts...) return nif, err } // CreateNetInterface creates the given network interface on a given node. func (n *NodeService) CreateNetInterface(ctx context.Context, nodeName string, nif NetInterface) error { _, err := n.client.doPOST(ctx, "/v1/nodes/"+nodeName+"/net-interfaces", nif) return err } // ModifyNetInterface modifies the given network interface on a given node. func (n *NodeService) ModifyNetInterface(ctx context.Context, nodeName, nifName string, nif NetInterface) error { _, err := n.client.doPUT(ctx, "/v1/nodes/"+nodeName+"/net-interfaces/"+nifName, nif) return err } // DeleteNetinterface deletes the given network interface on a given node. func (n *NodeService) DeleteNetinterface(ctx context.Context, nodeName, nifName string) error { _, err := n.client.doDELETE(ctx, "/v1/nodes/"+nodeName+"/net-interfaces/"+nifName, nil) return err } // GetStoragePoolView gets information about all storage pools in the cluster. func (n *NodeService) GetStoragePoolView(ctx context.Context, opts ...*ListOpts) ([]StoragePool, error) { var sps []StoragePool _, err := n.client.doGET(ctx, "/v1/view/storage-pools", &sps, opts...) return sps, err } // GetStoragePools gets information about all storage pools on a given node. func (n *NodeService) GetStoragePools(ctx context.Context, nodeName string, opts ...*ListOpts) ([]StoragePool, error) { var sps []StoragePool _, err := n.client.doGET(ctx, "/v1/nodes/"+nodeName+"/storage-pools", &sps, opts...) return sps, err } // GetStoragePool gets information about a specific storage pool on a given node. func (n *NodeService) GetStoragePool(ctx context.Context, nodeName, spName string, opts ...*ListOpts) (StoragePool, error) { var sp StoragePool _, err := n.client.doGET(ctx, "/v1/nodes/"+nodeName+"/storage-pools/"+spName, &sp, opts...) return sp, err } // CreateStoragePool creates a storage pool on a given node. func (n *NodeService) CreateStoragePool(ctx context.Context, nodeName string, sp StoragePool) error { _, err := n.client.doPOST(ctx, "/v1/nodes/"+nodeName+"/storage-pools", sp) return err } // ModifyStoragePool modifies a storage pool on a given node. func (n *NodeService) ModifyStoragePool(ctx context.Context, nodeName, spName string, genericProps GenericPropsModify) error { _, err := n.client.doPUT(ctx, "/v1/nodes/"+nodeName+"/storage-pools/"+spName, genericProps) return err } // DeleteStoragePool deletes a storage pool on a given node. func (n *NodeService) DeleteStoragePool(ctx context.Context, nodeName, spName string) error { _, err := n.client.doDELETE(ctx, "/v1/nodes/"+nodeName+"/storage-pools/"+spName, nil) return err } // GetStoragePoolPropsInfos gets meta information about the properties that can // be set on a storage pool on a particular node. func (n *NodeService) GetStoragePoolPropsInfos(ctx context.Context, nodeName string, opts ...*ListOpts) ([]PropsInfo, error) { var infos []PropsInfo _, err := n.client.doGET(ctx, "/v1/nodes/"+nodeName+"/storage-pools/properties/info", &infos, opts...) return infos, err } // GetPropsInfos gets meta information about the properties that can be set on // a node. func (n *NodeService) GetPropsInfos(ctx context.Context, opts ...*ListOpts) ([]PropsInfo, error) { var infos []PropsInfo _, err := n.client.doGET(ctx, "/v1/nodes/properties/info", &infos, opts...) return infos, err } // Evict the given node, migrating resources to the remaining nodes, if possible. func (n NodeService) Evict(ctx context.Context, nodeName string) error { _, err := n.client.doPUT(ctx, "/v1/nodes/"+nodeName+"/evict", nil) return err } // Evacuate the given node, migrating resources to remaining nodes. While Evict works only on offline nodes, this // is meant for online nodes. func (n NodeService) Evacuate(ctx context.Context, nodeName string) error { _, err := n.client.doPUT(ctx, "/v1/nodes/"+nodeName+"/evacuate", nil) return err } // Restore an evicted node, optionally keeping existing resources. func (n *NodeService) Restore(ctx context.Context, nodeName string, restore NodeRestore) error { _, err := n.client.doPUT(ctx, "/v1/nodes/"+nodeName+"/restore", restore) return err }