dom0/core: drop support for non-updateable templates
Implement 'updateable' property as 'template is None'
This commit is contained in:
		
							parent
							
								
									f143b6c1f2
								
							
						
					
					
						commit
						cdd73f3d14
					
				| @ -228,7 +228,6 @@ class QubesVm(object): | ||||
|             "volatile_img": { "eval": 'self.absolute_path(value, default_volatile_img)', 'order': 10 }, | ||||
|             "firewall_conf": { "eval": 'self.absolute_path(value, default_firewall_conf_file)', 'order': 10 }, | ||||
|             "installed_by_rpm": { "default": False, 'order': 10 }, | ||||
|             "updateable": { "default": False, 'order': 10 }, | ||||
|             "template": { "default": None, 'order': 10 }, | ||||
|             # order >= 20: have template set | ||||
|             "uses_default_netvm": { "default": True, 'order': 20 }, | ||||
| @ -266,7 +265,7 @@ class QubesVm(object): | ||||
|         # Simple string attrs | ||||
|         for prop in ['qid', 'name', 'dir_path', 'memory', 'maxmem', 'pcidevs', 'vcpus', 'internal',\ | ||||
|             'uses_default_kernel', 'kernel', 'uses_default_kernelopts',\ | ||||
|             'kernelopts', 'services', 'updateable', 'installed_by_rpm',\ | ||||
|             'kernelopts', 'services', 'installed_by_rpm',\ | ||||
|             'uses_default_netvm', 'include_in_backups' ]: | ||||
|             attrs[prop]['save'] = 'str(self.%s)' % prop | ||||
|         # Simple paths | ||||
| @ -279,7 +278,7 @@ class QubesVm(object): | ||||
| 
 | ||||
|         attrs['netvm']['save'] = 'str(self.netvm.qid) if self.netvm is not None else "none"' | ||||
|         attrs['netvm']['save_attr'] = "netvm_qid" | ||||
|         attrs['template']['save'] = 'str(self.template.qid) if self.template and not self.is_updateable() else "none"' | ||||
|         attrs['template']['save'] = 'str(self.template.qid) if self.template else "none"' | ||||
|         attrs['template']['save_attr'] = "template_qid" | ||||
|         attrs['label']['save'] = 'self.label.name' | ||||
| 
 | ||||
| @ -327,9 +326,6 @@ class QubesVm(object): | ||||
| 
 | ||||
|         # Some additional checks for template based VM | ||||
|         if self.template is not None: | ||||
|             if self.updateable: | ||||
|                 print >> sys.stderr, "ERROR: Template based VM cannot be updateable!" | ||||
|                 return False | ||||
|             if not self.template.is_template(): | ||||
|                 print >> sys.stderr, "ERROR: template_qid={0} doesn't point to a valid TemplateVM".\ | ||||
|                     format(self.template.qid) | ||||
| @ -457,6 +453,11 @@ class QubesVm(object): | ||||
|     def mac(self, new_mac): | ||||
|         self._mac = new_mac | ||||
| 
 | ||||
|     @property | ||||
|     def updateable(self): | ||||
|         return self.template is None | ||||
| 
 | ||||
|     # Leaved for compatibility | ||||
|     def is_updateable(self): | ||||
|         return self.updateable | ||||
| 
 | ||||
| @ -469,19 +470,6 @@ class QubesVm(object): | ||||
|         else: | ||||
|             return False | ||||
| 
 | ||||
|     def set_updateable(self): | ||||
|         if self.is_updateable(): | ||||
|             return | ||||
| 
 | ||||
|         raise QubesException ("Change 'updateable' flag is not supported. Please use qvm-create.") | ||||
| 
 | ||||
|     def set_nonupdateable(self): | ||||
|         if not self.is_updateable(): | ||||
|             return | ||||
| 
 | ||||
|         raise QubesException ("Change 'updateable' flag is not supported. Please use qvm-create.") | ||||
| 
 | ||||
| 
 | ||||
|     def pre_rename(self, new_name): | ||||
|         pass | ||||
| 
 | ||||
