def run(self, params, args): host = self.getSingleHost(args) (name, ) = self.fillParams([ ('name', None, True) ]) if not is_valid_hostname(name): raise ParamValue(self, 'name', 'a valid hostname label') if name in self.getHostnames(): raise CommandError(self, 'name already exists') self.db.execute('update nodes set name=%s where name=%s', (name, host))
def run(self, params, args): hosts = self.getHosts(args) (action, nukedisks, nukecontroller, sync) = self.fillParams([ ('action', None, True), ('nukedisks', None, False), ('nukecontroller', None, False), ('sync', True) ]) sync = self.str2bool(sync) if action not in ['os', 'install']: raise ParamValue(self, 'action', 'one of: os, install') # Get the mapping of hosts with boot actions and thier PK hosts_with_boot = {row[0]: row[1] for row in self.db.select( 'nodes.name, nodes.id from nodes, boot where nodes.id=boot.node' )} for host in hosts: if host in hosts_with_boot: self.db.execute( 'update boot set action=%s where node=%s', (action, hosts_with_boot[host]) ) else: self.db.execute(""" insert into boot(action, node) values ( %s, (select id from nodes where name=%s) ) """, (action, host)) if nukedisks is not None: args = hosts.copy() args.extend([ 'attr=nukedisks', 'value=%s' % self.str2bool(nukedisks) ]) self.command('set.host.attr', args) if nukecontroller is not None: args = hosts.copy() args.extend([ 'attr=nukecontroller', 'value=%s' % self.str2bool(nukecontroller) ]) self.command('set.host.attr', args) if sync: self.command('sync.host.boot', hosts)
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 run(self, params, args): (scope, device, mountpoint) = self.fillParams([ ('scope', 'global'), ('device', None), ('mountpoint', None)]) oses = [] appliances = [] hosts = [] name = None accepted_scopes = ['global', 'os', 'appliance', 'host'] # Some checking that we got usable input.: if scope not in accepted_scopes: raise ParamValue(self, '%s' % params, 'one of the following: %s' % accepted_scopes ) elif scope == 'global' and len(args) >= 1: raise ArgError(self, '%s' % args, 'unexpected, please provide a scope: %s' % accepted_scopes) elif scope == 'global' and (device is None and mountpoint is None): raise ParamRequired(self, 'device OR mountpoint') elif scope != 'global' and len(args) < 1: raise ArgRequired(self, '%s name' % scope) if scope == "os": oses = self.getOSNames(args) elif scope == "appliance": appliances = self.getApplianceNames(args) elif scope == "host": hosts = self.getHostnames(args) if scope != 'global': name = args[0] # # look up the id in the appropriate 'scope' table # tableid = -1 tablename = {"os":"oses", "appliance":"appliances", "host":"nodes"} if scope != 'global': self.db.execute("""select id from %s where name = '%s' """ % (tablename[scope], name)) tableid, = self.db.fetchone() deletesql = """delete from storage_partition where scope = '%s' and tableid = %s """ % (scope, tableid) if device and device != '*': deletesql += """ and device = '%s'""" % device if mountpoint and mountpoint != '*': deletesql += """ and mountpoint = '%s'""" % mountpoint self.db.execute(deletesql)
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) format_str = ','.join(['%s'] * len(switches)) sw_select = ''' nodes.name, ib.part_name, ib.part_key, ib.options FROM nodes, ib_partitions ib WHERE nodes.name IN (%s) AND nodes.id=ib.switch''' % format_str vals = list(switches) if name: sw_select += ' AND ib.part_name=%s' vals.append(name) sw_select += ' ORDER BY nodes.name' self.beginOutput() for line in self.db.select(sw_select, vals): self.addOutput(line[0], (line[1], '0x{0:04x}'.format(line[2]), line[3])) self.endOutput(header=['switch', 'partition', 'partition key', 'options'])
def getBootActionTypeOS(self, params, args): if not len(args): raise ArgRequired(self, 'action') if len(args) != 1: raise ArgUnique(self, 'action') b_action = args[0] (b_type, b_os) = self.fillParams([('type', None, True), ('os', '')]) if b_type not in ['os', 'install']: raise ParamValue(self, 'type', '"os" or "install"') if not b_os: b_os = self.os if b_os: b_os = self.getOSNames([b_os])[0] return (b_action, b_type, b_os)
def run(self, params, args): (req_action, req_type, req_sync) = self.fillParams([ ('action', None, True), ('type', None, True), ('sync', True) ]) if not len(args): raise ArgRequired(self, 'host') req_sync = self.str2bool(req_sync) req_type = req_type.lower() req_action = req_action.lower() types = { 'os' : 'osaction', 'install': 'installaction' } if req_type not in types.keys(): raise ParamValue(self, 'type', 'one of: %s' % ', '.join(types.keys())) exists = False for row in self.call('list.bootaction', [ req_action, 'type=%s' % req_type ]): exists = True if not exists: raise CommandError(self, 'bootaction %s does not exist' % req_action) hosts = self.getHostnames(args) for host in hosts: self.db.execute( """ update nodes set %s = (select id from bootnames where name='%s' and type='%s') where nodes.name = '%s' """ % (types[req_type], req_action, req_type, host)) if req_sync: self.command('sync.host.boot', hosts)
def getBootActionTypeOS(self, params, args): if not len(args): raise ArgRequired(self, 'action') if len(args) != 1: raise ArgUnique(self, 'action') b_action = args[0] (b_type, b_os) = self.fillParams([('type', None, True), ('os', '')]) if b_type not in ['os', 'install']: raise ParamValue(self, 'type', '"os" or "install"') # If bootaction type is not os, then get the default # os so code doesn't break. if not b_os and b_type != 'os': b_os = self.os if b_os: b_os = self.getOSNames([b_os])[0] return (b_action, b_type, b_os)
def run(self, params, args): filename, processor = self.fillParams([('file', None, True), ('processor', 'default')]) if not filename: raise ParamValue(self, 'file', 'valid csv filename') if not os.path.exists(filename): raise CommandError(self, 'file "%s" does not exist' % filename) # # implementations can't return values # self.hosts = {} self.runImplementation('load_%s' % processor, (filename, )) args = self.hosts self.runPlugins(args) # # checkin the 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): 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 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', 'valid os, appliance name or host name') if scope == 'global': name = 'global' else: name = args[0] device, size, fstype, mountpt, options, partid = \ self.fillParams([ ('device', None, True), ('size', None), ('type', None), ('mountpoint', None), ('options', None), ('partid', None), ]) if not device: raise ParamRequired(self, 'device') # Validate size if size: try: s = int(size) except: # # If mountpoint is 'swap' then allow # 'hibernate', 'recommended' as sizes. # if mountpt == 'swap' and \ size not in ['recommended', 'hibernation']: raise ParamType(self, 'size', 'integer') if s < 0: raise ParamValue(self, 'size', '>= 0') # Validate partid if partid: try: p = int(partid) except: partid = None if p < 1: raise ParamValue(self, 'partid', '>= 0') partid = p # # 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 for mountpt doesn't already exist # if mountpt: self.checkIt(device, scope, tableid, mountpt) if not options: options = "" # # now add the specifications to the database # sqlvars = "Scope, TableID, device, Mountpoint, Size, FsType, Options" sqldata = "'%s', %s, '%s', '%s', %s, '%s', '%s'" % \ (scope, tableid, device, mountpt, size, fstype, options) if partid: sqlvars += ", PartID" sqldata += ", %s" % partid self.db.execute("""insert into storage_partition (%s) values (%s) """ % (sqlvars, sqldata))
def run(self, params, args): if len(args) != 1: raise ArgUnique(self, 'switch') name, guid, hostname, interface, membership, enforce_sm = self.fillParams( [ ('name', None, True), ('guid', None), ('member', None), ('interface', None), ('membership', 'limited'), ('enforce_sm', False), ]) if not guid and not hostname: raise CommandError( self, 'either guid or member and interface must be specified') if guid: guid = guid.lower() if hostname and not interface or interface and not hostname: raise CommandError(self, 'member and interface must both be specified') elif hostname and interface: ifaces = self.call('list.host.interface', [hostname]) for row in ifaces: if row['interface'] == interface: guid = row['mac'] break else: #nobreak raise CommandError( self, f'member has no interface named "{interface}"') 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"') membership = membership.lower() if membership not in ['limited', 'full']: raise ParamValue(self, 'membership', 'either "limited" or "full"') 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) switch, = switches switch_id = self.db.select('id FROM nodes WHERE name=%s', switch)[0][0] # ensure the guid actually exists - guid should be unique across table guid_id = self.db.select('id FROM networks WHERE mac=%s', guid) try: guid_id = guid_id[0][0] except IndexError: raise CommandError( self, f'guid "{guid}" was not found in the interfaces table') # lookups using sql instead of api calls because all 'list switch partition' calls are expensive. # Ensure this partition exists on the switch if self.db.count( '(id) FROM ib_partitions WHERE part_name=%s AND switch=%s', (name, switch_id)) == 0: raise CommandError( self, f'partition {name} does not exist on switch {switch}') # Ensure this member does not already exist on the partition and switch if self.db.count( ''' (ib_m.id) FROM ib_memberships ib_m, ib_partitions ib_p, nodes, networks WHERE ib_m.switch=nodes.id AND nodes.name=%s AND networks.id=ib_m.interface AND ib_m.part_name=ib_p.id AND ib_p.part_name=%s AND networks.id=%s ''', (switch, name, guid_id)) > 0: raise CommandError( self, f'{guid} is already a member of switch partition {name}') self.db.execute( ''' INSERT INTO ib_memberships (switch, interface, part_name, member_type) VALUES (%s, %s, (SELECT id FROM ib_partitions WHERE part_name=%s AND switch=%s), %s) ''', (switch_id, guid_id, name, switch_id, membership))
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 ArgError(self, 'scope', 'must be unique or missing') 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 ParamValue(self, 'scope', 'valid os, appliance name or host name') if scope == 'global': name = None else: name = args[0] device, mountpoint = self.fillParams([('device', None), ('mountpoint', None)]) # # 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_partition where scope = '%s' and tableid = %s """ % (scope, tableid) if device and device != '*': deletesql += """ and device = '%s'""" % device if mountpoint and mountpoint != '*': deletesql += """ and mountpoint = '%s'""" % mountpoint self.db.execute(deletesql)
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): if not len(args): raise ArgRequired(self, 'switch') name, expanded, enforce_sm = self.fillParams([ ('name', None), ('expanded', False), ('enforce_sm', False), ]) expanded = self.str2bool(expanded) 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) sql_columns = 'swnodes.name AS switch, nodes.name AS host, networks.device, networks.mac, ib_p.part_name, ib_m.member_type' table_headers = [ 'switch', 'host', 'device', 'guid', 'partition', 'membership' ] if expanded: sql_columns += ', ib_p.part_key, ib_p.options' table_headers.extend(['partition key', 'options']) format_str = ','.join(['%s'] * len(switches)) member_select = sql_columns + ''' FROM nodes swnodes, nodes, networks, ib_partitions ib_p, ib_memberships ib_m WHERE swnodes.name in (%s) AND swnodes.id=ib_m.switch AND nodes.id=networks.node AND networks.id=ib_m.interface AND ib_p.id=ib_m.part_name ''' % format_str vals = list(switches) if name: member_select += ' AND ib_p.part_name in (%s)' vals.append(name) member_select += ' ORDER BY switch, host, part_name' self.beginOutput() for line in self.db.select(member_select, vals): if expanded: line = list(line) line[6] = '0x{0:04x}'.format(line[6]) self.addOutput(line[0], (line[1:])) self.endOutput(header=table_headers)
def run(self, params, args): # Parse Params (cmd, managed, x11, t, d, collate, n, method) = self.fillParams([ ('command', None, True), # Command ('managed', 'y'), # Run on Managed Hosts only ('x11', 'n'), # Run without X11 ('timeout', '0'), # Set timeout for commands ('delay', '0'), # Set delay between each thread ('collate', 'y'), # Collate output ('threads', self.getAttr('run.host.threads')), ('method', self.getAttr('run.host.impl')) ]) # Check that a command was even input: if cmd == '': raise ParamValue(self, 'cmd', 'string with contents') # Get list of hosts to run the command on self.hosts = self.getHostnames(args, self.str2bool(managed)) self.run_hosts = self.getRunHosts(self.hosts) # Get timeout for commands try: self.timeout = int(t) except: raise ParamType(self, 'timeout', 'integer') if self.timeout < 0: raise ParamValue(self, 'timeout', '> 0') # Get Number of threads to run concurrently if n is None: self.numthreads = 0 else: try: self.numthreads = int(n) except: raise ParamType(self, 'threads', 'integer') if self.numthreads < 0: raise ParamValue(self, 'threads', '> 0') # Get time to pause between subsequent threads try: self.delay = float(d) except: raise ParamType(self, 'delay', 'float') # Check if we want to unset the Display if not self.str2bool(x11): try: del os.environ['DISPLAY'] except KeyError: pass # Get the command self.cmd = cmd # Get the implementation to run. By default, run SSH if method is None: method = 'ssh' # Check if we should collate the output self.collate = self.str2bool(collate) if self.collate: self.beginOutput() self.runImplementation(method, [self.hosts, cmd]) if self.collate: self.endOutput(header=['host', 'output'], trimOwner=False)
def run(self, params, args): scope = None oses = [] appliances = [] hosts = [] globalOnly, = self.fillParams([('globalOnly', 'n')]) globalOnlyFlag = self.str2bool(globalOnly) if len(args) == 0: scope = 'global' elif len(args) == 1: try: oses = self.getOSNames(args) except: oses = [] try: appliances = self.getApplianceNames() except: appliances = [] try: hosts = self.getHostnames() except: hosts = [] else: raise ArgError(self, 'scope', 'must be unique or missing') 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 ParamValue(self, 'scope', 'valid os, appliance name or host name') query = None if scope == 'global': if globalOnlyFlag: query = """select scope, device, mountpoint, size, fstype, options, partid from storage_partition where scope = 'global' order by device,partid,fstype, size""" else: query = """(select scope, device, mountpoint, size, fstype, options, partid from storage_partition where scope = 'global') UNION ALL (select a.name, p.device, p.mountpoint, p.size, p.fstype, p.options, p.partid from storage_partition as p inner join nodes as a on p.tableid=a.id where p.scope='host') UNION ALL (select a.name, p.device, p.mountpoint, p.size, p.fstype, p.options, p.partid from storage_partition as p inner join appliances as a on p.tableid=a.id where p.scope='appliance') order by scope,device,partid,size,fstype""" elif scope == 'os': query = """select scope, device, mountpoint, size, fstype, options, partid from storage_partition where scope = "os" and tableid = (select id from oses where name = %s) order by device,partid,fstype,size""" elif scope == 'appliance': query = """select scope, device, mountpoint, size, fstype, options, partid from storage_partition where scope = "appliance" and tableid = (select id from appliances where name = %s) order by device,partid,fstype, size""" elif scope == 'host': query = """select scope, device, mountpoint, size, fstype, options, partid from storage_partition where scope="host" and tableid = (select id from nodes where name = %s) order by device,partid,fstype, size""" if not query: return self.beginOutput() if scope == 'global': self.db.execute(query) else: self.db.execute(query, [args[0]]) for name, device, mountpoint, size, fstype, options, partid in self.db.fetchall( ): if size == -1: size = "recommended" elif size == -2: size = "hibernation" if name == "host" or name == "appliance" or name == "os": name = args[0] if mountpoint == 'None': mountpoint = None if fstype == 'None': fstype = None if partid == 0: partid = None self.addOutput(name, [device, partid, mountpoint, size, fstype, options]) self.endOutput(header=[ 'scope', 'device', 'partid', 'mountpoint', 'size', 'fstype', 'options' ], trimOwner=False)
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): 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', 'valid os, appliance name or host name') if scope == 'global': name = 'global' else: name = args[0] device, size, fstype, mountpt, options, partid = self.fillParams([ ('device', None, True), ('size', None, True), ('type', None), ('mountpoint', None), ('options', None), ('partid', None), ]) if not device: raise ParamRequired(self, 'device') if not size: raise ParamRequired(self, 'size') # Validate size try: s = int(size) if s < 0: raise ParamValue(self, 'size', '>= 0') except: # If mountpoint is 'swap' then allow # 'hibernate', 'recommended' as sizes if mountpt == 'swap' and size not in [ 'recommended', 'hibernation' ]: raise ParamType(self, 'size', 'integer') else: raise ParamType(self, 'size', 'integer') # Validate partid if partid: try: p = int(partid) except ValueError: raise ParamValue(self, 'partid', 'an integer') if p < 1: raise ParamValue(self, 'partid', '>= 0') partid = p else: partid = 0 # Look up the id in the appropriate 'scope' table if scope == 'appliance': tableid = self.db.select('id from appliances where name=%s', [name])[0][0] elif scope == 'os': tableid = self.db.select('id from oses where name=%s', [name])[0][0] elif scope == 'host': tableid = self.db.select('id from nodes where name=%s', [name])[0][0] else: tableid = -1 # Make sure the specification for mountpt doesn't already exist if mountpt: self.checkIt(device, scope, tableid, mountpt) else: # Preserve the existing behavior (sad panda) mountpt = 'None' # Preserve the existing behavior (sad panda) if not fstype: fstype = 'None' if not options: options = "" # Now add the specifications to the database self.db.execute( """ INSERT INTO storage_partition( Scope, TableID, device, Mountpoint, Size, FsType, Options, PartID ) VALUES(%s, %s, %s, %s, %s, %s, %s, %s) """, (scope, tableid, device, mountpt, size, fstype, options, partid))
def run(self, params, args): if not len(args): raise ArgRequired(self, 'host') (action, nukedisks, nukecontroller, sync) = self.fillParams([ ('action', None, True), ('nukedisks', None, False), ('nukecontroller', None, False), ('sync', True) ]) sync = self.str2bool(sync) actions = [ 'os', 'install' ] if action not in actions: raise ParamValue(self, 'action', 'one of: %s' % ', '.join(actions)) boot = {} for h, a in self.db.select( """ n.name, b.action from nodes n, boot b where n.id = b.node """): boot[h] = a hosts = self.getHostnames(args) if not hosts: return for host in hosts: if host in boot.keys(): self.db.execute( """ update boot set action = '%s' where node = (select id from nodes where name = '%s') """ % (action, host)) else: self.db.execute( """ insert into boot (action, node) values ( '%s', (select id from nodes where name = '%s') ) """ % (action, host)) args = hosts.copy() if len(args) > 0: if nukedisks is not None: nukedisks = self.str2bool(nukedisks) args.extend(['attr=nukedisks', 'value=%s' % nukedisks]) self.command('set.host.attr',args) if nukecontroller is not None: nukecontroller = self.str2bool(nukecontroller) args.extend(['attr=nukecontroller', 'value=%s' % nukecontroller]) self.command('set.host.attr',args) if sync: self.command('sync.host.boot', hosts)
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 device, size, fstype, mountpoint, options, partid = self.fillParams([ ('device', None, True), ('size', None, True), ('type', None), ('mountpoint', None), ('options', None), ('partid', None), ]) if not device: raise ParamRequired(self, 'device') if not size: raise ParamRequired(self, 'size') # Validate size if mountpoint == 'swap' and size in ['recommended', 'hibernation']: if size == 'recommended': size = -1 else: size = -2 else: try: size = int(size) except: raise ParamType(self, 'size', 'integer') if size < 0: raise ParamValue(self, 'size', '>= 0') # Validate partid if partid: try: partid = int(partid) except ValueError: raise ParamType(self, 'partid', 'integer') if partid < 1: raise ParamValue(self, 'partid', '>= 0') else: partid = 0 # Make sure the specification for mountpoint doesn't already exist if mountpoint: # 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_partition.id) FROM storage_partition,scope_map WHERE storage_partition.scope_map_id = scope_map.id AND storage_partition.device = %s AND storage_partition.mountpoint = %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 """, (device, mountpoint, *scope_mapping)) != 0: raise CommandError( self, f'partition specification for device "{device}" ' f'and mount point "{mountpoint}" already exists') else: mountpoint = None if not fstype: fstype = None if not options: options = "" # Everything is valid, add the data for each scope_mapping for scope_mapping in scope_mappings: # 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 storage partition entry self.db.execute( """ INSERT INTO storage_partition( scope_map_id, device, mountpoint, size, fstype, options, partid ) VALUES (LAST_INSERT_ID(), %s, %s, %s, %s, %s, %s) """, (device, mountpoint, size, fstype, options, partid))
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() except: appliances = [] try: hosts = self.getHostnames() except: hosts = [] else: raise ArgError(self, 'scope', 'must be unique or missing') 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 ParamValue(self, 'scope', 'valid os, appliance name or host name') query = None if scope == 'global': query = """select adapter, enclosure, slot, raidlevel, arrayid, options from storage_controller where scope = 'global' order by enclosure, adapter, slot""" elif scope == 'os': # # not currently supported # return elif scope == 'appliance': query = """select adapter, enclosure, slot, raidlevel, arrayid, options from storage_controller where scope = "appliance" and tableid = (select id from appliances where name = '%s') order by enclosure, adapter, slot""" % args[0] elif scope == 'host': query = """select adapter, enclosure, slot, raidlevel, arrayid, options from storage_controller where scope = "host" and tableid = (select id from nodes where name = '%s') order by enclosure, adapter, slot""" % args[0] if not query: return name = None if scope == 'global': name = 'global' elif scope in ['appliance', 'host']: name = args[0] self.beginOutput() self.db.execute(query) i = 0 for row in self.db.fetchall(): adapter, enclosure, slot, raidlevel, arrayid, options = row if i > 0: name = None if adapter == -1: adapter = None if enclosure == -1: enclosure = None if slot == -1: slot = '*' if raidlevel == '-1': raidlevel = 'hotspare' if arrayid == -1: arrayid = 'global' elif arrayid == -2: arrayid = '*' # Remove leading and trailing double quotes options = options.strip("\"") self.addOutput( name, [enclosure, adapter, slot, raidlevel, arrayid, options]) i += 1 self.endOutput(header=[ 'scope', 'enclosure', 'adapter', 'slot', 'raidlevel', 'arrayid', 'options' ], trimOwner=False)
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): if not len(args): raise ArgRequired(self, 'switch') name, options_param, enforce_sm, force_add = self.fillParams([ ('name', None, True), ('options', None), ('enforce_sm', False), ('force_add', True), ]) # force is really whether or not this command came from ADD vs SET stack_set = self.str2bool(force_add) name = name.lower() if name == 'default': name = 'Default' pkey = 0x7fff else: try: pkey = int(name, 16) name = '0x{0:04x}'.format(pkey) except ValueError: raise ParamValue( self, 'name', 'a hex value between 0x0001 and 0x7ffe, or "default"') parsed_options = [] if options_param: options = options_param.split() bad_options = [opt for opt in options if '=' not in opt] options = dict( opt.split('=') for opt in options_param.split() if '=' in opt) if 'ipoib' in options: parsed_options.append( f"ipoib={self.str2bool(options['ipoib'])}") del options['ipoib'] if 'defmember' in options and options['defmember'].lower() in [ 'limited', 'full' ]: parsed_options.append( f"defmember={options['defmember'].lower()}") del options['defmember'] if options: # if there's any leftover, error msg = 'The following are invalid partition options: ' raise CommandError( self, msg + ' '.join(f'{k}={v}' for k, v in options.items())) if bad_options: # if there's non-key value, error msg = 'The following are invalid partition options: ' raise CommandError(self, msg + ' '.join(bad_options)) parsed_options_str = ' '.join(parsed_options) 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))) sql_check = 'id, options FROM ib_partitions WHERE switch=%s AND part_name=%s' for switch in switches: # if doing an ADD, we want to ensure the partition doesn't already exist exists = self.db.select(sql_check, (sw_ids[switch], name)) # since there's already a switch dict, use that to store some temporary data switch_attrs[switch]['_part_opts'] = parsed_options_str if not exists: continue # since there's already a switch dict, use that to store some temporary data switch_attrs[switch]['_part_id'] = exists[0][0] if not stack_set: raise CommandError( self, f'partition "{name}" already exists on switch "{switch}"') if options_param is None: # if user supplied no options field, for existing keep the previous options field switch_attrs[switch]['_part_opts'] = exists[0][1] # if it already exists, we do an UPDATE instead sql_update = 'UPDATE ib_partitions SET switch=%s, part_key=%s, part_name=%s, options=%s WHERE switch=%s and id=%s' sql_insert = 'INSERT INTO ib_partitions (switch, part_key, part_name, options) VALUES (%s, %s, %s, %s)' for switch in switches: if stack_set and exists: self.db.execute( sql_update, (sw_ids[switch], pkey, name, switch_attrs[switch]['_part_opts'], sw_ids[switch], switch_attrs[switch]['_part_id'])) else: self.db.execute(sql_insert, (sw_ids[switch], pkey, name, switch_attrs[switch]['_part_opts']))
def run(self, params, args): if len(args) != 1: raise ArgUnique(self, 'switch') name, guid, hostname, interface, enforce_sm = self.fillParams([ ('name', None), ('guid', None), ('member', None), ('interface', None), ('enforce_sm', False), ]) if guid: guid = guid.lower() if hostname and not interface or interface and not hostname: raise CommandError(self, 'member and interface must both be specified') elif hostname and interface: ifaces = self.call('list.host.interface', [hostname]) for row in ifaces: if row['interface'] == interface: guid = row['mac'] break else: #nobreak raise CommandError( self, f'member has no interface named "{interface}"') 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) switch, = switches switch_id, = self.db.select('id FROM nodes WHERE name=%s', switch) vals = [switch_id[0]] delete_stmt = '''DELETE FROM ib_memberships''' where_clause = 'WHERE ib_memberships.switch=%s' if name: part_id = self.db.select( 'id FROM ib_partitions WHERE part_name=%s AND switch=%s', (name, switch_id)) if not part_id: raise CommandError( self, f'{name} is not a partition on {switches[0]}') where_clause += ' AND ib_memberships.part_name=%s' vals.append(part_id[0][0]) if guid: where_clause += ' AND ib_memberships.interface=(SELECT id FROM networks WHERE mac=%s)' vals.append(guid) self.db.execute(f'{delete_stmt} {where_clause}', vals)