def run(self, params, args): (cmd, group) = self.fillParams([('command', None, True), ('group', None, True)]) groupid = None try: groupid = int(group) except ValueError: pass if groupid is None: try: groupid = grp.getgrnam(group).gr_gid except KeyError: raise CommandError(self, 'cannot find group %s' % group) self.db.execute('insert into access(command, groupid) values (%s, %s)', (cmd, groupid))
def deleteRule(self, table, rulename, extrasql=None): assert table assert rulename query = 'select * from %s where name="%s"' % (table, rulename) if extrasql: query = "%s and %s" % (query, extrasql) rows = self.db.execute(query) if rows == 0: raise CommandError( self, 'Could not find rule %s in %s' % (rulename, table)) query = 'delete from %s where name="%s"' % (table, rulename) if extrasql: query = "%s and %s" % (query, extrasql) self.db.execute(query)
def run(self, params, args): (attr, doc) = self.fillParams([ ('attr', None, True), ('doc', None, True), ]) if self.db.count('(id) FROM attributes WHERE name = %s', (attr, )) == 0: raise CommandError( self, 'Cannot set documentation for a non-existant attribute') self.db.execute('delete from attributes_doc where attr=%s', (attr, )) if doc: self.db.execute( """ insert into attributes_doc(attr, doc) values (%s, %s) """, (attr, doc))
def run(self, params, args): if len(args) == 0: raise ArgRequired(self, 'environment') if len(args) != 1: raise ArgUnique(self, 'environment') environment = args[0] if self.db.count( '(ID) from environments where name=%s', (environment,) ) > 0: raise CommandError(self, 'environment "%s" already exists' % environment) self.db.execute( 'insert into environments(name) values (%s)', (environment,) )
def run(self, params, args): (attr, doc) = self.fillParams([ ('attr', None, True), ('doc', None, True), ]) rows = self.db.select('attr from attributes where attr=%s', (attr,)) if not rows: raise CommandError(self, 'Cannot set documentation for a non-existant attribute') self.db.execute('delete from attributes_doc where attr=%s', (attr,)) if doc: self.db.execute(""" insert into attributes_doc(attr, doc) values (%s, %s) """, (attr, doc))
def run(self, params, args): (environment, ) = self.fillParams([ ('environment', None, True) ]) if not len(args): raise ArgRequired(self, 'host') if environment and environment not in self.getEnvironmentNames(): raise CommandError(self, 'environment parameter not valid') for host in self.getHostnames(args): self.db.execute(""" update nodes set environment= (select id from environments where name='%s') where name='%s' """ % (environment, host))
def run(self, params, args): if len(args) < 1: raise ArgRequired(self, 'host') me = self.db.getHostname() hosts = self.getHostnames(args) # Don't allow the user to remove the host the command # is running on. Right now that means cannot remove # the Frontend, but checked this way will allow for # future multiple Frontend's where you may still want # to remove some but not all of them. if me in hosts: raise CommandError(self, 'cannot remove "%s"' % me) # Don't run unless we actually got hosts back if hosts: self.runPlugins(hosts) self.command('sync.config')
def run(self, params, args): (b_action, b_type, b_os) = self.getBootActionTypeOS(params, args) if not self.actionExists(b_action, b_type, b_os): raise CommandError(self, 'action/type/os "%s/%s/%s" does not exists' % (b_action, b_type, b_os)) if not b_os: self.db.execute(""" delete from bootactions where os is NULL and bootname=(select id from bootnames where name=%s and type=%s) """, (b_action, b_type)) else: self.db.execute(""" delete from bootactions where os=(select id from oses where name=%s) and bootname=(select id from bootnames where name=%s and type=%s) """, (b_os, b_action, b_type))
def run(self, params, args): filename, processor = self.fillParams([('file', None, True), ('processor', 'default')]) if not os.path.exists(filename): raise CommandError(self, 'file "%s" does not exist' % filename) # # implementations can't return values # self.attrs = {} self.runImplementation('load_%s' % processor, (filename, )) self.runPlugins(self.attrs) self.command('sync.config') # Only sync the host config for the hosts in the # imported spreadsheet. hosts = self.getHostnames() for host in self.attrs.keys(): if host in hosts: self.call('sync.host.config', [host]) # # checkin the attribute spreadsheet # sheetsdir = '/export/stack/spreadsheets' if not os.path.exists(sheetsdir): os.makedirs(sheetsdir) RCSdir = '%s/RCS' % sheetsdir if not os.path.exists(RCSdir): os.makedirs(RCSdir) sheetsfile = '%s/%s' % (sheetsdir, os.path.basename(filename)) if not os.path.exists(sheetsfile) or not \ os.path.samefile(filename, sheetsfile): shutil.copyfile(filename, '%s' % sheetsfile) cmd = 'date | /opt/stack/bin/ci "%s"' % sheetsfile os.system(cmd) cmd = '/opt/stack/bin/co -f -l "%s"' % sheetsfile os.system(cmd)
def run(self, params, args): if len(args) < 1: raise ArgRequired(self, 'pallet') (arch, box) = self.fillParams([('arch', self.arch), ('box', 'default')]) rows = self.db.execute(""" select * from boxes where name='%s' """ % box) if not rows: raise CommandError(self, 'unknown box "%s"' % box) for (roll, version, release) in self.getRollNames(args, params): if release: rel = "rel='%s'" % release else: rel = 'rel=""' rows = self.db.execute(""" select b.name from stacks s, rolls r, boxes b where r.name = '%s' and r.version = '%s' and %s and r.arch = '%s' and b.name = '%s' and s.box = b.id and s.roll=r.id """ % (roll, version, rel, arch, box)) if not rows: self.db.execute(""" insert into stacks(box, roll) values ( (select id from boxes where name='%s'), (select id from rolls where name='%s' and version='%s' and %s and arch='%s') )""" % (box, roll, version, rel, arch)) # Regenerate stacki.repo os.system(""" /opt/stack/bin/stack report host repo localhost | /opt/stack/bin/stack report script | /bin/sh """)
def run(self, params, args): (service, network, outnetwork, chain, action, protocol, flags, comment, table, rulename) = self.doParams() # Make sure we have a new rule if self.db.count('(*) from global_firewall where name=%s', (rulename, )) > 0: raise CommandError( self, f'Rule with rulename "{rulename}" already exists') # Now let's add them self.db.execute( """insert into global_firewall (insubnet, outsubnet, service, protocol, action, chain, flags, comment, tabletype, name) values (%s, %s, %s, %s, %s, %s, %s, %s,%s, %s)""", (network, outnetwork, service, protocol, action, chain, flags, comment, table, rulename))
def run(self, params, args): (networks, address) = self.fillSetNetworkParams(args, 'address') if len(networks) > 1: raise ArgUnique(self, 'network') network = networks[0] # Make sure this is a valid network mask = self.db.select('mask from subnets where name=%s', (network, ))[0][0] try: ipaddress.IPv4Network(f'{address}/{mask}') except: msg = '%s/%s is not a valid network address and subnet mask combination' raise CommandError(self, msg % (address, mask)) self.db.execute('update subnets set address=%s where name=%s', (address, network))
def run(self, params, args): (b_action, b_type, b_os) = self.getBootActionTypeOS(params, args) (b_kernel, b_ramdisk, b_args, force) = self.fillParams([('kernel', '', True), ('ramdisk', ''), ('args', ''), ('force', True)]) force = self.str2bool(force) # If we don't force the update error out (AKA: the add command) existing = self.actionExists(b_action, b_type, b_os) if existing and not force: raise CommandError(self, 'action "%s" exists' % b_action) if not self.bootNameExists(b_action, b_type): self.db.execute( 'insert into bootnames(name, type) values (%s, %s)', (b_action, b_type)) if not existing: if b_os: self.db.execute( """ insert into bootactions(bootname, os) values ( (select id from bootnames where name=%s and type=%s), (select id from oses where name=%s) ) """, (b_action, b_type, b_os)) else: self.db.execute( """ insert into bootactions(bootname) values ( (select id from bootnames where name=%s and type=%s) ) """, (b_action, b_type)) for flag, command in [(b_kernel, 'kernel'), (b_args, 'args'), (b_ramdisk, 'ramdisk')]: if flag: self.command(f'set.bootaction.{command}', [ b_action, f'type={b_type}', f'os={b_os}', f'{command}={flag}' ])
def run(self, params, args): if not len(args): raise ArgRequired(self, 'switch') name, enforce_sm = self.fillParams([ ('name', None), ('enforce_sm', False), ]) if name: name = name.lower() if name == 'default': name = 'Default' elif name != None: try: name = '0x{0:04x}'.format(int(name, 16)) except ValueError: raise ParamValue(self, 'name', 'a hex value between 0x0001 and 0x7ffe, or "default"') switches = self.getSwitchNames(args) switch_attrs = self.getHostAttrDict(switches) for switch in switches: if switch_attrs[switch].get('switch_type') != 'infiniband': raise CommandError(self, f'{switch} does not have a switch_type of "infiniband"') if self.str2bool(enforce_sm): enforce_subnet_manager(self, switches) ids_sql = 'name, id FROM nodes WHERE name IN (%s)' % ','.join(['%s'] * len(switches)) sw_ids = dict((row[0], row[1]) for row in self.db.select(ids_sql, tuple(switches))) format_str = ','.join(['%s'] * len(switches)) delete_stmt = ''' DELETE from ib_partitions WHERE switch IN (%s)''' % format_str vals = list(sw_ids.values()) if name: delete_stmt += ' AND ib_partitions.part_name=%s' vals.append(name) self.db.execute(delete_stmt, vals)
def _load(self, text): parser = JsonComment(json) # standard JSON is stupid try: data = parser.loads(text) except ValueError as e: # parse the error message and split the input at the # syntax error i = int(re.search(r'char (.*?)\)', str(e)).group(1)) b = text[:i] a = text[i:] # find the line with the error and report it # 'blen' in honor of our intern line1 = (b[b.rfind('\n'):] + a[:a.find('\n')]).strip() blen = len((b[b.rfind('\n'):]).strip()) line2 = ' ' * blen + '^' raise CommandError(self, f'syntax error\n{line1}\n{line2}\n{e}') return data
def run(self, args): # remove any duplicates args = tuple(unique_everseen(lowered(args))) # The imps must exist self.owner.ensure_imps_exist(imps = args) # remove the implementations try: self.owner.db.execute("DELETE FROM firmware_imp WHERE name IN %s", (args,)) except IntegrityError: raise CommandError( cmd = self.owner, msg = ( "Failed to remove all implementations because some are still in use." " Please run 'stack list firmware model expanded=true' to list the" " models still using the implementation and 'stack remove firmware model'" " to remove them." ) )
def run(self, params, args): (b_action, b_type, b_os) = self.getBootActionTypeOS(params, args) (b_kernel, b_ramdisk, b_args, force) = self.fillParams([('kernel', '', True), ('ramdisk', ''), ('args', ''), ('force', False)]) force = self.str2bool(force) if self.actionExists(b_action, b_type, b_os): raise CommandError(self, 'action "%s" exists' % b_action) if not self.bootNameExists(b_action, b_type): self.db.execute(""" insert into bootnames (name, type) values ('%s', '%s')""" % (b_action, b_type)) if b_os: self.db.execute(""" insert into bootactions (bootname, os) values ( (select id from bootnames where name='%s' and type='%s'), (select id from oses where name='%s') )""" % (b_action, b_type, b_os)) else: self.db.execute(""" insert into bootactions (bootname) values ( (select id from bootnames where name='%s' and type='%s') )""" % (b_action, b_type)) for (flag, command) in [(b_kernel, 'kernel'), (b_args, 'args'), (b_ramdisk, 'ramdisk')]: if flag: self.command('set.bootaction.%s' % command, (b_action, 'type=%s' % b_type, 'os=%s' % b_os, '%s=%s' % (command, flag)))
def test_run_error( self, mock_unique_everseen, mock_lowered, basic_plugin, ): """Test that run fails when argument validation fails and does not touch the database.""" expected_makes = ("foo", "bar", "baz") mock_args = [*expected_makes] mock_unique_everseen.return_value = (arg for arg in mock_args) basic_plugin.owner.ensure_unique_makes.side_effect = CommandError( cmd=basic_plugin.owner, msg="Test error", ) with pytest.raises(CommandError): basic_plugin.run(args=mock_args) # Expect the database to be untouched basic_plugin.owner.db.execute.assert_not_called()
def run(self, params, args): if len(args) == 0: raise ArgRequired(self, 'environment') if len(args) != 1: raise ArgUnique(self, 'environment') environment = args[0] dup = False for row in self.db.select(""" * from environments where name='%s' """ % environment): dup = True if dup: raise CommandError(self, 'environment "%s" already exists' % environment) self.db.execute(""" insert into environments (name) values ('%s') """ % environment)
def run(self, params, args): if not len(args): raise ArgRequired(self, 'network') networks = self.getNetworkNames(args) # Get a list of networks currently attached to host interfaces in_use = { interface['network'] for interface in self.call('list.host.interface') } # See if any are in use for network in networks: if network in in_use: raise CommandError(self, f'network "{network}" in use') # Safe to delete them for network in networks: self.db.execute('delete from subnets where name=%s', (network, ))
def run(self, params, args): (profile, chapter) = self.fillParams([ ('profile', 'native'), ('chapter', None) ]) xmlinput = '' osname = None # If the command is not on a TTY, then try to read XML input. if not sys.stdin.isatty(): for line in sys.stdin.readlines(): if line.find('<stack:profile stack:os="') == 0: osname = line.split()[1][9:].strip('"') xmlinput += line if xmlinput and not osname: raise CommandError(self, "OS name not specified in profile") self.beginOutput() # If there's no XML input, either we have TTY, or we're running # in an environment where TTY cannot be created (ie. apache) if not xmlinput: hosts = self.getHostnames(args) if len(hosts) != 1: raise ArgUnique(self, 'host') host = hosts[0] osname = self.db.getHostOS(host) xmlinput = self.command('list.host.xml', [ host ]) self.runImplementation(osname, (xmlinput, profile, chapter)) # If we DO have XML input, simply parse it. else: self.runImplementation(osname, (xmlinput, profile, chapter)) self.endOutput(padChar='')
def run(self, params, args): hosts = self.getHostnames(args) (address, gateway, netmask) = self.fillParams([('address', None, True), ('gateway', None, True), ('netmask', '255.255.255.255')]) # # determine if this is a subnet identifier # subnet = 0 rows = self.db.execute("""select id from subnets where name = '%s' """ % gateway) if rows == 1: subnet, = self.db.fetchone() gateway = "''" else: subnet = 'NULL' gateway = "'%s'" % gateway # Verify the route doesn't already exist. If it does # for any of the hosts raise a CommandError. for host in hosts: rows = self.db.execute("""select * from node_routes r, nodes n where r.node=n.id and r.network='%s' and n.name='%s'""" % (address, host)) if rows: raise CommandError(self, 'route exists') # Now that we know things will work insert the route for # all the hosts for host in hosts: self.db.execute("""insert into node_routes values ((select id from nodes where name='%s'), '%s', '%s', %s, %s)""" % (host, address, netmask, gateway, subnet))
def run(self, params, args): apps = self.getApplianceNames(args) (address, gateway, netmask, interface) = self.fillParams([ ('address', None, True), ('gateway', None, True), ('netmask', '255.255.255.255'), ('interface', None), ]) if len(args) == 0: raise ParamRequired(self, 'appliance') # determine if this is a subnet identifier rows = self.db.select('id from subnets where name = %s', (gateway, )) if len(rows) == 1: subnet = rows[0][0] gateway = '' else: subnet = None # Verify the route doesn't already exist. If it does # for any of the appliances raise a CommandError. for app in apps: if self.db.count( """(*) from appliance_routes r, appliances a where r.appliance=a.id and r.network=%s and a.name=%s""", (address, app)) > 0: raise CommandError(self, 'route exists') # Now that we know things will work insert the route for # all the appliances for app in apps: self.db.execute( """insert into appliance_routes values ((select id from appliances where name=%s), %s, %s, %s, %s, %s)""", (app, address, netmask, gateway, subnet, interface))
def test_run_missing_args(self, mock_unique_everseen, mock_lowered, failure_mock, basic_plugin): """Test that run fails when any of the exist* functions fail.""" mock_args = ["foo", "bar", "baz"] mock_params = {"make": "mock_make", "version_regex": "mock_name"} mock_unique_everseen.return_value = (arg for arg in mock_args) mock_lowered.return_value = mock_params.values() mock_validation_functions = { "ensure_models_exist": basic_plugin.owner.ensure_models_exist, "ensure_version_regex_exists": basic_plugin.owner.ensure_version_regex_exists, } mock_validation_functions[failure_mock].side_effect = CommandError( cmd=basic_plugin.owner, msg="Test error") with pytest.raises(CommandError): basic_plugin.run(args=(mock_params, mock_args)) # model sure the DB is not modified with bad arguments. basic_plugin.owner.db.execute.assert_not_called()
def check_errors(self, results): """Checks for any errors in the results of run_implementations_parallel. If there are errors, this will aggregate them all into one CommandError and raise it. """ # drop any results that didn't have any errors and aggregate the rest into one exception error_messages = [] for error in (value.exception for value in results.values() if value is not None and value.exception is not None): # if this looks like a stacki exception type, grab the message from it. if hasattr(error, 'message') and callable(getattr( error, 'message')): error_messages.append(error.message()) else: error_messages.append(f'{error}') if error_messages: error_message = '\n'.join(error_messages) raise CommandError( cmd=self.owner, msg=f"Errors occurred while listing firmware:\n{error_message}" )
def get_model_id(self, make, model): """Get the ID of the model with the provided name related to the provided make. This will raise a CommandError if the make + model combo doesn't exist. """ row = self.db.select( """ firmware_model.id FROM firmware_model INNER JOIN firmware_make ON firmware_model.make_id=firmware_make.id WHERE firmware_make.name=%s AND firmware_model.name=%s """, (make, model), ) if not row: raise CommandError( cmd=self, msg=f"Firmware model {model} doesn't exist for make {make}.") return row[0][0]
def run(self, params, args): host, port, interface, = self.fillParams([ ('host', None, True), ('port', None, True), ('interface', None, False), ]) switches = self.getSwitchNames(args) if len(switches) > 1: raise ArgUnique(self, 'switch') # Check if host exists hosts = self.getHostnames([host]) for switch in switches: # Make sure switch has an interface if self.getSwitchNetwork(switch): self.addSwitchHost(switch, port, host, interface) else: raise CommandError(self, "switch '%s' doesn't have a management interface" % switch)
def copy(self, stacki_pallet_root, pallet_info, clean): ''' Copy a pallet to the local filesystem Specifically, rsync from `pallet_info.pallet_root` to `stacki_pallet_root`/name/version/release/os/arch/ ''' pallet_dir = pallet_info.pallet_root destdir = pathlib.Path(stacki_pallet_root).joinpath( *info_getter(pallet_info)) if destdir.exists() and clean: print( f'Cleaning {"-".join(info_getter(pallet_info))} from pallets directory' ) shutil.rmtree(destdir) print(f'Copying {"-".join(info_getter(pallet_info))} ...') if not destdir.exists(): destdir.mkdir(parents=True, exist_ok=True) # use rsync to perform the copy # archive implies # --recursive, # --links - copy symlinks as symlinks # --perms - preserve permissions # --times - preserve mtimes # --group - preserve group # --owner - preserve owner # --devices - preserve device files # --specials - preserve special files # we then overwrite the permissions to make apache happy. cmd = f'rsync --archive --chmod=D755 --chmod=F644 --exclude "TRANS.TBL" {pallet_dir}/ {destdir}/' result = self._exec(cmd, shlexsplit=True) if result.returncode != 0: raise CommandError(self, f'Unable to copy pallet:\n{result.stderr}') return destdir
def run(self, params, args): (b_kernel, ) = self.fillParams([('kernel', '', True)]) (b_action, b_type, b_os) = self.getBootActionTypeOS(params, args) if not self.actionExists(b_action, b_type, b_os): raise CommandError(self, 'action "%s" does not exist' % b_action) if b_os: self.db.execute(""" update bootactions set kernel = '%s' where os = (select id from oses where name = '%s') and bootname = (select id from bootnames where name = '%s' and type = '%s') """ % (b_kernel, b_os, b_action, b_type)) else: self.db.execute(""" update bootactions set kernel = '%s' where os is NULL and bootname = (select id from bootnames where name = '%s' and type = '%s') """ % (b_kernel, b_action, b_type))
def run(self, params, args): host = self.getSingleHost(args) key, = self.fillParams([ ('key', None, True) ]) # See if the key is a file name if os.path.exists(key): with open(key, 'r') as f: key = f.read() # Check if the key already exists if self.db.count("""(ID) from public_keys where node = (select id from nodes where name = %s) and public_key = %s """, (host, key) ) != 0: raise CommandError(self, f'the public key already exists for host {host}') # Add the key self.db.execute("""insert into public_keys(node, public_key) values ((select id from nodes where name = %s), %s)""", (host, key) )