Ejemplo n.º 1
0
    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]
        })
Ejemplo n.º 3
0
    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
        )
Ejemplo n.º 4
0
    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))))
Ejemplo n.º 5
0
    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]
        })
Ejemplo n.º 6
0
    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
        )
Ejemplo n.º 8
0
    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]
        })
Ejemplo n.º 9
0
    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'])
                ))
Ejemplo n.º 10
0
    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'])
                ))