Esempio n. 1
0
def test_str2bool():

    for true in ['yes', 'true', 'on', '1']:
        assert str2bool(true)

    for false in ['no', 'false', 'off', '0']:
        assert not str2bool(false)
Esempio n. 2
0
def test_str2bool():

	for true in [ 'yes', 'true', 'on', '1' ]:
		assert str2bool(true)

	for false in [ 'no', 'false', 'off', '0' ]:
		assert not str2bool(false)
Esempio n. 3
0
    def traverse_stack_package(self, node):
        """Expands <stack:package> to native autoyast syntax, later passes
		will collect all these section to create a single
		<software> section.

		<software>
			<patterns config:type="list"> <!-- stack:type="meta" -->
				<pattern>?</pattern>
			</patterns>
			<packages config:type="list"> 
				<package>?</package>
				...
			</package>
		</software>

		"""

        stage = self.getAttr(node, 'stack:stage', default='install')

        meta = self.getAttr(node, 'stack:meta', default='false')
        meta = str2bool(meta)

        enabled = self.getAttr(node, 'stack:enable', default='true')
        enabled = str2bool(enabled)

        pkgs = []
        for line in self.collect(node).split('\n'):
            pkg = line.strip()
            if pkg:
                pkgs.append(pkg)

        if not meta:
            if stage == 'boot':
                packages = self.newElementNode('sles:post-packages')
            else:
                packages = self.newElementNode('sles:packages')
            self.setAttribute(packages, 'config:type', 'list')
            for rpm in pkgs:
                package = self.newElementNode('sles:package')
                package.appendChild(self.newTextNode(rpm))
                packages.appendChild(package)
        else:
            packages = self.newElementNode('sles:patterns')
            self.setAttribute(packages, 'config:type', 'list')

            for rpm in pkgs:
                package = self.newElementNode('sles:pattern')
                package.appendChild(self.newTextNode(rpm))
                packages.appendChild(package)

        software = self.newElementNode('sles:software')
        software.appendChild(packages)

        node.parentNode.replaceChild(software, node)
        return False
Esempio n. 4
0
    def partitions(self):
        """
		Return a dictionary of the partitions.
		partition['partition_name'] = {'pkey': int, 'ipoib': bool, 'guids': [list, of, member, guids]}
		"""

        partitions = {}
        cur_partition = None
        for line in self.proc.ask('show ib partition'):
            if re.match(members_header, line):
                # drop the 'members' line, because it can look like partition names
                # lord help us if someone names their partition 'members'
                continue
            if re.match(partition_name, line):
                cur_partition = line.strip()
                partitions[cur_partition] = {
                    'pkey': '',
                    'ipoib': False,
                    'guids': [],
                }
                continue

            line = line.strip()
            if line.startswith('PKey'):
                _, key = line.split('=')
                partitions[cur_partition]['pkey'] = int(key, 16)
            elif line.startswith('ipoib'):
                _, ipoib = line.split('=')
                partitions[cur_partition]['ipoib'] = str2bool(ipoib.strip())
            elif line.startswith('GUID'):
                m = re.search(guid_format, line)
                partitions[cur_partition]['guids'].append(m.group(0))

        info(partitions.keys())
        return partitions
Esempio n. 5
0
    def run(self, params, args):

        (order, expanded) = self.fillParams([
            ('order', 'asc'),
            ('expanded', False),
        ])

        self.expanded = str2bool(expanded)

        switches = self.getSwitchNames(args)

        header = ['switch']
        values = {}
        for switch in switches:
            values[switch] = []

        for (provides, result) in self.runPlugins(switches):
            header.extend(result['keys'])
            for h, v in result['values'].items():
                values[h].extend(v)

        self.beginOutput()
        for switch in switches:
            if values[switch]:
                self.addOutput(switch, values[switch])
        self.endOutput(header=header, trimOwner=False)
Esempio n. 6
0
	def run(self, params, args):
		if len(args) != 1:
			raise ArgUnique(self, 'switch')

		sm_switch = args[0]

		(disable, ) = self.fillParams([
			('disable', False),
		])

		disable = str2bool(disable)

		ibswitches = [sw for sw in self.call('list.switch') if sw['model'] == 'm7800']
		ib_switch_names = [sw['switch'] for sw in ibswitches]

		if sm_switch not in ib_switch_names:
			msg = f'host {sm_switch} is not a supported infiniband switch\n'
			msg += 'Please verify the make and model attributes for this host.'
			raise CommandError(self, msg)

		self.switch_attrs = self.getHostAttrDict(ib_switch_names)

		if self.switch_attrs[sm_switch].get('switch_type') != 'infiniband':
			msg = f'{sm_switch} is not an infiniband switch, please verify "stack list host attr {sm_switch} attr=switch_type"'

		if disable:
			# explicit disable only affects this switch
			switch = self.get_sw_handle(sm_switch)
			switch.subnet_manager = False
			switch.disconnect()
			return

		# NOTE assumes a single management port with options set.
		# this obviously breaks if a switch can someday be on multiple fabrics
		fabric = self.switch_attrs[sm_switch].get('ibfabric')
		if not fabric:
			raise CommandError(self, f'switch {sm_switch} does not have its ibfabric set')

		switches_to_disable = []
		for ib_sw in ib_switch_names:
			if ib_sw == sm_switch:
				# this one is the sm
				continue

			sw_fabric = self.switch_attrs[ib_sw].get('ibfabric')
			if not sw_fabric or sw_fabric == fabric:
				# switches with no fabric specified should be disabled
				# other switches on the same fabric should be disabled
				switches_to_disable.append(ib_sw)
				continue

		for switch in switches_to_disable:
			sw_handle = self.get_sw_handle(switch)
			sw_handle.subnet_manager = False
			sw_handle.disconnect()

		sw_handle = self.get_sw_handle(sm_switch)
		sw_handle.subnet_manager = True
		sw_handle.disconnect()
Esempio n. 7
0
	def traverse_stack_file(self, node):
		"""<stack:file>

		Convert the file tags the shell code along with rcs
		ci/co.

		"""
	
		fileName    = self.getAttr(node, 'stack:name')
		fileMode    = self.getAttr(node, 'stack:mode')
		fileOwner   = self.getAttr(node, 'stack:owner')
		filePerms   = self.getAttr(node, 'stack:perms')
		fileQuoting = self.getAttr(node, 'stack:vars', default='literal')
		fileCommand = self.getAttr(node, 'stack:expr')
		fileText    = self.collect(node)

		fileRCS	    = self.getAttr(node, 'stack:rcs', default='true')
		fileRCS     = str2bool(fileRCS)


		if fileName:
			p, f = os.path.split(fileName)
			s    = 'if [ ! -e %s ]; then mkdir -p %s; fi\n' % (p, p)

			if fileRCS:
				s += self.rcsBegin(fileName, fileOwner, filePerms)

			if fileMode == 'append':
				gt = '>>'
			else:
				gt = '>'

			if fileCommand:
				s += '%s %s %s\n' % (fileCommand, gt, fileName)
			if not fileText:
				s += 'touch %s\n' % fileName
			else:
				if fileQuoting == 'expanded':
					eof = "EOF"
				else:
					eof = "'EOF'"

				s += "cat %s %s << %s" % (gt, fileName, eof)
				if fileText[0] != '\n':
					s += '\n'
				s += fileText
				if fileText[-1] != '\n':
					s += '\n'
				s += 'EOF\n'

			if fileOwner:
				s += 'chown %s %s\n' % (fileOwner, fileName)
			if filePerms:
				s += 'chmod %s %s\n' % (filePerms, fileName)

		node.parentNode.replaceChild(self.newTextNode(s), node)
		return False
Esempio n. 8
0
    def run(self, params, args):

        document, self.exec_commands, self.force = self.fillParams([
            ('document', None),
            ('exec', False),
            ('force', False),
        ])
        self.exec_commands = str2bool(self.exec_commands)
        self.force = str2bool(self.force)

        if not document:
            if not args:
                raise ArgRequired(self, 'filename')
            if len(args) > 1:
                raise ArgUnique(self, 'filename')
            document = self.load_file(args[0])

        self.main(document)
Esempio n. 9
0
	def traverse_stack_file(self, node):
		"""<stack:file>

		Convert the file tags the shell code along with rcs
		ci/co.

		"""
	
		fileName    = self.getAttr(node, 'stack:name')
		fileMode    = self.getAttr(node, 'stack:mode')
		fileOwner   = self.getAttr(node, 'stack:owner')
		filePerms   = self.getAttr(node, 'stack:perms')
		fileQuoting = self.getAttr(node, 'stack:vars', default='literal')
		fileCommand = self.getAttr(node, 'stack:expr')
		fileText    = self.collect(node)

		fileRCS	    = self.getAttr(node, 'stack:rcs', default='true')
		fileRCS     = str2bool(fileRCS)


		if fileName:
			p, f = os.path.split(fileName)
			s    = 'if [ ! -e %s ]; then mkdir -p %s; fi\n' % (p, p)

			if fileRCS:
				s += self.rcsBegin(fileName, fileOwner, filePerms)

			if fileMode == 'append':
				gt = '>>'
			else:
				gt = '>'

			if fileCommand:
				s += '%s %s %s\n' % (fileCommand, gt, fileName)
			if not fileText:
				s += 'touch %s\n' % fileName
			else:
				if fileQuoting == 'expanded':
					eof = "EOF"
				else:
					eof = "'EOF'"

				s += "cat %s %s << %s" % (gt, fileName, eof)
				if fileText[0] != '\n':
					s += '\n'
				s += fileText
				if fileText[-1] != '\n':
					s += '\n'
				s += 'EOF\n'

			if fileOwner:
				s += 'chown %s %s\n' % (fileOwner, fileName)
			if filePerms:
				s += 'chmod %s %s\n' % (filePerms, fileName)

		node.parentNode.replaceChild(self.newTextNode(s), node)
		return False
Esempio n. 10
0
def test_call():
	"""
	Test the stack.api.Call function to verify it returns
	a list of dictionaries.
	"""

	found = False
	for dict in Call('list appliance'):
		if dict['appliance'] == 'backend':
			found = True
			assert str2bool(dict['public'])
	assert found
Esempio n. 11
0
    def partitions(self):
        """
		Return a dictionary of the partitions.
		partition['partition_name'] = {'pkey': int, 'ipoib': bool, 'guids': [list, of, member, guids]}
		"""

        partitions = {}
        cur_partition = None
        new_console_format = None
        for line in remove_blank_lines(
                lines=self.proc.ask('show ib partition')):
            if re.match(members_header, line):
                # drop the 'members' line, because it can look like partition names
                # lord help us if someone names their partition 'members'
                continue

            header_match = re.match(partition_name, line)
            if header_match:
                # This should be the first thing we encounter when looping through the console
                # response, so we use it to set the format for the rest of the loop
                if new_console_format is None:
                    if header_match.group("format_1"):
                        new_console_format = False
                    elif header_match.group("format_2"):
                        new_console_format = True
                elif new_console_format and not header_match.group("format_2"):
                    continue
                elif not new_console_format and not header_match.group(
                        "format_1"):
                    continue

                cur_partition = line.strip().strip(":")
                partitions[cur_partition] = {
                    'pkey': '',
                    'ipoib': False,
                    'guids': {},
                }
                continue

            line = line.strip()
            if line.startswith('PKey'):
                _, key = line.split(':' if new_console_format else '=')
                partitions[cur_partition]['pkey'] = int(key, 16)
            elif line.startswith('ipoib'):
                _, ipoib = line.split(':' if new_console_format else '=')
                partitions[cur_partition]['ipoib'] = str2bool(ipoib.strip())
            elif line.startswith('GUID'):
                m = re.search(guid_member_format, line)
                guid, membership = m.groups()[0].lower(), m.groups()[2]
                partitions[cur_partition]['guids'][guid] = membership

        info(partitions.keys())
        return partitions
