Example #1
0
    def validate_imp(self, imp):
        """Validate that the implementation doesn't already exist in the database, and that the implementation files are on disk."""
        # Should not already exist
        if self.owner.imp_exists(imp=imp):
            raise ArgError(
                cmd=self.owner,
                arg="name",
                msg=
                f"An implementation named {imp} already exists in the database.",
            )

        # Should exist on disk
        list_firmware_imp = Path(
            inspect.getsourcefile(stack.commands.list.host.firmware),
        ).parent.resolve() / f"imp_{imp}.py"
        sync_firmware_imp = Path(
            inspect.getsourcefile(stack.commands.sync.host.firmware),
        ).parent.resolve() / f"imp_{imp}.py"
        if not list_firmware_imp.exists() or not sync_firmware_imp.exists():
            raise ArgError(
                cmd=self.owner,
                arg="name",
                msg=
                (f"Could not find an implementation named imp_{imp}.py. Please ensure an"
                 " implementation file is placed into each of the following locations:\n"
                 f"{list_firmware_imp}\n{sync_firmware_imp}"),
            )
Example #2
0
    def validate_regex(self, regex):
        """Make sure the provided regex is a valid Python regex."""
        # Don't allow empty string, which will compile into a regex fine.
        if not regex:
            raise ArgError(cmd=self.owner,
                           arg="regex",
                           msg=f"Regex cannot be an empty string.")

        # Require the version_regex to be a valid regex
        try:
            re.compile(regex)
        except re.error as exception:
            raise ArgError(cmd=self.owner,
                           arg="regex",
                           msg=f"Invalid regex supplied: {exception}.")
Example #3
0
    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
        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

        query = 'delete from storage_partition where scope = %s and tableid = %s'
        values = [scope, tableid]

        if device and device != '*':
            query += ' and device = %s'
            values.append(device)

        if mountpoint and mountpoint != '*':
            query += ' and mountpoint = %s'
            values.append(mountpoint)

        self.db.execute(query, values)
Example #4
0
    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))
Example #5
0
	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)
Example #6
0
    def validate_version(self, version, make, model):
        """Attempts to validate the version number against a version_regex if one is set for the
		make or model provided as well as ensuring the firmware version doesn't already exist.
		"""
        # Attempt to get the version regex entry.
        regex = self.owner.try_get_version_regex(make=make, model=model)
        if regex and not re.search(
                pattern=regex.regex, string=version, flags=re.IGNORECASE):
            raise ArgError(
                cmd=self.owner,
                arg="version",
                msg=
                (f"The format of the version number {version} does not validate based on the regex {regex.regex}"
                 f" named {regex.name}{f' with description {regex.description}' if regex.description else ''}."
                 ),
            )

        if self.owner.firmware_exists(make=make, model=model, version=version):
            raise ArgError(
                cmd=self.owner,
                arg="version",
                msg=
                f"The firmware version {version} for make {make} and model {model} already exists.",
            )
Example #7
0
	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))
Example #8
0
    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))
Example #9
0
    def run(self, args):
        params, hosts = args
        make, model, versions, sort, = self.owner.fillParams(names=[
            ("make", ""), ("model", ""), ("versions", ""), ("sort", "host")
        ],
                                                             params=params)

        sort_map = {
            "host": "nodes.Name",
            "make": "firmware_make.name",
            "model": "firmware_model.name",
            "version": "firmware.version",
        }
        # sort must be one of the allowed values
        try:
            # also convert to the column name for use in ORDER BY
            sort = sort_map[sort]
        except KeyError:
            raise ParamError(
                cmd=self.owner,
                param="sort",
                msg=f"Sort must be one of: {list(sort_map.keys())}")
        # process hosts if present
        if hosts:
            # hosts must exist
            hosts = self.owner.getHosts(args=hosts)
        # process make if present
        if make:
            # ensure the make exists
            if not self.owner.make_exists(make=make):
                raise ParamError(cmd=self.owner,
                                 param="make",
                                 msg=f"The make {make} doesn't exist.")
        # process model if present
        if model:
            # make is now required
            if not make:
                raise ParamRequired(cmd=self.owner, param="make")
            # ensure the model exists
            if not self.owner.model_exists(make=make, model=model):
                raise ParamError(
                    cmd=self.owner,
                    param="model",
                    msg=f"The model {model} doesn't exist for make {make}.")
        # Process versions if present
        if versions:
            # make and model are now required
            if not make:
                raise ParamRequired(cmd=self.owner, param="make")
            if not model:
                raise ParamRequired(cmd=self.owner, param="model")
            # turn a comma separated string into a list of versions and
            # get rid of any duplicate names
            versions = tuple(
                unique_everseen((version.strip()
                                 for version in versions.split(",")
                                 if version.strip())))
            # ensure the versions exist
            try:
                self.owner.ensure_firmwares_exist(make=make,
                                                  model=model,
                                                  versions=versions)
            except CommandError as exception:
                raise ArgError(cmd=self.owner,
                               arg="version",
                               msg=exception.message())

        results = self.get_firmware_mappings(
            hosts=hosts,
            make=make,
            model=model,
            versions=versions,
            sort=sort,
        )

        # return the results
        return {
            "keys": ["host", "version", "make", "model"],
            "values": results
        }
