# Path: zoe_lib/state/service.py
# class VolumeDescriptionHostPath(VolumeDescription):
#     """Host-based volumes."""
#     def __init__(self, name: str, path: str, readonly: bool):
#         super().__init__("host_directory")
#         self.path = path
#         self.mount_point = '/mnt/' + name
#         self.readonly = readonly
# 
# Path: zoe_lib/state/user.py
# class User(BaseRecord):
#     """An user object describes a Zoe user."""
# 
#     def __init__(self, d, sql_manager):
#         super().__init__(d, sql_manager)
# 
#         self.username = d['username']
#         self.password = d['password']
#         self.fs_uid = d['fs_uid']
#         self.email = d['email']
#         self.priority = d['priority']
#         self.enabled = d['enabled']
#         self.auth_source = d['auth_source']
#         self.role_id = d['role_id']
#         self.quota_id = d['quota_id']
# 
#         if self.auth_source == "pam":
#             try:
#                 self.fs_uid = pwd.getpwnam(self.username).pw_uid
#             except KeyError:
#                 self.fs_uid = d['fs_uid']
# 
#     def serialize(self):
#         """Generates a dictionary that can be serialized in JSON."""
#         return {
#             'id': self.id,
#             'username': self.username,
#             'fs_uid': self.fs_uid,
#             'email': self.email,
#             'priority': self.priority,
#             'enabled': self.enabled,
#             'auth_source': self.auth_source,
#             'quota_id': self.quota_id,
#             'role_id': self.role_id
#         }
# 
#     def set_email(self, new_email: str):
#         """Update the email address for this user."""
#         self.email = new_email
#         self.sql_manager.user.update(self.id, email=new_email)
# 
#     def set_password(self, new_password: str):
#         """Update the password."""
#         hashed_password = hash_algo.hash(new_password)
#         self.password = hashed_password
#         self.sql_manager.user.update(self.id, password=hashed_password)
# 
#     def check_password(self, candidate_pw: str) -> bool:
#         """Checks if the password is correct."""
#         if self.auth_source != "internal" or self.password is None:
#             return False
#         return hash_algo.verify(candidate_pw, self.password)
# 
#     def set_priority(self, new_priority: int):
#         """Update the priority for this user."""
#         self.priority = new_priority
#         self.sql_manager.user.update(self.id, priority=new_priority)
# 
#     def set_enabled(self, enable: bool):
#         """Enable or disable a user."""
#         self.enabled = enable
#         self.sql_manager.user.update(self.id, enabled=enable)
# 
#     def set_quota_id(self, quota_id):
#         """Set a different quota for this user."""
#         self.quota_id = quota_id
#         self.sql_manager.user.update(self.id, quota_id=quota_id)
# 
#     def set_role_id(self, role_id):
#         """Set a new role for this user."""
#         self.role_id = role_id
#         self.sql_manager.user.update(self.id, role_id=role_id)
# 
#     @property
#     def role(self):
#         """Get the role from the DB."""
#         return self.sql_manager.role.select(only_one=True, id=self.role_id)
# 
#     @property
#     def quota(self):
#         """Get the quota for this user."""
#         return self.sql_manager.quota.select(only_one=True, id=self.quota_id)
# 
#     def __repr__(self):
#         return self.username
# 
#     def __eq__(self, other):
#         if isinstance(other, User):
#             return self.id == other.id
#         else:
#             return False


import logging
import os
import zoe_lib.config
import zoe_master.workspace.base
from zoe_lib.state import VolumeDescriptionHostPath, User
class ZoeFSWorkspace(zoe_master.workspace.base.ZoeWorkspaceBase):
    """Filesystem workspace class."""
    def __init__(self):
        self.base_path = os.path.join(zoe_lib.config.get_conf().workspace_base_path, zoe_lib.config.get_conf().workspace_deployment_path)

    def exists(self, username):
        """Check if the workspace for user_id exists."""
        return os.path.exists(os.path.join(self.base_path, username))

    def get_path(self, username):
        """Get the volume path of the workspace."""
        return os.path.join(self.base_path, username)

    @classmethod
    def can_be_attached(cls):
        """Check if this workspace can be mounted as a Docker volume"""
        return True

    @classmethod
    def get_mountpoint(cls):
        """Get the volume mount point."""
        return 'workspace'

    def get(self, user: User):
        """Return a VolumeDescription for the user workspace."""
        if not self.exists(user.username):
            log.warning("Workspace for user {} does not exist".format(user.username))
        else:
            if os.stat(self.get_path(user.username)).st_uid != user.fs_uid:
                log.warning('The user fs_uid in the database does not match the workspace owner for user {}'.format(user.username))