Esempio n. 12
0
def test_call():
	"""
	Test the stack.api.Call function to verify it returns
	a list of dictionaries.
	"""

	found = False
	for dict in Call('list appliance'):
		if dict['appliance'] == 'backend':
			found = True
			assert str2bool(dict['public'])
	assert found
Esempio n. 13
0
	def partitions(self):
		"""
		Return a dictionary of the partitions.
		partition['partition_name'] = {'pkey': int, 'ipoib': bool, 'guids': [list, of, member, guids]}
		"""

		partitions = {}
		cur_partition = None
		new_console_format = None
		for line in remove_blank_lines(lines = self.proc.ask('show ib partition')):
			if re.match(members_header, line):
				# drop the 'members' line, because it can look like partition names
				# lord help us if someone names their partition 'members'
				continue

			header_match = re.match(partition_name, line)
			if header_match:
				# This should be the first thing we encounter when looping through the console
				# response, so we use it to set the format for the rest of the loop
				if new_console_format is None:
					if header_match.group("format_1"):
						new_console_format = False
					elif header_match.group("format_2"):
						new_console_format = True
				elif new_console_format and not header_match.group("format_2"):
					continue
				elif not new_console_format and not header_match.group("format_1"):
					continue

				cur_partition = line.strip().strip(":")
				partitions[cur_partition] = {
					'pkey': '',
					'ipoib': False,
					'guids': {},
				}
				continue

			line = line.strip()
			if line.startswith('PKey'):
				_, key = line.split(':' if new_console_format else '=')
				partitions[cur_partition]['pkey'] = int(key, 16)
			elif line.startswith('ipoib'):
				_, ipoib = line.split(':' if new_console_format else '=')
				partitions[cur_partition]['ipoib'] = str2bool(ipoib.strip())
			elif line.startswith('GUID'):
				m = re.search(guid_member_format, line)
				guid, membership = m.groups()[0].lower(), m.groups()[2]
				partitions[cur_partition]['guids'][guid] = membership

		info(partitions.keys())
		return partitions
Esempio n. 14
0
    def run(self, params, args):

        attrs, = self.fillParams([('attribute', None)])

        if attrs is not None:
            attrs = attrs.split(',')
        else:
            attrs = []

        groups = {}
        for row in self.call('list.host.attr'):

            host = row['host']
            attr = row['attr']
            val = row['value']

            # TODO - Update to use the qualifier to scope these
            # groups (e.g. a:backend)

            if attr == 'appliance':
                if val not in groups:
                    groups[val] = {'hosts': []}
                groups[val]['hosts'].append(host)

            elif attr == 'rack':
                rack = 'rack%s' % val
                if rack not in groups:
                    groups[rack] = {'hosts': []}
                groups[rack]['hosts'].append(host)

            elif attr == 'managed':
                if str2bool(val) is True:
                    if attr not in groups:
                        groups[attr] = {'hosts': []}
                    groups['managed']['hosts'].append(host)

            elif attr in attrs:
                if attr not in groups:
                    groups[attr] = {'hosts': []}
                groups[attr]['hosts'].append(host)

        self.beginOutput()
        self.addOutput('', '<stack:file stack:name="/etc/ansible/hosts">')
        for cat in groups:
            self.addOutput('', '[%s]' % cat)
            hostlist = '\n'.join(groups[cat]['hosts'])
            self.addOutput('', hostlist)
            self.addOutput('', '')
        self.addOutput('', '</stack:file>')
        self.endOutput(padChar='')
Esempio n. 15
0
	def traverse_stack_package(self, node):
		"""<stack:package>

		Build the packageSet.

		"""

		nodefile = self.getAttr(node, 'stack:file')

		meta	 = self.getAttr(node, 'stack:meta', default='false')
		meta     = str2bool(meta)

		enabled  = self.getAttr(node, 'stack:enable', default='true')
		enabled  = str2bool(enabled)

		for line in self.collect(node).split('\n'):
			pkg = line.strip()
			if pkg:
				if meta:
					pkg = '@%s' % pkg
				self.gen.packageSet.append(pkg, enabled, nodefile)

		return False
Esempio n. 16
0
    def traverse_stack_package(self, node):
        """<stack:package>

		Build the packageSet.

		"""

        nodefile = self.getAttr(node, 'stack:file')

        meta = self.getAttr(node, 'stack:meta', default='false')
        meta = str2bool(meta)

        enabled = self.getAttr(node, 'stack:enable', default='true')
        enabled = str2bool(enabled)

        for line in self.collect(node).split('\n'):
            pkg = line.strip()
            if pkg:
                if meta:
                    pkg = '@%s' % pkg
                self.gen.packageSet.append(pkg, enabled, nodefile)

        return False
Esempio n. 17
0
	def traverse(self, node):
		"""<*>

		stack:gc="true" means garabage collect the node.
		
		Any previous traversal can set this attribute
		to have the tag removed from the tree.

		"""

		gc = self.getAttr(node, 'stack:gc')
		gc = str2bool(gc)

		if gc:
			self.removeNode(node)
		return True
Esempio n. 18
0
    def doSecureErase(self, enclosure, adapter, slot):
        if enclosure:
            slotaddress = '/c%d/e%d/s%d' % \
             (adapter, enclosure, slot)
        else:
            slotaddress = '/c%d/s%d' % (adapter, slot)

        res = self.run([slotaddress, 'show', 'all'])
        if res['Command Status']['Status'] == 'Failure':
            return
        s = res['Response Data'][
            'Drive %s - Detailed Information' %
            slotaddress]['Drive %s Policies/Settings' %
                         slotaddress]['Cryptographic Erase Capable']
        if str2bool(s):
            self.run([slotaddress, 'secureerase', 'force'])
Esempio n. 19
0
    def traverse(self, node):
        """<*>

		stack:gc="true" means garabage collect the node.
		
		Any previous traversal can set this attribute
		to have the tag removed from the tree.

		"""

        gc = self.getAttr(node, 'stack:gc')
        gc = str2bool(gc)

        if gc:
            self.removeNode(node)
        return True
Esempio n. 20
0
    def run(self, params, args):
        prms = self._params
        # Get Host Attributes
        s = self.call('list.host.attr')

        host_bucket = {'managed': {'hosts': []}}
        for i in s:
            host = i['host']
            attr = i['attr']
            val = i['value']
            # Categorize by appliances
            if attr == 'appliance':
                if val not in host_bucket:
                    host_bucket[val] = {'hosts': []}
                host_bucket[val]['hosts'].append(host)
            # Categorize by rack
            if attr == 'rack':
                rack = 'rack%s' % val
                if rack not in host_bucket:
                    host_bucket[rack] = {'hosts': []}
                host_bucket[rack]['hosts'].append(host)
            # Managed Hosts
            if attr == 'managed':
                if str2bool(val) == True:
                    host_bucket['managed']['hosts'].append(host)
#			if len(prms) > 0:
            if prms:
                k = list(prms.keys())
                if 'attribute' in k:
                    for i in prms['attribute'].split(','):
                        if attr == i:
                            if attr not in host_bucket:
                                host_bucket[attr] = {'hosts': []}
                            host_bucket[attr]['hosts'].append(host)
                else:
                    raise CommandError(self,
                                       'argument "%s" not recognized' % k[0])
        self.beginOutput()
        self.addOutput('', '<stack:file stack:name="/etc/ansible/hosts">')
        for cat in host_bucket:
            self.addOutput('', '[%s]' % cat)
            hostlist = '\n'.join(host_bucket[cat]['hosts'])
            self.addOutput('', hostlist)
            self.addOutput('', '')
        self.addOutput('', '</stack:file>')
        self.endOutput()
Esempio n. 21
0
	def traverse_stack_script(self, node):
		"""<stack:script>

		"""
		nodefile = self.getAttr(node, 'stack:file')
		stage    = self.getAttr(node, 'stack:stage',  default='install-post')
		shell    = self.getAttr(node, 'stack:shell')
		flags    = [ ]

		if stage == 'install-post':
			chroot = str2bool(self.getAttr(node, 'stack:chroot', default='true'))
		else:
			chroot = False

		if stage == 'install-post' and not chroot:
			flags.append('--nochroot')
			flags.append('--log /mnt/sysimage%s' % self.gen.log)
		else:
			flags.append('--log %s' % self.gen.log)

		if shell:
			flags.append('--interpreter %s' % shell)

		script = [ ]
		if stage in self.stages:
			script.append('%%%s %s' % (self.stages[stage], 
						   ' '.join(flags)))
			script.append(self.collect(node))
			script.append('%end')
		elif stage in [ 'boot-pre', 'boot-post' ]:
			boot, when = stage.split('-')

			script = [ '%%post --log %s' % self.gen.log ]
			script.append("cat >> /etc/sysconfig/stack-%s << '__EOF__'" % when)
			script.append(self.collect(node))
			script.append('__EOF__')
			script.append('%end')

		self.gen.scriptSection.append('\n'.join(script), nodefile)
		return False
Esempio n. 22
0
    def traverse_stack_script(self, node):
        """<stack:script>

		"""
        nodefile = self.getAttr(node, 'stack:file')
        stage = self.getAttr(node, 'stack:stage', default='install-post')
        shell = self.getAttr(node, 'stack:shell')
        flags = []

        if stage == 'install-post':
            chroot = str2bool(
                self.getAttr(node, 'stack:chroot', default='true'))
        else:
            chroot = False

        if stage == 'install-post' and not chroot:
            flags.append('--nochroot')
            flags.append('--log /mnt/sysimage%s' % self.gen.log)
        else:
            flags.append('--log %s' % self.gen.log)

        if shell:
            flags.append('--interpreter %s' % shell)

        script = []
        if stage in self.stages:
            script.append('%%%s %s' % (self.stages[stage], ' '.join(flags)))
            script.append(self.collect(node))
            script.append('%end')
        elif stage in ['boot-pre', 'boot-post']:
            boot, when = stage.split('-')

            script = ['%%post --log %s' % self.gen.log]
            script.append("cat >> /etc/sysconfig/stack-%s << '__EOF__'" % when)
            script.append(self.collect(node))
            script.append('__EOF__')
            script.append('%end')

        self.gen.scriptSection.append('\n'.join(script), nodefile)
        return False
