Skip to main content
Glama
sharing.pyโ€ข5.64 kB
""" Sharing models for TrueNAS MCP Server """ from typing import Optional, List, Dict, Any from pydantic import Field, field_validator from .base import BaseModel class SMBShare(BaseModel): """SMB/CIFS share model""" id: int = Field(..., description="Share ID") name: str = Field(..., description="Share name") path: str = Field(..., description="Share path") comment: Optional[str] = Field("", description="Share comment") enabled: bool = Field(True, description="Share enabled status") ro: bool = Field(False, description="Read-only") browsable: bool = Field(True, description="Browsable in network neighborhood") guestok: bool = Field(False, description="Allow guest access") hostsallow: List[str] = Field(default_factory=list, description="Allowed hosts/networks") hostsdeny: List[str] = Field(default_factory=list, description="Denied hosts/networks") home: bool = Field(False, description="Home share") timemachine: bool = Field(False, description="Time Machine backup share") recyclebin: bool = Field(False, description="Enable recycle bin") shadowcopy: bool = Field(False, description="Enable shadow copies") audit: Dict[str, Any] = Field(default_factory=dict, description="Audit settings") @field_validator("path") def validate_path(cls, v): """Validate share path""" if not v.startswith("/mnt/"): raise ValueError("Share path must start with /mnt/") return v @field_validator("name") def validate_name(cls, v): """Validate share name""" import re if not re.match(r"^[a-zA-Z0-9][a-zA-Z0-9_.-]*$", v): raise ValueError("Share name must start with alphanumeric and contain only alphanumeric, underscore, dot, and hyphen") return v class NFSExport(BaseModel): """NFS export model""" id: int = Field(..., description="Export ID") path: str = Field(..., description="Export path") comment: Optional[str] = Field("", description="Export comment") enabled: bool = Field(True, description="Export enabled status") ro: bool = Field(False, description="Read-only") maproot_user: Optional[str] = Field("root", description="Map root user to") maproot_group: Optional[str] = Field("wheel", description="Map root group to") mapall_user: Optional[str] = Field(None, description="Map all users to") mapall_group: Optional[str] = Field(None, description="Map all groups to") networks: List[str] = Field(default_factory=list, description="Allowed networks") hosts: List[str] = Field(default_factory=list, description="Allowed hosts") alldirs: bool = Field(False, description="Allow mounting subdirectories") quiet: bool = Field(False, description="Suppress some warnings") security: List[str] = Field(default_factory=lambda: ["sys"], description="Security flavors") @field_validator("path") def validate_path(cls, v): """Validate export path""" if not v.startswith("/mnt/"): raise ValueError("Export path must start with /mnt/") return v @field_validator("networks") def validate_networks(cls, v): """Validate network format""" import re cidr_pattern = r"^(\d{1,3}\.){3}\d{1,3}/\d{1,2}$" for network in v: if network != "0.0.0.0/0" and not re.match(cidr_pattern, network): raise ValueError(f"Invalid network format: {network}") return v class ISCSITarget(BaseModel): """iSCSI target model""" id: int = Field(..., description="Target ID") name: str = Field(..., description="Target IQN") alias: Optional[str] = Field(None, description="Target alias") mode: str = Field("ISCSI", description="Target mode") groups: List[Dict[str, Any]] = Field(default_factory=list, description="Initiator groups") @field_validator("name") def validate_iqn(cls, v): """Validate IQN format""" import re iqn_pattern = r"^iqn\.\d{4}-\d{2}\.[a-z0-9.-]+:[a-z0-9.-]+$" if not re.match(iqn_pattern, v.lower()): raise ValueError(f"Invalid IQN format: {v}") return v class ISCSIExtent(BaseModel): """iSCSI extent (LUN) model""" id: int = Field(..., description="Extent ID") name: str = Field(..., description="Extent name") type: str = Field("DISK", description="Extent type (DISK or FILE)") disk: Optional[str] = Field(None, description="Disk/zvol path") path: Optional[str] = Field(None, description="File path") filesize: Optional[int] = Field(None, description="File size in bytes") blocksize: int = Field(512, description="Block size") pblocksize: bool = Field(False, description="Physical block size reporting") avail_threshold: Optional[int] = Field(None, description="Available threshold") comment: Optional[str] = Field("", description="Comment") enabled: bool = Field(True, description="Enabled status") ro: bool = Field(False, description="Read-only") rpm: str = Field("SSD", description="RPM type") @field_validator("blocksize") def validate_blocksize(cls, v): """Validate block size""" valid_sizes = [512, 1024, 2048, 4096] if v not in valid_sizes: raise ValueError(f"Invalid block size: {v}") return v @field_validator("rpm") def validate_rpm(cls, v): """Validate RPM type""" valid_rpms = ["UNKNOWN", "SSD", "5400", "7200", "10000", "15000"] if v not in valid_rpms: raise ValueError(f"Invalid RPM type: {v}") return v

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/vespo92/TrueNasCoreMCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server