ccmlib/cmds/command.py (102 lines of code) (raw):

# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import absolute_import import os import sys from optparse import BadOptionError, Option, OptionParser import re from six import print_ import ccmlib from ccmlib import common from ccmlib.cluster_factory import ClusterFactory from ccmlib.remote import PARAMIKO_IS_AVAILABLE, get_remote_usage # This is fairly fragile, but handy for now class ForgivingParser(OptionParser): def __init__(self, usage=None, option_list=None, option_class=Option, version=None, conflict_handler="error", description=None, formatter=None, add_help_option=True, prog=None, epilog=None): OptionParser.__init__(self, usage, option_list, option_class, version, conflict_handler, description, formatter, add_help_option, prog, epilog) self.ignored = [] def _process_short_opts(self, rargs, values): opt = rargs[0] try: OptionParser._process_short_opts(self, rargs, values) except BadOptionError: self.ignored.append(opt) self.eat_args(rargs) def _process_long_opt(self, rargs, values): opt = rargs[0] try: OptionParser._process_long_opt(self, rargs, values) except BadOptionError: self.ignored.append(opt) self.eat_args(rargs) def eat_args(self, rargs): while len(rargs) > 0 and rargs[0][0] != '-': self.ignored.append(rargs.pop(0)) def get_ignored(self): return self.ignored class Cmd(object): options_list = [] usage = "" descr_text = "" ignore_unknown_options = False def get_parser(self): if self.usage == "": pass # Do not collapse to PARAMIKO_IS_AVAILABLE, we need to pull it dynamically for testing purposes if ccmlib.remote.PARAMIKO_IS_AVAILABLE: self.usage = self.usage.replace("usage: ccm", "usage: ccm [remote_options]") + \ os.linesep + os.linesep + \ get_remote_usage() parser = self._get_default_parser(self.usage, self.description(), self.ignore_unknown_options) for args, kwargs in self.options_list: parser.add_option(*args, **kwargs) return parser def validate(self, parser, options, args, cluster_name=False, node_name=False, load_cluster=False, load_node=True): self.options = options self.args = args if options.config_dir is None: self.path = common.get_default_path() else: self.path = options.config_dir if cluster_name: if len(args) == 0: print_('Missing cluster name', file=sys.stderr) parser.print_help() exit(1) if not re.match('^[a-zA-Z0-9_-]+$', args[0]): print_('Cluster name should only contain word characters or hyphen', file=sys.stderr) exit(1) self.name = args[0] if node_name: if len(args) == 0: print_('Missing node name', file=sys.stderr) parser.print_help() exit(1) self.name = args[0] if load_cluster: self.cluster = self._load_current_cluster() if node_name and load_node: try: self.node = self.cluster.nodes[self.name] except KeyError: print_('Unknown node %s in cluster %s' % (self.name, self.cluster.name), file=sys.stderr) exit(1) def run(self): pass def _get_default_parser(self, usage, description, ignore_unknown_options=False): if ignore_unknown_options: parser = ForgivingParser(usage=usage, description=description) else: parser = OptionParser(usage=usage, description=description) parser.add_option('--config-dir', type="string", dest="config_dir", help="Directory for the cluster files [default to {0}]".format(common.get_default_path_display_name())) return parser def description(self): return self.descr_text def _load_current_cluster(self): name = common.current_cluster_name(self.path) if name is None: print_('No currently active cluster (use ccm cluster switch)') exit(1) try: return ClusterFactory.load(self.path, name) except common.LoadError as e: print_(str(e)) exit(1)