Esempio n. 23
0
	def run(self, args):

		host = args[0]

		bond_reg = re.compile('bond[0-9]+')
		udev_output = ""

		result = self.owner.call('list.host.interface', [ 'expanded=true', host ])
		for o in result:
			interface = o['interface']
			default   = str2bool(o['default'])
			ip        = o['ip']
			netname   = o['network']
			vlanid    = o['vlan']
			mac       = o['mac']
			if mac:
				mac = mac.lower()
			channel   = o['channel']
			options   = o['options']
			netmask   = o['mask']
			gateway   = o['gateway']

			startmode = None
			bootproto = 'static'

			if ip and not netname:
				Warn(f'WARNING: skipping interface "{interface}" on host "{o["host"]}" - '
				      'interface has an IP but no network')
				continue

			# If we don't have an interface, we don't need a config file
			if not interface:
				continue

			if netname and ip and netmask:
				net       = ipaddress.IPv4Network('%s/%s' % (ip, netmask), strict=False)
				broadcast = str(net.broadcast_address)
				network   = str(net.network_address)
			else:
				broadcast = None
				network   = None

			if options:
				options = shlex.split(o['options'])
			else:
				options = []

			if 'noreport' in options:
				continue # don't do anything if noreport set

			ib_re = re.compile('^ib[0-9]+$')
			if mac:
				if not ib_re.match(interface) and interface != 'ipmi':
					udev_output += 'SUBSYSTEM=="net", '
					udev_output += 'ACTION=="add", '
					udev_output += 'DRIVERS=="?*", '
					udev_output += 'ATTR{address}=="%s", ' % mac
					udev_output += 'ATTR{type}=="1", '
					udev_output += 'KERNEL=="eth*", '
					udev_output += 'NAME="%s"\n\n' % interface

			if interface == 'ipmi':
				ipmisetup = '/tmp/ipmisetup'
				self.owner.addOutput(host, '<stack:file stack:name="%s">' % ipmisetup)
				self.owner.writeIPMI(host, ip, channel, netmask, gateway, vlanid)
				self.owner.addOutput(host, '</stack:file>')
				self.owner.addOutput(host, 'chmod 500 %s' % ipmisetup)
				continue

			if len(interface.split(':')) == 2:
				#
				# virtual interface configuration
				#
				self.owner.addOutput(host, 
						     '<stack:file stack:mode="append" stack:name="/etc/sysconfig/network/ifcfg-%s">' 
						     % interface.split(':')[0])

				self.owner.addOutput(host, '# AUTHENTIC STACKI')

				vnum = interface.split(':')[1]
				if ip:
					self.owner.addOutput(host, 'IPADDR%s=%s' % (vnum, ip))
				if netmask:
					self.owner.addOutput(host, 'NETMASK%s=%s' % (vnum, netmask))
				if network:
					self.owner.addOutput(host, 'NETWORK%s=%s' % (vnum, network))
				if broadcast:
					self.owner.addOutput(host, 'BROADCAST%s=%s' % (vnum, broadcast))
					
				self.owner.addOutput(host, 'LABEL%s=%s' % (vnum, vnum))

			else:
				self.owner.addOutput(host, 
				     '<stack:file stack:name="/etc/sysconfig/network/ifcfg-%s">' 
				     % interface)

				self.owner.addOutput(host, '# AUTHENTIC STACKI')

				if vlanid and self.owner.host_based_routing(host, interface, vlanid):
					parent_device = interface.strip().split('.')[0]
					self.owner.addOutput(host, 'ETHERDEVICE=%s' % parent_device)
					self.owner.addOutput(host, 'VLAN=yes')
					startmode = 'auto'
				else:
					self.owner.addOutput(host, 'USERCONTROL=no')

				dhcp = 'dhcp' in options

				if dhcp:
					bootproto = 'dhcp'
					if default:
						self.owner.addOutput(host, 'DHCLIENT_SET_HOSTNAME="yes"')
						self.owner.addOutput(host, 'DHCLIENT_SET_DEFAULT_ROUTE="yes"')
					else:
						self.owner.addOutput(host, 'DHCLIENT_SET_HOSTNAME="no"')
						self.owner.addOutput(host, 'DHCLIENT_SET_DEFAULT_ROUTE="no"')

				if 'onboot=no' in options:
					startmode = 'manual'
				elif ip or dhcp or channel or 'bridge' in options:
					#
					# if there is an IP address, or this
					# interface should DHCP, or anything in
					# the 'channel' field (e.g., this is a
					# bridged or bonded interface), or if 'bridge'
					# is in the options, then turn this interface on
					#
					startmode = 'auto'
				
				if not dhcp:
					if ip:
						self.owner.addOutput(host, 'IPADDR=%s' % ip)
					if netmask:
						self.owner.addOutput(host, 'NETMASK=%s' % netmask)
					if network:
						self.owner.addOutput(host, 'NETWORK=%s' % network)
					if broadcast:
						self.owner.addOutput(host, 'BROADCAST=%s' % broadcast)

				if mac:
					self.owner.addOutput(host, 'HWADDR=%s' % mac.strip())

				#
				# bonded interface, e.g., 'bond0'
				#
				if bond_reg.match(interface):
					#
					# if a 'bond*' device is present, then always make
					# sure it is enabled on boot.
					#
					startmode = 'auto'

					self.owner.addOutput(host, 'BONDING_MASTER=yes')

					#
					# find the interfaces that are part of this bond
					#
					i = 0
					for p in result:
						if p['channel'] == interface:
							self.owner.addOutput(host,
								'BONDING_SLAVE%d="%s"'
								% (i, p['interface']))
							i = i + 1

					#
					# Check if there are bonding options set
					#
					for opt in options:
						if opt.startswith('bonding-opts='):
							i = opt.find('=')
							bo = opt[i + 1:]
							self.owner.addOutput(host,
								'BONDING_MODULE_OPTS="%s"' % bo)
							break

				#
				# check if this is part of a bonded channel
				#
				if channel and bond_reg.match(channel):
					startmode = 'auto'
					bootproto = 'none'

				if not startmode:
					startmode = 'off'

				self.owner.addOutput(host, 'STARTMODE=%s' % startmode)
				self.owner.addOutput(host, 'BOOTPROTO=%s' % bootproto)

				#
				# if this is a bridged interface, then go look for the
				# physical interface this bridge is associated with
				#
				if 'bridge' in options:
					for p in result:
						if p['channel'] == interface:
							self.owner.addOutput(host, 'BRIDGE=yes')
							self.owner.addOutput(host, 'BRIDGE_FORWARDDELAY=0')
							self.owner.addOutput(host, 'BRIDGE_STP=off')
							self.owner.addOutput(host, 'BRIDGE_PORTS=%s' % p['interface'])
							break

			self.owner.addOutput(host, '\n')
			self.owner.addOutput(host, '</stack:file>')

		if udev_output:
			self.owner.addOutput(host, 
					     '<stack:file stack:name="/etc/udev/rules.d/70-persistent-net.rules">')
			self.owner.addOutput(host, udev_output)
			self.owner.addOutput(host, '</stack:file>')
Esempio n. 24
0
    def addHostAttrs(self, attributes):
        readonly = {}

        versions = {}
        for row in self.call('list.pallet'):
            # Compute a version number for each os pallet
            #
            # If the pallet already has a '.' take everything
            # before the '.' and add '.x'. If the version has no
            # '.' add '.x'
            name = row['name']
            version = row['version']
            release = row['release']
            key = '%s-%s-%s' % (name, version, release)

            if name in ['SLES', 'CentOS']:  # FIXME: Ubuntu is missing
                versions[key] = (name, '%s.x' % version.split('.')[0])

        boxes = {}
        for row in self.call('list.box'):
            pallets = row['pallets'].split()
            carts = row['carts'].split()

            name = 'unknown'
            version = 'unknown'
            for pallet in pallets:
                if pallet in versions.keys():
                    (name, version) = versions[pallet]
                    break

            boxes[row['name']] = {
                'pallets': pallets,
                'carts': carts,
                'os.name': name,
                'os.version': version
            }

        for (name, environment, rack, rank, metadata) in self.db.select("""
				n.name, e.name, n.rack, n.rank, n.metadata 
				from nodes n
				left join environments e on n.environment=e.id
				"""):
            readonly[name] = {}
            readonly[name]['rack'] = rack
            readonly[name]['rank'] = rank
            if environment:
                readonly[name]['environment'] = environment
            if metadata:
                readonly[name]['metadata'] = metadata

        for (name, box, appliance) in self.db.select(""" 
				n.name, b.name,
				a.name from
				nodes n, boxes b, appliances a where
				n.appliance=a.id and n.box=b.id
				"""):
            readonly[name]['box'] = box
            readonly[name]['pallets'] = boxes[box]['pallets']
            readonly[name]['carts'] = boxes[box]['carts']
            #			readonly[name]['os.name']            = boxes[box]['os.name']
            readonly[name]['os.version'] = boxes[box]['os.version']
            readonly[name]['appliance'] = appliance

        for (name, zone, address) in self.db.select("""
				n.name, s.zone, nt.ip from
				networks nt, nodes n, subnets s where
				nt.main=true and nt.node=n.id and
				nt.subnet=s.id
				"""):
            if address:
                readonly[name]['hostaddr'] = address
            readonly[name]['domainname'] = zone

        for host in readonly:
            readonly[host]['os'] = self.db.getHostOS(host)
            readonly[host]['hostname'] = host

        for row in self.call('list.host.group'):
            for group in row['groups'].split():
                readonly[row['host']]['group.%s' % group] = 'true'
            readonly[row['host']]['groups'] = row['groups']

        for host in attributes:
            a = attributes[host]
            r = readonly[host]
            ro = True

            if 'const_overwrite' in a:

                # This attribute allows a host to overwrite
                # constant attributes. This is crazy dangerous,
                # do not use this attribute.

                (n, v, t, s) = a['const_overwrite']
                ro = str2bool(v)

            if ro:
                for key in r:  # slam consts on top of attrs
                    a[key] = (r[key], 'const', 'host')
            else:
                for key in r:  # only add new consts to attrs
                    if key not in a:
                        a[key] = (r[key], 'const', 'host')

        return attributes
Esempio n. 25
0
                try:
                        help.run({'subdir': submodpath}, [])
                except stack.exception.CommandError, e:
                        sys.stderr.write('%s\n' % e)
                        return -1
		print help.getText()
		return -1

        
	# Check to see if STACKDEBUG variable is set.
	# This determines if the stack trace should be
	# dumped when an exception occurs.
        
	STACKDEBUG = None
	if os.environ.has_key('STACKDEBUG'):
		STACKDEBUG = str2bool(os.environ['STACKDEBUG'])

	try:
		command = getattr(module, 'Command')(Database)
		t0 = time.time()
		rc = command.runWrapper(name, args[i:])
#		syslog.syslog(syslog.LOG_INFO, 'runtime %.3f' % (time.time() - t0))
	except stack.exception.CommandError as e:
		sys.stderr.write('%s\n' % e)
		syslog.syslog(syslog.LOG_ERR, '%s' % e)
                return -1
	except:
		# Sanitize Exceptions, and log them.
		exc, msg, tb = sys.exc_info()
		for line in traceback.format_tb(tb):
			syslog.syslog(syslog.LOG_DEBUG, '%s' % line)
