def run(self, id, delete_dataset=False): share = self.datastore.get_by_id('shares', id) target_type = share['target_type'] dataset = None if target_type == 'DATASET' or target_type == 'ZVOL': dataset = share['target_path'] elif delete_dataset: raise TaskException(errno.EINVAL, 'Cannot delete dataset for non-dataset share') if not share: raise TaskException(errno.ENOENT, 'Share not found') path = self.dispatcher.call_sync('share.get_directory_path', share['id']) try: delete_config( path, '{0}-{1}'.format(share['type'], share['name']) ) except OSError: pass self.run_subtask_sync('share.{0}.delete'.format(share['type']), id) self.dispatcher.dispatch_event('share.changed', { 'operation': 'delete', 'ids': [id] }) if dataset and delete_dataset: self.run_subtask_sync('volume.dataset.delete', dataset)
def run(self, id): container = self.datastore.get_by_id('containers', id) try: delete_config( self.dispatcher.call_sync( 'volume.resolve_path', container['target'], os.path.join('vm', container['name']) ), 'vm-{0}'.format(container['name']) ) except (RpcException, OSError): pass pool = container['target'] root_ds = os.path.join(pool, 'vm') container_ds = os.path.join(root_ds, container['name']) try: self.join_subtasks(self.run_subtask('volume.dataset.delete', container_ds)) except RpcException as err: if err.code != errno.ENOENT: raise err self.datastore.delete('containers', id) self.dispatcher.dispatch_event('container.changed', { 'operation': 'delete', 'ids': [id] })
def run(self, id, updated_params): container = self.datastore.get_by_id('containers', id) if container['immutable']: raise TaskException(errno.EACCES, 'Cannot modify immutable container {0}.'.format(id)) try: delete_config( self.dispatcher.call_sync( 'volume.resolve_path', container['target'], os.path.join('vm', container['name']) ), 'vm-{0}'.format(container['name']) ) except (RpcException, OSError): pass if 'template' in updated_params: readme = updated_params['template'].pop('readme') if readme: root = self.dispatcher.call_sync('container.get_container_root', container['id']) with open(os.path.join(root, 'README.md'), 'w') as readme_file: readme_file.write(readme) if 'devices' in updated_params: self.join_subtasks(self.run_subtask('container.cache.update', container['template']['name'])) for res in updated_params['devices']: existing = first_or_default(lambda i: i['name'] == res['name'], container['devices']) if existing: self.update_device(container, existing, res) else: self.create_device(container, res) if not updated_params.get('enabled', True): self.join_subtasks(self.run_subtask('container.stop', id)) container.update(updated_params) self.datastore.update('containers', id, container) self.dispatcher.dispatch_event('container.changed', { 'operation': 'update', 'ids': [id] }) container = self.datastore.get_by_id('containers', id) save_config( self.dispatcher.call_sync( 'volume.resolve_path', container['target'], os.path.join('vm', container['name']) ), 'vm-{0}'.format(container['name']), container )
def run(self, id, updated_fields): share = self.datastore.get_by_id('shares', id) remove_unchanged(updated_fields, share) path = self.dispatcher.call_sync('share.get_directory_path', share['id']) try: delete_config( path, '{0}-{1}'.format(share['type'], share['name']) ) except OSError: pass if 'type' in updated_fields: old_share_type = share['type'] new_share_type = self.dispatcher.call_sync('share.supported_types').get(updated_fields['type']) if share['target_type'] == 'DATASET': pool, dataset = split_dataset(share['target_path']) self.join_subtasks( self.run_subtask('volume.dataset.update', dataset, { 'permissions_type': new_share_type['perm_type'] }) ) share.update(updated_fields) self.join_subtasks(self.run_subtask('share.{0}.delete'.format(old_share_type), id)) self.join_subtasks(self.run_subtask('share.{0}.create'.format(updated_fields['type']), share)) else: self.join_subtasks(self.run_subtask('share.{0}.update'.format(share['type']), id, updated_fields)) if 'permissions' in updated_fields: path = self.dispatcher.call_sync('share.translate_path', id) self.join_subtasks(self.run_subtask('file.set_permissions', path, updated_fields['permissions'])) self.dispatcher.dispatch_event('share.changed', { 'operation': 'update', 'ids': [share['id']] }) updated_share = self.datastore.get_by_id('shares', id) path = self.dispatcher.call_sync('share.get_directory_path', updated_share['id']) try: save_config( path, '{0}-{1}'.format(updated_share['type'], updated_share['name']), updated_share ) except OSError as err: self.add_warning(TaskWarning(errno.ENXIO, 'Cannot save backup config file: {0}'.format(str(err))))
def run(self, id): share = self.datastore.get_by_id('shares', id) path = self.dispatcher.call_sync('share.get_directory_path', share['id']) try: delete_config( path, '{0}-{1}'.format(share['type'], share['name']) ) except OSError: pass self.join_subtasks(self.run_subtask('share.{0}.delete'.format(share['type']), id)) self.dispatcher.dispatch_event('share.changed', { 'operation': 'delete', 'ids': [id] })
def run(self, id): share = self.datastore.get_by_id('shares', id) if not share: raise TaskException(errno.ENOENT, 'Share not found') path = self.dispatcher.call_sync('share.get_directory_path', share['id']) try: delete_config(path, '{0}-{1}'.format(share['type'], share['name'])) except OSError: pass self.join_subtasks( self.run_subtask('share.{0}.delete'.format(share['type']), id)) self.dispatcher.dispatch_event('share.changed', { 'operation': 'delete', 'ids': [id] })
def run(self, id, updated_params): container = self.datastore.get_by_id('containers', id) try: delete_config( self.dispatcher.call_sync( 'volume.resolve_path', container['target'], os.path.join('vm', container['name']) ), 'vm-{0}'.format(container['name']) ) except (RpcException, OSError): pass if 'devices' in updated_params: for res in updated_params['devices']: existing = first_or_default(lambda i: i['name'] == res['name'], container['devices']) if existing: self.update_device(container, existing, res) else: self.create_device(container, res) if not updated_params.get('enabled', True): self.join_subtasks(self.run_subtask('container.stop', id)) container.update(updated_params) self.datastore.update('containers', id, container) self.dispatcher.dispatch_event('container.changed', { 'operation': 'update', 'ids': [id] }) container = self.datastore.get_by_id('containers', id) save_config( self.dispatcher.call_sync( 'volume.resolve_path', container['target'], os.path.join('vm', container['name']) ), 'vm-{0}'.format(container['name']), container )
def run(self, id): share = self.datastore.get_by_id('shares', id) if not share: raise TaskException(errno.ENOENT, 'Share not found') path = self.dispatcher.call_sync('share.get_directory_path', share['id']) try: delete_config( path, '{0}-{1}'.format(share['type'], share['name']) ) except OSError: pass self.run_subtask_sync('share.{0}.delete'.format(share['type']), id) self.dispatcher.dispatch_event('share.changed', { 'operation': 'delete', 'ids': [id] })
def run(self, id, updated_fields, enable_service=False): share = self.datastore.get_by_id('shares', id) if not share: raise TaskException(errno.ENOENT, 'Share not found') if share['immutable']: raise TaskException(errno.EACCES, 'Cannot modify immutable share {0}.'.format(id)) if 'name' in updated_fields or 'type' in updated_fields: share.update(updated_fields) if self.datastore.exists( 'shares', ('id', '!=', id), ('type', '=', share['type']), ('name', '=', share['name']) ): raise TaskException(errno.EEXIST, 'Share {0} of type {1} already exists'.format( share['name'], share['type'] )) path_after_update = updated_fields.get('target_path', share['target_path']) type_after_update = updated_fields.get('target_type', share['target_type']) permissions = updated_fields.pop('permissions', None) share_path = self.dispatcher.call_sync('share.expand_path', path_after_update, type_after_update) if type_after_update in ('DIRECTORY', 'FILE'): pool_mountpoints = tuple(self.dispatcher.call_sync('volume.query', [], {'select': 'mountpoint'})) if not path_after_update.startswith(pool_mountpoints): raise TaskException(errno.EINVAL, "Provided directory or file has to reside within user defined ZFS pool") if not os.path.exists(share_path): raise TaskException( errno.ENOENT, 'Selected share target {0} does not exist'.format(path_after_update) ) share = self.datastore.get_by_id('shares', id) remove_unchanged(updated_fields, share) path = self.dispatcher.call_sync('share.get_directory_path', share['id']) try: delete_config( path, '{0}-{1}'.format(share['type'], share['name']) ) except (OSError, ValueError): pass if 'type' in updated_fields: old_share_type = share['type'] new_share_type = self.dispatcher.call_sync('share.supported_types').get(updated_fields['type']) if share['target_type'] == 'DATASET': pool, dataset = split_dataset(share['target_path']) self.join_subtasks( self.run_subtask('volume.dataset.update', dataset, { 'permissions_type': new_share_type['perm_type'] }) ) share.update(updated_fields) self.run_subtask_sync('share.{0}.delete'.format(old_share_type), id) self.run_subtask_sync('share.{0}.create'.format(updated_fields['type']), share) else: self.run_subtask_sync('share.{0}.update'.format(share['type']), id, updated_fields) if permissions: path = self.dispatcher.call_sync('share.translate_path', id) self.run_subtask_sync('file.set_permissions', path, permissions) self.dispatcher.dispatch_event('share.changed', { 'operation': 'update', 'ids': [share['id']] }) updated_share = self.datastore.get_by_id('shares', id) path = self.dispatcher.call_sync('share.get_directory_path', updated_share['id']) try: save_config( path, '{0}-{1}'.format(updated_share['type'], updated_share['name']), updated_share, file_perms=0o600 ) except OSError as err: self.add_warning(TaskWarning(errno.ENXIO, 'Cannot save backup config file: {0}'.format(str(err)))) service_state = self.dispatcher.call_sync('service.query', [('name', '=', share['type'])], {'single': True}) if service_state['state'] != 'RUNNING': if enable_service: config = service_state['config'] config['enable'] = True self.run_subtask_sync('service.update', service_state['id'], {'config': config}) else: self.add_warning(TaskWarning( errno.ENXIO, "Share has been updated but the service {0} is not currently running " "Please enable the {0} service.".format(share['type']) ))
def run(self, id, updated_fields, enable_service=False): share = self.datastore.get_by_id('shares', id) if not share: raise TaskException(errno.ENOENT, 'Share not found') if share['immutable']: raise TaskException(errno.EACCES, 'Cannot modify immutable share {0}.'.format(id)) if 'name' in updated_fields or 'type' in updated_fields: share.update(updated_fields) if self.datastore.exists( 'shares', ('id', '!=', id), ('type', '=', share['type']), ('name', '=', share['name']) ): raise TaskException(errno.EEXIST, 'Share {0} of type {1} already exists'.format( share['name'], share['type'] )) path_after_update = updated_fields.get('target_path', share['target_path']) type_after_update = updated_fields.get('target_type', share['target_type']) permissions = updated_fields.pop('permissions', None) share_path = self.dispatcher.call_sync('share.expand_path', path_after_update, type_after_update) if not os.path.exists(share_path): raise TaskException( errno.ENOENT, 'Selected share target {0} does not exist'.format(path_after_update) ) share = self.datastore.get_by_id('shares', id) remove_unchanged(updated_fields, share) path = self.dispatcher.call_sync('share.get_directory_path', share['id']) try: delete_config( path, '{0}-{1}'.format(share['type'], share['name']) ) except (OSError, ValueError): pass if 'type' in updated_fields: old_share_type = share['type'] new_share_type = self.dispatcher.call_sync('share.supported_types').get(updated_fields['type']) if share['target_type'] == 'DATASET': pool, dataset = split_dataset(share['target_path']) self.join_subtasks( self.run_subtask('volume.dataset.update', dataset, { 'permissions_type': new_share_type['perm_type'] }) ) share.update(updated_fields) self.run_subtask_sync('share.{0}.delete'.format(old_share_type), id) self.run_subtask_sync('share.{0}.create'.format(updated_fields['type']), share) else: self.run_subtask_sync('share.{0}.update'.format(share['type']), id, updated_fields) if permissions: path = self.dispatcher.call_sync('share.translate_path', id) self.run_subtask_sync('file.set_permissions', path, permissions) self.dispatcher.dispatch_event('share.changed', { 'operation': 'update', 'ids': [share['id']] }) updated_share = self.datastore.get_by_id('shares', id) path = self.dispatcher.call_sync('share.get_directory_path', updated_share['id']) try: save_config( path, '{0}-{1}'.format(updated_share['type'], updated_share['name']), updated_share ) except OSError as err: self.add_warning(TaskWarning(errno.ENXIO, 'Cannot save backup config file: {0}'.format(str(err)))) service_state = self.dispatcher.call_sync('service.query', [('name', '=', share['type'])], {'single': True}) if service_state['state'] != 'RUNNING': if enable_service: config = service_state['config'] config['enable'] = True self.run_subtask_sync('service.update', service_state['id'], {'config': config}) else: self.add_warning(TaskWarning( errno.ENXIO, "Share has been updated but the service {0} is not currently running " "Please enable the {0} service.".format(share['type']) ))