| @ -875,7 +863,7 @@ class QubesVm(object): | ||||
|         args['privatedev'] = "'script:file:{dir}/private.img,xvdb,w',".format(dir=self.dir_path) | ||||
|         args['volatiledev'] = "'script:file:{dir}/volatile.img,xvdc,w',".format(dir=self.dir_path) | ||||
|         modulesmode='r' | ||||
|         if self.is_updateable() and self.kernel is None: | ||||
|         if self.updateable and self.kernel is None: | ||||
|             modulesmode='w' | ||||
|         args['otherdevs'] = "'script:file:{dir}/modules.img,xvdd,{mode}',".format(dir=self.kernels_dir, mode=modulesmode) | ||||
|         args['kernelopts'] = self.kernelopts | ||||
| @ -937,7 +925,7 @@ class QubesVm(object): | ||||
|             shutil.copy(source_template.dir_path + '/vm-' + qubes_whitelisted_appmenus, | ||||
|                     self.dir_path + '/' + qubes_whitelisted_appmenus) | ||||
| 
 | ||||
|         if self.is_updateable(): | ||||
|         if self.updateable: | ||||
|             template_root = source_template.root_img | ||||
|             if verbose: | ||||
|                 print >> sys.stderr, "--> Copying the template's root image: {0}".\ | ||||
| @ -1067,7 +1055,7 @@ class QubesVm(object): | ||||
|                 "VM directory doesn't exist: {0}".\ | ||||
|                 format(self.dir_path)) | ||||
| 
 | ||||
|         if self.is_updateable() and not os.path.exists (self.root_img): | ||||
|         if self.updateable and not os.path.exists (self.root_img): | ||||
|             raise QubesException ( | ||||
|                 "VM root image file doesn't exist: {0}".\ | ||||
|                 format(self.root_img)) | ||||
| @ -1483,7 +1471,6 @@ class QubesTemplateVm(QubesVm): | ||||
|     def _get_attrs_config(self): | ||||
|         attrs_config = super(QubesTemplateVm, self)._get_attrs_config() | ||||
|         attrs_config['dir_path']['eval'] = 'value if value is not None else qubes_templates_dir + "/" + self.name' | ||||
|         attrs_config['updateable']['default'] = True | ||||
|         attrs_config['label']['default'] = default_template_label | ||||
| 
 | ||||
|         # New attributes | ||||
| @ -1506,18 +1493,9 @@ class QubesTemplateVm(QubesVm): | ||||
|     def type(self): | ||||
|         return "TemplateVM" | ||||
| 
 | ||||
|     def set_updateable(self): | ||||
|         if self.is_updateable(): | ||||
|             return | ||||
| 
 | ||||
|         assert not self.is_running() | ||||
|         # Make sure that all the AppVMs are non-updateable... | ||||
|         for appvm in self.appvms.values(): | ||||
|             if appvm.is_updateable(): | ||||
|                 raise QubesException("One of the AppVMs ('{0}')is also 'updateable'\ | ||||
|                                      -- cannot make the TemplateVM {'{1}'} 'nonupdatable'".\ | ||||
|                                      format (appvm.name, self.name)) | ||||
|         self.updateable = True | ||||
|     @property | ||||
|     def updateable(self): | ||||
|         return True | ||||
| 
 | ||||
|     def get_rootdev(self, source_template=None): | ||||
|         return "'script:origin:{dir}/root.img:{dir}/root-cow.img,xvda,w',".format(dir=self.dir_path) | ||||
| @ -1633,7 +1611,7 @@ class QubesTemplateVm(QubesVm): | ||||
| 
 | ||||
|         self.reset_volatile_storage(verbose=verbose) | ||||
| 
 | ||||
|         if not self.is_updateable(): | ||||
|         if not self.updateable: | ||||
|             raise QubesException ("Cannot start Template VM that is marked \"nonupdatable\"") | ||||
| 
 | ||||
|         # TODO?: check if none of running appvms are outdated | ||||
| @ -2104,7 +2082,7 @@ class QubesAppVm(QubesVm): | ||||
| 
 | ||||
|         super(QubesAppVm, self).create_on_disk(verbose, source_template=source_template) | ||||
| 
 | ||||