Esempio n. 26
0
    def run(self, args):

        host = args[0]

        bond_reg = re.compile('bond[0-9]+')
        udev_output = ""

        result = self.owner.call('list.host.interface',
                                 ['expanded=true', host])
        for o in result:
            interface = o['interface']
            default = str2bool(o['default'])
            ip = o['ip']
            netname = o['network']
            vlanid = o['vlan']
            mac = o['mac']
            if mac:
                mac = mac.lower()
            channel = o['channel']
            options = o['options']
            netmask = o['mask']
            gateway = o['gateway']

            startmode = None
            bootproto = 'static'

            if ip and not netname:
                Warn(
                    f'WARNING: skipping interface "{interface}" on host "{o["host"]}" - '
                    'interface has an IP but no network')
                continue

            if netname and ip and netmask:
                net = ipaddress.IPv4Network('%s/%s' % (ip, netmask),
                                            strict=False)
                broadcast = str(net.broadcast_address)
                network = str(net.network_address)
            else:
                broadcast = None
                network = None

            if options:
                options = shlex.split(o['options'])
            else:
                options = []

            if 'noreport' in options:
                continue  # don't do anything if noreport set

            ib_re = re.compile('^ib[0-9]+$')
            if mac:
                if not ib_re.match(interface) and interface != 'ipmi':
                    udev_output += 'SUBSYSTEM=="net", '
                    udev_output += 'ACTION=="add", '
                    udev_output += 'DRIVERS=="?*", '
                    udev_output += 'ATTR{address}=="%s", ' % mac
                    udev_output += 'ATTR{type}=="1", '
                    udev_output += 'KERNEL=="eth*", '
                    udev_output += 'NAME="%s"\n\n' % interface

            if not interface:
                continue

            if interface == 'ipmi':
                ipmisetup = '/tmp/ipmisetup'
                self.owner.addOutput(
                    host, '<stack:file stack:name="%s">' % ipmisetup)
                self.owner.writeIPMI(host, ip, channel, netmask, gateway,
                                     vlanid)
                self.owner.addOutput(host, '</stack:file>')
                self.owner.addOutput(host, 'chmod 500 %s' % ipmisetup)
                continue

            if len(interface.split(':')) == 2:
                #
                # virtual interface configuration
                #
                self.owner.addOutput(
                    host,
                    '<stack:file stack:mode="append" stack:name="/etc/sysconfig/network/ifcfg-%s">'
                    % interface.split(':')[0])

                self.owner.addOutput(host, '# AUTHENTIC STACKI')

                vnum = interface.split(':')[1]
                if ip:
                    self.owner.addOutput(host, 'IPADDR%s=%s' % (vnum, ip))
                if netmask:
                    self.owner.addOutput(host,
                                         'NETMASK%s=%s' % (vnum, netmask))
                if network:
                    self.owner.addOutput(host,
                                         'NETWORK%s=%s' % (vnum, network))
                if broadcast:
                    self.owner.addOutput(host,
                                         'BROADCAST%s=%s' % (vnum, broadcast))

                self.owner.addOutput(host, 'LABEL%s=%s' % (vnum, vnum))

            else:
                self.owner.addOutput(
                    host,
                    '<stack:file stack:name="/etc/sysconfig/network/ifcfg-%s">'
                    % interface)

                self.owner.addOutput(host, '# AUTHENTIC STACKI')

                if vlanid and self.owner.host_based_routing(
                        host, interface, vlanid):
                    parent_device = interface.strip().split('.')[0]
                    self.owner.addOutput(host,
                                         'ETHERDEVICE=%s' % parent_device)
                    self.owner.addOutput(host, 'VLAN=yes')
                    startmode = 'auto'
                else:
                    self.owner.addOutput(host, 'USERCONTROL=no')

                dhcp = 'dhcp' in options

                if dhcp:
                    bootproto = 'dhcp'
                    if default:
                        self.owner.addOutput(host,
                                             'DHCLIENT_SET_HOSTNAME="yes"')
                        self.owner.addOutput(
                            host, 'DHCLIENT_SET_DEFAULT_ROUTE="yes"')
                    else:
                        self.owner.addOutput(host,
                                             'DHCLIENT_SET_HOSTNAME="no"')
                        self.owner.addOutput(
                            host, 'DHCLIENT_SET_DEFAULT_ROUTE="no"')

                if 'onboot=no' in options:
                    startmode = 'manual'
                elif ip or dhcp or channel or 'bridge' in options:
                    #
                    # if there is an IP address, or this
                    # interface should DHCP, or anything in
                    # the 'channel' field (e.g., this is a
                    # bridged or bonded interface), or if 'bridge'
                    # is in the options, then turn this interface on
                    #
                    startmode = 'auto'

                if not dhcp:
                    if ip:
                        self.owner.addOutput(host, 'IPADDR=%s' % ip)
                    if netmask:
                        self.owner.addOutput(host, 'NETMASK=%s' % netmask)
                    if network:
                        self.owner.addOutput(host, 'NETWORK=%s' % network)
                    if broadcast:
                        self.owner.addOutput(host, 'BROADCAST=%s' % broadcast)

                if mac:
                    self.owner.addOutput(host, 'HWADDR=%s' % mac.strip())

                #
                # bonded interface, e.g., 'bond0'
                #
                if bond_reg.match(interface):
                    #
                    # if a 'bond*' device is present, then always make
                    # sure it is enabled on boot.
                    #
                    startmode = 'auto'

                    self.owner.addOutput(host, 'BONDING_MASTER=yes')

                    #
                    # find the interfaces that are part of this bond
                    #
                    i = 0
                    for p in result:
                        if p['channel'] == interface:
                            self.owner.addOutput(
                                host,
                                'BONDING_SLAVE%d="%s"' % (i, p['interface']))
                            i = i + 1

                    #
                    # Check if there are bonding options set
                    #
                    for opt in options:
                        if opt.startswith('bonding-opts='):
                            i = opt.find('=')
                            bo = opt[i + 1:]
                            self.owner.addOutput(
                                host, 'BONDING_MODULE_OPTS="%s"' % bo)
                            break

                #
                # check if this is part of a bonded channel
                #
                if channel and bond_reg.match(channel):
                    startmode = 'auto'
                    bootproto = 'none'

                if not startmode:
                    startmode = 'off'

                self.owner.addOutput(host, 'STARTMODE=%s' % startmode)
                self.owner.addOutput(host, 'BOOTPROTO=%s' % bootproto)

                #
                # if this is a bridged interface, then go look for the
                # physical interface this bridge is associated with
                #
                if 'bridge' in options:
                    for p in result:
                        if p['channel'] == interface:
                            self.owner.addOutput(host, 'BRIDGE=yes')
                            self.owner.addOutput(host, 'BRIDGE_FORWARDDELAY=0')
                            self.owner.addOutput(host, 'BRIDGE_STP=off')
                            self.owner.addOutput(
                                host, 'BRIDGE_PORTS=%s' % p['interface'])
                            break

            self.owner.addOutput(host, '\n')
            self.owner.addOutput(host, '</stack:file>')

        if udev_output:
            self.owner.addOutput(
                host,
                '<stack:file stack:name="/etc/udev/rules.d/70-persistent-net.rules">'
            )
            self.owner.addOutput(host, udev_output)
            self.owner.addOutput(host, '</stack:file>')
Esempio n. 27
0
    def run(self, args):
        hosts, interfaces = args
        existinghosts = self.getHostnames()
        existing_memberships = {}
        existing_groups = {}
        for group in self.owner.call('list.group'):
            existing_groups[group['group']] = group['hosts']
        for member in self.owner.call('list.host.group'):
            existing_memberships[member['host']] = member['groups'].split()

        # prune group assignments for incoming hosts
        for host in hosts.keys():
            # no need to prune hosts not from the spreadsheet, or totally new hosts
            if host not in existinghosts:
                continue

            for group in existing_memberships[host]:
                self.owner.call('remove.host.group',
                                [host, 'group=%s' % group])

        sys.stderr.write('\tAdd Host\n')
        for host in hosts.keys():

            sys.stderr.write('\t\t%s\r' % host)

            #
            # add the host if it doesn't exist
            #
            if host not in existinghosts:
                args = [host]
                appliance = hosts[host].get('appliance')
                box = hosts[host].get('box')
                rack = hosts[host].get('rack')
                rank = hosts[host].get('rank')

                for paramName in ['appliance', 'box', 'rack', 'rank']:
                    paramValue = hosts[host].get(paramName)
                    if paramValue:
                        args.append('%s=%s' % (paramName, paramValue))
                        del hosts[host][paramName]

                self.owner.call('add.host', args)

            if 'installaction' in hosts[host]:
                self.owner.call('set.host.bootaction', [
                    host, 'sync=false', 'type=install',
                    'action=%s' % hosts[host]['installaction']
                ])
                del hosts[host]['installaction']
            if 'osaction' in hosts[host]:
                self.owner.call('set.host.bootaction', [
                    host, 'sync=false', 'type=os',
                    'action=%s' % hosts[host]['osaction']
                ])
                del hosts[host]['osaction']

            if 'groups' in hosts[host]:
                for groupname in hosts[host]['groups']:
                    if groupname not in existing_groups:
                        self.owner.call('add.group', [groupname])
                        existing_groups[groupname] = None

                    param = 'group=%s' % groupname
                    self.owner.call('add.host.group', [host, param])
                del hosts[host]['groups']
            #
            # set the host attributes that are explicitly
            # identified in the spreadsheet
            #
            for key in hosts[host].keys():
                if key == 'boss':
                    continue

                if key == 'comment':
                    self.owner.call(
                        'set.host.comment',
                        [host, 'comment=%s' % hosts[host][key]])
                else:
                    self.owner.call(
                        'set.host.%s' % key,
                        [host, '%s=%s' % (key, hosts[host][key])])

            sys.stderr.write('\t\t%s\r' % (' ' * len(host)))

        #
        # process the host's interface(s)
        #

        hosts = interfaces.keys()
        argv = []
        for a in interfaces.keys():
            argv.append(a)

        if argv:  # remove previous host interfaces (if any)
            argv.append('all=true')
            self.owner.call('remove.host.interface', argv)

        sys.stderr.write('\tAdd Host Interface\n')
        for host in hosts:

            sys.stderr.write('\t\t%s\r' % host)

            for interface in interfaces[host].keys():
                ip = None
                mac = None
                network = None
                ifhostname = None
                channel = None
                options = None
                vlan = None
                default = None

                if 'ip' in interfaces[host][interface].keys():
                    ip = interfaces[host][interface]['ip']
                if 'mac' in interfaces[host][interface].keys():
                    mac = interfaces[host][interface]['mac']
                if 'network' in interfaces[host][interface].keys():
                    network = interfaces[host][interface]['network']
                if 'ifhostname' in interfaces[host][interface].keys():
                    ifhostname = interfaces[host][interface]['ifhostname']
                if 'channel' in interfaces[host][interface].keys():
                    channel = interfaces[host][interface]['channel']
                if 'options' in interfaces[host][interface].keys():
                    options = interfaces[host][interface]['options']
                if 'vlan' in interfaces[host][interface].keys():
                    vlan = interfaces[host][interface]['vlan']
                if 'default' in interfaces[host][interface].keys():
                    default = str2bool(interfaces[host][interface]['default'])
                else:
                    default = False

                #
                # now add the interface
                #
                cmdparams = [
                    host, 'unsafe=true',
                    'interface=%s' % interface,
                    'default=%s' % default
                ]
                if mac:
                    cmdparams.append('mac=%s' % mac)
                if ip:
                    cmdparams.append('ip=%s' % ip)
                if network:
                    cmdparams.append('network=%s' % network)
                if ifhostname:
                    cmdparams.append('name=%s' % ifhostname)
                if vlan:
                    cmdparams.append('vlan=%d' % vlan)
                if default:
                    cmdparams.append('name=%s' % host)
                if 'bond' == interface[:4]:
                    cmdparams.append('module=bonding')

                self.owner.call('add.host.interface', cmdparams)

                if channel:
                    cmdparams = [
                        host,
                        'interface=%s' % interface,
                        'channel=%s' % channel
                    ]
                    self.owner.call('set.host.interface.channel', cmdparams)

                if options:
                    cmdparams = [
                        host,
                        'interface=%s' % interface,
                        'options=%s' % options
                    ]
                    self.owner.call('set.host.interface.options', cmdparams)

            sys.stderr.write('\t\t%s\r' % (' ' * len(host)))
