def __init__(self): self.name = self.__module__.split(".")[-1] self.wd = xmltools.WorkerDescription(self.name, prefix="/status") self.config_elt = self._get_config() self.cache_dir = os.path.join(context.cache_dir(), "bundles") try: os.mkdir(self.cache_dir) except OSError as e: if e.errno == errno.EEXIST: # don't worry about it pass self.cache_maint()
def __init__(self, datadir=None): if datadir: self.datadir = datadir else: self.datadir = os.path.join(context.cache_dir(), 'workers', 'dummyordered') self.wd = xmltools.WorkerDescription("dummyordered", prefix='/status') self.pdb = pretend_db(os.path.join(self.datadir, "pdb")) self.pc = pretend_config(os.path.join(self.datadir, "conf.txt")) self.dispatch = { '/status/worker/sysitem': self.handle_ordered, '/status/worker/tofile': self.handle_file, '/status/worker/notordered': self.handle_notordered, }
def _process(self, work, operation): # Prep necessary variables type = work.xpath('pkginfo/@type')[0] bundle = work.xpath('machinationFetcherBundle/@id')[0] bundle_path = os.path.join(context.cache_dir(), 'bundles', bundle) if "interactive" in work.keys(): inter = work.attrib["interactive"] else: inter = False # If it's interactive and not MSI, we need an uninstall check if inter and (type != "msi"): if not work.find("check"): err = "Interactive package without installation check: " err += bundle l.emsg(err) res.attrib["status"] = "error" res.attrib["message"] = err return res ins_check = [work.xpath('check/@type')[0], work.xpath('check/@id')[0]] else: ins_check = None # MSIs have additional options in pkginfo if type == "msi": pkginfo = work.find("pkginfo") else: pkginfo = None op = "_{0}_{1}".format(operation, type) back = getattr(self, op)(bundle_path, pkginfo, ins_check, inter) if not back: open(os.path.join(bundle_path,'.done'), 'a').close() return back
def _add(self, work): res = etree.Element("wu", id=work.attrib["id"]) cmdopts = {'printerName': ['/x', '/n', work[0].get("id") ], 'remotePath': ['/r', work[0].xpath('remotePath')[0].text ], 'model': ['/m', work[0].xpath('model')[0].text ]} # Start building a printui command printer = [os.path.join( os.environ.get('SYSTEMROOT', os.path.join('C:', 'Windows')), 'system32', 'printui.exe')] # Use staged driver driver. printer.append('/u') # Construct human readable printer name ('base' name in # windows, hence /b). printer.extend( [ '/b', self.descriptive_name(work[0]) ] ) # Queue name. printer.extend(['/n', work[0].get("id")]) # 'Remote path' = port, url or path to print server queue printer.extend(['/r', work[0].xpath('remotePath')[0].text ]) # Now we need model information. We'll need to get that from # context.desired_status. Outside of Machination a wrapper # script will need to supply a fake context. printer_model = work[0].xpath( 'model/text()' )[0] xp = '/status/worker[@id="printer"]/model[@id="%s"]' % printer_model model_elt = context.desired_status.getroot().xpath(xp)[0] # Normally the driver name is the same as the model_elt id. In # exceptional circumstances it may be necessary to set # something different. In that case there should be a # driverName child of model. try: driverName = model_elt.xpath("driverName/text()")[0] except IndexError: driverName = model_elt.get("id") printer.extend(['/m',driverName]) # Handle inf path differently depending on whether the driver # is built in or needed to be downloaded. bundle_elts = model_elt.xpath('machinationFetcherBundle') if bundle_elts: # We needed to download it. Fetcher should have done the # download already, we just have to point to the file printer.extend( [ '/if', '/f', os.path.join(context.cache_dir(), "bundles", bundle_elts[0].get("id"), model_elt.xpath('infFile/text()')[0]) ] ) print(model_elt.xpath('infLocation/text()')) bundle_elts_inf = model_elt.xpath('infLocation') if bundle_elts_inf: printer.extend( [ '/l', os.path.join(context.cache_dir(), "bundles", bundle_elts[0].get("id"), model_elt.xpath('infLocation/text()')[0]) ] ) else: # No bundles: builtin driver. printer.extend( [ '/if', '/f', os.path.join( os.environ.get('windir'),'inf', 'ntprint.inf' ) ] ) print(printer) #after parsing the xml go and add that printer return_code = self.print_ui(printer) #check the return code from processAdd if return_code: res.attrib["status"] = "error" else: res.attrib["status"] = "success" return res
def self_update(self, wu): """Perform a Machination self update. Sequence: - Copy bin_dir()/self_update to cache_dir() - Write installedVersion to cache_dir()/installed_version.xml - os.execl() cache_dir()/self_update which will: - remove worker packages except __machination__ - remove core and __machination__ only if changed - add core package (if changed) - add worker packages """ # Create a directory in which to store self update material sudir = os.path.join(context.cache_dir(), "selfupdate") try: os.mkdir(sudir) except OSError as e: if e.errno != errno.EEXIST: raise # Copy the self update script su_script_name = "machination-self-update.py" shutil.copy(os.path.join(context.bin_dir(), su_script_name), sudir) su_script = os.path.join(sudir, su_script_name) # Write installedVersion elements (current and desired) iv = etree.Element("iv") # Write the location of bundles into iv (at /iv/@bundleDir) iv.set("bundleDir", os.path.join(context.cache_dir(), "bundles")) wu[0].set("version", "desired") self.generated_iv.set("version", "current") iv.append(self.generated_iv) iv.append(wu[0]) # Check to make sure we aren't being asked to downgrade any # packages. curver = {} nocando = [] for b in self.generated_iv: name, version = self.get_version(b.get("id"), name_too=True) curver[name] = version curxpath = 'installedVersion[@version="current"]/machinationFetcherBundle' for b in iv.xpath(curxpath): name, version = self.get_version(b.get("id"), name_too=True) if name not in curver: # pkg remove continue if version < curver[name]: l.wmsg("Refusing to downgrade " + name) l.wmsg("desired-status asks for version {} " + "but {} is installed".format(version, curver[name])) # Can't remove b while we're iterating - remember it # for later. nocando.append(b) for b in nocando: name, version = self.get_version(b.get("id"), name_too=True) wu[0].remove(b) wu[0].add(etree.Element("machinationFetcherBundle", id="{}-{}".format(name, curver[name]))) iv_file = os.path.join(sudir, "installed_version.xml") with open(iv_file, "w") as ivf: ivf.write(etree.tostring(iv, pretty_print=True).decode()) # Hand over to the self update script os.execl(sys.executable, "machination-self-update", su_script, iv_file)