def validate_imp(self, make, model, imp): """Validate whether an imp is required due to the model not already existing, and validate that if the model exists that any requested implementation matches. """ # require an implementation if the model does not exist. if not imp and not self.owner.model_exists(make=make, model=model): # Get the list of valid makes + models and add them to the error message in an attempt to be helpful makes_and_models = "\n".join( f"{make_model['make']} + {make_model['model']}" for make_model in self.owner.call( command="list.firmware.model")) raise ParamError( cmd=self.owner, param="imp", msg= (f"is required because make and model combination {make} + {model} doesn't exist." f" Did you mean to use one of the below makes and/or models?\n{makes_and_models}" ), ) # Raise an error if the implementation was provided for an already existing model, and it does not match. if imp and self.owner.model_exists(make=make, model=model): existing_imp = self.owner.call(command="list.firmware.model", args=[model, f"make={make}" ])[0]["implementation"] if imp != existing_imp: raise ParamError( cmd=self.owner, param="imp", msg= (f"The provided imp {imp} doesn't match the existing imp {existing_imp} for the already existing" f" make + model {make} + {model}. Did you not mean to specify an imp? The parameter is not required" " for existing models.\nIf you want to change what implementation is used, run" " 'stack set firmware model imp'."), )
def run(self, params, args): if not len(args): raise ArgRequired(self, 'host') cmd, debug = self.fillParams([('command', None, True), ('debug', False)]) if cmd == 'status': # # used by "stack list host power" -- this is an easy way in which to # share code between the two commands # # set 'debug' to True in order to get output from the status command # debug = True elif cmd not in ['on', 'off', 'reset']: raise ParamError(self, 'command', 'must be "on", "off" or "reset"') self.debug = self.str2bool(debug) for host in self.getHostnames(args): for o in self.call('list.host.interface', [host]): if o['interface'] == 'ipmi': self.doPower(host, o['ip'], cmd) break
def validate_hash_alg_supported(self, hash_alg): """Validates that the requested hash algorithm is supported.""" try: stack.firmware.ensure_hash_alg_supported(hash_alg=hash_alg) except stack.firmware.FirmwareError as exception: raise ParamError( cmd=self.owner, param="hash_alg", msg=f"{exception}", ) from exception
def calculate_hash(self, file_path, hash_alg, hash_value): """Calculate the file hash and verify it against the provided hash, if present.""" try: return stack.firmware.calculate_hash(file_path=file_path, hash_alg=hash_alg, hash_value=hash_value) except stack.firmware.FirmwareError as exception: raise ParamError( cmd=self.owner, param="hash", msg=f"{exception}", ) from exception
def validate_name(self, name): """Validate the name is provided and is unique.""" # A name is required if not name: raise ParamRequired(cmd=self.owner, param="name") # The name must not already exist if self.owner.version_regex_exists(name=name): raise ParamError( cmd=self.owner, param="name", msg= f"A version_regex with the name {name} already exists in the database." )
def fetch_firmware(self, source, make, model, cleanup): """Try to fetch the firmware from the source and return the path to the file.""" try: file_path = stack.firmware.fetch_firmware( source=source, make=make, model=model, ) cleanup.callback(self.file_cleanup, file_path=file_path) return file_path except stack.firmware.FirmwareError as exception: raise ParamError( cmd=self.owner, param="source", msg=f"{exception}", ) from exception
def run(self, args): params, hosts = args make, model, versions, sort, = self.owner.fillParams(names=[ ("make", ""), ("model", ""), ("versions", ""), ("sort", "host") ], params=params) sort_map = { "host": "nodes.Name", "make": "firmware_make.name", "model": "firmware_model.name", "version": "firmware.version", } # sort must be one of the allowed values try: # also convert to the column name for use in ORDER BY sort = sort_map[sort] except KeyError: raise ParamError( cmd=self.owner, param="sort", msg=f"Sort must be one of: {list(sort_map.keys())}") # process hosts if present if hosts: # hosts must exist hosts = self.owner.getHosts(args=hosts) # process make if present if make: # ensure the make exists if not self.owner.make_exists(make=make): raise ParamError(cmd=self.owner, param="make", msg=f"The make {make} doesn't exist.") # process model if present if model: # make is now required if not make: raise ParamRequired(cmd=self.owner, param="make") # ensure the model exists if not self.owner.model_exists(make=make, model=model): raise ParamError( cmd=self.owner, param="model", msg=f"The model {model} doesn't exist for make {make}.") # Process versions if present if versions: # make and model are now required if not make: raise ParamRequired(cmd=self.owner, param="make") if not model: raise ParamRequired(cmd=self.owner, param="model") # turn a comma separated string into a list of versions and # get rid of any duplicate names versions = tuple( unique_everseen((version.strip() for version in versions.split(",") if version.strip()))) # ensure the versions exist try: self.owner.ensure_firmwares_exist(make=make, model=model, versions=versions) except CommandError as exception: raise ArgError(cmd=self.owner, arg="version", msg=exception.message()) results = self.get_firmware_mappings( hosts=hosts, make=make, model=model, versions=versions, sort=sort, ) # return the results return { "keys": ["host", "version", "make", "model"], "values": results }
def run(self, params, args): scope = None oses = [] appliances = [] hosts = [] if len(args) == 0: scope = 'global' elif len(args) == 1: try: oses = self.getOSNames(args) except: oses = [] try: appliances = self.getApplianceNames(args) except: appliances = [] try: hosts = self.getHostnames(args) except: hosts = [] else: raise CommandError(self, 'must supply zero or one argument') if not scope: if args[0] in oses: scope = 'os' elif args[0] in appliances: scope = 'appliance' elif args[0] in hosts: scope = 'host' if not scope: raise CommandError(self, 'argument "%s" must be a valid os, appliance name or host name' % args[0]) if scope == 'global': name = 'global' else: name = args[0] adapter, enclosure, slot, hotspare, raidlevel, arrayid, options, force = self.fillParams([ ('adapter', None), ('enclosure', None), ('slot', None), ('hotspare', None), ('raidlevel', None), ('arrayid', None, True), ('options', ''), ('force', 'n') ]) if not hotspare and not slot: raise ParamRequired(self, [ 'slot', 'hotspare' ]) if arrayid != 'global' and not raidlevel: raise ParamRequired(self, 'raidlevel') if adapter: try: adapter = int(adapter) except: raise ParamType(self, 'adapter', 'integer') if adapter < 0: raise ParamValue(self, 'adapter', '>= 0') else: adapter = -1 if enclosure: try: enclosure = int(enclosure) except: raise ParamType(self, 'enclosure', 'integer') if enclosure < 0: raise ParamValue(self, 'enclosure', '>= 0') else: enclosure = -1 slots = [] if slot: for s in slot.split(','): if s == '*': # # represent '*' in the database as '-1' # s = -1 else: try: s = int(s) except: raise ParamType(self, 'slot', 'integer') if s < 0: raise ParamValue(self, 'slot', '>= 0') if s in slots: raise ParamError(self, 'slot', ' "%s" is listed twice' % s) slots.append(s) hotspares = [] if hotspare: for h in hotspare.split(','): try: h = int(h) except: raise ParamType(self, 'hotspare', 'integer') if h < 0: raise ParamValue(self, 'hostspare', '>= 0') if h in hotspares: raise ParamError(self, 'hostspare', ' "%s" is listed twice' % h) hotspares.append(h) if arrayid in [ 'global', '*' ]: pass else: try: arrayid = int(arrayid) except: raise ParamType(self, 'arrayid', 'integer') if arrayid < 1: raise ParamValue(self, 'arrayid', '>= 0') if arrayid == 'global' and len(hotspares) == 0: raise ParamError(self, 'arrayid', 'is "global" with no hotspares. Please supply at least one hotspare') # # look up the id in the appropriate 'scope' table # tableid = None if scope == 'global': tableid = -1 elif scope == 'appliance': self.db.execute("""select id from appliances where name = '%s' """ % name) tableid, = self.db.fetchone() elif scope == 'host': self.db.execute("""select id from nodes where name = '%s' """ % name) tableid, = self.db.fetchone() # # make sure the specification doesn't already exist # force = self.str2bool(force) for slot in slots: if not force: self.checkIt(name, scope, tableid, adapter, enclosure, slot) for hotspare in hotspares: if not force: self.checkIt(name, scope, tableid, adapter, enclosure, hotspare) if arrayid == 'global': arrayid = -1 elif arrayid == '*': arrayid = -2 # # now add the specifications to the database # for slot in slots: self.db.execute("""insert into storage_controller (scope, tableid, adapter, enclosure, slot, raidlevel, arrayid, options) values ('%s', %s, %s, %s, %s, %s, %s, '%s') """ % (scope, tableid, adapter, enclosure, slot, raidlevel, arrayid, options)) for hotspare in hotspares: raidlevel = -1 if arrayid == 'global': arrayid = -1 self.db.execute("""insert into storage_controller (scope, tableid, adapter, enclosure, slot, raidlevel, arrayid, options) values ('%s', %s, %s, %s, %s, %s, %s, '%s') """ % (scope, tableid, adapter, enclosure, hotspare, raidlevel, arrayid, options))
def doParams(self): (service, network, outnetwork, chain, action, protocol, flags, comment, table, rulename) = self.fillParams([ ('service', None, True), ('network', None), ('output-network', None), ('chain', None, True), ('action', None, True), ('protocol', None, True), ('flags', None), ('comment', None), ('table', 'filter'), ('rulename', None), ]) if not network and not outnetwork: raise ParamRequired(self, ('network', 'output-network')) if table not in [ 'filter', 'raw', 'mangle', 'nat']: raise ParamError(self, 'table', 'is not valid') # # check if the network exists # if network == 'all': network = 0 elif network: rows = self.db.execute("""select id from subnets where name = '%s'""" % (network)) if rows == 0: raise CommandError(self, 'network "%s" not in the database. Run "stack list network" to get a list of valid networks.' % network) network, = self.db.fetchone() else: network = 'NULL' if outnetwork == 'all': outnetwork = 0 elif outnetwork: rows = self.db.execute("""select id from subnets where name = '%s'""" % (outnetwork)) if rows == 0: raise CommandError(self, 'output-network "%s" not in the database. Run "stack list network" to get a list of valid networks.') outnetwork, = self.db.fetchone() else: outnetwork = 'NULL' self.serviceCheck(service) action = action.upper() chain = chain.upper() if protocol: protocol = '"%s"' % protocol else: protocol = 'NULL' if flags: flags = '"%s"' % flags else: flags = 'NULL' if comment: comment = '"%s"' % comment else: comment = 'NULL' if not rulename: import uuid rulename = "%s" % uuid.uuid1() return (service, network, outnetwork, chain, action, protocol, flags, comment, table, rulename)
def run(self, params, args): scope = None oses = [] appliances = [] hosts = [] if len(args) == 0: scope = 'global' elif len(args) == 1: try: oses = self.getOSNames(args) except: oses = [] try: appliances = self.getApplianceNames(args) except: appliances = [] try: hosts = self.getHostnames(args) except: hosts = [] else: raise ArgRequired(self, 'scope') if not scope: if args[0] in oses: scope = 'os' elif args[0] in appliances: scope = 'appliance' elif args[0] in hosts: scope = 'host' if not scope: raise ArgValue(self, 'scope', 'a valid os, appliance name or host name') if scope == 'global': name = None else: name = args[0] adapter, enclosure, slot = self.fillParams([('adapter', None), ('enclosure', None), ('slot', None, True)]) if adapter and adapter != '*': try: adapter = int(adapter) except: raise ParamType(self, 'adapter', 'integer') if adapter < 0: raise ParamValue(self, 'adapter', '>= 0') else: adapter = -1 if enclosure and enclosure != '*': try: enclosure = int(enclosure) except: raise ParamType(self, 'enclosure', 'integer') if enclosure < 0: raise ParamValue(self, 'enclosure', '>= 0') else: enclosure = -1 slots = [] if slot and slot != '*': for s in slot.split(','): try: s = int(s) except: raise ParamType(self, 'slot', 'integer') if s < 0: raise ParamValue(self, 'slot', '>= 0') if s in slots: raise ParamError(self, 'slot', '"%s" is listed twice' % s) slots.append(s) # # look up the id in the appropriate 'scope' table # tableid = None if scope == 'global': tableid = -1 elif scope == 'appliance': self.db.execute("""select id from appliances where name = '%s' """ % name) tableid, = self.db.fetchone() elif scope == 'host': self.db.execute("""select id from nodes where name = '%s' """ % name) tableid, = self.db.fetchone() deletesql = """delete from storage_controller where scope = '%s' and tableid = %s """ % (scope, tableid) if adapter != -1: deletesql += ' and adapter = %s' % adapter if enclosure != -1: deletesql += ' and enclosure = %s' % enclosure if slot != '*': for slot in slots: dsql = '%s and slot = %s' % (deletesql, slot) self.db.execute(dsql) else: self.db.execute(deletesql)
def run(self, params, args): # Get the scope and make sure the args are valid scope, = self.fillParams([('scope', 'global')]) scope_mappings = self.getScopeMappings(args, scope) # Now validate the params adapter, enclosure, slot = self.fillParams([('adapter', None), ('enclosure', None), ('slot', None, True)]) # Make sure the adapter is an integer greater than 0, if it exists if adapter and adapter != '*': try: adapter = int(adapter) except: raise ParamType(self, 'adapter', 'integer') if adapter < 0: raise ParamValue(self, 'adapter', '>= 0') else: adapter = None # Make sure the enclosure is an integer greater than 0, if it exists if enclosure and enclosure != '*': try: enclosure = int(enclosure) except: raise ParamType(self, 'enclosure', 'integer') if enclosure < 0: raise ParamValue(self, 'enclosure', '>= 0') else: enclosure = None # Parse the slots slots = [] if slot: for s in slot.split(','): # Make sure the slot is valid if s == '*': # We're removing them all s = None else: try: s = int(s) except: raise ParamType(self, 'slot', 'integer') if s < 0: raise ParamValue(self, 'slot', '>= 0') if s in slots: raise ParamError(self, 'slot', f'"{s}" is listed twice') # Looks good slots.append(s) scope_ids = [] for scope_mapping in scope_mappings: for slot in slots: # Check that the controller configuration exists for the scope query = """ scope_map.id FROM storage_controller,scope_map WHERE storage_controller.scope_map_id = scope_map.id AND scope_map.scope = %s AND scope_map.appliance_id <=> %s AND scope_map.os_id <=> %s AND scope_map.environment_id <=> %s AND scope_map.node_id <=> %s """ values = list(scope_mapping) # 0 might be valid so need to check for None if adapter is not None: query += " AND storage_controller.adapter = %s" values.append(adapter) if enclosure is not None: query += " AND storage_controller.enclosure = %s" values.append(enclosure) if slot is not None: query += " AND storage_controller.slot = %s" values.append(slot) rows = self.db.select(query, values) if not rows: if adapter is None: adapter = '*' if enclosure is None: enclosure = '*' if slot is None: slot = '*' raise CommandError( self, f'disk specification for "{adapter}/' f'{enclosure}/{slot}" doesn\'t exist') scope_ids.extend(flatten(rows)) # Controller disk specifications existed for all the scope mappings, # so delete them. # Note: We just delete the scope mapping, the ON DELETE CASCADE takes # care of removing the storage_controller table entries for us. self.db.execute('delete from scope_map where id in %s', (scope_ids, ))
def run(self, params, args): # Get the scope and make sure the args are valid scope, = self.fillParams([('scope', 'global')]) scope_mappings = self.getScopeMappings(args, scope) # Now validate the params adapter, enclosure, slot, hotspare, raidlevel, arrayid, options = self.fillParams([ ('adapter', None), ('enclosure', None), ('slot', None), ('hotspare', None), ('raidlevel', None), ('arrayid', None, True), ('options', '') ]) # Gotta have either a hotspare list or a slot list if not hotspare and not slot: raise ParamRequired(self, ['slot', 'hotspare']) # Non-global arrays need a raid level if arrayid != 'global' and not raidlevel: raise ParamRequired(self, 'raidlevel') # Make sure the adapter is an integer greater than 0, if it exists if adapter: try: adapter = int(adapter) except: raise ParamType(self, 'adapter', 'integer') if adapter < 0: raise ParamValue(self, 'adapter', '>= 0') else: adapter = -1 # Make sure the enclosure is an integer greater than 0, if it exists if enclosure: try: enclosure = int(enclosure) except: raise ParamType(self, 'enclosure', 'integer') if enclosure < 0: raise ParamValue(self, 'enclosure', '>= 0') else: enclosure = -1 # Parse the slots slots = [] if slot: for s in slot.split(','): # Make sure the slot is valid if s == '*': # Represent '*' in the database as '-1' s = -1 else: try: s = int(s) except: raise ParamType(self, 'slot', 'integer') if s < 0: raise ParamValue(self, 'slot', '>= 0') if s in slots: raise ParamError( self, 'slot', f'"{s}" is listed twice' ) # Needs to be unique in the scope for scope_mapping in scope_mappings: # Check that the route is unique for the scope if self.db.count(""" (storage_controller.id) FROM storage_controller,scope_map WHERE storage_controller.scope_map_id = scope_map.id AND storage_controller.adapter = %s AND storage_controller.enclosure = %s AND storage_controller.slot = %s AND scope_map.scope = %s AND scope_map.appliance_id <=> %s AND scope_map.os_id <=> %s AND scope_map.environment_id <=> %s AND scope_map.node_id <=> %s """, (adapter, enclosure, s, *scope_mapping)) != 0: raise CommandError( self, f'disk specification for "{adapter}/' f'{enclosure}/{s}" already exists' ) # Looks good slots.append(s) # Parse the hotspares hotspares = [] if hotspare: for h in hotspare.split(','): # Make sure the hotspare is valid try: h = int(h) except: raise ParamType(self, 'hotspare', 'integer') if h < 0: raise ParamValue(self, 'hotspare', '>= 0') if h in hotspares: raise ParamError( self, 'hotspare', f'"{h}" is listed twice' ) if h in slots: raise ParamError( self, 'hotspare', f'"{h}" is listed in slots' ) # Needs to be unique in the scope for scope_mapping in scope_mappings: # Check that the route is unique for the scope if self.db.count(""" (storage_controller.id) FROM storage_controller,scope_map WHERE storage_controller.scope_map_id = scope_map.id AND storage_controller.adapter = %s AND storage_controller.enclosure = %s AND storage_controller.slot = %s AND scope_map.scope = %s AND scope_map.appliance_id <=> %s AND scope_map.os_id <=> %s AND scope_map.environment_id <=> %s AND scope_map.node_id <=> %s """, (adapter, enclosure, h, *scope_mapping)) != 0: raise CommandError( self, f'disk specification for "{adapter}/' f'{enclosure}/{h}" already exists' ) # Looks good hotspares.append(h) # Check the arrayid if arrayid not in {'global', '*'}: try: arrayid = int(arrayid) except: raise ParamType(self, 'arrayid', 'integer') if arrayid < 1: raise ParamValue(self, 'arrayid', '>= 1') if arrayid == 'global' and len(hotspares) == 0: raise ParamError(self, 'arrayid', 'is "global" with no hotspares') # Special encodings for arrayid if arrayid == 'global': arrayid = -1 elif arrayid == '*': arrayid = -2 # Everything is valid, add the data for each scope_mapping for scope_mapping in scope_mappings: # Add the slots for slot in slots: # First add the scope mapping self.db.execute(""" INSERT INTO scope_map( scope, appliance_id, os_id, environment_id, node_id ) VALUES (%s, %s, %s, %s, %s) """, scope_mapping) # Then add the slot controller entry self.db.execute(""" INSERT INTO storage_controller( scope_map_id, adapter, enclosure, slot, raidlevel, arrayid, options ) VALUES (LAST_INSERT_ID(), %s, %s, %s, %s, %s, %s) """, (adapter, enclosure, slot, raidlevel, arrayid, options)) # And add the hotspares for hotspare in hotspares: # First add the scope mapping self.db.execute(""" INSERT INTO scope_map( scope, appliance_id, os_id, environment_id, node_id ) VALUES (%s, %s, %s, %s, %s) """, scope_mapping) # Then add the hotspare controller entry self.db.execute(""" INSERT INTO storage_controller( scope_map_id, adapter, enclosure, slot, raidlevel, arrayid, options ) VALUES (LAST_INSERT_ID(), %s, %s, %s, '-1', %s, %s) """, (adapter, enclosure, hotspare, arrayid, options))
def run(self, params, args): # Get the scope and make sure the args are valid scope, = self.fillParams([('scope', 'global')]) scope_mappings = self.getScopeMappings(args, scope) # Now validate the params (name, table_type, chain, action, service, protocol, input_network, output_network, flags, comment) = self.fillParams([ ('rulename', None), ('table', 'filter'), ('chain', None, True), ('action', None, True), ('service', None, True), ('protocol', None, True), ('network', None), ('output-network', None), ('flags', None), ('comment', None) ]) # Generate a random firewall rule name if needed if not name: name = str(uuid.uuid1()) # Make sure table is a valid choice if table_type not in {'filter', 'raw', 'mangle', 'nat'}: raise ParamError(self, 'table', 'is not valid') # Catch any blank parameters in chain, action, service, and protocol if not chain: raise ParamRequired(self, 'chain') if not action: raise ParamRequired(self, 'action') if not service: raise ParamRequired(self, 'service') if not protocol: raise ParamRequired(self, 'protocol') # Uppercase chain and action chain = chain.upper() action = action.upper() # Convert our networks to subnet ids input_network = blank_str_to_None(input_network) if input_network: rows = self.db.select('id from subnets where name=%s', (input_network, )) if not rows: raise CommandError( self, f'"{input_network}" is not a valid network') in_subnet_id = rows[0][0] else: in_subnet_id = None output_network = blank_str_to_None(output_network) if output_network: rows = self.db.select('id from subnets where name = %s', (output_network, )) if not rows: raise CommandError( self, f'"{output_network}" is not a valid network') out_subnet_id = rows[0][0] else: out_subnet_id = None # Normalize the service sting by stripping whitespace and lowercasing it service = re.sub(r'\s+', '', service).lower() # Make sure the service string is valid if not re.fullmatch( r""" all # 'all' | # OR (?: \d+(?::\d+)? # a port number with optional ':N' range | # OR [a-z]+ # a service name ) (?: , # zero or more comma-seperated repetitions (?: # of the above pattern \d+(?::\d+)? | [a-z]+ ) )* """, service, re.VERBOSE): raise CommandError( self, f'"{service}" is not a valid service specification') # Make sure blank strings are None for flags and comment flags = blank_str_to_None(flags) comment = blank_str_to_None(comment) for scope_mapping in scope_mappings: # Check that the rule name is unique for the scope if self.db.count( """ (firewall_rules.id) FROM firewall_rules,scope_map WHERE firewall_rules.scope_map_id = scope_map.id AND firewall_rules.name = %s AND scope_map.scope = %s AND scope_map.appliance_id <=> %s AND scope_map.os_id <=> %s AND scope_map.environment_id <=> %s AND scope_map.node_id <=> %s """, (name, *scope_mapping)) != 0: raise CommandError(self, f'rule named "{name}" already exists') # And that the rule is unique for the scope if self.db.count( """ (firewall_rules.id) FROM firewall_rules,scope_map WHERE firewall_rules.scope_map_id = scope_map.id AND firewall_rules.table_type = %s AND firewall_rules.chain = %s AND firewall_rules.action = %s AND firewall_rules.service = %s AND firewall_rules.protocol = %s AND firewall_rules.in_subnet_id <=> %s AND firewall_rules.out_subnet_id <=> %s AND firewall_rules.flags <=>%s AND scope_map.scope = %s AND scope_map.appliance_id <=> %s AND scope_map.os_id <=> %s AND scope_map.environment_id <=> %s AND scope_map.node_id <=> %s """, (table_type, chain, action, service, protocol, in_subnet_id, out_subnet_id, flags, *scope_mapping)) != 0: raise CommandError(self, 'firewall rule already exists') # Everything looks good, add the new rules for scope_mapping in scope_mappings: # First add the scope mapping for the new rule self.db.execute( """ INSERT INTO scope_map( scope, appliance_id, os_id, environment_id, node_id ) VALUES (%s, %s, %s, %s, %s) """, scope_mapping) # Then add the rule itself self.db.execute( """ INSERT INTO firewall_rules( scope_map_id, name, table_type, chain, action, service, protocol, in_subnet_id, out_subnet_id, flags, comment ) VALUES (LAST_INSERT_ID(), %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) """, (name, table_type, chain, action, service, protocol, in_subnet_id, out_subnet_id, flags, comment))
def doParams(self): (service, network, outnetwork, chain, action, protocol, flags, comment, table, rulename) = self.fillParams([ ('service', None, True), ('network', None), ('output-network', None), ('chain', None, True), ('action', None, True), ('protocol', None, True), ('flags', None), ('comment', None), ('table', 'filter'), ('rulename', None), ]) if not network and not outnetwork: raise ParamRequired(self, ('network', 'output-network')) if table not in ['filter', 'raw', 'mangle', 'nat']: raise ParamError(self, 'table', 'is not valid') # # check if the network exists # if network == 'all': network = 0 elif network: rows = self.db.select('id from subnets where name = %s', (network, )) if len(rows) == 0: raise CommandError( self, 'network "%s" not in the database. Run "stack list network" to get a list of valid networks.' % network) network = rows[0][0] elif network == "": network = None if outnetwork == 'all': outnetwork = 0 elif outnetwork: rows = self.db.select('id from subnets where name = %s', (outnetwork, )) if len(rows) == 0: raise CommandError( self, 'output-network "%s" not in the database. Run "stack list network" to get a list of valid networks.' % outnetwork) outnetwork = rows[0][0] elif outnetwork == "": outnetwork = None self.serviceCheck(service) action = action.upper() chain = chain.upper() # Make sure empty strings are None if protocol == "": protocol = None if flags == "": flags = None if comment == "": comment = None if not rulename: rulename = str(uuid.uuid1()) return (service, network, outnetwork, chain, action, protocol, flags, comment, table, rulename)
def run(self, params, args): if not len(args): raise ArgRequired(self, 'host') cmd, debug, force_imp = self.fillParams([ ('command', None, True), ('debug', False), ('method', None) ]) host_errors = [] self.debug = self.str2bool(debug) impl_output = namedtuple('output', 'out debug success') self.loadImplementation() # The first implementation is ipmi by default # but can be forced by the method parameter # If this is set, only that implementation will be run if force_imp: if force_imp not in self.impl_list: raise ParamError(self, 'method', f'{force_imp} not found as a valid implementation') imp_names = [force_imp] # Otherwise use all the implementations else: # Gather all set power implmentations besides ipmi and ssh imp_names = [imp for imp in self.impl_list if imp not in ['ssh', 'ipmi']] # Add ipmi to be the first implementation used if 'ipmi' in self.impl_list: imp_names.insert(0, 'ipmi') # Add ssh to be the last implementation used if 'ssh' in self.impl_list: imp_names.append('ssh') if cmd not in ['on', 'off', 'reset', 'status']: raise ParamError(self, 'command', 'must be "on", "off", "reset", or "status"') for host in self.getHostnames(args): # Flag for if an implementation has # successfully run. Set to true if an # implementation returns success in its output imp_success = False self.beginOutput() # Iterate through each implementation # if one succeeds, we are done with the command for imp in imp_names: imp_msg = self.runImplementation(imp, [host, cmd, impl_output]) if imp_msg.out: self.addOutput(host, imp_msg.out) if self.debug: # Output debug information if the parameter was set if not imp_msg.success and imp_msg.debug: self.addOutput(host, f'Failed to set power via {imp}: "{imp_msg.debug}"') # Handle if an implementation fails but has no debug information elif not imp_msg.success: self.addOutput(host, f'Failed to set power via {imp}') elif imp_msg.success: self.addOutput(host, f'Successfully set power via {imp}') # We don't need to run anymore implementations # now that one has succeeded for this host if imp_msg.success: imp_success = True self.mq_publish(host, cmd) break if self.debug and not imp_success: self.addOutput(host, f'Could not set power cmd {cmd} on host {host}') self.endOutput(padChar='', trimOwner=True)