Esempio n. 28
0
    def run(self, args):
        filename, = args

        self.list_host_interface = \
         self.owner.call('list.host.interface')
        self.appliances = self.getApplianceNames()
        # need all the info from networks(/subnets)
        self.networks = dict((k, next(v)) for k, v in groupby(
            self.owner.call('list.network'), itemgetter('network')))
        self.boxes = self.getBoxNames()
        self.actions = [
            entry['bootaction'] for entry in self.owner.call('list.bootaction')
        ]

        try:
            reader = stack.csv.reader(open(filename, encoding='ascii'))

            header = None
            for row in reader:

                if not header:
                    header = row

                    #
                    # make checking the header easier
                    #
                    required = [
                        'name', 'appliance', 'ip', 'mac', 'interface', 'rack',
                        'rank', 'network'
                    ]

                    for i in range(0, len(row)):
                        if header[i] in required:
                            required.remove(header[i])

                    if len(required) > 0:
                        msg = 'the following required fields are not present in the input file: "%s"' % ', '.join(
                            required)
                        raise CommandError(self.owner, msg)

                    continue

                name = None
                box = None
                appliance = None
                rack = None
                rank = None
                ip = None
                mac = None
                interface = None
                network = None
                ifhostname = None
                channel = None
                options = None
                vlan = None
                boss = None
                default = None
                comment = None
                installaction = None
                osaction = None
                groups = None

                for i in range(0, len(row)):
                    field = row[i]
                    if not field:
                        continue

                    if header[i] == 'name':
                        name = field.lower()
                    if header[i] == 'box':
                        box = field
                    if header[i] == 'appliance':
                        appliance = field
                    elif header[i] == 'rack':
                        rack = field
                    elif header[i] == 'rank':
                        rank = field
                    elif header[i] == 'ip':
                        try:
                            if field == "auto" or ipaddress.IPv4Address(field):
                                ip = field
                        except:
                            msg = 'invalid IP %s in the input file' % ip
                            raise CommandError(self.owner, msg)
                    elif header[i] == 'mac':
                        #
                        # make sure the MAC has lowercase
                        # letters
                        #
                        mac = field.lower()
                    elif header[i] == 'interface':
                        interface = field.lower()
                    elif header[i] == 'network':
                        network = field.lower()
                    elif header[i] == 'interface hostname':
                        ifhostname = field.lower()
                    elif header[i] == 'channel':
                        channel = field
                    elif header[i] == 'options':
                        options = field
                    elif header[i] == 'vlan':
                        try:
                            vlan = int(field)
                        except:
                            msg = 'VLAN "%s" must be an integer' % field
                            raise CommandError(self.owner, msg)

                        if vlan < 1:
                            msg = 'VLAN "%s" must be greater than 0' % vlan
                            raise CommandError(self.owner, msg)
                    elif header[i] == 'boss':
                        boss = field
                    elif header[i] == 'default':
                        default = field
                    elif header[i] == 'comment':
                        comment = field
                    elif header[i] == 'installaction':
                        installaction = field
                    elif header[i] in ['osaction', 'runaction']:
                        osaction = field
                    elif header[i] == 'groups':
                        groups = field

                if not name:
                    msg = 'empty host name found in "name" column'
                    raise CommandError(self.owner, msg)

                if name not in self.owner.hosts.keys():
                    self.owner.hosts[name] = {}

                if box:
                    self.checkBox(box)
                    self.owner.hosts[name]['box'] = box

                if appliance:
                    if 'appliance' in self.owner.hosts[name].keys() and \
                      self.owner.hosts[name]['appliance'] != appliance:
                        msg = 'two different appliance types specified for host "%s"' % name
                        raise CommandError(self.owner, msg)

                    self.owner.hosts[name]['appliance'] = appliance

                if rack:
                    if 'rack' in self.owner.hosts[name].keys() and \
                      self.owner.hosts[name]['rack'] != rack:
                        msg = 'two different rack numbers specified for host "%s"' % name
                        raise CommandError(self.owner, msg)

                    self.owner.hosts[name]['rack'] = rack

                if rank:
                    if 'rank' in self.owner.hosts[name].keys() and \
                      self.owner.hosts[name]['rank'] != rank:
                        msg = 'two different rank numbers specified for host "%s"' % name
                        raise CommandError(self.owner, msg)

                    self.owner.hosts[name]['rank'] = rank

                if not interface:
                    continue

                if name not in self.owner.interfaces.keys():
                    self.owner.interfaces[name] = {}

                if interface in self.owner.interfaces[name].keys():
                    msg = 'interface "%s" already specified for host "%s"' % (
                        interface, name)
                    raise CommandError(self.owner, msg)

                self.owner.interfaces[name][interface] = {}

                if default:
                    self.owner.interfaces[name][interface]['default'] = default
                if ip:
                    if not network:
                        raise CommandError(
                            self.owner,
                            'inclusion of IP requires inclusion of network')
                    self.owner.interfaces[name][interface]['ip'] = ip
                if mac:
                    self.owner.interfaces[name][interface]['mac'] = mac
                if network:
                    self.owner.interfaces[name][interface]['network'] = network
                if ifhostname:
                    self.owner.interfaces[name][interface][
                        'ifhostname'] = ifhostname
                if channel:
                    self.owner.interfaces[name][interface]['channel'] = channel
                if options:
                    self.owner.interfaces[name][interface]['options'] = options
                if vlan:
                    self.owner.interfaces[name][interface]['vlan'] = vlan
                if boss:
                    self.owner.hosts[name]['boss'] = boss

                if comment:
                    if 'comment' not in self.owner.hosts[name].keys():
                        self.owner.hosts[name]['comment'] = comment
                    else:
                        self.owner.hosts[name]['comment'] += \
                         ', %s' % comment
                if installaction:
                    if installaction not in self.actions:
                        msg = 'installaction "%s" does not exist in the database' % installaction
                        raise CommandError(self.owner, msg)
                    else:
                        self.owner.hosts[name]['installaction'] = installaction

                if osaction:
                    if osaction not in self.actions:
                        msg = 'bootaction "%s" does not exist in the database' % osaction
                        raise CommandError(self.owner, msg)
                    else:
                        self.owner.hosts[name]['osaction'] = osaction

                if groups:
                    self.owner.hosts[name]['groups'] = groups.split(',')
        except UnicodeDecodeError:
            raise CommandError(self.owner, 'non-ascii character in file')

        #
        # check if the 'Boss' column was set
        #
        thisboss = self.db.getHostname('localhost')
        hasboss = 0
        for name in self.owner.hosts.keys():
            if 'boss' in self.owner.hosts[name]:
                if self.owner.hosts[name]['boss'] == thisboss:
                    hasboss = 1
                    break

        if hasboss:
            #
            # now remove all hosts not associated with this Boss
            #
            for name in self.owner.hosts.keys():
                if self.owner.hosts[name]['boss'] != thisboss:
                    del self.owner.hosts[name]

                    for o in self.list_host_interface:
                        if o['name'] == name:
                            self.owner.call('remove.host', [name])

        #
        # sanity checks
        #
        macs = []
        ips = {}
        for name in self.owner.hosts.keys():
            #
            # ensure at least one of the host entries has an
            # appliance associated with it
            #
            if 'appliance' not in self.owner.hosts[name].keys():
                msg = 'must supply an appliance type for host "%s"' % (name)
                raise CommandError(self.owner, msg)
            else:
                self.checkAppliance(self.owner.hosts[name]['appliance'])

            #
            # 'default' checking
            #
            ifaces = self.owner.interfaces[name].keys()

            #
            # if there is only one interface, make it the default
            #
            if len(ifaces) == 1:
                for interface in ifaces:
                    self.owner.interfaces[name][interface]['default'] = 'True'
            else:
                #
                # if there is more than one interface for this
                # host, make sure that one of the interfaces
                # is specified as the 'default' interface
                #
                default = False
                multiple_defaults = False
                for interface in ifaces:
                    if 'default' in self.owner.interfaces[name][
                            interface] and str2bool(
                                self.owner.interfaces[name][interface]
                                ['default']) is True:
                        if not default:
                            default = True
                        else:
                            multiple_defaults = True
                if not default:
                    msg = 'host "%s" has multiple interfaces but none of the interfaces are designated as\na "default" interface. add a "default" column to your spreadsheet and\nmark one of the interfaces as "True" in the default column' % name
                    raise CommandError(self.owner, msg)

                if multiple_defaults:
                    msg = 'host "%s" has more than one interface designated as the "default" interface.\nedit your spreadsheet so that only one interface is the "default".' % name
                    raise CommandError(self.owner, msg)

            #
            # interface specific checks
            #
            for interface in self.owner.interfaces[name].keys():
                try:
                    ip = self.owner.interfaces[name][interface]['ip']
                except:
                    ip = None
                try:
                    vlan = self.owner.interfaces[name][interface]['vlan']
                except:
                    vlan = 'default'
                if ip:
                    #					self.checkIP(ip)
                    if vlan in ips:
                        if ip != 'auto' and ip in ips[vlan]:
                            msg = 'duplicate IP "%s" in the input file' % ip
                            raise CommandError(self.owner, msg)
                    else:
                        ips[vlan] = []

                    ips[vlan].append(ip)

                try:
                    mac = self.owner.interfaces[name][interface]['mac']
                except:
                    mac = None
                if mac:
                    #					self.checkMAC(mac)
                    if mac in macs:
                        msg = 'duplicate MAC "%s" in the input file' % mac
                        raise CommandError(self.owner, msg)

                    macs.append(mac)

                try:
                    network = self.owner.interfaces[name][interface]['network']
                except:
                    network = None
                if network:
                    self.checkNetwork(network)

                    if ip:
                        # check if 'ip' could exist in 'network'
                        network_ip, netmask = itemgetter('address', 'mask')(
                            self.networks[network])
                        ipnetwork = ipaddress.IPv4Network(network_ip + '/' +
                                                          netmask)

                        # Handle cases where ipaddr = "auto"
                        if ip != "auto" and \
                         ipaddress.IPv4Address(ip) not in ipnetwork:
                            msg = 'IP "%s" is not in the "%s" IP space (%s/%s)' % \
                             (ip, network, network_ip, ipnetwork.prefixlen)
                            raise CommandError(self.owner, msg)

                #
                # if 'channel' is specified and if it starts
                # with 'bond', make sure there is an interface
                # for this host that matches the the bond value
                #
                if re.match('bond[0-9]+$', interface):
                    found = 0
                    for iface in self.owner.interfaces[name].keys():
                        if 'channel' not in self.owner.interfaces[name][
                                iface].keys():
                            continue

                        if interface == self.owner.interfaces[name][iface][
                                'channel']:
                            found = 1
                            break

                    if not found:
                        msg = 'bonded interface "%s" is specified for host "%s", ' % (
                            interface, name)
                        msg += 'but there is no channel "%s" specified for any interface associated with this host' % (
                            interface)
                        raise CommandError(self.owner, msg)
Esempio n. 29
0
    def run(self, params, args):
        filename, sync, = self.fillParams([
            ('file', None, True),
            ('sync', True),
        ])

        if not os.path.exists(filename):
            raise CommandError(self, f'file {filename} does not exist')

        with open(os.path.abspath(filename), 'r') as f:
            try:
                loaded_json = f.read()
                self.data = json.loads(loaded_json)
            except ValueError as e:
                # determine the location of the invalid character and print a helpful error message
                # the json module returnes a message containing the location of the bad character
                location = int(re.search(r'char (.*?)\)', str(e)).group(1))
                # make two strings, before and after the bad character
                b = loaded_json[:location]
                a = loaded_json[location:]
                # grab the entire line that the error is on
                error_line = (b[b.rfind('\n'):] + a[:a.find('\n')]).strip()
                # determine the length of the error line before the bad character
                blen = len((b[b.rfind('\n'):]).strip())
                pointer_line = ' ' * blen + '^'

                raise CommandError(
                    self,
                    f'Invalid json document:\n{error_line}\n{pointer_line}\n{e}'
                )

        # run a few pre checks
        self.checks(args)

        # make a backup of the database in its current state in the event of any errors
        s = subprocess.run(['/etc/cron.daily/backup-cluster-db'])
        if s.returncode != 0:
            raise CommandError(
                self, 'unable to backup the cluster database, aborting')

        # so that we are able to report how successful the load was
        self.successes = 0
        self.warnings = 0
        self.errors = 0

        # start a logger
        self.log = logging.getLogger("load-json")
        logging.basicConfig(filename='/var/log/load-json.log',
                            filemode='w+',
                            level=logging.INFO)

        try:
            self.runPlugins(args)

            # the usual load commands sync their configs after the load
            if str2bool(sync):
                self.notify('\tSyncing config\n')
                self.command('sync.config')
                self.log.info('config synced')
                self.notify('\n\tSyncing host network localhost\n')
                self.command('sync.host.network', ['localhost'])
                self.log.info('config synced')

        except CommandError as e:
            self.log.info(f'Load terminated early: {e}')
            self.errors += 1

        # report how well the load went
        self.notify(
            f'\nload finished with:\n{self.successes} successes\n{self.warnings} warnings\n{self.errors} errors\nCheck /var/log/load-json.log for details.\n'
        )

        # if there are errors, revert db changes and raise a CommandError
        if self.errors != 0:
            self.notify(
                '\nThere were errors during the load, restoring the database. Check /var/log/load-json.log for details.\n'
            )
            s = subprocess.run(['bash', '/var/db/restore-stacki-database.sh'])
            if s.returncode != 0:
                raise CommandError(
                    self,
                    'There were errors and the database could not be restored. Check /var/log/load-json.log for details'
                )

            raise CommandError(
                self,
                'The database has been restored. No changes have been made.')