|         if self.is_updateable(): | ||||
|         if self.updateable: | ||||
|             if verbose: | ||||
|                 print >> sys.stderr, "--> Copying the template's appmenus templates dir:\n{0} ==>\n{1}".\ | ||||
|                         format(source_template.appmenus_templates_dir, self.appmenus_templates_dir) | ||||
| @ -2170,7 +2148,6 @@ class QubesVmCollection(dict): | ||||
|     def add_new_appvm(self, name, template, | ||||
|                       dir_path = None, conf_file = None, | ||||
|                       private_img = None, | ||||
|                       updateable = False, | ||||
|                       label = None): | ||||
| 
 | ||||
|         qid = self.get_new_unused_qid() | ||||
| @ -2180,7 +2157,6 @@ class QubesVmCollection(dict): | ||||
|                          netvm = self.get_default_netvm(), | ||||
|                          kernel = self.get_default_kernel(), | ||||
|                          uses_default_kernel = True, | ||||
|                          updateable=updateable, | ||||
|                          label=label) | ||||
| 
 | ||||
|         if not self.verify_new_vm (vm): | ||||
| @ -2236,14 +2212,13 @@ class QubesVmCollection(dict): | ||||
|     def add_new_netvm(self, name, template, | ||||
|                       dir_path = None, conf_file = None, | ||||
|                       private_img = None, installed_by_rpm = False, | ||||
|                       label = None, updateable = False): | ||||
|                       label = None): | ||||
| 
 | ||||
|         qid = self.get_new_unused_qid() | ||||
|         netid = self.get_new_unused_netid() | ||||
|         vm = QubesNetVm (qid=qid, name=name, template=template, | ||||
|                          netid=netid, label=label, | ||||
|                          private_img=private_img, installed_by_rpm=installed_by_rpm, | ||||
|                          updateable=updateable, | ||||
|                          kernel = self.get_default_kernel(), | ||||
|                          uses_default_kernel = True, | ||||
|                          dir_path=dir_path, conf_file=conf_file) | ||||
| @ -2264,7 +2239,7 @@ class QubesVmCollection(dict): | ||||
|     def add_new_proxyvm(self, name, template, | ||||
|                      dir_path = None, conf_file = None, | ||||
|                      private_img = None, installed_by_rpm = False, | ||||
|                      label = None, updateable = False): | ||||
|                      label = None): | ||||
| 
 | ||||
|         qid = self.get_new_unused_qid() | ||||
|         netid = self.get_new_unused_netid() | ||||
| @ -2272,7 +2247,6 @@ class QubesVmCollection(dict): | ||||
|                               netid=netid, label=label, | ||||
|                               private_img=private_img, installed_by_rpm=installed_by_rpm, | ||||
|                               dir_path=dir_path, conf_file=conf_file, | ||||
|                               updateable=updateable, | ||||
|                               kernel = self.get_default_kernel(), | ||||
|                               uses_default_kernel = True, | ||||
|                               netvm = self.get_default_fw_netvm()) | ||||
| @ -2482,7 +2456,7 @@ class QubesVmCollection(dict): | ||||
|         kwargs = {} | ||||
|         common_attr_list = ("qid", "name", "dir_path", "conf_file", | ||||
|                 "private_img", "root_img", "template_qid", | ||||
|                 "installed_by_rpm", "updateable", "internal", | ||||
|                 "installed_by_rpm", "internal", | ||||
|                 "uses_default_netvm", "label", "memory", "vcpus", "pcidevs", | ||||
|                 "maxmem", "kernel", "uses_default_kernel", "kernelopts", "uses_default_kernelopts", | ||||
|                 "mac", "services", "include_in_backups" ) | ||||
| @ -2493,8 +2467,6 @@ class QubesVmCollection(dict): | ||||
|                 kwargs.pop(attribute) | ||||
| 
 | ||||
|         kwargs["qid"] = int(kwargs["qid"]) | ||||
|         if "updateable" in kwargs: | ||||
|             kwargs["updateable"] = True if kwargs["updateable"] == "True" else False | ||||
| 
 | ||||
