summaryrefslogtreecommitdiffstats
path: root/src/ceph-volume/plugin/zfs/ceph_volume_zfs/zfs.py
blob: e9911c75ed242a1ef2749cea2de7d3d0eaf33d13 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# -*- coding: utf-8 -*-

from __future__ import print_function
import argparse
import os
import sys
import logging

from textwrap import dedent
from ceph_volume import log, conf, configuration
from ceph_volume import exceptions
from ceph_volume import terminal

# The ceph-volume-zfs specific code
import ceph_volume_zfs.zfs
from ceph_volume_zfs import devices
# from ceph_volume_zfs.util import device
from ceph_volume_zfs.devices import zfs

# the supported actions
from ceph_volume_zfs.devices.zfs import inventory
from ceph_volume_zfs.devices.zfs import prepare
from ceph_volume_zfs.devices.zfs import zap


if __name__ == '__main__':
    zfs.ZFS()


class ZFS(object):

    # help info for subcommands
    help = "Use ZFS as the underlying technology for OSDs"

    # help info for the plugin
    help_menu = "Deploy OSDs with ZFS"
    _help = dedent("""
        Use ZFS as the underlying technology for OSDs

        {sub_zfshelp}
    """)
    name = 'zfs'

    def __init__(self, argv=None, parse=True):
        self.zfs_mapper = {
            'inventory': inventory.Inventory,
            'prepare': prepare.Prepare,
            'zap': zap.Zap,
        }
        if argv is None:
            self.argv = sys.argv
        else:
            self.argv = argv
        if parse:
            self.main(self.argv)

    def print_help(self, warning=False):
        return self._help.format(
            sub_zfshelp=terminal.subhelp(self.zfs_mapper)
        )

    def get_environ_vars(self):
        environ_vars = []
        for key, value in os.environ.items():
            if key.startswith('CEPH_'):
                environ_vars.append("%s=%s" % (key, value))
        if not environ_vars:
            return ''
        else:
            environ_vars.insert(0, '\nEnviron Variables:')
            return '\n'.join(environ_vars)

    def load_ceph_conf_path(self, cluster_name='ceph'):
        abspath = '/etc/ceph/%s.conf' % cluster_name
        conf.path = os.getenv('CEPH_CONF', abspath)
        conf.cluster = cluster_name

    def stat_ceph_conf(self):
        try:
            configuration.load(conf.path)
            return terminal.green(conf.path)
        except exceptions.ConfigurationError as error:
            return terminal.red(error)

    def load_log_path(self):
        conf.log_path = os.getenv('CEPH_VOLUME_LOG_PATH', '/var/log/ceph')

    def _get_split_args(self):
        subcommands = self.zfs_mapper.keys()
        slice_on_index = len(self.argv)
        pruned_args = self.argv
        for count, arg in enumerate(pruned_args):
            if arg in subcommands:
                slice_on_index = count
                break
        return pruned_args[:slice_on_index], pruned_args[slice_on_index:]

    def main(self, argv=None):
        if argv is None:
            return
        self.load_ceph_conf_path()
        # these need to be available for the help, which gets parsed super
        # early
        self.load_ceph_conf_path()
        self.load_log_path()
        main_args, subcommand_args = self._get_split_args()
        # no flags where passed in, return the help menu instead of waiting for
        # argparse which will end up complaning that there are no args
        if len(argv) < 1:
            print(self.print_help(warning=True))
            return
        parser = argparse.ArgumentParser(
            prog='ceph-volume-zfs',
            formatter_class=argparse.RawDescriptionHelpFormatter,
            description=self.print_help(),
        )
        parser.add_argument(
            '--cluster',
            default='ceph',
            help='Cluster name (defaults to "ceph")',
        )
        parser.add_argument(
            '--log-level',
            default='debug',
            help='Change the file log level (defaults to debug)',
        )
        parser.add_argument(
            '--log-path',
            default='/var/log/ceph/',
            help='Change the log path (defaults to /var/log/ceph)',
        )
        args = parser.parse_args(main_args)
        conf.log_path = args.log_path
        if os.path.isdir(conf.log_path):
            conf.log_path = os.path.join(args.log_path, 'ceph-volume-zfs.log')
        log.setup()
        logger = logging.getLogger(__name__)
        logger.info("Running command: ceph-volume-zfs %s %s",
                    " ".join(main_args), " ".join(subcommand_args))
        # set all variables from args and load everything needed according to
        # them
        self.load_ceph_conf_path(cluster_name=args.cluster)
        try:
            conf.ceph = configuration.load(conf.path)
        except exceptions.ConfigurationError as error:
            # we warn only here, because it is possible that the configuration
            # file is not needed, or that it will be loaded by some other means
            # (like reading from zfs tags)
            logger.exception('ignoring inability to load ceph.conf')
            terminal.red(error)
        # dispatch to sub-commands
        terminal.dispatch(self.zfs_mapper, subcommand_args)