Esempio n. 30
0
    def run(self, params, args):
        if len(args) != 1:
            raise ArgUnique(self, 'switch')

        sm_switch = args[0]

        (disable, ) = self.fillParams([
            ('disable', False),
        ])

        disable = str2bool(disable)

        ibswitches = [
            sw for sw in self.call('list.switch') if sw['model'] == 'm7800'
        ]
        ib_switch_names = [sw['switch'] for sw in ibswitches]

        if sm_switch not in ib_switch_names:
            msg = f'host {sm_switch} is not a supported infiniband switch\n'
            msg += 'Please verify the make and model attributes for this host.'
            raise CommandError(self, msg)

        ib_sw_nets = self.call('list.host.interface', ib_switch_names)

        self.switch_attrs = self.getHostAttrDict(ib_switch_names)

        if disable:
            switch = self.get_sw_handle(sm_switch)
            switch.subnet_manager = False
            switch.disconnect()
            return

        # NOTE assumes a single management port with options set.
        # this obviously breaks if a switch can someday be on multiple fabrics

        opts = next(sw['options'] for sw in ib_sw_nets
                    if sw['host'] == sm_switch)
        if not opts:
            raise CommandError(
                self, f'switch {sm_switch} does not have its ibfabric set')

        for opt in shlex.split(opts):
            if opt.startswith('ibfabric='):
                _, fabric = opt.split('=')
                break

        if not fabric:
            raise CommandError(
                self, f'switch {sm_switch} does not have its ibfabric set')

        switches_to_disable = []
        for ib_sw in ib_sw_nets:
            if ib_sw['host'] == sm_switch:
                # this is the sm
                continue

            if not ib_sw['options']:
                # switches with no fabric specified should be disabled
                switches_to_disable.append(ib_sw['host'])
                continue

            opts = [
                opt for opt in shlex.split(ib_sw['options'])
                if opt.startswith('ibfabric=')
            ]
            if not opts:
                # switches with no fabric specified should be disabled
                switches_to_disable.append(ib_sw['host'])
                continue

            _, sw_fabric = opts[0].split('=')
            if sw_fabric == fabric:
                # other switches on the same fabric should be disabled
                switches_to_disable.append(ib_sw['host'])
                continue

        for switch in switches_to_disable:
            sw_handle = self.get_sw_handle(switch)
            sw_handle.subnet_manager = False
            sw_handle.disconnect()

        sw_handle = self.get_sw_handle(sm_switch)
        sw_handle.subnet_manager = True
        sw_handle.disconnect()
Esempio n. 31
0
    def traverse_stack_package(self, node):
        """Expands <stack:package> to native autoyast syntax, later passes
		will collect all these section to create a single
		<software> section.

		<software>
			<patterns config:type="list"> <!-- stack:type="meta" -->
				<pattern>?</pattern>
			</patterns>
			<packages config:type="list"> 
				<package>?</package>
				...
			</package>
		</software>

		"""

        stage = self.getAttr(node, 'stack:stage', default='install')
        enabled = str2bool(self.getAttr(node, 'stack:enable', default='true'))
        pattern = str2bool(self.getAttr(node, 'stack:meta', default='fase'))

        pkgs = []
        for line in self.collect(node).split('\n'):
            pkg = line.strip()
            if pkg:
                pkgs.append(pkg)

        if not pattern:
            # Figure out if the package(s) are:
            #
            # post-packages   - installed on first boot for broken RPMs
            # packages        - installed during installation as God intended
            # remove-packages - deletes a package for no good reason

            innerTag = 'sles:package'

            if stage == 'boot':
                outerTag = 'sles:post-packages'
            else:
                outerTag = 'sles:packages'

            if not enabled:
                outerTag = 'sles:remove-packages'
        else:
            # Patterns only support:
            #
            # post-pattern
            # pattern
            # (no remove patterns)

            innerTag = 'sles:pattern'

            if stage == 'boot':
                outerTag = 'sles:post-patterns'
            else:
                outerTag = 'sles:patterns'

        outer = self.newElementNode(outerTag)
        self.setAttribute(outer, 'config:type', 'list')
        for rpm in pkgs:
            inner = self.newElementNode(innerTag)
            inner.appendChild(self.newTextNode(rpm))
            outer.appendChild(inner)

        software = self.newElementNode('sles:software')
        software.appendChild(outer)

        node.parentNode.replaceChild(software, node)
        return False
Esempio n. 32
0
def main():
	"""Where the magic begins."""
	global host_partitions
	global csv_partitions
	host_disks = get_host_disks()

	count = 5
	while count > 0:
		if len(host_disks) == 0:
			time.sleep(1)
			count -= 1
			host_disks = get_host_disks()
		else:
			break

	#
	# if fstab is corrupted, get_host_fstab() will throw and exception.
	# catch it and just report an empty fstab
	#
	try:
		host_fstab = get_host_fstab(host_disks)
	except:
		host_fstab = []

	host_partitions = get_host_partitions(host_disks, host_fstab)

	if not csv_partitions:
		if attributes['os.version'] == "11.x" and attributes['os'] == "sles":
			ostype = "sles11"
		elif attributes['os.version'] == "12.x" and attributes['os'] == "sles":
			ostype = "sles12"
		else:
			# Give ostype some default
			ostype = "sles11"

		if os.path.exists('/sys/firmware/efi'):
			default = 'uefi'
		else:
			default = 'default'

		var = '%s_%s' % (ostype, default)
		if hasattr(sles, var):
			parts = getattr(sles, var)
		else:
			parts = getattr(sles, 'default')

		if 'boot_device' in attributes:
			bootdisk = attributes['boot_device']
		else:
			bootdisk = host_disks[0]

		csv_partitions = []
		partid = 1

		for m, s, f in parts:
			csv_partitions.append(
				{
					'partid': partid,
					'scope': 'global',
					'device': bootdisk,
					'mountpoint': m,
					'size': s,
					'fstype': f,
					'options': ''
				})

			partid += 1

	#
	# there are 2 scenarios:
	#
	# 1) nukedisks == True
	# 2) nukedisks == False
	# 3) nukedisks == a list of disks to nuke <-- Not sure we actually handle this yet.
	#
	# 1 is easy -- nuke the disks and recreate the partitions specified in the
	# "partitions" variable
	#
	# For 2, reformat "/", "/boot" (if present) and "/var" on the boot disk, then
	# reconnect all other discovered partitions.

	# if host_fstab is an empty list, turning on nukedisks=True" to avoid SLES defaults
	if host_fstab == []:
		nuke_disks = True
		attributes['nukedisks'] = "True"
	elif 'nukedisks' in attributes:
		nuke_disks = str2bool(attributes['nukedisks'])
	else:
		nuke_disks = False
		attributes['nukedisks'] = "False"

	if not nuke_disks:
		# Need output of the existing fstab to be utilized for post-install script.
		if not os.path.exists(fs_info):
			os.makedirs(fs_info)
		with open(str(fs_info + '/__init__.py'), 'w') as fstab_info:
			fstab_info.write('old_fstab = %s\n\n' % host_fstab)

	#
	# process all nuked disks first
	#
	nuke_list = get_nukes(host_disks, nuke_disks, attributes['nukedisks'])

	for disk in nuke_list:
		nuke_it(disk)

		initialize = True
		output_disk(disk, initialize)
	#
	# now process all non-nuked disks
	#
	initialize = False
	for disk in host_disks:
		if disk not in nuke_list:
			output_disk(disk, initialize)

	print(prettify(partitioning_config))
Esempio n. 33
0
        if adapter != None:
            return (ctrl, adapter)

    return (None, None)


##
## MAIN
##

# Halt the install with an error message on the console and in the message queue
# if we are unable to create a RAID.
# To override, set the attribute 'halt_install_on_error=False'.

halt_on_error = str2bool(attributes.get('halt_install_on_error', True))
nukecontroller = str2bool(attributes.get('nukecontroller', False))
secureerase = str2bool(attributes.get('secureerase', False))

#
# if 'secureerase' is true, then that implies that 'nukecontroller' is true
#
if secureerase:
    nukecontroller = True

#
# only run this code if 'nukecontroller' is true
#
if not nukecontroller:
    sys.exit(0)