|         if "include_in_backups" in kwargs: | ||||
|             kwargs["include_in_backups"] = True if kwargs["include_in_backups"] == "True" else False | ||||
|  | ||||
| @ -390,7 +390,7 @@ def backup_prepare(base_backup_dir, vms_list = None, exclude_list = [], print_ca | ||||
| 
 | ||||
|         if vm.is_appvm(): | ||||
|             files_to_backup += file_to_backup(vm.icon_path) | ||||
|         if vm.is_updateable(): | ||||
|         if vm.updateable: | ||||
|             if os.path.exists(vm.dir_path + "/apps.templates"): | ||||
|                 # template | ||||
|                 files_to_backup += file_to_backup(vm.dir_path + "/apps.templates") | ||||
| @ -405,7 +405,7 @@ def backup_prepare(base_backup_dir, vms_list = None, exclude_list = [], print_ca | ||||
|         if os.path.exists(vm.dir_path + '/whitelisted-appmenus.list'): | ||||
|             files_to_backup += file_to_backup(vm.dir_path + '/whitelisted-appmenus.list') | ||||
| 
 | ||||
|         if vm.is_updateable(): | ||||
|         if vm.updateable: | ||||
|             sz = vm.get_disk_usage(vm.root_img) | ||||
|             files_to_backup += file_to_backup(vm.root_img, sz) | ||||
|             vm_sz += sz | ||||
| @ -419,9 +419,9 @@ def backup_prepare(base_backup_dir, vms_list = None, exclude_list = [], print_ca | ||||
| 
 | ||||
|         fmt="{{0:>{0}}} |".format(fields_to_display[1]["width"] + 1) | ||||
|         if vm.is_netvm(): | ||||
|             s += fmt.format("NetVM" + (" + Sys" if vm.is_updateable() else "")) | ||||
|             s += fmt.format("NetVM" + (" + Sys" if vm.updateable else "")) | ||||
|         else: | ||||
|             s += fmt.format("AppVM" + (" + Sys" if vm.is_updateable() else "")) | ||||
|             s += fmt.format("AppVM" + (" + Sys" if vm.updateable else "")) | ||||
| 
 | ||||
|         fmt="{{0:>{0}}} |".format(fields_to_display[2]["width"] + 1) | ||||
|         s += fmt.format(size_to_human(vm_sz)) | ||||
| @ -702,7 +702,7 @@ def backup_restore_print_summary(restore_info, print_callback = print_stdout): | ||||
|                  ('Proxy' if vm.is_proxyvm() else \ | ||||
|                  (' Net' if vm.is_netvm() else 'App'))"}, | ||||
| 
 | ||||
|         "updbl" : {"func": "'Yes' if vm.is_updateable() else ''"}, | ||||
|         "updbl" : {"func": "'Yes' if vm.updateable else ''"}, | ||||
| 
 | ||||
|         "template": {"func": "'n/a' if vm.is_template() or vm.template is None else\ | ||||
|                      vm_info['template']"}, | ||||
| @ -834,8 +834,6 @@ def backup_restore_do(backup_dir, restore_info, host_collection = None, print_ca | ||||
|             error_callback("Skiping...") | ||||
|             continue | ||||
| 
 | ||||
|         updateable = vm.updateable | ||||
| 
 | ||||
|         new_vm = None | ||||
| 
 | ||||
|         try: | ||||
| @ -845,7 +843,6 @@ def backup_restore_do(backup_dir, restore_info, host_collection = None, print_ca | ||||
|                                                dir_path=vm.dir_path, | ||||
|                                                installed_by_rpm=False) | ||||
| 
 | ||||
|             new_vm.updateable = updateable | ||||
|             new_vm.verify_files() | ||||
|         except Exception as err: | ||||
|             error_callback("ERROR: {0}".format(err)) | ||||
| @ -888,8 +885,6 @@ def backup_restore_do(backup_dir, restore_info, host_collection = None, print_ca | ||||
|         else: | ||||
|             uses_default_netvm = True | ||||
| 
 | ||||
|         updateable = vm.updateable | ||||
| 
 | ||||
|         new_vm = None | ||||
|         try: | ||||
|             restore_vm_dir (backup_dir, vm.dir_path, qubes_servicevms_dir); | ||||
| @ -898,13 +893,11 @@ def backup_restore_do(backup_dir, restore_info, host_collection = None, print_ca | ||||
|                 new_vm = host_collection.add_new_netvm(vm.name, template, | ||||
|                                               conf_file=vm.conf_file, | ||||
|                                               dir_path=vm.dir_path, | ||||
|                                               updateable=updateable, | ||||
|                                               label=vm.label) | ||||
|             elif vm.type == "ProxyVM": | ||||
|                 new_vm = host_collection.add_new_proxyvm(vm.name, template, | ||||
|                                               conf_file=vm.conf_file, | ||||
|                                               dir_path=vm.dir_path, | ||||
|                                               updateable=updateable, | ||||
|                                               label=vm.label) | ||||
|         except Exception as err: | ||||
|             error_callback("ERROR: {0}".format(err)) | ||||
| @ -953,15 +946,12 @@ def backup_restore_do(backup_dir, restore_info, host_collection = None, print_ca | ||||
|         else: | ||||
|             uses_default_netvm = True | ||||
| 
 | ||||
|         updateable = vm.updateable | ||||
| 
 | ||||
|         new_vm = None | ||||
|         try: | ||||
|             restore_vm_dir (backup_dir, vm.dir_path, qubes_appvms_dir); | ||||
|             new_vm = host_collection.add_new_appvm(vm.name, template, | ||||
|                                           conf_file=vm.conf_file, | ||||
|                                           dir_path=vm.dir_path, | ||||
|                                           updateable=updateable, | ||||
|                                           label=vm.label) | ||||
|         except Exception as err: | ||||
|             error_callback("ERROR: {0}".format(err)) | ||||
|  | ||||
| @ -60,7 +60,7 @@ def main(): | ||||
|                                               dir_path=options.dir_path, installed_by_rpm=False) | ||||
|     elif isinstance(src_vm, QubesAppVm): | ||||
|         dst_vm = qvm_collection.add_new_appvm(name=dstname, template=src_vm.template, | ||||
|                                               updateable=src_vm.updateable, label=src_vm.label,  | ||||
|                                               label=src_vm.label, | ||||
|                                               dir_path=options.dir_path) | ||||
|     else: | ||||
|         print >> sys.stderr, "ERROR: Clone not supported for this type of VM" | ||||
|  | ||||
| @ -117,11 +117,11 @@ def main(): | ||||
| 
 | ||||
|     vm = None | ||||
|     if options.netvm: | ||||
|         vm = qvm_collection.add_new_netvm(vmname, new_vm_template, label = label, updateable = options.standalone) | ||||
|         vm = qvm_collection.add_new_netvm(vmname, new_vm_template, label = label) | ||||
|     elif options.proxyvm: | ||||
|         vm = qvm_collection.add_new_proxyvm(vmname, new_vm_template, label = label, updateable = options.standalone) | ||||
|         vm = qvm_collection.add_new_proxyvm(vmname, new_vm_template, label = label) | ||||
|     else: | ||||
|         vm = qvm_collection.add_new_appvm(vmname, new_vm_template, label = label, updateable = options.standalone) | ||||
|         vm = qvm_collection.add_new_appvm(vmname, new_vm_template, label = label) | ||||
| 
 | ||||
|     if options.internal: | ||||
|         vm.internal = True | ||||
|  | ||||
| @ -44,7 +44,7 @@ fields = { | ||||
|              ('Proxy' if vm.is_proxyvm() else \ | ||||
|              (' Net' if vm.is_netvm() else ''))"}, | ||||
| 
 | ||||
|     "updbl" : {"func": "'Yes' if vm.is_updateable() else ''"}, | ||||
|     "updbl" : {"func": "'Yes' if vm.updateable else ''"}, | ||||
| 
 | ||||
|     "template": {"func": "'n/a' if vm.is_template() else\ | ||||
|                  ('None' if vm.template is None else\ | ||||
|  | ||||
| @ -41,7 +41,7 @@ def do_list(vm): | ||||
|         print fmt.format ("template", vm.template.name) | ||||
|     if vm.netvm is not None: | ||||
|         print fmt.format ("netvm", vm.netvm.name) | ||||
|     print fmt.format ("updateable?", vm.is_updateable()) | ||||
|     print fmt.format ("updateable?", vm.updateable) | ||||
|     print fmt.format ("installed by RPM?", vm.installed_by_rpm) | ||||
|     print fmt.format ("include in backups", vm.include_in_backups) | ||||
|     print fmt.format ("dir", vm.dir_path) | ||||
| @ -152,59 +152,6 @@ def set_netvm(vms, vm, args): | ||||
| 
 | ||||
|     vm.netvm = netvm | ||||
| 
 | ||||
| def set_updateable(vms, vm, args): | ||||
|     if vm.is_updateable(): | ||||
|         print >> sys.stderr, "VM '{0}' is already set 'updateable', no action required.".format(vm.name) | ||||
|         return True | ||||
| 
 | ||||
|     if vm.is_running(): | ||||
|         print >> sys.stderr, "Cannot change 'updateable' attribute of a running VM. Shut it down first." | ||||
|         return False | ||||
| 
 | ||||
|     if vm.is_appvm(): | ||||
|         # Check if the Template is *non* updateable... | ||||
|         if not vm.template.is_updateable(): | ||||
|             print >> sys.stderr, "VM '{0}': Setting 'updateable' attribute to True.".format(vm.name) | ||||
|             vm.set_updateable() | ||||
|         else: | ||||
|             print >> sys.stderr, "The Template VM ('{0}') is marked as 'updateable' itself!".format(vm.template.name) | ||||
|             print >> sys.stderr, "Cannot make the AppVM updateable too, as this might cause COW-backed storage incoherency." | ||||
|             print >> sys.stderr, "If you want to make this AppVM updateable, you must first make the Template VM nonupdateable." | ||||
|             return False | ||||
| 
 | ||||
|     if vm.is_template(): | ||||
|         # Make sure that all the AppVMs are non-updateable... | ||||
|         for appvm in vm.appvms.values(): | ||||
|             if appvm.is_updateable(): | ||||
|                 print >> sys.stderr, "At least one of the AppVMs ('{0}') of this Template VM is also marked 'updateable'.".format(appvm.name) | ||||
|                 print >> sys.stderr, "Cannot make the Template VM updateable too, as this might cause COW-backed storage incoherency." | ||||
|                 print >> sys.stderr, "If you want to make this Template VM updateable, you must first make all its decedent AppVMs nonupdateable." | ||||
|                 return False | ||||
| 
 | ||||
| 
 | ||||
|         print >> sys.stderr, "VM '{0}': Setting 'updateable' attribute to True.".format(vm.name) | ||||
|         vm.set_updateable() | ||||
|   | ||||
|     return True | ||||
| 
 | ||||
| def set_nonupdateable(vms, vm, args): | ||||
|     if not vm.is_updateable(): | ||||
|         print >> sys.stderr, "VM '{0}' is already set 'nonupdateable', no action required.".format(vm.name) | ||||
|         return True | ||||
| 
 | ||||
|     if vm.is_running(): | ||||
|         print >> sys.stderr, "Cannot change 'updateable' attribute of a running VM. Shut it down first." | ||||
|         return False | ||||
| 
 | ||||
|     if vm.is_netvm(): | ||||
|         print >> sys.stderr, "Why, on earth, would you want to make a NetVM 'nonupdateable'?" | ||||
|         return False | ||||
| 
 | ||||
| 
 | ||||
|     print >> sys.stderr, "VM '{0}': Setting 'updateable' attribute to False.".format(vm.name) | ||||
|     vm.set_nonupdateable() | ||||
|     return True | ||||
| 
 | ||||
| def set_kernel(vms, vm, args): | ||||
|     if vm.template is not None: | ||||
|         print >> sys.stderr, "Cannot set kernel for template-based VM. Set it for template instead." | ||||
| @ -310,8 +257,6 @@ def set_include_in_backups(vms, vm, args): | ||||
| 
 | ||||
| properties = { | ||||
|     "include_in_backups": set_include_in_backups, | ||||
|     "updateable": set_updateable, | ||||
|     "nonupdateable": set_nonupdateable, | ||||
|     "pcidevs": set_pcidevs, | ||||
|     "label" : set_label, | ||||
|     "netvm" : set_netvm, | ||||
|  | ||||
| @ -164,8 +164,8 @@ def main(): | ||||
|         print >>sys.stderr, "ERROR: A VM with the name '{0}' does not exist in the system.".format(vmname) | ||||
|         exit(1) | ||||
| 
 | ||||
|     if not vm.is_updateable(): | ||||
|         print >>sys.stderr, "ERROR: To sync appmenus for non-updateable VM, do it on template instead" | ||||
|     if vm.template is not None: | ||||
|         print >>sys.stderr, "ERROR: To sync appmenus for template based VM, do it on template instead" | ||||
|         exit(1) | ||||
| 
 | ||||
|     if not vm.is_running(): | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Marek Marczykowski
						Marek Marczykowski