# Path: nasman/snapshots/forms.py
# class SnapshotForm(forms.Form):
#     name = forms.CharField(
#         label='Snapshot name',
#         max_length=120,
#         required=True,
#         widget=BootstrapTextWidget,
#     )
#     filesystem = forms.TypedChoiceField(
#         label='Parent filesystem',
#         choices=filesystem_choices,
#         widget=BootstrapSelectWidget,
#     )
#     recursive = forms.BooleanField(
#         label='Recurse filesystems?',
#         widget=BootstrapCheckboxWidget,
#         required=False,
#     )
# 
# Path: nasman/snapshots/views/base.py
# class BaseView(SetHeadlineMixin):
#     pass
# 
# Path: nasman/snapshots/utils/zfs.py
# class ZFSUtil(BaseUtil):
#     """
#     Helper utility for accessing ZFS features
#     """
# 
#     @classmethod
#     def get_filesystems(cls):
#         """
#         Gets a list of filesystems
#         :return: A list of `ZFSFilesystem` objects
#         :rtype: list
#         """
#         parsed = _parse_cmd_output(
#             ['zfs', 'list', '-Hp', '-tfilesystem', '-oname,mountpoint']
#         )
#         if parsed is None:
#             return None
#         filesystems = []
#         for fs in parsed:
#             filesystems.append(
#                 ZFSFilesystem(
#                     fs[0],
#                     fs[1]
#                 )
#             )
#         return filesystems
# 
#     @classmethod
#     def get_snapshots(cls, refresh=False):
#         """
#         Gets a list of snapshots
#         :return: A list of `ZFSSnapshot`
#         :rtype: list
#         """
#         cached = cache.get('zfs-snapshots')
#         if not refresh and cached is not None:
#             logger.info('Returning cached list')
#             return cached
#         parsed = _parse_cmd_output(
#             ['zfs', 'list', '-Hp', '-tsnap', '-oname,creation']
#         )
#         if parsed is None:
#             return None
#         snaps = []
#         for snap in parsed:
#             ts = datetime.fromtimestamp(int(snap[1]))
#             ts = pytz.timezone(cls.timezone_name).localize(ts)
#             snaps.append(
#                 ZFSSnapshot(
#                     snap[0],
#                     ts
#                 )
#             )
#         cache.set('zfs-snapshots', snaps, 43200)
#         logger.info('Refreshed list of snapshots {}'.format(snaps))
#         return snaps
# 
#     @classmethod
#     def get_filesystem(cls, fs_name):
#         """
#         Gets a filesystem by name
#         :param fs_name: Name of the filesystem to get
#         :type fs_name: basestring
#         :return: A `ZFSFilesystem`
#         :rtype: `nasman.snapshots.zfs.ZFSFilesystem`
#         """
#         parsed = _parse_cmd_output(
#             ['zfs',
#              'list',
#              '-Hp',
#              '-tfilesystem',
#              '-oname,mountpoint',
#              fs_name]
#         )
#         if parsed is None:
#             return None
#         return ZFSFilesystem(parsed[0][0], parsed[0][1])
# 
#     @classmethod
#     def get_snapshot(cls, snap_name):
#         """
#         Gets a snapshot by name
#         :param snap_name: Name of the snapshot to get
#         :type snap_name: basestring
#         :return: A `ZFSSnapshot`
#         :rtype: `nasman.snapshots.zfs.ZFSSnapshot`
#         """
#         parsed = _parse_cmd_output(
#             ['zfs',
#              'list',
#              '-Hp',
#              '-tsnap',
#              '-oname,creation',
#              snap_name]
#         )
#         if parsed is None:
#             return None
#         return ZFSSnapshot(parsed[0][0], parsed[0][1])
# 
#     @classmethod
#     def create_snapshot(cls, snap_name, fs_name, recurse):
#         """
#         Creates a snapshot
#         :param snap_name: Name of the snapshot to create
#         :type snap_name: str
#         :param fs_name: Name of the filesystem to take snapshot of
#         :type fs_name: str
#         :param recurse: Whether to recurse filesystems
#         :type recurse: bool
#         :return: The snapshot just created
#         :rtype: `nasman.snapshots.zfs.ZFSSnapshot`
#         """
#         cache.delete('zfs-snapshots')
#         full_name = '{0}@{1}'.format(
#             fs_name,
#             snap_name
#         )
#         cmd = ['zfs',
#                'snapshot',
#                full_name
#                ]
#         if recurse:
#             cmd.append('-r')
#         parsed = _parse_cmd_output(cmd)
#         if parsed is None:
#             return None
#         return cls.get_snapshot(full_name)