Esempio n. 34
0
	def run(self, args):
		filename, = args

		self.list_host_interface = \
			self.owner.call('list.host.interface')
		self.appliances = self.getApplianceNames()
		# need all the info from networks(/subnets)
		self.networks = dict((k, next(v)) for k, v in groupby(self.owner.call('list.network'), itemgetter('network')))
		self.boxes = self.getBoxNames()
		self.actions = [entry['bootaction'] for entry in self.owner.call('list.bootaction')]

		try:
			reader = stack.csv.reader(open(filename, encoding='ascii'))

			header = None
			for row in reader:

				if not header:
					header = row

					#
					# make checking the header easier
					#
					required = [ 'name', 'appliance', 'ip', 'mac',
						'interface', 'rack', 'rank', 'network' ]

					for i in range(0, len(row)):
						if header[i] in required:
							required.remove(header[i])

					if len(required) > 0:
						msg = 'the following required fields are not present in the input file: "%s"' % ', '.join(required)	
						raise CommandError(self.owner, msg)

					continue

				name = None
				box = None
				appliance = None
				rack = None
				rank = None
				ip = None
				mac = None
				interface = None
				network = None
				ifhostname = None
				channel = None
				options = None
				vlan = None
				boss = None
				default = None
				comment = None
				installaction = None
				osaction = None
				groups = None

				for i in range(0, len(row)):
					field = row[i]
					if not field:
						continue

					if header[i] == 'name':
						name = field.lower()
					if header[i] == 'box':
						box = field
					if header[i] == 'appliance':
						appliance = field
					elif header[i] == 'rack':
						rack = field
					elif header[i] == 'rank':
						rank = field
					elif header[i] == 'ip':
						try:
							if field == "auto" or ipaddress.IPv4Address(field):
								ip = field
						except:
							msg = 'invalid IP %s in the input file' % ip
							raise CommandError(self.owner, msg)
					elif header[i] == 'mac':
						#
						# make sure the MAC has lowercase
						# letters
						#
						mac = field.lower()
					elif header[i] == 'interface':
						interface = field.lower()
					elif header[i] == 'network':
						network = field.lower()
					elif header[i] == 'interface hostname':
						ifhostname = field.lower()
					elif header[i] == 'channel':
						channel = field
					elif header[i] == 'options':
						options = field
					elif header[i] == 'vlan':
						try:
							vlan = int(field)
						except:
							msg = 'VLAN "%s" must be an integer' % field
							raise CommandError(self.owner, msg)

						if vlan < 1:
							msg = 'VLAN "%s" must be greater than 0' % vlan
							raise CommandError(self.owner, msg)
					elif header[i] == 'boss':
						boss = field
					elif header[i] == 'default':
						default = field
					elif header[i] == 'comment':
						comment = field
					elif header[i] == 'installaction':
						installaction = field
					elif header[i] in [ 'osaction', 'runaction' ]:
						osaction = field
					elif header[i] == 'groups':
						groups = field
							
				if not name:
					msg = 'empty host name found in "name" column'
					raise CommandError(self.owner, msg)

				if name not in self.owner.hosts.keys():
					self.owner.hosts[name] = {}

				if box:
					self.checkBox(box)
					self.owner.hosts[name]['box'] = box

				if appliance:
					if 'appliance' in self.owner.hosts[name].keys() and \
							self.owner.hosts[name]['appliance'] != appliance:
						msg = 'two different appliance types specified for host "%s"' % name
						raise CommandError(self.owner, msg)

					self.owner.hosts[name]['appliance'] = appliance

				if rack:
					if 'rack' in self.owner.hosts[name].keys() and \
							self.owner.hosts[name]['rack'] != rack:
						msg = 'two different rack numbers specified for host "%s"' % name
						raise CommandError(self.owner, msg)

					self.owner.hosts[name]['rack'] = rack

				if rank:
					if 'rank' in self.owner.hosts[name].keys() and \
							self.owner.hosts[name]['rank'] != rank:
						msg = 'two different rank numbers specified for host "%s"' % name
						raise CommandError(self.owner, msg)

					self.owner.hosts[name]['rank'] = rank

				if not interface:
					continue

				if name not in self.owner.interfaces.keys():
					self.owner.interfaces[name] = {}

				if interface in self.owner.interfaces[name].keys():
					msg = 'interface "%s" already specified for host "%s"' % (interface, name)
					raise CommandError(self.owner, msg)

				self.owner.interfaces[name][interface] = {}
				
				if default:
					self.owner.interfaces[name][interface]['default'] = default
				if ip:
					if not network:
						raise CommandError(self.owner, 'inclusion of IP requires inclusion of network')
					self.owner.interfaces[name][interface]['ip'] = ip
				if mac:
					self.owner.interfaces[name][interface]['mac'] = mac
				if network:
					self.owner.interfaces[name][interface]['network'] = network
				if ifhostname:
					self.owner.interfaces[name][interface]['ifhostname'] = ifhostname
				if channel:
					self.owner.interfaces[name][interface]['channel'] = channel
				if options:
					self.owner.interfaces[name][interface]['options'] = options
				if vlan:
					self.owner.interfaces[name][interface]['vlan'] = vlan
				if boss:
					self.owner.hosts[name]['boss'] = boss

				if comment:
					if 'comment' not in self.owner.hosts[name].keys():
						self.owner.hosts[name]['comment'] = comment
					else:
						self.owner.hosts[name]['comment'] += \
							', %s' % comment
				if installaction:
					if installaction not in self.actions:
						msg = 'installaction "%s" does not exist in the database' % installaction
						raise CommandError(self.owner, msg)
					else:
						self.owner.hosts[name]['installaction'] = installaction

				if osaction:
					if osaction not in self.actions:
						msg = 'bootaction "%s" does not exist in the database' % osaction
						raise CommandError(self.owner, msg)
					else:
						self.owner.hosts[name]['osaction'] = osaction

				if groups:
					self.owner.hosts[name]['groups'] = groups.split(',')
		except UnicodeDecodeError:
			raise CommandError(self.owner, 'non-ascii character in file')

		#
		# check if the 'Boss' column was set
		#
		thisboss = self.db.getHostname('localhost')
		hasboss = 0
		for name in self.owner.hosts.keys():
			if 'boss' in self.owner.hosts[name]:
				if self.owner.hosts[name]['boss'] == thisboss:
					hasboss = 1
					break

		if hasboss:
			#
			# now remove all hosts not associated with this Boss
			#
			for name in self.owner.hosts.keys():
				if self.owner.hosts[name]['boss'] != thisboss:
					del self.owner.hosts[name]

					for o in self.list_host_interface:
						if o['name'] == name:
							self.owner.call(
								'remove.host',
								[ name ])

		#
		# sanity checks
		#
		macs = []
		ips = {}
		for name in self.owner.hosts.keys():
			#
			# ensure at least one of the host entries has an
			# appliance associated with it
			#
			if 'appliance' not in self.owner.hosts[name].keys():
				msg = 'must supply an appliance type for host "%s"' % (name)
				raise CommandError(self.owner, msg)
			else:
				self.checkAppliance(
					self.owner.hosts[name]['appliance'])

			#
			# 'default' checking
			#
			ifaces = self.owner.interfaces[name].keys()
			
			#
			# if there is only one interface, make it the default
			#
			if len(ifaces) == 1:
				for interface in ifaces:
					self.owner.interfaces[name][interface]['default'] = 'True'
			else:
				#
				# if there is more than one interface for this
				# host, make sure that one of the interfaces
				# is specified as the 'default' interface
				#
				default = False
				multiple_defaults = False
				for interface in ifaces:
					if 'default' in self.owner.interfaces[name][interface] and str2bool(self.owner.interfaces[name][interface]['default']) is True:
						if not default:
							default = True
						else:
							multiple_defaults = True
				if not default:
					msg = 'host "%s" has multiple interfaces but none of the interfaces are designated as\na "default" interface. add a "default" column to your spreadsheet and\nmark one of the interfaces as "True" in the default column' % name
					raise CommandError(self.owner, msg)

				if multiple_defaults:
					msg = 'host "%s" has more than one interface designated as the "default" interface.\nedit your spreadsheet so that only one interface is the "default".' % name
					raise CommandError(self.owner, msg)
					
			#
			# interface specific checks
			#
			for interface in self.owner.interfaces[name].keys():
				try:
					ip = self.owner.interfaces[name][interface]['ip']
				except:
					ip = None
				try:
					vlan = self.owner.interfaces[name][interface]['vlan']
				except:
					vlan = 'default'
				if ip:
#					self.checkIP(ip)
					if vlan in ips:
						if ip != 'auto' and ip in ips[vlan]:
							msg = 'duplicate IP "%s" in the input file' % ip
							raise CommandError(self.owner, msg)
					else:
						ips[vlan] = []

					ips[vlan].append(ip)

				try:
					mac = self.owner.interfaces[name][interface]['mac']
				except:
					mac = None
				if mac:
#					self.checkMAC(mac)
					if mac in macs:
						msg = 'duplicate MAC "%s" in the input file' % mac
						raise CommandError(self.owner, msg)

					macs.append(mac)

				try:
					network = self.owner.interfaces[name][interface]['network']
				except:
					network = None
				if network:
					self.checkNetwork(network)

					if ip:
						# check if 'ip' could exist in 'network'
						network_ip, netmask = itemgetter('address', 'mask')(self.networks[network])
						ipnetwork = ipaddress.IPv4Network(network_ip + '/' + netmask)

						# Handle cases where ipaddr = "auto"
						if ip != "auto" and \
							ipaddress.IPv4Address(ip) not in ipnetwork:
							msg = 'IP "%s" is not in the "%s" IP space (%s/%s)' % \
								(ip, network, network_ip, ipnetwork.prefixlen)
							raise CommandError(self.owner, msg)

				#
				# if 'channel' is specified and if it starts
				# with 'bond', make sure there is an interface
				# for this host that matches the the bond value
				#
				if re.match('bond[0-9]+$', interface):
					found = 0
					for iface in self.owner.interfaces[name].keys():
						if 'channel' not in self.owner.interfaces[name][iface].keys():
							continue

						if interface == self.owner.interfaces[name][iface]['channel']:
							found = 1
							break

					if not found:
						msg = 'bonded interface "%s" is specified for host "%s", ' % (interface, name)
						msg += 'but there is no channel "%s" specified for any interface associated with this host' % (interface)
						raise CommandError(self.owner, msg)
Esempio n. 35
0
	def traverse_stack_package(self, node):
		"""Expands <stack:package> to native autoyast syntax, later passes
		will collect all these section to create a single
		<software> section.

		<software>
			<patterns config:type="list"> <!-- stack:type="meta" -->
				<pattern>?</pattern>
			</patterns>
			<packages config:type="list"> 
				<package>?</package>
				...
			</package>
		</software>

		"""

		stage   = self.getAttr(node, 'stack:stage', default='install')
		enabled = str2bool(self.getAttr(node, 'stack:enable', default='true'))
		pattern = str2bool(self.getAttr(node, 'stack:meta', default='fase'))
			

		pkgs = []
		for line in self.collect(node).split('\n'):
			pkg = line.strip()
			if pkg:
				pkgs.append(pkg)

		if not pattern:
			# Figure out if the package(s) are:
			#
			# post-packages   - installed on first boot for broken RPMs
			# packages        - installed during installation as God intended
			# remove-packages - deletes a package for no good reason

			innerTag = 'sles:package'

			if stage == 'boot':
				outerTag = 'sles:post-packages'
			else:
				outerTag = 'sles:packages'

			if not enabled:
				outerTag = 'sles:remove-packages'
		else:
			# Patterns only support:
			#
			# post-pattern
			# pattern
			# (no remove patterns)

			innerTag = 'sles:pattern'

			if stage == 'boot':
				outerTag = 'sles:post-patterns'
			else:
				outerTag = 'sles:patterns'


		outer = self.newElementNode(outerTag)
		self.setAttribute(outer, 'config:type', 'list')
		for rpm in pkgs:
			inner = self.newElementNode(innerTag)
			inner.appendChild(self.newTextNode(rpm))
			outer.appendChild(inner)

		software = self.newElementNode('sles:software')
		software.appendChild(outer)

		node.parentNode.replaceChild(software, node)
		return False
Esempio n. 36
0
	def run(self, args):
		hosts, interfaces = args
		existinghosts = self.getHostnames()
		existing_memberships = {}
		existing_groups = {}
		for group in self.owner.call('list.group'):
			existing_groups[group['group']] = group['hosts']
		for member in self.owner.call('list.host.group'):
			existing_memberships[member['host']] = member['groups'].split()

		# prune group assignments for incoming hosts
		for host in hosts.keys():
			# no need to prune hosts not from the spreadsheet, or totally new hosts
			if host not in existinghosts:
				appliance    = hosts[host].get('appliance')
				if appliance == 'frontend':
					raise CommandError(self, 'Renaming frontend is not supported!')
				continue

			for group in existing_memberships[host]:
				self.owner.call('remove.host.group', [host, 'group=%s' % group])



		sys.stderr.write('\tAdd Host\n')
		for host in hosts.keys():

			sys.stderr.write('\t\t%s\r' % host)

			#
			# add the host if it doesn't exist
			#
			if host not in existinghosts:
				args         = [ host ]
				appliance    = hosts[host].get('appliance')
				box          = hosts[host].get('box')
				rack         = hosts[host].get('rack')
				rank         = hosts[host].get('rank')

				for paramName in [ 'appliance', 'box',
						   'rack', 'rank' ]:
					paramValue = hosts[host].get(paramName)
					if paramValue:
						args.append('%s=%s' %
							(paramName, paramValue))
						del hosts[host][paramName]

				self.owner.call('add.host', args)

			if 'installaction' in hosts[host]:
				self.owner.call('set.host.bootaction',
						[ host,
						  'sync=false',
						  'type=install',
						  'action=%s' % hosts[host]['installaction']
					  ])
				del hosts[host]['installaction']
			if 'osaction' in hosts[host]:
				self.owner.call('set.host.bootaction',
						[ host,
						  'sync=false',
						  'type=os',
						  'action=%s' % hosts[host]['osaction']
					  ])
				del hosts[host]['osaction']

			if 'groups' in hosts[host]:
				for groupname in hosts[host]['groups']:
					if groupname not in existing_groups:
						self.owner.call('add.group', [groupname])
						existing_groups[groupname] = None

					param = 'group=%s' % groupname
					self.owner.call('add.host.group', [host, param])
				del hosts[host]['groups']
			#
			# set the host attributes that are explicitly
			# identified in the spreadsheet
			#
			for key in hosts[host].keys():
				if key == 'boss':
					continue

				if key == 'comment':
					self.owner.call('set.host.comment',
						[ host, 'comment=%s'
						% hosts[host][key] ])
				else:
					self.owner.call('set.host.%s' % key,
						[ host, '%s=%s' % (key, hosts[host][key]) ])


			sys.stderr.write('\t\t%s\r' % (' ' * len(host)))


		#
		# process the host's interface(s)
		#

		hosts = list(interfaces.keys())

		# ensure the fronted is the first to get loaded
		_frontend = self.db.getHostname('localhost')
		for index, host in enumerate(hosts):
			if host == _frontend:
				tmp_host = hosts[0]
				hosts[0] = host
				hosts[index] = tmp_host

		argv = []
		for a in interfaces.keys():
			argv.append(a)

		if argv: # remove previous host interfaces (if any)
			argv.append('all=true')
			self.owner.call('remove.host.interface', argv)

		sys.stderr.write('\tAdd Host Interface\n')
		autoip_list = []

		for host in hosts:

			sys.stderr.write('\t\t%s\r' % host)

			for interface in interfaces[host].keys():
				ip = None
				mac = None
				network = None
				ifhostname = None
				channel = None
				options = None
				vlan = None
				default = None

				if 'ip' in interfaces[host][interface].keys():
					ip = interfaces[host][interface]['ip']
				if 'mac' in interfaces[host][interface].keys():
					mac = interfaces[host][interface]['mac']
				if 'network' in interfaces[host][interface].keys():
					network = interfaces[host][interface]['network']
				if 'ifhostname' in interfaces[host][interface].keys():
					ifhostname = interfaces[host][interface]['ifhostname']
				if 'channel' in interfaces[host][interface].keys():
					channel = interfaces[host][interface]['channel']
				if 'options' in interfaces[host][interface].keys():
					options = interfaces[host][interface]['options']
				if 'vlan' in interfaces[host][interface].keys():
					vlan = interfaces[host][interface]['vlan']
				if 'default' in interfaces[host][interface].keys():
					default = str2bool(interfaces[host][interface]['default'])
				else:
					default = False

				#
				# now add the interface
				#
				cmdparams = [ host,
					'unsafe=true',
					'interface=%s' % interface,
					'default=%s' % default ]
				if mac:
					cmdparams.append('mac=%s' % mac)
				if ip:
					cmdparams.append('ip=%s' % ip)
				if network:
					cmdparams.append('network=%s' % network)
				if ifhostname:
					cmdparams.append('name=%s' % ifhostname)
				if vlan:
					cmdparams.append('vlan=%d' % vlan)
				if default:
					cmdparams.append('name=%s' % host)
				if 'bond' == interface[:4]:
					cmdparams.append('module=bonding')
				if channel:
					cmdparams.append('channel=%s' % channel)
				if options:
					cmdparams.append('options=%s' % options)

				if ip != 'auto':
					self.owner.call('add.host.interface', cmdparams)
				else:
					autoip_list.append(cmdparams)

			sys.stderr.write('\t\t%s\r' % (' ' * len(host)))

		# Add interfaces with ip=AUTO at the end.
		for t in autoip_list:
			self.owner.call('add.host.interface', t)
