def init(self): self.vendordb = VendorDB() self.vendordb.init() parser = OptionParser() parser.add_option("-c", "--controller", dest="controller", help="set default controller to CONTROLLER", metavar="CONTROLLER", default=self.controller) (options, args) = parser.parse_args() self.controller = options.controller if not self.controller: self.controller = "127.0.0.1:8000" if not sys.stdin.isatty(): self.batch = True self.init_obj_type_info_dict() self.pp = PrettyPrinter(self.obj_type_info_dict) self.store = StoreClient() self.store.set_controller(self.controller)
class Validate(): # initialize in init_obj_type_info obj_type_info_dict = {} # see init_obj_type_info_dict obj_types = [] obj_keys = {} known_controllers = ["127.0.0.1:8000"] controller = None # LOOK! manage this separately until we can for sure talk to eth0 addr instead of 127.0.0.1 controller_for_prompt = "127.0.0.1:8000" cluster = "default" run = True # Cached options for last completion last_line = None last_options = None # Are we running in batch mode, i.e. "cat commands | cli.py" batch = False # used for parsing as an arg local_name_pattern = "localhost://([A-Za-z0-9_:@\-\.\/]+$)" # contained objects pp = None store = None model_handler = None # # -------------------------------------------------------------------------------- # init_obj_type_info_dict # # Builds the init_obj_type_info_dict, which is a dictionary indexed by # the current mode, which also results in a dictionary, then indexed # by a either a 'field' or 'field_ordering' key. # # When init_obj_type_info_dict is indexed by the table/model name, the # value is a dictionary. That dictionary has several keys: # - 'fields' # - 'field_orderings' # # The 'fields' indexed result returns a dictionary, each of which # is indexed by the names of the fields within the table/model. further # indicies describe details about that field within the table: # - 'formatter' desscribes the prettyPrinter function for that field # - 'primary_key' identifes this field as the key for the table/model. # - 'verbose_name' identfies an additonal name for the field, inteneded # to be more descriptive # - 'has_rest_model' True/False # - 'json_serialize_string' True/False # - 'help_text' String providing more clues about the intent of this field # # The 'field_ordering' dictionary associated with the name of the table/model # is used to order the output. # # Also populates the self.obj_keys[], which is a dictionary mapping the table/model # name to the name of the storage key (table/model's column) for that table. # def init_obj_type_info_dict(self): self.cli_model_info = CliModelInfo() self.obj_type_info_dict = self.cli_model_info.get_complete_obj_type_info_dict() self.obj_types = [k for (k,v) in self.obj_type_info_dict.items() if 'has_rest_model' in v] for (k,d) in self.obj_type_info_dict.items(): candidate_keys = [f for f in d['fields'].keys() if d['fields'][f].get('primary_key', False)] if len(candidate_keys) > 0: self.obj_keys[k] = candidate_keys[0] # # -------------------------------------------------------------------------------- # make_unit_formatter # def make_unit_formatter(self, units): return lambda x,y: '%s %s' % (x, units) # # -------------------------------------------------------------------------------- # init_obj_type_info_dict # # Builds the init_obj_type_info_dict, which is a dictionary indexed by # the current mode, which also results in a dictionary, then indexed # by a either a 'field' or 'field_ordering' key. # # When init_obj_type_info_dict is indexed by the table/model name, the # value is a dictionary. That dictionary has several keys: # - 'fields' # - 'field_orderings' # # The 'fields' indexed result returns a dictionary, each of which # is indexed by the names of the fields within the table/model. further # indicies describe details about that field within the table: # - 'formatter' desscribes the prettyPrinter function for that field # - 'primary_key' identifes this field as the key for the table/model. # - 'verbose_name' identfies an additonal name for the field, inteneded # to be more descriptive # - 'has_rest_model' True/False # - 'json_serialize_string' True/False # - 'help_text' String providing more clues about the intent of this field # # The 'field_ordering' dictionary associated with the name of the table/model # is used to order the output. # # Also populates the self.obj_keys[], which is a dictionary mapping the table/model # name to the name of the storage key (table/model's column) for that table. # def init_obj_type_info_dict(self): self.cli_model_info = CliModelInfo() self.obj_type_info_dict = self.cli_model_info.get_complete_obj_type_info_dict() self.obj_types = [k for (k,v) in self.obj_type_info_dict.items() if 'has_rest_model' in v] for (k,d) in self.obj_type_info_dict.items(): candidate_keys = [f for f in d['fields'].keys() if d['fields'][f].get('primary_key', False)] if len(candidate_keys) > 0: self.obj_keys[k] = candidate_keys[0] # # -------------------------------------------------------------------------------- # init # def init(self): self.vendordb = VendorDB() self.vendordb.init() parser = OptionParser() parser.add_option("-c", "--controller", dest="controller", help="set default controller to CONTROLLER", metavar="CONTROLLER", default=self.controller) (options, args) = parser.parse_args() self.controller = options.controller if not self.controller: self.controller = "127.0.0.1:8000" if not sys.stdin.isatty(): self.batch = True self.init_obj_type_info_dict() self.pp = PrettyPrinter(self.obj_type_info_dict) self.store = StoreClient() self.store.set_controller(self.controller) # # -------------------------------------------------------------------------------- # parse_optional_parameters # def parse_optional_parameters(self, params, words): parsed = {} i = 0 while i < len(words): word = words[i] possible = [x for x in params if x.startswith(word)] if len(possible) == 0: raise ParamException('unknown option: %s' % word) elif len(possible) > 1: raise ParamException('ambiguous option: %s\n%s' % (word, "\n".join(possible))) else: param_name = possible[0] param = params[param_name] if (param['type'] == 'flag'): parsed[param_name] = True else: if i+1 < len(words): argument = words[i+1] if (param['type'] == 'string'): parsed[param_name] = argument elif (param['type'] == 'int'): try: parsed[param_name] = int(argument) except ValueError: raise ParamException('option %s requires ' + 'integer argument' % word) elif (param['type'] == 'enum'): arg_possible = [x for x in param['values'] if x.startswith(argument)] if (len(arg_possible) == 0): raise ParamException('option %s value must be in (%s)' % (word,", ".join(param['values']))) elif (len(arg_possible) > 1): raise ParamException('ambiguous option %s value:\n%s' % (word, "\n".join(arg_possible))) else: parsed[param_name] = arg_possible[0] i += 1 else: raise ParamException('option %s requires an argument' % word) i += 1 return parsed # # -------------------------------------------------------------------------------- # rest_error_to_dict # Turn an exception into an error dictionary, which can later be printed. # using rest_error_dict_to_message(). # def rest_error_to_dict(self, e, detail=None): errors = None # try to identifify validation requests if isinstance(e, httplib.BadStatusLine): errors = {'connection_error' : 'REST API server %s: ' 'server not running' % self.controller} return errors elif isinstance(e, urllib2.HTTPError): code = e.code error_returned = e.readline() if code == 404: if detail: errors = {'not_found_error' : 'Not Found: %s' % detail} else: errors = {'not_found_error' : 'Not Found: %s' % error_returned} elif code == 500 or code == 403: errors = {'connection_error' : 'REST API server %s unable to connect: ' 'Cassandra possibly not running' % self.controller} elif code == 400: try: errors = json.loads(error_returned) except: # if the error can't be converted into a dictionary, then imbed the complete # errors as the value for a specific error key. errors = {'error_result_error': "Can't convert returned error: %s" % error_returned} pass else: errors = {'unknown_error': 'HttpError %s' % error_returned} else: errors = {'unknown_error': "Need error managmenet for error %s" % type(e)} return errors # # -------------------------------------------------------------------------------- # rest_error_dict_to_message # Turn an rest_error_dict returned from rest_error_to_dict # into an error message which can ge printed. Code assumes multiple errors # won't occur; if a 'field_error' exists, for example, a 'model_error' won't # also be posted in the error # def rest_error_dict_to_message(self, rest_error_dict): error_msg = "" if 'field_errors' in rest_error_dict: for (k,v) in rest_error_dict['field_errors'].items(): error_msg += "Syntax error: field %s: %s" % (k,v) # traceback.print_stack(), to find out why the error occured elif 'model_error' in rest_error_dict: error_msg += "Error: %s" % rest_error_dict['model_error'] elif 'not_found_error' in rest_error_dict: error_msg += "Error: %s" % rest_error_dict['not_found_error'] elif 'connection_error' in rest_error_dict: error_msg += rest_error_dict['connection_error'] elif 'error_result_error' in rest_error_dict: error_msg += rest_error_dict['error_result_error'] elif 'unknown_error' in rest_error_dict: error_msg += rest_error_dict['unknown_error'] else: error_msg = "REST API server on controller-node %s " % self.controller error_msg += "had %s error:\n" % rest_error_dict['error_type'] error_msg += rest_error_dict['description'] return error_msg # # -------------------------------------------------------------------------------- # method_from_name # def method_from_name(self, name): return getattr(self, "validate_" + name.replace("-","_"), None) # # -------------------------------------------------------------------------------- # validate_port # # - validate port foreign key (to switch) # def validate_port(self): error = None print "validate_port" # collect known switches switch_ids = None switch_key = self.obj_keys["switch"] try: switch_table = self.store.get_table_from_store("switch") switch_ids = [x[switch_key] for x in switch_table] except Exception, e: error = self.rest_error_to_dict(e) print self.rest_error_dict_to_message(error) pass if error: print "Unable to collect switch, no switch dpid validation for port table" error = None # collect known ports port_table = None port_key = self.obj_keys["port"] try: port_table = self.store.get_table_from_store("port") except Exception, e: error = self.rest_error_to_dict(e) print self.rest_error_dict_to_message(error) pass
class Validate(): # initialize in init_obj_type_info obj_type_info_dict = {} # see init_obj_type_info_dict obj_types = [] obj_keys = {} known_controllers = ["127.0.0.1:8000"] controller = None # LOOK! manage this separately until we can for sure talk to eth0 addr instead of 127.0.0.1 controller_for_prompt = "127.0.0.1:8000" cluster = "default" run = True # Cached options for last completion last_line = None last_options = None # Are we running in batch mode, i.e. "cat commands | cli.py" batch = False # used for parsing as an arg local_name_pattern = "localhost://([A-Za-z0-9_:@\-\.\/]+$)" # contained objects pp = None store = None model_handler = None # # -------------------------------------------------------------------------------- # init_obj_type_info_dict # # Builds the init_obj_type_info_dict, which is a dictionary indexed by # the current mode, which also results in a dictionary, then indexed # by a either a 'field' or 'field_ordering' key. # # When init_obj_type_info_dict is indexed by the table/model name, the # value is a dictionary. That dictionary has several keys: # - 'fields' # - 'field_orderings' # # The 'fields' indexed result returns a dictionary, each of which # is indexed by the names of the fields within the table/model. further # indicies describe details about that field within the table: # - 'formatter' desscribes the prettyPrinter function for that field # - 'primary_key' identifes this field as the key for the table/model. # - 'verbose_name' identfies an additonal name for the field, inteneded # to be more descriptive # - 'has_rest_model' True/False # - 'json_serialize_string' True/False # - 'help_text' String providing more clues about the intent of this field # # The 'field_ordering' dictionary associated with the name of the table/model # is used to order the output. # # Also populates the self.obj_keys[], which is a dictionary mapping the table/model # name to the name of the storage key (table/model's column) for that table. # def init_obj_type_info_dict(self): self.cli_model_info = CliModelInfo() self.obj_type_info_dict = self.cli_model_info.get_complete_obj_type_info_dict( ) self.obj_types = [ k for (k, v) in self.obj_type_info_dict.items() if 'has_rest_model' in v ] for (k, d) in self.obj_type_info_dict.items(): candidate_keys = [ f for f in d['fields'].keys() if d['fields'][f].get('primary_key', False) ] if len(candidate_keys) > 0: self.obj_keys[k] = candidate_keys[0] # # -------------------------------------------------------------------------------- # make_unit_formatter # def make_unit_formatter(self, units): return lambda x, y: '%s %s' % (x, units) # # -------------------------------------------------------------------------------- # init_obj_type_info_dict # # Builds the init_obj_type_info_dict, which is a dictionary indexed by # the current mode, which also results in a dictionary, then indexed # by a either a 'field' or 'field_ordering' key. # # When init_obj_type_info_dict is indexed by the table/model name, the # value is a dictionary. That dictionary has several keys: # - 'fields' # - 'field_orderings' # # The 'fields' indexed result returns a dictionary, each of which # is indexed by the names of the fields within the table/model. further # indicies describe details about that field within the table: # - 'formatter' desscribes the prettyPrinter function for that field # - 'primary_key' identifes this field as the key for the table/model. # - 'verbose_name' identfies an additonal name for the field, inteneded # to be more descriptive # - 'has_rest_model' True/False # - 'json_serialize_string' True/False # - 'help_text' String providing more clues about the intent of this field # # The 'field_ordering' dictionary associated with the name of the table/model # is used to order the output. # # Also populates the self.obj_keys[], which is a dictionary mapping the table/model # name to the name of the storage key (table/model's column) for that table. # def init_obj_type_info_dict(self): self.cli_model_info = CliModelInfo() self.obj_type_info_dict = self.cli_model_info.get_complete_obj_type_info_dict( ) self.obj_types = [ k for (k, v) in self.obj_type_info_dict.items() if 'has_rest_model' in v ] for (k, d) in self.obj_type_info_dict.items(): candidate_keys = [ f for f in d['fields'].keys() if d['fields'][f].get('primary_key', False) ] if len(candidate_keys) > 0: self.obj_keys[k] = candidate_keys[0] # # -------------------------------------------------------------------------------- # init # def init(self): self.vendordb = VendorDB() self.vendordb.init() parser = OptionParser() parser.add_option("-c", "--controller", dest="controller", help="set default controller to CONTROLLER", metavar="CONTROLLER", default=self.controller) (options, args) = parser.parse_args() self.controller = options.controller if not self.controller: self.controller = "127.0.0.1:8000" if not sys.stdin.isatty(): self.batch = True self.init_obj_type_info_dict() self.pp = PrettyPrinter(self.obj_type_info_dict) self.store = StoreClient() self.store.set_controller(self.controller) # # -------------------------------------------------------------------------------- # parse_optional_parameters # def parse_optional_parameters(self, params, words): parsed = {} i = 0 while i < len(words): word = words[i] possible = [x for x in params if x.startswith(word)] if len(possible) == 0: raise ParamException('unknown option: %s' % word) elif len(possible) > 1: raise ParamException('ambiguous option: %s\n%s' % (word, "\n".join(possible))) else: param_name = possible[0] param = params[param_name] if (param['type'] == 'flag'): parsed[param_name] = True else: if i + 1 < len(words): argument = words[i + 1] if (param['type'] == 'string'): parsed[param_name] = argument elif (param['type'] == 'int'): try: parsed[param_name] = int(argument) except ValueError: raise ParamException('option %s requires ' + 'integer argument' % word) elif (param['type'] == 'enum'): arg_possible = [ x for x in param['values'] if x.startswith(argument) ] if (len(arg_possible) == 0): raise ParamException( 'option %s value must be in (%s)' % (word, ", ".join(param['values']))) elif (len(arg_possible) > 1): raise ParamException( 'ambiguous option %s value:\n%s' % (word, "\n".join(arg_possible))) else: parsed[param_name] = arg_possible[0] i += 1 else: raise ParamException('option %s requires an argument' % word) i += 1 return parsed # # -------------------------------------------------------------------------------- # rest_error_to_dict # Turn an exception into an error dictionary, which can later be printed. # using rest_error_dict_to_message(). # def rest_error_to_dict(self, e, detail=None): errors = None # try to identifify validation requests if isinstance(e, httplib.BadStatusLine): errors = { 'connection_error': 'REST API server %s: ' 'server not running' % self.controller } return errors elif isinstance(e, urllib2.HTTPError): code = e.code error_returned = e.readline() if code == 404: if detail: errors = {'not_found_error': 'Not Found: %s' % detail} else: errors = { 'not_found_error': 'Not Found: %s' % error_returned } elif code == 500 or code == 403: errors = { 'connection_error': 'REST API server %s unable to connect: ' 'Cassandra possibly not running' % self.controller } elif code == 400: try: errors = json.loads(error_returned) except: # if the error can't be converted into a dictionary, then imbed the complete # errors as the value for a specific error key. errors = { 'error_result_error': "Can't convert returned error: %s" % error_returned } pass else: errors = {'unknown_error': 'HttpError %s' % error_returned} else: errors = { 'unknown_error': "Need error managmenet for error %s" % type(e) } return errors # # -------------------------------------------------------------------------------- # rest_error_dict_to_message # Turn an rest_error_dict returned from rest_error_to_dict # into an error message which can ge printed. Code assumes multiple errors # won't occur; if a 'field_error' exists, for example, a 'model_error' won't # also be posted in the error # def rest_error_dict_to_message(self, rest_error_dict): error_msg = "" if 'field_errors' in rest_error_dict: for (k, v) in rest_error_dict['field_errors'].items(): error_msg += "Syntax error: field %s: %s" % (k, v) # traceback.print_stack(), to find out why the error occured elif 'model_error' in rest_error_dict: error_msg += "Error: %s" % rest_error_dict['model_error'] elif 'not_found_error' in rest_error_dict: error_msg += "Error: %s" % rest_error_dict['not_found_error'] elif 'connection_error' in rest_error_dict: error_msg += rest_error_dict['connection_error'] elif 'error_result_error' in rest_error_dict: error_msg += rest_error_dict['error_result_error'] elif 'unknown_error' in rest_error_dict: error_msg += rest_error_dict['unknown_error'] else: error_msg = "REST API server on controller-node %s " % self.controller error_msg += "had %s error:\n" % rest_error_dict['error_type'] error_msg += rest_error_dict['description'] return error_msg # # -------------------------------------------------------------------------------- # method_from_name # def method_from_name(self, name): return getattr(self, "validate_" + name.replace("-", "_"), None) # # -------------------------------------------------------------------------------- # validate_port # # - validate port foreign key (to switch) # def validate_port(self): error = None print "validate_port" # collect known switches switch_ids = None switch_key = self.obj_keys["switch"] try: switch_table = self.store.get_table_from_store("switch") switch_ids = [x[switch_key] for x in switch_table] except Exception, e: error = self.rest_error_to_dict(e) print self.rest_error_dict_to_message(error) pass if error: print "Unable to collect switch, no switch dpid validation for port table" error = None # collect known ports port_table = None port_key = self.obj_keys["port"] try: port_table = self.store.get_table_from_store("port") except Exception, e: error = self.rest_error_to_dict(e) print self.rest_error_dict_to_message(error) pass