import logging
from subprocess import CalledProcessError
from braces.views import MessageMixin, JSONResponseMixin, AjaxResponseMixin
from django.contrib.humanize.templatetags.humanize import naturaltime
from django.core.urlresolvers import reverse_lazy
from django.shortcuts import redirect
from django.views.generic import View
from vanilla import FormView, ListView
from ..forms import SnapshotForm
from .base import BaseView
from .. import tasks
from ..utils.zfs import ZFSUtil

logger = logging.getLogger(__name__)


class SnapshotCreate(MessageMixin, BaseView, FormView):
    headline = 'Create new snapshot'
    form_class = SnapshotForm
    template_name = 'snapshot_form.html'
    success_url = reverse_lazy('nasman:snapshots')

    def form_valid(self, form):
        snap_name = form.cleaned_data['name']
        fs_name = form.cleaned_data['filesystem']
        recurse = form.cleaned_data['recursive']
        try:
            ZFSUtil.create_snapshot(snap_name, fs_name, recurse)
        except CalledProcessError as e:
            self.messages.error(
                '{1}'.format(
                    snap_name,
                    str(e.output.decode('utf-8'))
                ).capitalize(),
                extra_tags='ban'
            )
        else:
            self.messages.info(
                'Created {0}'.format(form.cleaned_data['name'])
            )
        return super(SnapshotCreate, self).form_valid(form)