# Path: zoe_lib/state/service.py
# class VolumeDescriptionHostPath(VolumeDescription):
#     """Host-based volumes."""
#     def __init__(self, name: str, path: str, readonly: bool):
#         super().__init__("host_directory")
#         self.path = path
#         self.mount_point = '/mnt/' + name
#         self.readonly = readonly
# 
# Path: zoe_lib/state/user.py
# class User(BaseRecord):
#     """An user object describes a Zoe user."""
# 
#     def __init__(self, d, sql_manager):
#         super().__init__(d, sql_manager)
# 
#         self.username = d['username']
#         self.password = d['password']
#         self.fs_uid = d['fs_uid']
#         self.email = d['email']
#         self.priority = d['priority']
#         self.enabled = d['enabled']
#         self.auth_source = d['auth_source']
#         self.role_id = d['role_id']
#         self.quota_id = d['quota_id']
# 
#         if self.auth_source == "pam":
#             try:
#                 self.fs_uid = pwd.getpwnam(self.username).pw_uid
#             except KeyError:
#                 self.fs_uid = d['fs_uid']
# 
#     def serialize(self):
#         """Generates a dictionary that can be serialized in JSON."""
#         return {
#             'id': self.id,
#             'username': self.username,
#             'fs_uid': self.fs_uid,
#             'email': self.email,
#             'priority': self.priority,
#             'enabled': self.enabled,
#             'auth_source': self.auth_source,
#             'quota_id': self.quota_id,
#             'role_id': self.role_id
#         }
# 
#     def set_email(self, new_email: str):
#         """Update the email address for this user."""
#         self.email = new_email
#         self.sql_manager.user.update(self.id, email=new_email)
# 
#     def set_password(self, new_password: str):
#         """Update the password."""
#         hashed_password = hash_algo.hash(new_password)
#         self.password = hashed_password
#         self.sql_manager.user.update(self.id, password=hashed_password)
# 
#     def check_password(self, candidate_pw: str) -> bool:
#         """Checks if the password is correct."""
#         if self.auth_source != "internal" or self.password is None:
#             return False
#         return hash_algo.verify(candidate_pw, self.password)
# 
#     def set_priority(self, new_priority: int):
#         """Update the priority for this user."""
#         self.priority = new_priority
#         self.sql_manager.user.update(self.id, priority=new_priority)
# 
#     def set_enabled(self, enable: bool):
#         """Enable or disable a user."""
#         self.enabled = enable
#         self.sql_manager.user.update(self.id, enabled=enable)
# 
#     def set_quota_id(self, quota_id):
#         """Set a different quota for this user."""
#         self.quota_id = quota_id
#         self.sql_manager.user.update(self.id, quota_id=quota_id)
# 
#     def set_role_id(self, role_id):
#         """Set a new role for this user."""
#         self.role_id = role_id
#         self.sql_manager.user.update(self.id, role_id=role_id)
# 
#     @property
#     def role(self):
#         """Get the role from the DB."""
#         return self.sql_manager.role.select(only_one=True, id=self.role_id)
# 
#     @property
#     def quota(self):
#         """Get the quota for this user."""
#         return self.sql_manager.quota.select(only_one=True, id=self.quota_id)
# 
#     def __repr__(self):
#         return self.username
# 
#     def __eq__(self, other):
#         if isinstance(other, User):
#             return self.id == other.id
#         else:
#             return False


# Path: zoe_master/workspace/filesystem.py
import logging
import os
import zoe_lib.config
import zoe_master.workspace.base
from zoe_lib.state import VolumeDescriptionHostPath, User

class ZoeFSWorkspace(zoe_master.workspace.base.ZoeWorkspaceBase):
    """Filesystem workspace class."""
    def __init__(self):
        self.base_path = os.path.join(zoe_lib.config.get_conf().workspace_base_path, zoe_lib.config.get_conf().workspace_deployment_path)

    def exists(self, username):
        """Check if the workspace for user_id exists."""
        return os.path.exists(os.path.join(self.base_path, username))

    def get_path(self, username):
        """Get the volume path of the workspace."""
        return os.path.join(self.base_path, username)

    @classmethod
    def can_be_attached(cls):
        """Check if this workspace can be mounted as a Docker volume"""
        return True

    @classmethod
    def get_mountpoint(cls):
        """Get the volume mount point."""
        return 'workspace'

    def get(self, user: User):
        """Return a VolumeDescription for the user workspace."""
        if not self.exists(user.username):
            log.warning("Workspace for user {} does not exist".format(user.username))
        else:
            if os.stat(self.get_path(user.username)).st_uid != user.fs_uid:
                log.warning('The user fs_uid in the database does not match the workspace owner for user {}'.format(user.username))

        return VolumeDescriptionHostPath(path=self.get_path(user.username), name=self.get_mountpoint(), readonly=False)