Exemplo n.º 1
0
    def _collate_container_params(self, containertemplate, commonparams,
                                  containerelem, overlays):

        containerparams = [('lxc.utsname', self.lxc_name)]

        if containertemplate:
            containerparams.extend(containertemplate.params)

        for k, v in commonparams:
            containerparams.append((k, v))

        for paramelem in containerelem.findall('./parameters/parameter'):
            if (str(paramelem.attrib['name']) == 'lxc.utsname'):
                # the lxc_name is set by the container element atribute
                print >>sys.stderr, \
                    'Found lxc.utsname in containertemplate. Ignoring'
                continue

            containerparams.append((str(paramelem.attrib['name']),
                                    str(paramelem.attrib['value'])))

        for i, parampair in enumerate(containerparams):
            k, v = parampair

            containerparams[i] = (k, format_string(v, overlays))

        return containerparams
Exemplo n.º 2
0
    def _createfile(self,
                    publishdir,
                    logdir,
                    index,
                    runtime_overlays,
                    env_overlays,
                    etce_config_overlays):
        reserved_overlays = {}
        
        reserved_overlays['etce_index'] = index

        # etce_hostname formats are limited to the index and the
        # overlays specified in the test.xml file.
        etce_hostname_cm = ChainMap({'etce_index': reserved_overlays['etce_index']},
                                    self._template_local_overlaylists[index],
                                    self._template_local_overlays,
                                    self._templates_global_overlaylists[index],
                                    self._global_overlays)
            
        reserved_overlays['etce_hostname'] = format_string(self._hostname_format, etce_hostname_cm)

        if logdir:
            reserved_overlays['etce_log_path'] = \
                os.path.join(logdir, reserved_overlays['etce_hostname'])

        publishfile = os.path.join(publishdir, 
                                   reserved_overlays['etce_hostname'], 
                                   self._output_file_name)

        other_keys = set([])

        non_reserved_overlays = [ runtime_overlays,
                                  env_overlays,
                                  self._template_local_overlaylists[index],
                                  self._template_local_overlays,
                                  self._templates_global_overlaylists[index],
                                  self._global_overlays,
                                  etce_config_overlays ] 

        map(other_keys.update, non_reserved_overlays)

        key_clashes =  other_keys.intersection(set(reserved_overlays.keys()))

        if key_clashes:
            raise ValueError('Overlay keys {%s} are reserved. Quitting.' % \
                             ','.join(map(str,key_clashes)))

        overlays = ChainMap(reserved_overlays, *non_reserved_overlays)

        # format str can add subdirectories, so make those if necessary
        if not os.path.exists(os.path.dirname(publishfile)):
            os.makedirs(os.path.dirname(publishfile))

        if os.path.exists(publishfile):
            print 'Warning: %s already exists. Overwriting!' % publishfile

        format_file(self._absname, publishfile, overlays)
    def formatted_hostnames(self):
        formatted_hostnames = []
        for index in self.indices:
            chainmap = ChainMap({'etce_index':index},
                                self._template_local_overlaylists[index],
                                self._template_local_overlays,
                                self._templates_global_overlaylists[index],
                                self._global_overlays)

            formatted_hostnames.append(format_string(self._hostname_format, chainmap))

        return formatted_hostnames
Exemplo n.º 4
0
    def _get_initscript(self, containertemplate, containerelem, overlays):
        initscript= ('',None)

        if containertemplate:
            initscript = containertemplate.initscript

        for initscriptelem in containerelem.findall('./initscript'):
            initscript = ('init.sh', initscriptelem.text)

        if initscript[1]:
            lines = []

            for line in initscript[1].split('\n'):
                line = line.strip()

                if len(line) > 0:
                    lines.append(format_string(line.strip(), overlays))

            initscript = (initscript[0], '\n'.join(lines))

        return initscript