# Path: nasman/snapshots/forms.py
# class SnapshotForm(forms.Form):
#     name = forms.CharField(
#         label='Snapshot name',
#         max_length=120,
#         required=True,
#         widget=BootstrapTextWidget,
#     )
#     filesystem = forms.TypedChoiceField(
#         label='Parent filesystem',
#         choices=filesystem_choices,
#         widget=BootstrapSelectWidget,
#     )
#     recursive = forms.BooleanField(
#         label='Recurse filesystems?',
#         widget=BootstrapCheckboxWidget,
#         required=False,
#     )
# 
# Path: nasman/snapshots/views/base.py
# class BaseView(SetHeadlineMixin):
#     pass
# 
# Path: nasman/snapshots/utils/zfs.py
# class ZFSUtil(BaseUtil):
#     """
#     Helper utility for accessing ZFS features
#     """
# 
#     @classmethod
#     def get_filesystems(cls):
#         """
#         Gets a list of filesystems
#         :return: A list of `ZFSFilesystem` objects
#         :rtype: list
#         """
#         parsed = _parse_cmd_output(
#             ['zfs', 'list', '-Hp', '-tfilesystem', '-oname,mountpoint']
#         )
#         if parsed is None:
#             return None
#         filesystems = []
#         for fs in parsed:
#             filesystems.append(
#                 ZFSFilesystem(
#                     fs[0],
#                     fs[1]
#                 )
#             )
#         return filesystems
# 
#     @classmethod
#     def get_snapshots(cls, refresh=False):
#         """
#         Gets a list of snapshots
#         :return: A list of `ZFSSnapshot`
#         :rtype: list
#         """
#         cached = cache.get('zfs-snapshots')
#         if not refresh and cached is not None:
#             logger.info('Returning cached list')
#             return cached
#         parsed = _parse_cmd_output(
#             ['zfs', 'list', '-Hp', '-tsnap', '-oname,creation']
#         )
#         if parsed is None:
#             return None
#         snaps = []
#         for snap in parsed:
#             ts = datetime.fromtimestamp(int(snap[1]))
#             ts = pytz.timezone(cls.timezone_name).localize(ts)
#             snaps.append(
#                 ZFSSnapshot(
#                     snap[0],
#                     ts
#                 )
#             )
#         cache.set('zfs-snapshots', snaps, 43200)
#         logger.info('Refreshed list of snapshots {}'.format(snaps))
#         return snaps
# 
#     @classmethod
#     def get_filesystem(cls, fs_name):
#         """
#         Gets a filesystem by name
#         :param fs_name: Name of the filesystem to get
#         :type fs_name: basestring
#         :return: A `ZFSFilesystem`
#         :rtype: `nasman.snapshots.zfs.ZFSFilesystem`
#         """
#         parsed = _parse_cmd_output(
#             ['zfs',
#              'list',
#              '-Hp',
#              '-tfilesystem',
#              '-oname,mountpoint',
#              fs_name]
#         )
#         if parsed is None:
#             return None
#         return ZFSFilesystem(parsed[0][0], parsed[0][1])
# 
#     @classmethod
#     def get_snapshot(cls, snap_name):
#         """
#         Gets a snapshot by name
#         :param snap_name: Name of the snapshot to get
#         :type snap_name: basestring
#         :return: A `ZFSSnapshot`
#         :rtype: `nasman.snapshots.zfs.ZFSSnapshot`
#         """
#         parsed = _parse_cmd_output(
#             ['zfs',
#              'list',
#              '-Hp',
#              '-tsnap',
#              '-oname,creation',
#              snap_name]
#         )
#         if parsed is None:
#             return None
#         return ZFSSnapshot(parsed[0][0], parsed[0][1])
# 
#     @classmethod
#     def create_snapshot(cls, snap_name, fs_name, recurse):
#         """
#         Creates a snapshot
#         :param snap_name: Name of the snapshot to create
#         :type snap_name: str
#         :param fs_name: Name of the filesystem to take snapshot of
#         :type fs_name: str
#         :param recurse: Whether to recurse filesystems
#         :type recurse: bool
#         :return: The snapshot just created
#         :rtype: `nasman.snapshots.zfs.ZFSSnapshot`
#         """
#         cache.delete('zfs-snapshots')
#         full_name = '{0}@{1}'.format(
#             fs_name,
#             snap_name
#         )
#         cmd = ['zfs',
#                'snapshot',
#                full_name
#                ]
#         if recurse:
#             cmd.append('-r')
#         parsed = _parse_cmd_output(cmd)
#         if parsed is None:
#             return None
#         return cls.get_snapshot(full_name)


# Path: nasman/snapshots/views/snapshots.py
import logging
from subprocess import CalledProcessError
from braces.views import MessageMixin, JSONResponseMixin, AjaxResponseMixin
from django.contrib.humanize.templatetags.humanize import naturaltime
from django.core.urlresolvers import reverse_lazy
from django.shortcuts import redirect
from django.views.generic import View
from vanilla import FormView, ListView
from ..forms import SnapshotForm
from .base import BaseView
from .. import tasks
from ..utils.zfs import ZFSUtil


logger = logging.getLogger(__name__)


class SnapshotCreate(MessageMixin, BaseView, FormView):
    headline = 'Create new snapshot'
    form_class = SnapshotForm
    template_name = 'snapshot_form.html'
    success_url = reverse_lazy('nasman:snapshots')

    def form_valid(self, form):
        snap_name = form.cleaned_data['name']
        fs_name = form.cleaned_data['filesystem']
        recurse = form.cleaned_data['recursive']
        try:
            ZFSUtil.create_snapshot(snap_name, fs_name, recurse)
        except CalledProcessError as e:
            self.messages.error(
                '{1}'.format(
                    snap_name,
                    str(e.output.decode('utf-8'))
                ).capitalize(),
                extra_tags='ban'
            )
        else:
            self.messages.info(
                'Created {0}'.format(form.cleaned_data['name'])
            )
        return super(SnapshotCreate, self).form_valid(form)


class SnapshotList(JSONResponseMixin, AjaxResponseMixin, BaseView, ListView):