Esempio n. 37
0
		# Once we import, get the CLI, adapter
		ctrl = controller.CLI()
		adapter = ctrl.getAdapter()

		if adapter != None:
			return (ctrl, adapter)

	return(None, None)

##
## MAIN
##

if 'nukecontroller' in attributes:
	nukecontroller = str2bool(attributes['nukecontroller'])
else:
	nukecontroller = False

if 'secureerase' in attributes:
	secureerase = str2bool(attributes['secureerase'])
else:
	secureerase = False

#
# if 'secureerase' is true, then that implies that 'nukecontroller' is true
#
if secureerase:
	nukecontroller = True
	
#
Esempio n. 38
0
def main():
    """Where the magic begins."""
    global host_partitions
    global csv_partitions
    host_disks = get_host_disks()

    count = 5
    while count > 0:
        if len(host_disks) == 0:
            time.sleep(1)
            count -= 1
            host_disks = get_host_disks()
        else:
            break

    #
    # if fstab is corrupted, get_host_fstab() will throw and exception.
    # catch it and just report an empty fstab
    #
    try:
        host_fstab = get_host_fstab(host_disks)
    except:
        host_fstab = []

    host_partitions = get_host_partitions(host_disks, host_fstab)

    if not csv_partitions:
        if attributes['os.version'] == "11.x" and attributes['os'] == "sles":
            ostype = "sles11"
        elif attributes['os.version'] == "12.x" and attributes['os'] == "sles":
            ostype = "sles12"
        else:
            # Give ostype some default
            ostype = "sles11"

        if os.path.exists('/sys/firmware/efi'):
            default = 'uefi'
        else:
            default = 'default'

        var = '%s_%s' % (ostype, default)
        if hasattr(sles, var):
            parts = getattr(sles, var)
        else:
            parts = getattr(sles, 'default')

        if 'boot_device' in attributes:
            bootdisk = attributes['boot_device']
        else:
            bootdisk = host_disks[0]

        csv_partitions = []
        partid = 1

        for m, s, f in parts:
            csv_partitions.append({
                'partid': partid,
                'scope': 'global',
                'device': bootdisk,
                'mountpoint': m,
                'size': s,
                'fstype': f,
                'options': ''
            })

            partid += 1

    #
    # there are 2 scenarios:
    #
    # 1) nukedisks == True
    # 2) nukedisks == False
    # 3) nukedisks == a list of disks to nuke <-- Not sure we actually handle this yet.
    #
    # 1 is easy -- nuke the disks and recreate the partitions specified in the
    # "partitions" variable
    #
    # For 2, reformat "/", "/boot" (if present) and "/var" on the boot disk, then
    # reconnect all other discovered partitions.

    # if host_fstab is an empty list, turning on nukedisks=True" to avoid SLES defaults
    if host_fstab == []:
        nuke_disks = True
        attributes['nukedisks'] = "True"
    elif 'nukedisks' in attributes:
        nuke_disks = str2bool(attributes['nukedisks'])
    else:
        nuke_disks = False
        attributes['nukedisks'] = "False"

    if not nuke_disks:
        # Need output of the existing fstab to be utilized for post-install script.
        if not os.path.exists(fs_info):
            os.makedirs(fs_info)
        with open(str(fs_info + '/__init__.py'), 'w') as fstab_info:
            fstab_info.write('old_fstab = %s\n\n' % host_fstab)

    #
    # process all nuked disks first
    #
    nuke_list = get_nukes(host_disks, nuke_disks, attributes['nukedisks'])

    for disk in nuke_list:
        nuke_it(disk)

        initialize = True
        output_disk(disk, initialize)
    #
    # now process all non-nuked disks
    #
    initialize = False
    for disk in host_disks:
        if disk not in nuke_list:
            output_disk(disk, initialize)

    print(prettify(partitioning_config))
Esempio n. 39
0
    def run(self, params, args):
        if len(args) != 1:
            raise ArgUnique(self, 'switch')

        sm_switch = args[0]

        (disable, ) = self.fillParams([
            ('disable', False),
        ])

        disable = str2bool(disable)

        ibswitches = [
            sw for sw in self.call('list.switch') if sw['model'] == 'm7800'
        ]
        ib_switch_names = [sw['switch'] for sw in ibswitches]

        if sm_switch not in ib_switch_names:
            msg = f'host {sm_switch} is not a supported infiniband switch\n'
            msg += 'Please verify the make and model attributes for this host.'
            raise CommandError(self, msg)

        self.switch_attrs = self.getHostAttrDict(ib_switch_names)

        if self.switch_attrs[sm_switch].get('switch_type') != 'infiniband':
            msg = f'{sm_switch} is not an infiniband switch, please verify "stack list host attr {sm_switch} attr=switch_type"'

        if disable:
            # explicit disable only affects this switch
            switch = self.get_sw_handle(sm_switch)
            switch.subnet_manager = False
            switch.disconnect()
            return

        # NOTE assumes a single management port with options set.
        # this obviously breaks if a switch can someday be on multiple fabrics
        fabric = self.switch_attrs[sm_switch].get('ibfabric')
        if not fabric:
            raise CommandError(
                self, f'switch {sm_switch} does not have its ibfabric set')

        switches_to_disable = []
        for ib_sw in ib_switch_names:
            if ib_sw == sm_switch:
                # this one is the sm
                continue

            sw_fabric = self.switch_attrs[ib_sw].get('ibfabric')
            if not sw_fabric or sw_fabric == fabric:
                # switches with no fabric specified should be disabled
                # other switches on the same fabric should be disabled
                switches_to_disable.append(ib_sw)
                continue

        for switch in switches_to_disable:
            sw_handle = self.get_sw_handle(switch)
            sw_handle.subnet_manager = False
            sw_handle.disconnect()

        sw_handle = self.get_sw_handle(sm_switch)
        sw_handle.subnet_manager = True
        sw_handle.disconnect()
Esempio n. 40
0
	def addHostAttrs(self, attributes):
		readonly = {}

		versions = {}
		for row in self.call('list.pallet'):
			# Compute a version number for each os pallet
			#
			# If the pallet already has a '.' take everything
			# before the '.' and add '.x'. If the version has no
			# '.' add '.x'
			name    = row['name']
			version = row['version']
			release = row['release']
			key     = '%s-%s-%s' % (name, version, release)

			if name in [ 'SLES', 'CentOS' ]: # FIXME: Ubuntu is missing
				versions[key] = (name, '%s.x' % version.split('.')[0])

		boxes = {}
		for row in self.call('list.box'):
			pallets = row['pallets'].split()
			carts   = row['carts'].split()
			
			name    = 'unknown'
			version = 'unknown'
			for pallet in pallets:
				if pallet in versions.keys():
					(name, version) = versions[pallet]
					break

			boxes[row['name']] = { 'pallets'    : pallets,
					       'carts'	    : carts,
					       'os.name'    : name, 
					       'os.version' : version }

		for (name, environment, rack, rank, metadata) in self.db.select(
				"""
				n.name, e.name, n.rack, n.rank, n.metadata 
				from nodes n
				left join environments e on n.environment=e.id
				"""):
			readonly[name]	       = {}
			readonly[name]['rack'] = rack
			readonly[name]['rank'] = rank
			if environment:
				readonly[name]['environment'] = environment
			if metadata:
				readonly[name]['metadata'] = metadata

		for (name, box, appliance) in self.db.select(
				""" 
				n.name, b.name,
				a.name from
				nodes n, boxes b, appliances a where
				n.appliance=a.id and n.box=b.id
				"""):
			readonly[name]['box']		     = box
			readonly[name]['pallets']	     = boxes[box]['pallets']
			readonly[name]['carts']		     = boxes[box]['carts']
#			readonly[name]['os.name']            = boxes[box]['os.name']
			readonly[name]['os.version']         = boxes[box]['os.version']
			readonly[name]['appliance']	     = appliance

				
		for (name, zone, address) in self.db.select(
				"""
				n.name, s.zone, nt.ip from
				networks nt, nodes n, subnets s where
				nt.main=true and nt.node=n.id and
				nt.subnet=s.id
				"""):
			if address:
				readonly[name]['hostaddr']   = address
			readonly[name]['domainname'] = zone

		for host in readonly:
			readonly[host]['os']	   = self.db.getHostOS(host)
			readonly[host]['hostname'] = host

		for row in self.call('list.host.group'):
			for group in row['groups'].split():
				readonly[row['host']]['group.%s' % group] = 'true'
			readonly[row['host']]['groups'] = row['groups']
		

		for host in attributes:
			a  = attributes[host]
			r  = readonly[host]
			ro = True

			if 'const_overwrite' in a:

				# This attribute allows a host to overwrite
				# constant attributes. This is crazy dangerous,
				# do not use this attribute.

				(n, v, t, s) = a['const_overwrite']
				ro = str2bool(v)

			if ro:
				for key in r: # slam consts on top of attrs
					a[key] = (r[key], 'const', 'host')
			else:
				for key in r: # only add new consts to attrs
					if key not in a:
						a[key] = (r[key], 'const', 'host')

		return attributes
Esempio n. 41
0
        # Once we import, get the CLI, adapter
        ctrl = controller.CLI()
        adapter = ctrl.getAdapter()

        if adapter != None:
            return (ctrl, adapter)

    return (None, None)


##
## MAIN
##

if 'nukecontroller' in attributes:
    nukecontroller = str2bool(attributes['nukecontroller'])
else:
    nukecontroller = False

if 'secureerase' in attributes:
    secureerase = str2bool(attributes['secureerase'])
else:
    secureerase = False

#
# if 'secureerase' is true, then that implies that 'nukecontroller' is true
#
if secureerase:
    nukecontroller = True

#