示例#1
0
    def desired_status(self):
        """Get the desired status. Will download and compile status if necessary."""
        if self._desired_status is None:
            services = context.machination_worker_elt.xpath("services/service")
            # TODO download from all services and merge. For now just
            # do the first one.
            #            hurl = services[0].xpath('hierarchy/@id')
            service_id = services[0].get("id")
            l.lmsg('Connecting to service "{}"'.format(service_id))
            # find the machination id for this service
            mid = context.get_id(service_id)
            wc = WebClient.from_service_id(service_id, "os_instance")
            #            channel = wc.call("ProfChannel", 'os_instance')
            try:
                data = wc.call("GetAssertionList", "os_instance", mid)
            except:
                # couldn't dowload assertions - go with last desireed
                # status. Should already be canonicalized.
                l.wmsg("Failed to download assertions - using desired status from context.")
                self._desired_status = copy.deepcopy(context.desired_status.getroot())
            else:
                # we do have some assertions - compile them
                #                pprint.pprint(data)
                ac = AssertionCompiler(wc)
                self._desired_status, res = ac.compile(data)
                mc14n(self._desired_status)
                # Save as desired-status.xml
                with open(os.path.join(context.status_dir(), "desired-status.xml"), "w") as ds:
                    ds.write(etree.tostring(self._desired_status, pretty_print=True).decode())

        return self._desired_status
示例#2
0
 def load_previous_status(self):
     """Load previous_status.xml"""
     fname = os.path.join(context.status_dir(), "previous-status.xml")
     try:
         self._previous_status = etree.parse(fname).getroot()
     except IOError:
         # couldn't read file may be lack of permission or not exists
         # if not exists (first run?) we should make a new status
         if not os.path.isfile(fname):
             self._previous_status = E.status()
         else:
             raise
     mc14n(self._previous_status)
     return self._previous_status
示例#3
0
 def gather_status(self):
     """Invoke all workers' generate_status() and gather into one."""
     l.lmsg("Gathering status from workers.")
     status = copy.deepcopy(self.load_previous_status())
     # find all workers
     stelt = status.xpath("/status")[0]
     done = set()
     for welt in status.xpath("/status/worker"):
         # the following should create a worker object and store it
         # in self.workers
         worker = self.worker(welt.get("id"))
         if worker is not None:
             try:
                 wstatus = worker.generate_status()
             except AttributeError:
                 # No generate_status method: leave the previous
                 # status element intact. This will, in effect,
                 # cause the status to be tracked by do_update()
                 # when it writes sucessful changes to
                 # previous_status.xml
                 pass
             stelt.remove(welt)
             try:
                 stelt.append(wstatus)
             except Exception as e:
                 stelt.append(welt)
         done.add(welt.get("id"))
     for welt in self.desired_status().xpath("/status/worker"):
         if welt.get("id") in done:
             continue
         worker = self.worker(welt.get("id"))
         if worker is not None:
             try:
                 wstatus = worker.generate_status()
             except AttributeError:
                 # No generate_status method and no previous status
                 # element, create one
                 # stelt.append(etree.Element('worker', id=welt.get('id')))
                 pass
             else:
                 stelt.append(wstatus)
     mc14n(status)
     return status
示例#4
0
    def generate_status(self):
        """Generate worker status element.

        Part generated: Everything from desired status is just
        returned, apart from:
          - versionInstalled: auto-generated from installed packages
        """
        # The current status of machination is just what desired
        # status says it is, apart from installedVersion.

        # Copy the __machination__ worker element as our starting point.
        w_elt = copy.deepcopy(context.get_worker_elt(self.name))

        # Grab the installedVersion element.
        try:
            desiv = w_elt.xpath("installedVersion")[0]
        except IndexError:
            # No installedVersion, create an empty one for the rest of
            # the algorithm.
            desiv = etree.Element("installedVersion")
        else:
            w_elt.remove(desiv)

        # Find installedVersion information
        geniv = getattr(self, self.get_installed_func())()
        # Use geniv as a template to build new element. We do this so
        # that the installedVersion element's children are in the same
        # order.
        self.generated_iv = etree.Element("installedVersion")
        for desb in desiv.xpath("machinationFetcherBundle"):
            try:
                genb = geniv.xpath('machinationFetcherBundle[@id="{}"]'.format(desb.get("id")))[0]
            except IndexError:
                # No counterpart.
                pass
            else:
                # Found counterpart in geniv, add to generated_iv.
                self.generated_iv.append(genb)
        # Now add any elements left in geniv to generated_iv
        for genb in geniv:
            self.generated_iv.append(genb)

        w_elt.append(self.generated_iv)

        return xmltools.mc14n(w_elt)
示例#5
0
from machination.xmltools import XMLCompare
from machination.xmltools import generate_wus
from machination.xmltools import mc14n
import sys
from lxml import etree
import pprint

left = mc14n(etree.parse(sys.argv[1]))
right = mc14n(etree.parse(sys.argv[2]))

# print(etree.tostring(left, pretty_print = True).decode())
# print(etree.tostring(right, pretty_print = True).decode())

deps = etree.fromstring("<status><deps/></status>")[0]
comp = XMLCompare(left, right)
wudeps = comp.wudeps(deps.iterchildren(tag=etree.Element))

pprint.pprint(comp.bystate)
pprint.pprint(comp.actions())
pprint.pprint(comp.find_work())

wus, working = generate_wus(comp.find_work(), comp)

for wu in wus:
    print(etree.tostring(wu, pretty_print=True).decode())

print(etree.tostring(working, pretty_print=True).decode())
示例#6
0
 def __init__(self, initial_status=None, desired_status=None):
     self.workers = {}
     mc14n(context.desired_status)
     self._initial_status = initial_status
     self._desired_status = desired_status
     self._previous_status = None