Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / ceph-volume / ceph_volume / main.py
1 from __future__ import print_function
2 import argparse
3 import os
4 import pkg_resources
5 import sys
6 import logging
7
8 import ceph_volume
9 from ceph_volume.decorators import catches
10 from ceph_volume import log, devices, configuration, conf, exceptions, terminal
11
12
13 class Volume(object):
14     _help = """
15 ceph-volume: Deploy Ceph OSDs using different device technologies like lvm or
16 physical disks.
17
18 Version: {version}
19
20 Log Path: {log_path}
21 Ceph Conf: {ceph_path}
22
23 {sub_help}
24 {plugins}
25 {environ_vars}
26 {warning}
27     """
28
29     def __init__(self, argv=None, parse=True):
30         self.mapper = {'lvm': devices.lvm.LVM, 'simple': devices.simple.Simple}
31         self.plugin_help = "No plugins found/loaded"
32         if argv is None:
33             self.argv = sys.argv
34         else:
35             self.argv = argv
36         if parse:
37             self.main(self.argv)
38
39     def help(self, warning=False):
40         warning = 'See "ceph-volume --help" for full list of options.' if warning else ''
41         return self._help.format(
42             warning=warning,
43             version=ceph_volume.__version__,
44             log_path=conf.log_path,
45             ceph_path=self.stat_ceph_conf(),
46             plugins=self.plugin_help,
47             sub_help=terminal.subhelp(self.mapper),
48             environ_vars=self.get_environ_vars()
49         )
50
51     def get_environ_vars(self):
52         environ_vars = []
53         for key, value in os.environ.items():
54             if key.startswith('CEPH_'):
55                 environ_vars.append("%s=%s" % (key, value))
56         if not environ_vars:
57             return ''
58         else:
59             environ_vars.insert(0, '\nEnviron Variables:')
60             return '\n'.join(environ_vars)
61
62     def enable_plugins(self):
63         """
64         Load all plugins available, add them to the mapper and extend the help
65         string with the information from each one
66         """
67         plugins = _load_library_extensions()
68         for plugin in plugins:
69             self.mapper[plugin._ceph_volume_name_] = plugin
70         self.plugin_help = '\n'.join(['%-19s %s\n' % (
71             plugin.name, getattr(plugin, 'help_menu', ''))
72             for plugin in plugins])
73         if self.plugin_help:
74             self.plugin_help = '\nPlugins:\n' + self.plugin_help
75
76     def load_ceph_conf_path(self, cluster_name='ceph'):
77         abspath = '/etc/ceph/%s.conf' % cluster_name
78         conf.path = os.getenv('CEPH_CONF', abspath)
79         conf.cluster = cluster_name
80
81     def load_log_path(self):
82         conf.log_path = os.getenv('CEPH_VOLUME_LOG_PATH', '/var/log/ceph')
83
84     def stat_ceph_conf(self):
85         try:
86             configuration.load(conf.path)
87             return terminal.green(conf.path)
88         except exceptions.ConfigurationError as error:
89             return terminal.red(error)
90
91     def _get_split_args(self):
92         subcommands = self.mapper.keys()
93         slice_on_index = len(self.argv) + 1
94         pruned_args = self.argv[1:]
95         for count, arg in enumerate(pruned_args):
96             if arg in subcommands:
97                 slice_on_index = count
98                 break
99         return pruned_args[:slice_on_index], pruned_args[slice_on_index:]
100
101     @catches()
102     def main(self, argv):
103         # these need to be available for the help, which gets parsed super
104         # early
105         self.load_ceph_conf_path()
106         self.load_log_path()
107         self.enable_plugins()
108         main_args, subcommand_args = self._get_split_args()
109         # no flags where passed in, return the help menu instead of waiting for
110         # argparse which will end up complaning that there are no args
111         if len(argv) <= 1:
112             print(self.help(warning=True))
113             return
114         parser = argparse.ArgumentParser(
115             prog='ceph-volume',
116             formatter_class=argparse.RawDescriptionHelpFormatter,
117             description=self.help(),
118         )
119         parser.add_argument(
120             '--cluster',
121             default='ceph',
122             help='Cluster name (defaults to "ceph")',
123         )
124         parser.add_argument(
125             '--log-level',
126             default='debug',
127             help='Change the file log level (defaults to debug)',
128         )
129         parser.add_argument(
130             '--log-path',
131             default='/var/log/ceph/',
132             help='Change the log path (defaults to /var/log/ceph)',
133         )
134         args = parser.parse_args(main_args)
135         conf.log_path = args.log_path
136         if os.path.isdir(conf.log_path):
137             conf.log_path = os.path.join(args.log_path, 'ceph-volume.log')
138         log.setup()
139         logger = logging.getLogger(__name__)
140         # set all variables from args and load everything needed according to
141         # them
142         self.load_ceph_conf_path(cluster_name=args.cluster)
143         try:
144             conf.ceph = configuration.load(conf.path)
145         except exceptions.ConfigurationError as error:
146             # we warn only here, because it is possible that the configuration
147             # file is not needed, or that it will be loaded by some other means
148             # (like reading from lvm tags)
149             logger.exception('ignoring inability to load ceph.conf')
150             terminal.red(error)
151         # dispatch to sub-commands
152         terminal.dispatch(self.mapper, subcommand_args)
153
154
155 def _load_library_extensions():
156     """
157     Locate all setuptools entry points by the name 'ceph_volume_handlers'
158     and initialize them.
159     Any third-party library may register an entry point by adding the
160     following to their setup.py::
161
162         entry_points = {
163             'ceph_volume_handlers': [
164                 'plugin_name = mylib.mymodule:Handler_Class',
165             ],
166         },
167
168     `plugin_name` will be used to load it as a sub command.
169     """
170     logger = logging.getLogger('ceph_volume.plugins')
171     group = 'ceph_volume_handlers'
172     entry_points = pkg_resources.iter_entry_points(group=group)
173     plugins = []
174     for ep in entry_points:
175         try:
176             logger.debug('loading %s' % ep.name)
177             plugin = ep.load()
178             plugin._ceph_volume_name_ = ep.name
179             plugins.append(plugin)
180         except Exception as error:
181             logger.exception("Error initializing plugin %s: %s" % (ep, error))
182     return plugins