class WebConfig(Config): """ default password is 123456, fc91f9f874d2ef4d48fdde151271716f268977c1f77241d5321b61fda137ac3c is sha256 hash of result of PBKDF2 to 123456 """ CONF_FILE = os.path.join(STORLEVER_CONF_DIR, 'web.yaml') DEFAULT_CONF = { 'password': '******', 'language': 'chinese' } SCHEMA = Schema({ 'password': Use(str), # filesystem type 'language': Use(str), # dev file }) def __init__(self, conf=None): self.conf_file = self.CONF_FILE self.conf = conf self.schema = self.SCHEMA def parse(self): if self.conf_file is not None and self.conf_file != "": try: with open(self.conf_file, "r") as f: self.conf = yaml.load(f) if self.schema: self.conf = self.schema.validate(self.conf) return self.conf except IOError as e: if e.errno == errno.ENOENT: self.conf = self.DEFAULT_CONF self.write() return self.conf else: raise ConfigError(str(e)) except Exception: raise ConfigError(str(Exception)) else: raise ConfigError("conf file absent") @classmethod def from_file(cls): conf = cls() conf.parse() return conf @classmethod def to_file(cls, conf): conf = cls(conf=conf) conf.write() return conf
def __init__(self): # need a mutex to protect create/delete bond interface self.lock = lock() self.support_fs_type = {} self.conf_file = os.path.join(STORLEVER_CONF_DIR, FS_CONF_FILE_NAME) self.fs_conf_schema = Schema({ "type": Use(str), # filesystem type "dev_file": Use(str), # dev file "dev_uuid": Use(str), # dev uuid "mount_point": Use(str), # mount point of this fs, "mount_option": Use(str), # mount option of this fs "check_onboot": BoolVal(), # fsck fs on boot Optional("comment"): Default(Use(str), default=""), # comment, AutoDel(str): object # for all other key we auto delete }) self.fs_dict_schema = Schema({ DoNotCare(str): self.fs_conf_schema }) # sync fs conf to fstab on boot self.sync_to_fstab()
tgt_mgr = tgtmgr.TgtManager return tgt_mgr.get_tgt_conf() tgt_conf_schema = Schema({ # Define iscsi incoming discovery authentication setting. If it is # empty, no authentication is performed. The format is username:passwd Optional("incomingdiscoveryuser"): StrRe(r"^(|\w+:\w+)$"), # Define iscsi outgoing discovery authentication setting. If it is # empty, no authentication is performe The format is username:passwd Optional("outgoingdiscoveryuser"): StrRe(r"^(|\w+:\w+)$"), DoNotCare(Use(str)): object # for all other key we don't care }) @put_view(route_name='tgt_conf') def put_tgt_conf(request): tgt_mgr = tgtmgr.TgtManager tgt_conf = get_params_from_request(request, tgt_conf_schema) tgt_mgr.set_tgt_conf(tgt_conf, operator=request.client_addr) return Response(status=200) @get_view(route_name='tgt_target_iqn_list') def get_tgt_target_iqn_list(request): tgt_mgr = tgtmgr.TgtManager
"comment": "Provides the fundamental functions of the low-lever system, " "like date, time, log, shutdown, reboot, and etc" } LOG_DIR = "/var/log" LOG_FILE_PATH_PREFIX = "/tmp/syslog" SELINUX_CONF_DIR = "/etc/selinux/" SELINUX_CONF_FILE = "config" ETC_HOSTS_FILE = "/etc/hosts" ETC_NETWORK_FILE = "/etc/sysconfig/network" HOST_LIST_SCHEMA = Schema([{ "addr": Use(str), "hostname": Use(str), Optional("alias"): Default(Use(str), default=""), AutoDel(str): object # for all other key we auto delete }]) class SysManager(object): """contains all methods to manage the system""" def __init__(self): self.dist_name = None self.dist_version = None self.dist_id = None def system_restore_cb(self): self.set_hostname("localhost", "System Restore")
from storlever.lib.schema import Schema, Use, Optional, \ Default, DoNotCare, BoolVal, IntVal, AutoDel from storlever.lib.lock import lock from storlever.mngr.system.cfgmgr import STORLEVER_CONF_DIR, cfg_mgr from storlever.mngr.system.servicemgr import service_mgr SNMP_CONF_FILE_NAME = "snmp_conf.yaml" SNMP_ETC_CONF_DIR = "/etc/snmp/" SNMP_ETC_CONF_FILE = "snmpd.conf" SNMP_MONITOR_CONF_SCHEMA = Schema({ # monitor name "monitor_name": Use(str), # options to control the monitor's behavior, # see monitor options section of man snmpd.conf for more detail Optional("option"): Default(Use(str), default=""), # expression to check of this monitor, # see monitor expression of man snmpd.conf for more detail "expression": Use(str), AutoDel(str): object # for all other key we auto delete }) SNMP_SINK_CONF_SCHEMA = Schema({
from storlever.mngr.system.servicemgr import service_mgr from storlever.mngr.system.modulemgr import ModuleManager MODULE_INFO = { "module_name": "zabbix_agent", "rpms": ["zabbix-agent"], "comment": "Provides the support of zabbix agent config for storlever" } ZABBIX_AGENT_CONF_FILE_NAME = "zabbix_agentd_conf.yaml" ZABBIX_AGENT_ETC_CONF_DIR = "/etc/zabbix/" ZABBIX_AGENT_CONF_FILE = "zabbix_agentd.conf" ZABBIX_AGENT_CONF_SCHEMA = Schema({ Optional("hostname"): Default(Use(str), default=""), # How often list of active checks is refreshed, in seconds. # Note that after failing to refresh active checks the next refresh # will be attempted after 60 seconds. Optional("refresh_active_check"): Default(IntVal(min=60, max=3600), default=120), # the server ip:port list for active check.zabbix_agent would get the active check list # from each server at the refresh_active_check frequency. Entry string Format is IP:PORT Optional("active_check_server_list"): Default([Use(str)], default=[]), # the server ip list for passive check. each passive check's source ip must # exist in this list. Entry string Format is IP Optional("passive_check_server_list"):
"rpms": [ "samba", ], "comment": "Provides the management functions for SAMBA server" } SMB_CONF_FILE_NAME = "smb_conf.yaml" SMB_ETC_CONF_DIR = "/etc/samba/" SMB_ETC_CONF_FILE = "smb.conf" SMBSTATUS_CMD = "/usr/bin/smbstatus" PDBEDIT_CMD = "/usr/bin/pdbedit" SHARE_CONF_SCHEMA = Schema({ # Name of this share "share_name": Use(str), # This parameter specifies a directory to which the user of the service is to # be given access.default is empty Optional("path"): Default(Use(str), default=""), # This is a text field that is seen next to a share when a client does a # queries the server, either via the network neighborhood or via net view to # list what shares are available. Default is empty Optional("comment"): Default(Use(str), default=""), # When a file is created, the necessary permissions are calculated according # to the mapping from DOS modes to UNIX permissions, and the resulting UNIX # mode is then bit-wise ?AND?ed with this parameter. This parameter may be
MODULE_INFO = { "module_name": "FTP", "rpms": [ "vsftpd" ], "comment": "Provides the management functions for FTP server" } FTP_CONF_FILE_NAME = "ftp_conf.yaml" VSFTPD_ETC_CONF_DIR = "/etc/vsftpd/" VSFTPD_ETC_CONF_FILE = "vsftpd.conf" VSFTPD_ETC_USER_LIST = "user_list" VSFTPD_ETC_CHROOT_LIST = "chroot_list" FTP_USER_CONF_SCHEMA = Schema({ "user_name": Use(str), # When enabled, the user can log in ftp Optional("login_enable"): Default(BoolVal(), default=True), # When enabled, the user will be placed into the chroot jail Optional("chroot_enable"): Default(BoolVal(), default=False), AutoDel(str): object # for all other key we auto delete }) FTP_CONF_SCHEMA = Schema({ Optional("listen"): Default(BoolVal(), default=False), # ftp service listen on ipv4 port Optional("listen6"): Default(BoolVal(), default=False), # ftp service listen on ipv6 port Optional("listen_port"): Default(IntVal(min=1, max=65535), default=21), # ftp port number # The maximum amount of time between commands from a remote client. # Once triggered, the connection to the remote client is closed
"comment": "Provides the configuration management of the NTP server in sytem , " "like setup the peer server, set self stratum, and etc" } NTP_CONF_FILE_NAME = "ntp_conf.yaml" NTP_ETC_CONF_DIR = "/etc/" NTP_ETC_CONF_FILE = "ntp.conf" NTP_ETC_STORLEVER_CONF_DIR = "/etc/ntp/" NTP_ETC_STORLEVER_CONF_FILE = "ntp.storlever.conf" NTPQ_CMD = "/usr/sbin/ntpq" NTP_SERVER_CONF_SCHEMA = Schema({ # it can be a ipv4 address, ipv6 address, or host dns name "server_addr": Use(str), # if set to True, it would be forced to resolve the host name to # ipv6 address in DNS resolution Optional("ipv6"): Default(BoolVal(), default=False), # Marks the server as preferred. All other things being equal, # this host will be chosen for synchronization among set of correctly operating hosts Optional("prefer"): Default(BoolVal(), default=False), # Specifies a mode number which is interpreted in a device # specific fashion. For instance, it selects a dialing, # protocol in the ACTS driver and a device subtype in the # parse drivers. # Only valid for reference clock server, i.e. server_addr is 127.127.t.n Optional("mode"): Default(IntVal(min=0, max=65535), default=0),
def test_dict(self): schema = Schema({ "key1": str, # key1 should be string "key2": Use(int), # key3 should be in or int in string "key3": [IntVal(min=10, max=20)], # key4 is optional, Optional("key4"): str, Optional('key5'): Default(IntVal(min=100, max=200), default=100), DoNotCare(str): object # for all those key we don't care }) data = schema.validate({ "key1": "abc", "key2": '123', "key3": [10, 15, 20], "key5": 199, }) self.assertEqual(data, { "key1": "abc", "key2": 123, "key3": [10, 15, 20], "key5": 199 }) data = schema.validate({ "key1": "abc", "key2": '123', "key3": [10, 15, 20], }) self.assertEqual(data, { "key1": "abc", "key2": 123, "key3": [10, 15, 20], "key5": 100 }) data = schema.validate({ "key1": "abc", "key2": '123', "key3": [10, 15, 20], "key4": 'abc' }) self.assertEqual( data, { "key1": "abc", "key2": 123, "key3": [10, 15, 20], "key4": 'abc', "key5": 100 }) data = schema.validate({ "key1": "abc", "key2": '123', "key3": [10, 15, 20], "key4": 'abc', "key100": 'bbc', 'key200': [123, 23, 334] }) self.assertEqual( data, { "key1": "abc", "key2": 123, "key3": [10, 15, 20], "key4": 'abc', "key5": 100, "key100": 'bbc', 'key200': [123, 23, 334] }) with self.assertRaises(SchemaError): schema.validate({ 'key1': 123, "key2": '123', "key3": [10, 15, 20], "key4": 223, }) with self.assertRaises(SchemaError): schema.validate({ 'key1': 123, "key2": '123', "key3": [10, 15, 20], "key4": 'abc', "key100": 'bbc', 'key200': [123, 23, 334] }) with self.assertRaises(SchemaError): schema.validate({ 'key1': 'abc', "key2": '123', "key3": [10, 15, 20], "key4": 'abc', 'key5': 0, "key100": 'bbc', 'key200': [123, 23, 334] })
'system': sys_uname[0], 'release': sys_uname[2], 'version': sys_uname[3], 'machine': sys_uname[4], 'processor': sys_uname[5], 'dist_name': dist_name, 'dist_version': dist_version, 'dist_id': dist_id, "uptime": str(uptime).split('.')[0], "loadavg": [av1, av2, av3] } return info local_host_schema = Schema({ Optional("hostname"): Use(str), # name should be string DoNotCare(Use(str)): object # for all those key we don't care }) @put_view(route_name='system_localhost') def put_system_localhost(request): sys_mgr = sysinfo.sys_mgr() # get sys manager params = get_params_from_request(request, local_host_schema) if "hostname" in params: sys_mgr.set_hostname(params["hostname"], user=request.client_addr) return Response(status=200) @get_view(route_name='cpu_list') def system_cpu_list_get(request):
ftp_mgr = ftpmgr.FtpManager return ftp_mgr.get_ftp_conf() ftp_conf_schema = Schema({ Optional("listen"): BoolVal(), # ftp service listen on ipv4 port Optional("listen6"): BoolVal(), # ftp service listen on ipv6 port Optional("listen_port"): IntVal(min=1, max=65535), # ftp port number # The maximum amount of time between commands from a remote client. # Once triggered, the connection to the remote client is closed Optional("idle_session_timeout"): Use(int), # the maximum data transfer rate for anonymous users in bytes per second. # The default value is 0, which does not limit the transfer rate. Optional("anon_max_rate"): Use(int), # the maximum rate data is transferred for local users in bytes per second. # The default value is 0, which does not limit the transfer rate. Optional("local_max_rate"): Use(int), # the maximum number of simultaneous clients allowed to connect to # the server when it is running in standalone mode. Any additional client # connections would result in an error message. # The default value is 0, which does not limit connections. Optional("max_clients"):
# must use a contiguous mask length and must not be inside square brackets # to avoid confusion with character-class wildcards. Wildcard characters # generally do not work on IP addresses, though they may work by accident # when reverse DNS lookups fail. "host": StrRe("^(\S)*$"), # The options to be used for host Optional("options"): Default(StrRe("^(\S)*$"), default=""), AutoDel(str): object # for all other key we auto delete }) EXPORT_POINT_CONF_SCHEMA = Schema({ # export point name "name": Use(str), # absolute path "path": Use(str), # client list for this export point Optional("clients"): Default([EXPORT_CLIENT_CONF_SCHEMA],default=[]), AutoDel(str): object # for all other key we auto delete }) NFS_CONF_SCHEMA = Schema({ Optional("export_point_list"): Default([EXPORT_POINT_CONF_SCHEMA], default=[]), AutoDel(str): object # for all other key we auto delete })
MODULE_INFO = { "module_name": "mail", "rpms": ["mailx"], "comment": "Provides the support to send email by mailx utility" } MAIL_CONF_FILE_NAME = "mail_conf.yaml" MAIL_ETC_CONF_DIR = "/etc/" MAIL_ETC_CONF_FILE = "mail.rc" MAIL_CMD = "/bin/mail" MAIL_CONF_SCHEMA = Schema({ # the email address of user's account, it would also be place in the FROM header of the email Optional("email_addr"): Default(Use(str), default=""), # smtp server address to send the mail Optional("smtp_server"): Default(Use(str), default=""), # password for the account Optional("password"): Default(Use(str), default=""), AutoDel(str): object # for all other key we auto delete }) class MailManager(object): """contains all methods to manage NTP server in linux system"""
# they are used at all, is a function of the particular # clock driver. However, by convention flag4 is used to # enable recording monitoring data to the clockstats file # configured with the filegen command. Further information # on the filegen command can be found in Monitoring # Options. # Only valid for reference clock server, i.e. server_addr is 127.127.t.n Optional("flag1"): Default(IntVal(min=0, max=1), default=0), Optional("flag2"): Default(IntVal(min=0, max=1), default=0), Optional("flag3"): Default(IntVal(min=0, max=1), default=0), Optional("flag4"): Default(IntVal(min=0, max=1), default=0), DoNotCare(Use(str)): object # for all other key we don't care }]) @put_view(route_name='ntp_server_list') def put_ntp_server_list(request): ntp_mgr = ntpmgr.NtpManager new_server_list = get_params_from_request(request, ntp_server_list_schema) ntp_mgr.set_server_conf_list(new_server_list, operator=request.client_addr) return Response(status=200) @get_view(route_name='ntp_restrict_list') def get_ntp_restrict_list(request): ntp_mgr = ntpmgr.NtpManager
#/network/eth_list/{port_name}/stat @get_view(route_name='port_stat') def get_port_stat(request): port_name = request.matchdict['port_name'] eth_face = ifmgr.if_mgr() netif_info = eth_face.get_interface_by_name(port_name) stat_info = netif_info.statistic_info return stat_info port_mod_schema = Schema({ Optional("ip"): StrRe(r"^(|\d+\.\d+\.\d+\.\d+)$"), # ip addr Optional("netmask"): StrRe(r"^(|\d+\.\d+\.\d+\.\d+)$"), # netmask addr Optional("gateway"): StrRe(r"^(|\d+\.\d+\.\d+\.\d+)$"), # gateway addr DoNotCare(Use(str)): object # for all those key we don't care }) #curl -v -X PUT -d ip=192.168.0.222 -d gateway=192.168.1.1 -d netmask=255.255.0.0 http://192.168.1.123:6543/storlever/api/v1/network/eth_list/eth0 @put_view(route_name='single_port') def modify_single_port(request): port_info = get_params_from_request(request, port_mod_schema) port_name = request.matchdict['port_name'] eth_face = ifmgr.if_mgr() eth = eth_face.get_interface_by_name(port_name) eth.set_ip_config(ip=port_info.get("ip", None), netmask=port_info.get("netmask", None), gateway=port_info.get("gateway", None), user=request.client_addr) return Response(status=200)
import time import shutil import re import tarfile import os from storlever.lib.exception import StorLeverCmdError, StorLeverError from storlever.lib.command import check_output from storlever.lib.schema import Schema, Use, Optional, \ Default, DoNotCare, BoolVal, IntVal, AutoDel MODULE_CONF_SCHEMA = Schema({ "module_name": Use(str), Optional("rpms"): Default([Use(str)], default=[]), Optional("extra_files"): Default([Use(str)], default=[]), Optional("comment"): Default(Use(str), default=""), AutoDel(str): object # for all other key we auto delete }) RPM_CMD = "/bin/rpm" class ModuleManager(object): """contains all methods to manage the storlever cfg"""
vg_info = { 'name': vgs[vg].name, 'uuid': vgs[vg].uuid, 'size': vgs[vg].size, 'free_size': vgs[vg].free_size, } vg_dict.append(vg_info) return vg_dict new_vg_schema = Schema({ "vgname": StrRe(r"^([a-zA-Z].+)$"), "dev": Default(ListVal(StrRe(r"^(/dev/sd[a-z]|/dev/md.+)$")), default=[]), DoNotCare(Use(str)): object # for all those key we don't care }) #curl -v -X POST -d vgname=vg1 -d dev=/dev/sdb,/dev/sdc http://192.168.1.123:6543/storlever/api/v1/block/lvm/vg_list #enable eth* or disable eth* @post_view(route_name='vg_list') def create_vg(request): lvm_mng = lvm.lvm_mgr() params = get_params_from_request(request, new_vg_schema) vg = lvm_mng.new_vg(params['vgname'], params['dev']) if vg is None: return Response(status=500) else:
"module_name": "tgt", "rpms": [ "scsi-target-utils", ], "comment": "Provides the management functions for iscsi target server(tgt)" } LUN_CONF_SCHEMA = Schema({ # lun number "lun": IntVal(1, 255), # path to a regular file, or block device, or a sg char device "path": Use(str), # the type of device . Possible device-types are: # disk : emulate a disk device # tape : emulate a tape reader # ssc : same as tape # cd : emulate a DVD drive # changer : emulate a media changer device # pt : passthrough type to export a /dev/sg device Optional("device_type"): Default(Use(str), default="disk"), # the type of backend storage. Possible backend types are: # rdwr : Use normal file I/O. This is the default for disk devices # aio : Use Asynchronous I/O # sg : Special backend type for passthrough devices