def run(self, params, args): hosts = self.getHostnames(args) (name, interface, mac) = self.fillParams([ ('name', None, True), ('interface', None), ('mac', None) ]) if len(name.split('.')) > 1: raise ParamType(self, 'name', 'non-FQDN (base hostname)') if not interface and not mac: raise ParamRequired(self, ('interface', 'mac')) if len(hosts) != 1: raise ArgUnique(self, 'host') host = hosts[0] if name.upper() == "NULL": name = host if interface: self.db.execute(""" update networks, nodes set networks.name='%s' where nodes.name='%s' and networks.node=nodes.id and networks.device like '%s' """ % (name, host, interface)) else: self.db.execute(""" update networks, nodes set networks.name='%s' where nodes.name='%s' and networks.node=nodes.id and networks.mac like '%s' """ % (name, host, mac))
def run(self, params, args): (vlan, interface, mac) = self.fillParams([('vlan', None, True), ('interface', None), ('mac', None)]) if not interface and not mac: raise ParamRequired(self, ('interface', 'mac')) try: vlanid = int(vlan) except: raise ParamType(self, 'vlan', 'integer') for host in self.getHostnames(args): if interface: self.db.execute(""" update networks net, nodes n set net.vlanid = IF(%d = 0, NULL, %d) where net.device like '%s' and n.name = '%s' and net.node = n.id """ % (vlanid, vlanid, interface, host)) else: self.db.execute(""" update networks net, nodes n set net.vlanid = IF(%d = 0, NULL, %d) where net.mac like'%s' and n.name = '%s' and net.node = n.id """ % (vlanid, vlanid, mac, host))
def run(self, params, args): (host, interface, port) = self.fillParams([('host', None), ('interface', None), ('port', None)]) switches = self.getSwitchNames(args) if len(switches) == 0: raise ArgRequired(self, 'switch') if len(switches) > 1: raise ArgUnique(self, 'switch') switch = switches[0] hosts = self.getHostnames([host]) host = hosts[0] if not host: raise ParamRequired(self, ('host')) if not interface: raise ParamRequired(self, ('interface')) if not port: raise ParamRequired(self, ('port')) try: port = int(port) except: raise ParamType(self, 'port', 'integer') # # check if the host/port is defined for this switch # found = False for o in self.call('list.switch.host', [switch]): if o['host'] == host and o['port'] == port: found = True if not found: raise ArgError(self, 'host/port', '"%s/%s" not found' % (host, port)) # # see if the interface exists for this host # row = self.db.select("""net.id from networks net, nodes n where n.name='%s' and net.device='%s' and net.node = n.id""" % (host, interface)) if not row: raise CommandError( self, 'interface "%s" does not exist for host "%s"' % (interface, host)) interfaceid, = row[0] self.db.execute("""update switchports set interface=%s where port=%s and switch=(select id from nodes where name='%s') """ % (interfaceid, port, switch))
def run(self, params, args): hosts = self.getHosts(args) (vlan, interface, mac, network) = self.fillParams([('vlan', None, True), ('interface', None), ('mac', None), ('network', None)]) # Gotta have one of these if not any([interface, mac, network]): raise ParamRequired(self, ('interface', 'mac', 'network')) # Make sure interface, mac, and/or network exist on our hosts self.validate(hosts, interface, mac, network) # vlan has to be an integer try: vlan = int(vlan) except: raise ParamType(self, 'vlan', 'integer') # If vlan is 0 then it should be NULL in the db if vlan == 0: vlan = None for host in hosts: if network: sql = """ update networks,nodes,subnets set networks.vlanid=%s where nodes.name=%s and subnets.name=%s and networks.node=nodes.id and networks.subnet=subnets.id """ values = [vlan, host, network] else: sql = """ update networks,nodes set networks.vlanid=%s where nodes.name=%s and networks.node=nodes.id """ values = [vlan, host] if interface: sql += " and networks.device=%s" values.append(interface) if mac: sql += " and networks.mac=%s" values.append(mac) self.db.execute(sql, values)
def run(self, params, args): if len(args) == 0: raise ArgRequired(self, 'network') if len(args) != 1: raise ArgUnique(self, 'network') name = args[0] if ' ' in name: raise CommandError(self, 'network name must not contain a space') (address, mask, gateway, mtu, zone, dns, pxe) = self.fillParams([('address', None, True), ('mask', None, True), ('gateway', None), ('mtu', '1500'), ('zone', name), ('dns', 'n'), ('pxe', 'n')]) dns = self.str2bool(dns) pxe = self.str2bool(pxe) # A None gateway is a blank string if gateway is None: gateway = '' # The mtu parameter needs to be an int if mtu: try: mtu = int(mtu) except: raise ParamType(self, 'mtu', 'integer') # Make sure the network doesn't already exist if self.db.count('(ID) from subnets where name=%s', (name, )) != 0: raise CommandError(self, 'network "%s" exists' % name) # Check that we are a valid network try: if ipaddress.IPv4Network(u"%s/%s" % (address, mask)): pass except: msg = '%s/%s is not a valid network address and subnet mask combination' raise CommandError(self, msg % (address, mask)) # Insert our data self.db.execute( """ insert into subnets (name, address, mask, gateway, mtu, zone, dns, pxe) values (%s, %s, %s, %s, %s, %s, %s, %s) """, (name, address, mask, gateway, mtu, zone, dns, pxe))
def run(self, params, args): host = self.getSingleHost(args) (name, interface, mac, network) = self.fillParams([ ('name', None, True), ('interface', None), ('mac', None), ('network', None) ]) # Name can't be a FQDN (IE: have dots) if '.' in name: raise ParamType(self, 'name', 'non-FQDN (base hostname)') # Gotta have one of these if not any([interface, mac, network]): raise ParamRequired(self, ('interface', 'mac', 'network')) # Make sure interface, mac, and/or network exist on our hosts self.validate([host], interface, mac, network) # If name is set to 'NULL' it gets the host name if name.upper() == 'NULL': name = host # Make the change in the DB if network: sql = """ update networks,nodes,subnets set networks.name=%s where nodes.name=%s and subnets.name=%s and networks.node=nodes.id and networks.subnet=subnets.id """ values = [name, host, network] else: sql = """ update networks,nodes set networks.name=%s where nodes.name=%s and networks.node=nodes.id """ values = [name, host] if interface: sql += " and networks.device=%s" values.append(interface) if mac: sql += " and networks.mac=%s" values.append(mac) self.db.execute(sql, values)
def run(self, params, args): switches = self.getSwitchNames(args) if not switches: raise ArgRequired(self, 'switch') elif len(switches) > 1: raise ArgUnique(self, 'switch') switch = switches[0] (host, interface, port) = self.fillParams([ ('host', None), ('interface', None), ('port', None) ]) hosts = self.getHostnames([host]) if not hosts: raise ParamRequired(self, ('host')) elif len(hosts) > 1: raise ParamUnique(self, 'host') host = hosts[0] try: port = int(port) except: raise ParamType(self, 'port', 'integer') # Check if the host/port is defined for this switch for row in self.call('list.switch.host', [switch]): if row['host'] == host and row['port'] == port: break else: raise ArgError(self, 'host/port', f'"{host}/{port}" not found') # See if the interface exists for this host row = self.db.select(""" networks.id FROM networks, nodes WHERE nodes.name=%s AND networks.device=%s AND networks.node=nodes.id """, (host, interface)) if not row: raise CommandError( self, f'interface "{interface}" does not exist for host "{host}"' ) self.db.execute(""" UPDATE switchports SET interface=%s WHERE port=%s AND switch=(SELECT id FROM nodes WHERE name=%s) """, (row[0][0], port, switch))
def run(self, params, args): switches = self.getSwitchNames(args) if not switches: raise ArgRequired(self, 'switch') elif len(switches) > 1: raise ArgUnique(self, 'switch') switch = switches[0] (host, interface, port) = self.fillParams([('host', None), ('interface', None), ('port', None)]) hosts = self.getHostnames([host]) if not hosts: raise ParamRequired(self, ('host')) elif len(hosts) > 1: raise ParamUnique(self, 'host') host = hosts[0] try: port = int(port) except: raise ParamType(self, 'port', 'integer') # Check if the host/interface is defined for this switch for row in self.call('list.switch.host', [switch]): if row['host'] == host and row['interface'] == interface: break else: raise ArgError(self, 'host/interface', f'"{host}/{interface}" not found') # Update the switch port self.db.execute( """ UPDATE switchports SET port=%s WHERE interface=( SELECT networks.id FROM networks, nodes WHERE nodes.name=%s AND networks.device=%s AND networks.node=nodes.id ) AND switch=(SELECT id FROM nodes WHERE name=%s) """, (port, host, interface, switch))
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): host = self.getSingleHost(args) (interface, mac, network, ip, module, name, vlan, default, options, channel, unsafe) = self.fillParams([ ('interface', None), ('mac', None), ('network', None), ('ip', None), ('module', None), ('name', None), ('vlan', None), ('default', None), ('options', None), ('channel', None), ('unsafe', False) ]) # Make sure empty strings are converted to None (interface, mac, network, ip, module, name, vlan, default, options, channel) = map(blank_str_to_None, ( interface, mac, network, ip, module, name, vlan, default, options, channel )) # Gotta have an interface or mac if not interface and not mac: raise ParamRequired(self, ('interface', 'mac')) # Name can't be a FQDN (IE: have dots) if name and '.' in name: raise ParamType(self, 'name', 'non-FQDN (base hostname)') # Check if the network exists subnet_id = None if network: rows = self.db.select('ID from subnets where name = %s', (network,)) if len(rows) == 0: raise CommandError(self, f'network "{network}" does not exist') else: subnet_id = rows[0][0] # The vlan parameter needs to be an int if vlan: try: vlan = int(vlan) except: raise ParamType(self, 'vlan', 'integer') # Stacki can use the usafe parameter to disable the check if the # interface already exists. The spreadsheet loading uses this # since before add.host.interface is called all the interfaces # are removed. unsafe = self.str2bool(unsafe) if not unsafe: for row in self.call('list.host.interface', [ host ]): if interface == row['interface']: raise CommandError(self, f'interface {interface} exists on {host}') if mac and mac == row['mac']: raise CommandError(self, f'mac {mac} exists on {host}') # Some parameters accept the string 'NULL' to mean put a NULL in the db if ip and ip.upper() == 'NULL': ip = None if module and module.upper() == 'NULL': module = None if channel and channel.upper() == 'NULL': channel = None # If name is set to 'NULL' it gets the host name, but confusingly # if name is None it gets a NULL in the db. Not sure the history # of this unique behavior. if name and name.upper() == 'NULL': name = host # If vlan is 0 then it should be NULL in the db if vlan == 0: vlan = None # Default is a boolean default = self.str2bool(default) # If ip is set to "auto" we let the 'set' command handle it ip_is_auto = False if ip and ip.upper() == "AUTO": ip_is_auto = True ip = None # The auto ip feature requires a network parameter if subnet_id is None: raise ParamRequired(self, 'network') # Unset other default interface if the added one is the default interface if default: self.db.execute(""" update networks set main=0 where node=(select id from nodes where name=%s) """, (host,) ) # Insert all our data self.db.execute(""" insert into networks( node, mac, ip, name, device, subnet, module, vlanid, options, channel, main ) values ( (select id from nodes where name=%s), %s, %s, %s, %s, %s, %s, %s, %s, %s, %s ) """,( host, mac, ip, name, interface, subnet_id, module, vlan, options, channel, default )) # Handle auto ip if needed if ip_is_auto: self.command('set.host.interface.ip', ( host, f'mac={mac}' if mac else f'interface={interface}', 'ip=auto' ))
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): 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): hosts = self.getHostnames(args) (interface, mac, network, ip, module, name, vlan, default, options, unsafe) = self.fillParams([('interface', None), ('mac', None), ('network', None), ('ip', None), ('module', None), ('name', None), ('vlan', None), ('default', None), ('options', None), ('unsafe', False)]) if not interface and not mac: raise ParamRequired(self, ('interface', 'mac')) if name and len(name.split('.')) > 1: raise ParamType(self, 'name', 'non-FQDN (base hostname)') if len(hosts) != 1: raise ArgUnique(self, 'host') host = hosts[0] # Stacki can use the usafe parameter to disable the check if the # interface already exists. The spreadsheet loading uses this # since before add.host.interface is called all the interfaces # are removed. unsafe = self.str2bool(unsafe) if not unsafe: for dict in self.call('list.host.interface', [host]): if interface == dict['interface']: raise CommandError(self, 'interface exists') if mac and mac == dict['mac']: raise CommandError(self, 'mac exists') fields = [ 'network', 'ip', 'module', 'name', 'vlan', 'default', 'options' ] # Insert the mac or interface into the database and then use # that to key off of for all the subsequent fields. # Give the MAC preferrence (need to pick one) but still do the # right thing when MAC and Interface are both specified. # # The MAC handle includes some optimization to include more # information on the initial insert, in order to reduce the # updates for each extra field. if mac: handle = 'mac=%s' % mac fields.append('interface') keys = ['node', 'mac'] vals = [ '(select id from nodes where name="%s")' % host, '"%s"' % mac ] if interface: fields.remove('interface') keys.append('device') vals.append('"%s"' % interface) if network: fields.remove('network') keys.append('subnet') vals.append('(select id from subnets s where s.name="%s")' % network) if ip: fields.remove('ip') keys.append('ip') vals.append('NULLIF("%s","NULL")' % ip.upper()) if name: if name.upper() == "NULL": name = host fields.remove('name') keys.append('name') vals.append('"%s"' % name) if default: fields.remove('default') keys.append('main') vals.append('%d' % self.str2bool(default)) if options: fields.remove('options') keys.append('options') vals.append('"%s"' % options) self.db.execute(""" insert into networks(%s) values (%s) """ % (','.join(keys), ','.join(vals))) else: handle = 'interface=%s' % interface fields.append('mac') self.db.execute(""" insert into networks(node, device) values ((select id from nodes where name='%s'), '%s') """ % (host, interface)) for key in fields: if key in params: self.command('set.host.interface.%s' % key, (host, handle, "%s=%s" % (key, params[key])))
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): # 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): # 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): # 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, ))