Exemplo n.º 5
0
    def _parseplan(self, lxcplanfile):
        lxcplanelem = self.parse(lxcplanfile)

        kernelparameters = {}

        containertemplates = {}

        rootdirectories = {}

        lxcplanelems = \
            lxcplanelem.findall('./containertemplates/containertemplate')

        for containertemplateelem in lxcplanelems:
            containertemplate_name = containertemplateelem.attrib['name']

            containertemplate_parent_name = \
                containertemplateelem.attrib.get('parent', None)

            containertemplate_parent = None

            if containertemplate_parent_name:
                if not containertemplate_parent_name in containertemplates:
                    errmsg = 'parent "%s" of containertemplate "%s" not ' \
                             'previously listed. Quitting.' % \
                             (containertemplate_parent_name,
                              containertemplate_name)
                    raise ValueError(errmsg)

                containertemplate_parent = \
                    containertemplates[containertemplate_parent_name]

            containertemplates[containertemplate_name] = \
                ContainerTemplate(containertemplateelem,
                                  containertemplate_parent)

        hostelems = lxcplanelem.findall('./hosts/host')

        bridges = {}

        containers = {}

        hostnames = []

        for hostelem in hostelems:
            hostname = hostelem.attrib.get('hostname')

            hostnames.append(hostname)

            # 'localhost' is permitted as a catchall hostname to mean the
            # local machine only when one host is specified in the file
            if hostname == 'localhost':
                if len(hostelems) > 1:
                    error = '"localhost" hostname only permitted when one ' \
                            'host is specified. Quitting'
                    raise ValueError(error)

            # kernel params
            kernelparameters[hostname] = {}

            for paramelem in hostelem.findall('./kernelparameters/parameter'):
                kernelparameters[hostname][paramelem.attrib['name']] = \
                    paramelem.attrib['value']

            # bridges (explicit)
            bridges[hostname] = {}

            for bridgeelem in hostelem.findall('./bridges/bridge'):
                bridge = Bridge(bridgeelem)

                bridges[hostname][bridge.name] = bridge

            containers[hostname] = []

            params = []

            containerselem = hostelem.findall('./containers')[0]

            root_directory = \
                os.path.join(ConfigDictionary().get('etce', 'WORK_DIRECTORY'), 'lxcroot')

            rootdirectories[hostname] = root_directory

            # ensure no repeated lxc_indices
            alllxcids = set([])

            for containerelem in hostelem.findall('./containers/container'):
                containerlxcids = etce.utils.nodestr_to_nodelist(
                    str(containerelem.attrib['lxc_indices']))

                repeatedids = alllxcids.intersection(containerlxcids)

                assert len(repeatedids) == 0, \
                    'Found repeated lxcid(s): {%s}. Quitting.' % \
                    ','.join([ str(nid) for nid in list(repeatedids) ])

                alllxcids.update(containerlxcids)

            # Create containers from container elems
            for containerelem in hostelem.findall('./containers/container'):
                templatename = containerelem.attrib.get('template', None)

                template = containertemplates.get(templatename, None)

                lxcids = etce.utils.nodestr_to_nodelist(
                    str(containerelem.attrib['lxc_indices']))

                # fetch the overlays, use etce file values as default
                overlays = ConfigDictionary().asdict()['overlays']

                for overlayelem in containerelem.findall('./overlays/overlay'):
                    oname = overlayelem.attrib['name']

                    ovalue = overlayelem.attrib['value']

                    overlays[oname] = etce.utils.configstrtoval(ovalue)

                # fetch the overlaylists
                overlaylists = {}

                for overlaylistelem in containerelem.findall(
                        './overlays/overlaylist'):
                    oname = overlaylistelem.attrib['name']

                    separator = overlaylistelem.attrib.get('separator', ',')

                    ovalues = overlaylistelem.attrib['values'].split(separator)

                    overlaylists[oname] = ovalues

                # treat all values for each name as an int if possible,
                # else all strings
                for oname, ovals in overlaylists.items():
                    converted_vals = []
                    try:
                        converted_vals = [
                            etce.utils.configstrtoval(oval) for oval in ovals
                        ]

                        overlaylists[oname] = converted_vals
                    except ValueError:
                        # leave as strings
                        pass

                # Why must a default value be supplied here when
                # schema declares this attribute with a default value?
                for i, lxcid in enumerate(lxcids):
                    # start with overlays
                    lxcoverlays = copy.copy(overlays)

                    # then add list items for this node
                    for oname, ovals in overlaylists.items():
                        lxcoverlays[oname] = ovals[i]

                    # then lxcindex, lxc_name and lxc_directory (cannot be overwritten)
                    lxcoverlays.update({'lxc_index': lxcid})

                    lxcoverlays.update({
                        'lxc_name':
                        format_string(containerelem.attrib['lxc_name'],
                                      lxcoverlays)
                    })

                    lxcoverlays.update({
                        'lxc_directory':
                        os.path.join(root_directory, lxcoverlays['lxc_name'])
                    })

                    containers[hostname].append(
                        Container(containerelem, lxcoverlays, params, template,
                                  bridges[hostname], hostname))

            # Roll over containers to get names of implicit bridges added
            # from the container interface bridge names and augment
            # the bridges list
            for container in containers[hostname]:
                for iname, iparams in container.interfaces.items():
                    if not iname in bridges[hostname]:
                        bridges[hostname][iname] = BridgeImplicit(iname)

        return hostnames, kernelparameters, bridges, containers, rootdirectories