Example #10
0
    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)
Example #11
0
    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)
Example #12
0
    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)
Example #13
0
	def run(self, args):
		params, args = args
		make, model = self.owner.fillParams(
			names = [
				('make', None),
				('model', None)
			],
			params = params
		)
		# get rid of any duplicate names
		versions = tuple(unique_everseen(args))

		if versions:
			# if versions were provided, require a make and model
			if make is None:
				raise ParamRequired(cmd = self.owner, param = 'make')
			if model is None:
				raise ParamRequired(cmd = self.owner, param = 'model')
			# ensure the versions exist in the DB
			try:
				self.owner.ensure_firmwares_exist(make = make, model = model, versions = versions)
			except CommandError as exception:
				raise ArgError(
					cmd = self.owner,
					arg = 'version',
					msg = exception.message()
				)
			# check the files for the versions specified
			for row in self.owner.db.select(
				'''
				firmware.version, firmware.source, firmware.hash_alg, firmware.hash, firmware.file
				FROM firmware
					INNER JOIN firmware_model
						ON firmware.model_id=firmware_model.id
					INNER JOIN firmware_make
						ON firmware_model.make_id=firmware_make.id
				WHERE firmware.version IN %s AND firmware_make.name=%s AND firmware_model.name=%s
				''',
				(versions, make, model)
			):
				version, source, hash_alg, hash_value, local_file = row
				# check that the local file exists, and fetch it if not
				if not Path(local_file).exists():
					try:
						local_file = stack.firmware.fetch_firmware(
							source = source,
							make = make,
							model = model,
							filename = local_file.name
						)
					except stack.firmware.FirmwareError as exception:
						raise CommandError(
							cmd = self.owner,
							msg = f'Error while fetching version {version} for make {make} and model {model}: {exception}'
						)
				# verify the hash
				try:
					stack.firmware.calculate_hash(file_path = local_file, hash_alg = hash_alg, hash_value = hash_value)
				except stack.firmware.FirmwareError as exception:
					raise CommandError(
						cmd = self.owner,
						msg = f'Error during file verification: {exception}'
					)

		else:
			for row in self.owner.db.select(
				'''
				firmware.version, firmware.source, firmware.hash_alg, firmware.hash, firmware.file, firmware_make.name, firmware_model.name
				FROM firmware
					INNER JOIN firmware_model
						ON firmware.model_id=firmware_model.id
					INNER JOIN firmware_make
						ON firmware_model.make_id=firmware_make.id
				'''
			):
				version, source, hash_alg, hash_value, local_file, make, model = row
				local_file = Path(local_file)
				# check that the local file exists, and fetch it if not
				if not local_file.exists():
					try:
						local_file = stack.firmware.fetch_firmware(
							source = source,
							make = make,
							model = model,
							filename = local_file.name
						)
					except stack.firmware.FirmwareError as exception:
						raise CommandError(
							cmd = self.owner,
							msg = f'Error while fetching version {version} for make {make} and model {model}: {exception}'
						)
				# verify the hash
				try:
					stack.firmware.calculate_hash(file_path = local_file, hash_alg = hash_alg, hash_value = hash_value)
				except stack.firmware.FirmwareError as exception:
					raise CommandError(
						cmd = self.owner,
						msg = f'Error during file verification: {exception}'
					)

		# prune any files that shouldn't be there
		files_expected = [
			Path(file_path).resolve(strict = True)
			for file_path in (row[0] for row in self.owner.db.select('firmware.file FROM firmware'))
		]
		for file_path in stack.firmware.BASE_PATH.glob('**/*'):
			file_path = file_path.resolve(strict = True)
			if file_path.is_file() and file_path not in files_expected:
				file_path.unlink()