Exemplo n.º 6
0
    def _process_interfaces(self, containertemplate, containerelem, overlays):
        interfaces = defaultdict(lambda: {})

        bridge_entry_ipv4 = {}

        bridge_entry_ipv6 = {}

        if containertemplate:
            for bridgename, paramdict in containertemplate.interfaces.items():
                bridgename = format_string(bridgename, overlays)
                for iname, ival in paramdict.items():
                    interfaces[bridgename][format_string(iname, overlays)] = \
                        format_string(ival, overlays)

            for bridgename, entryname in \
                containertemplate.hosts_entries_ipv4.items():
                bridgename = format_string(bridgename, overlays)
                bridge_entry_ipv4[bridgename] = format_string(
                    entryname, overlays)

            for bridgename, entryname in \
                containertemplate.hosts_entries_ipv6.items():
                bridgename = format_string(bridgename, overlays)
                bridge_entry_ipv6[bridgename] = format_string(
                    entryname, overlays)

        # overwrite with local values from container
        for interfaceelem in containerelem.findall('./interfaces/interface'):
            bridgename = format_string(str(interfaceelem.attrib['bridge']),
                                       overlays)

            interfaceparams = interfaces[bridgename]

            for iparamelem in interfaceelem.findall('./parameter'):
                iname = format_string(str(iparamelem.attrib['name']), overlays)

                ival = format_string(str(iparamelem.attrib['value']), overlays)

                interfaceparams[iname] = ival

            entry_name_ipv4 = \
                interfaceelem.attrib.get(
                    'hosts_entry_ipv4',
                    bridge_entry_ipv4.get(bridgename, None))

            if entry_name_ipv4:
                bridge_entry_ipv4[bridgename] = \
                    format_string(entry_name_ipv4, overlays)

            entry_name_ipv6 = \
                interfaceelem.attrib.get(
                    'hosts_entry_ipv6',
                    bridge_entry_ipv6.get(bridgename, None))

            if entry_name_ipv6:
                bridge_entry_ipv6[bridgename] = \
                    format_string(entry_name_ipv6, overlays)

        hosts_entries_ipv4 = []

        for bridgename, entry_name_ipv4 in bridge_entry_ipv4.items():
            if not 'lxc.network.ipv4' in interfaces[bridgename]:
                error = 'Found hosts_entry_ipv4 attribute for ' \
                        'bridge "%s" for container "%s" but ' \
                        'no corresponding "lxc.network.ipv4" ' \
                        'value for the interface. Quitting.' \
                        % (bridgename, self.lxc_name)
                raise ValueError(error)

            addr = interfaces[bridgename]['lxc.network.ipv4']

            hosts_entries_ipv4.append((entry_name_ipv4, addr.split('/')[0]))

        hosts_entries_ipv6 = []

        for bridgename, entry_name_ipv6 in bridge_entry_ipv6.items():
            if not 'lxc.network.ipv6' in interfaces[bridgename]:
                error = 'Found hosts_entry_ipv6 attribute for ' \
                        'bridge "%s" for container "%s" but ' \
                        'no corresponding "lxc.network.ipv6" ' \
                        'value for the interface. Quitting.' \
                        % (bridgename, self.lxc_name)
                raise ValueError(error)

            addr = interfaces[bridgename]['lxc.network.ipv6']

            hosts_entries_ipv6.append((entry_name_ipv6, addr))

        return interfaces, hosts_entries_ipv4, hosts_entries_ipv6
    def _createdir(self,
                   subdirectory_map,
                   publishdir,
                   logdir,
                   index,
                   runtime_overlays,
                   env_overlays,
                   etce_config_overlays):
        # assemble the format dictionary from the various overlays
        # most local value takes precedent
        reserved_overlays = {}

        reserved_overlays['etce_index'] = index

        # etce_hostname formats are limited to the index and the
        # overlays specified in the test.xml file.
        etce_hostname_cm = ChainMap({'etce_index': reserved_overlays['etce_index']},
                                    self._template_local_overlaylists[index],
                                    self._template_local_overlays,
                                    self._templates_global_overlaylists[index],
                                    self._global_overlays)
        
        reserved_overlays['etce_hostname'] = format_string(self._hostname_format, etce_hostname_cm)

        if logdir:
            reserved_overlays['etce_log_path'] = \
                os.path.join(logdir, reserved_overlays['etce_hostname'])
            
        node_publishdir = os.path.join(publishdir, reserved_overlays['etce_hostname'])

        non_reserved_overlays = [ runtime_overlays,
                                  env_overlays,
                                  self._template_local_overlaylists[index],
                                  self._template_local_overlays,
                                  self._templates_global_overlaylists[index],
                                  self._global_overlays,
                                  etce_config_overlays ] 
        
        other_keys = set([])

        for some_overlays in non_reserved_overlays:
            other_keys.update(some_overlays)

        key_clashes =  other_keys.intersection(set(reserved_overlays))

        if key_clashes:
            raise ValueError('Overlay keys {%s} are reserved. Quitting.' % \
                             ','.join(map(str,key_clashes)))

        overlays = ChainMap(reserved_overlays, *non_reserved_overlays)

        print('Processing template directory "%s" for etce_index=%d ' \
              'and destination=%s' % \
              (self.template_directory_name, index, node_publishdir))

        if not os.path.exists(node_publishdir):
            os.makedirs(node_publishdir)


        found = False

        for relpath,entry in subdirectory_map.items():
            # ignore files outside of the template directory
            pathtoks = relpath.split(os.path.sep)
            
            if not pathtoks[0] == self.template_directory_name:
                continue
            
            dstfile = os.path.join(node_publishdir,*pathtoks[1:])

            dstdir = os.path.dirname(dstfile)
            
            if not os.path.exists(dstdir):
                os.makedirs(dstdir)

            format_file(entry.full_name, dstfile, overlays)