Example #1
0
class ZpoolProvider(Provider):
    @description("Lists ZFS pools")
    @query('zfs-pool')
    def query(self, filter=None, params=None):
        zfs = libzfs.ZFS()
        return wrap(zfs).query(*(filter or []), **(params or {}))

    @accepts()
    @returns(h.array(h.ref('zfs-pool')))
    def find(self):
        zfs = libzfs.ZFS()
        return list(map(lambda p: p.__getstate__(), zfs.find_import()))

    @accepts()
    @returns(h.ref('zfs-pool'))
    def get_boot_pool(self):
        name = self.configstore.get('system.boot_pool_name')
        zfs = libzfs.ZFS()
        return zfs.get(name).__getstate__()

    @accepts(str)
    @returns(h.array(str))
    def get_disks(self, name):
        try:
            zfs = libzfs.ZFS()
            pool = zfs.get(name)
            return pool.disks
        except libzfs.ZFSException, err:
            raise RpcException(errno.EFAULT, str(err))
Example #2
0
class SwapProvider(Provider):
    @accepts()
    @returns(h.array(h.ref('swap-mirror')))
    @description("Returns information about swap mirrors present in the system"
                 )
    def info(self):
        return get_swap_info(self.dispatcher).values()
Example #3
0
class SessionProvider(Provider):
    @query('session')
    def query(self, filter=None, params=None):
        return self.datastore.query('sessions',
                                    *(filter or []),
                                    **(params or {}))

    @accepts()
    @returns(h.array(h.ref('sessions')))
    @description("Returns the logged in and active user sessions" +
                 "Does not include the service sessions in this.")
    def get_live_user_sessions(self):
        live_user_session_ids = []
        for conn in self.dispatcher.ws_server.connections:
            # The if check for 'uid' below is to seperate the actuall gui/cli
            # users of the websocket connection from that of system services
            # like etcd, statd and so on.
            if hasattr(conn.user, 'uid'):
                live_user_session_ids.append(conn.session_id)
        return self.datastore.query('sessions',
                                    ('id',
                                     'in',
                                     live_user_session_ids),
                                    **({}))

    @description("Returns the loggedin user for the current session")
    @returns(str)
    @pass_sender
    def whoami(self, sender):
        return sender.user.name
Example #4
0
class SystemAdvancedProvider(Provider):

    @accepts()
    @returns(h.ref('system-advanced'))
    def get_config(self):
        cs = self.configstore
        return {
            'console_cli': cs.get('system.console.cli'),
            'console_screensaver': cs.get('system.console.screensaver'),
            'serial_console': cs.get('system.serial.console'),
            'serial_port': cs.get('system.serial.port'),
            'serial_speed': cs.get('system.serial.speed'),
            'powerd': cs.get('service.powerd.enable'),
            'swapondrive': cs.get('system.swapondrive'),
            'autotune': cs.get('system.autotune'),
            'debugkernel': cs.get('system.debug.kernel'),
            'uploadcrash': cs.get('system.upload_crash'),
            'motd': cs.get('system.motd'),
            'boot_scrub_internal': cs.get('system.boot_scrub_internal'),
            'periodic_notify_user': cs.get('system.periodic.notify_user'),
        }

    @description('Returns array of serial port address')
    @accepts()
    @returns(h.array(str))
    def serial_ports(self):
        return filter(
            lambda y: bool(y),
            system(
                "/usr/sbin/devinfo -u | grep uart | grep 0x | cut -d- -f 1 | awk '{print $1}'",
                shell=True)[0].strip('\n').split('\n'))
Example #5
0
class SystemInfoProvider(Provider):
    def __init__(self):
        self.__version = None

    @accepts()
    @returns(h.array(str))
    def uname_full(self):
        return os.uname()

    @accepts()
    @returns(str)
    @description("Return the full version string, e.g. FreeNAS-8.1-r7794-amd64.")
    def version(self):
        if self.__version is None:
            # See #9113
            conf = Configuration.Configuration()
            manifest = conf.SystemManifest()
            if manifest:
                self.__version = manifest.Version()
            else:
                with open(VERSION_FILE) as fd:
                    self.__version = fd.read().strip()

        return self.__version

    @accepts()
    @returns(float, float, float)
    def load_avg(self):
        return os.getloadavg()

    @accepts()
    @returns(h.object(properties={
        'cpu_model': str,
        'cpu_cores': int,
        'memory_size': long,
    }))
    def hardware(self):
        return {
            'cpu_model': get_sysctl("hw.model"),
            'cpu_cores': get_sysctl("hw.ncpu"),
            'memory_size': get_sysctl("hw.physmem")
        }

    @accepts()
    @returns(h.object(properties={
        'system_time': str,
        'boot_time': str,
        'uptime': str,
        'timezone': str,
    }))
    def time(self):
        boot_time = datetime.fromtimestamp(psutil.BOOT_TIME, tz=tz.tzlocal())
        return {
            'system_time': datetime.now(tz=tz.tzlocal()).isoformat(),
            'boot_time': boot_time.isoformat(),
            'uptime': (datetime.now(tz=tz.tzlocal()) - boot_time).total_seconds(),
            'timezone': time.tzname[time.daylight],
        }
Example #6
0
class SupportProvider(Provider):
    @accepts(str, str)
    @returns(h.array(str))
    def categories(self, user, password):
        sw_name = self.dispatcher.call_sync('system.info.version').split(
            '-')[0].lower()
        try:
            r = requests.post(
                'https://%s/%s/api/v1.0/categories' % (ADDRESS, sw_name),
                data=json.dumps({
                    'user': user,
                    'password': password,
                }),
                headers={'Content-Type': 'application/json'},
                timeout=10,
            )
            data = r.json()
        except simplejson.JSONDecodeError as e:
            logger.debug('Failed to decode ticket attachment response: %s',
                         r.text)
            raise RpcException(errno.EINVAL,
                               'Failed to decode ticket response')
        except requests.ConnectionError as e:
            raise RpcException(errno.ENOTCONN,
                               'Connection failed: {0}'.format(str(e)))
        except requests.Timeout as e:
            raise RpcException(errno.ETIMEDOUT,
                               'Connection timed out: {0}'.format(str(e)))

        if 'error' in data:
            raise RpcException(errno.EINVAL, data['message'])

        return data
Example #7
0
class SystemUIProvider(Provider):

    @accepts()
    @returns(h.ref('system-ui'))
    def get_config(self):

        protocol = []
        if self.configstore.get('service.nginx.http.enable'):
            protocol.append('HTTP')
        if self.configstore.get('service.nginx.https.enable'):
            protocol.append('HTTPS')

        return {
            'webui_procotol': protocol,
            'webui_listen': self.configstore.get(
                'service.nginx.listen',
            ),
            'webui_http_port': self.configstore.get(
                'service.nginx.http.port',
            ),
            'webui_http_redirect_https': self.configstore.get(
                'service.nginx.http.redirect_https',
            ),
            'webui_https_certificate': self.configstore.get(
                'service.nginx.https.certificate',
            ),
            'webui_https_port': self.configstore.get(
                'service.nginx.https.port',
            ),
        }
Example #8
0
class SystemDatasetProvider(Provider):
    @private
    @description("Initializes the .system dataset")
    @accepts()
    @returns()
    def init(self):
        pool = self.configstore.get('system.dataset.pool')
        create_system_dataset(self.dispatcher, pool)
        mount_system_dataset(self.dispatcher, pool, SYSTEM_DIR)

    @private
    @description(
        "Creates directory in .system dataset and returns reference to it")
    @accepts(str)
    @returns(str)
    def request_directory(self, name):
        path = os.path.join(SYSTEM_DIR, name)
        if os.path.exists(path):
            if os.path.isdir(path):
                return path

            raise RpcException(errno.EPERM,
                               'Cannot grant directory {0}'.format(name))

        os.mkdir(path)
        return path

    @description("Returns current .system dataset parameters")
    @returns(h.object())
    def status(self):
        return {
            'id': self.configstore.get('system.dataset.id'),
            'pool': self.configstore.get('system.dataset.pool')
        }
Example #9
0
class NetworkProvider(Provider):
    @returns(h.ref('network-config'))
    def get_global_config(self):
        return ConfigNode('network', self.configstore)

    @returns(h.array(str))
    def get_my_ips(self):
        ips = []
        ifaces = self.dispatcher.call_sync(
            'networkd.configuration.query_interfaces')
        for i, v in ifaces.iteritems():
            if 'LOOPBACK' in v['flags']:
                continue
            for aliases in v['aliases']:
                if aliases['address'] and aliases['family'] != 'LINK':
                    ips.append(aliases['address'])
        return ips
Example #10
0
class SystemGeneralProvider(Provider):

    @accepts()
    @returns(h.ref('system-general'))
    def get_config(self):
        return {
            'hostname': self.configstore.get('system.hostname'),
            'language': self.configstore.get('system.language'),
            'timezone': self.configstore.get('system.timezone'),
            'syslog_server': self.configstore.get('system.syslog_server'),
            'console_keymap': self.configstore.get('system.console.keymap')
        }

    @accepts()
    @returns(h.array(h.array(str)))
    def keymaps(self):
        if not os.path.exists(KEYMAPS_INDEX):
            return []

        rv = []
        with open(KEYMAPS_INDEX, 'r') as f:
            d = f.read()
        fnd = re.findall(r'^(?P<name>[^#\s]+?)\.kbd:en:(?P<desc>.+)$', d, re.M)
        for name, desc in fnd:
            rv.append((name, desc))
        return rv

    @accepts()
    @returns(h.array(str))
    def timezones(self):
        result = []
        for root, _, files in os.walk(ZONEINFO_DIR):
            for f in files:
                if f in (
                    'zone.tab',
                ):
                    continue
                result.append(os.path.join(root, f).replace(
                    ZONEINFO_DIR + '/', '')
                )
        return result
Example #11
0
class SharesProvider(Provider):
    @query('share')
    def query(self, filter=None, params=None):
        return self.datastore.query('shares', *(filter or []), **(params or {}))

    @description("Returns list of supported sharing providers")
    @returns(h.array(str))
    def supported_types(self):
        result = []
        for p in self.dispatcher.plugins.values():
            if p.metadata and p.metadata.get('type') == 'sharing':
                result.append(p.metadata['method'])

        return result

    @description("Returns list of clients connected to particular share")
    def get_connected_clients(self, share_name):
        share = self.datastore.get_by_id('shares', share_name)
        if not share:
            raise RpcException(errno.ENOENT, 'Share not found')

        return self.dispatcher.call_sync('shares.{0}.get_connected_clients'.format(share['type']), share_name)
Example #12
0
    def get_connected_clients(self, share_name):
        share = self.datastore.get_one('shares', ('type', '=', 'nfs'),
                                       ('id', '=', share_name))
        result = []
        f = open('/var/db/mountdtab')
        for line in f:
            host, path = line.split()
            if share['target'] in path:
                result.append(host)

        f.close()
        return result


@description("Adds new NFS share")
@accepts(h.ref('nfs-share'))
class CreateNFSShareTask(Task):
    def describe(self, share):
        return "Creating NFS share {0}".format(share['id'])

    def verify(self, share):
        return ['service:nfs']

    def run(self, share):
        self.datastore.insert('shares', share)
        self.dispatcher.call_sync('etcd.generation.generate_group', 'nfs')
        self.dispatcher.call_sync('services.ensure_started', 'nfs')
        self.dispatcher.call_sync('services.reload', 'nfs')
        self.dispatcher.dispatch_event('shares.nfs.changed', {
            'operation': 'create',
            'ids': [share['id']]
Example #13
0
        except simplejson.JSONDecodeError as e:
            logger.debug("Failed to decode ticket attachment response: %s", r.text)
            raise RpcException(errno.EINVAL, "Failed to decode ticket response")
        except requests.ConnectionError as e:
            raise RpcException(errno.ENOTCONN, "Connection failed: {0}".format(str(e)))
        except requests.Timeout as e:
            raise RpcException(errno.ETIMEDOUT, "Connection timed out: {0}".format(str(e)))

        if "error" in data:
            raise RpcException(errno.EINVAL, data["message"])

        return data


@description("Submits a new support ticket")
@accepts(h.ref("support-ticket"))
class SupportSubmitTask(Task):
    def describe(self, ticket):
        return "Submitting ticket"

    def verify(self, ticket):
        return ["system"]

    def run(self, ticket):
        try:
            version = self.dispatcher.call_sync("system.info.version")
            sw_name = version.split("-")[0].lower()
            data = {
                "title": ticket["subject"],
                "body": ticket["description"],
                "version": version.split("-", 1)[-1],
Example #14
0
class FilesystemProvider(Provider):
    @description("Lists contents of given directory")
    @accepts(str)
    @returns(h.array(h.ref('directory')))
    def list_dir(self, path):
        result = []
        if not os.path.isdir(path):
            raise RpcException(errno.ENOENT,
                               'Path {0} is not a directory'.format(path))

        for i in os.listdir(path):
            try:
                st = os.stat(os.path.join(path, i))
            except OSError:
                continue

            item = {
                'name': i,
                'type': get_type(st),
                'size': st.st_size,
                'modified': st.st_mtime
            }

            result.append(item)

        return result

    @accepts(str)
    @returns(h.ref('stat'))
    def stat(self, path):
        try:
            st = os.stat(path)
        except OSError, err:
            raise RpcException(err.errno, str(err))

        return {
            'path': path,
            'type': get_type(st),
            'atime': st.st_atime,
            'mtime': st.st_mtime,
            'ctime': st.st_ctime,
            'uid': st.st_uid,
            'gid': st.st_gid,
            'permissions': {
                'user': {
                    'read': st.st_mode & stat.S_IRUSR,
                    'write': st.st_mode & stat.S_IWUSR,
                    'execute': st.st_mode & stat.S_IXUSR
                },
                'group': {
                    'read': st.st_mode & stat.S_IRGRP,
                    'write': st.st_mode & stat.S_IWGRP,
                    'execute': st.st_mode & stat.S_IXGRP
                },
                'others': {
                    'read': st.st_mode & stat.S_IROTH,
                    'write': st.st_mode & stat.S_IWOTH,
                    'execute': st.st_mode & stat.S_IXOTH
                },
            }
        }
Example #15
0
    @accepts(str)
    def get_connected_clients(self, share_name):
        share = self.datastore.get_one('shares', ('type', '=', 'nfs'), ('id', '=', share_name))
        result = []
        f = open('/var/db/mountdtab')
        for line in f:
            host, path = line.split()
            if share['target'] in path:
                result.append(host)

        f.close()
        return result


@description("Adds new NFS share")
@accepts(h.ref('nfs-share'))
class CreateNFSShareTask(Task):
    def describe(self, share):
        return "Creating NFS share {0}".format(share['id'])

    def verify(self, share):
        return ['service:nfs']

    def run(self, share):
        self.datastore.insert('shares', share)
        self.dispatcher.call_sync('etcd.generation.generate_group', 'nfs')
        self.dispatcher.call_sync('services.ensure_started', 'nfs')
        self.dispatcher.call_sync('services.reload', 'nfs')
        self.dispatcher.dispatch_event('shares.nfs.changed', {
            'operation': 'create',
            'ids': [share['id']]
Example #16
0
                gid = i
                break

        if not gid:
            raise RpcException(errno.ENOSPC, 'No free GIDs available')

        return gid


@description("Create an user in the system")
@accepts(
    h.all_of(
        h.ref('user'),
        h.required('username', 'group'),
        h.forbidden('builtin', 'logged-in', 'sessions'),
        h.object({'password': {
            'type': 'string'
        }}),
        h.any_of(h.required('password'), h.required('unixhash', 'smbhash'),
                 h.required('password_disabled')),
    ))
class UserCreateTask(Task):
    def describe(self, user):
        return "Adding user {0}".format(user['username'])

    def verify(self, user):

        errors = []

        for code, message in check_unixname(user['username']):
            errors.append(('name', code, message))
Example #17
0
        conf = Configuration.Configuration()
        conf.LoadTrainsConfig()
        return conf.CurrentTrain()

    @accepts()
    @returns(h.ref('update'))
    def get_config(self):
        return {
            'train': self.dispatcher.configstore.get('update.train'),
            'check_auto': self.dispatcher.configstore.get('update.check_auto'),
            'update_server': Configuration.Configuration().UpdateServerURL(),
        }


@description("Set the System Updater Cofiguration Settings")
@accepts(h.ref('update'))
class UpdateConfigureTask(Task):

    def describe(self):
        return "System Updater Configure Settings"

    def verify(self, props):
        # TODO: Fix this verify's resource allocation as unique task
        train_to_set = props.get('train')
        conf = Configuration.Configuration()
        conf.LoadTrainsConfig()
        trains = conf.AvailableTrains() or []
        if trains:
            trains = trains.keys()
        if train_to_set not in trains:
            raise VerifyException(
Example #18
0
            conns = filter(lambda c: c.pid == i.pid, psutil.net_connections('inet'))
            conn = first_or_default(lambda c: c.laddr[1] == 548, conns)

            if not conn:
                continue

            result.append({
                'host': conn.laddr[0],
                'share': None,
                'user': i.username()
            })


@description("Adds new AFP share")
@accepts(h.ref('afp-share'))
class CreateAFPShareTask(Task):
    def describe(self, share):
        return "Creating AFP share {0}".format(share['id'])

    def verify(self, share):
        return ['service:afp']

    def run(self, share):
        self.datastore.insert('shares', share)
        self.dispatcher.call_sync('etcd.generation.generate_group', 'afp')
        self.dispatcher.call_sync('services.ensure_started', 'afp')
        self.dispatcher.call_sync('services.reload', 'afp')
        self.dispatcher.dispatch_event('shares.afp.changed', {
            'operation': 'create',
            'ids': [share['id']]
Example #19
0
    def get_boot_pool(self):
        name = self.configstore.get('system.boot_pool_name')
        zfs = libzfs.ZFS()
        return zfs.get(name).__getstate__()

    @accepts(str)
    @returns(h.array(str))
    def get_disks(self, name):
        try:
            zfs = libzfs.ZFS()
            pool = zfs.get(name)
            return pool.disks
        except libzfs.ZFSException, err:
            raise RpcException(errno.EFAULT, str(err))

    @returns(h.object())
    def get_capabilities(self):
        return {
            'vdev_types': {
                'disk': {
                    'min_devices': 1,
                    'max_devices': 1
                },
                'mirror': {
                    'min_devices': 2
                },
                'raidz1': {
                    'min_devices': 2
                },
                'raidz2': {
                    'min_devices': 3
Example #20
0
@description('Provides access to the alert system')
class AlertsProvider(Provider):
    @query('alert')
    def query(self, filter=None, params=None):
        return self.datastore.query('alerts', *(filter or []), **(params
                                                                  or {}))

    def dismiss(self, id):
        try:
            self.datastore.delete('alerts', id)
        except DatastoreException, e:
            raise TaskException(errno.EBADMSG,
                                'Cannot delete alert: {0}'.format(str(e)))

    @accepts(h.ref('alert'))
    def emit(self, alert):
        alertprops = registered_alerts.get(alert['name'])
        if alertprops is None:
            raise RpcException(
                errno.ENOENT, "Alert {0} not registered".format(alert['name']))

        # Try to find the first matching namespace
        emitters = None
        dot = alert['name'].split('.')
        for i in xrange(len(dot), 0, -1):
            namespace = '.'.join(dot[0:i])
            afilter = self.datastore.get_one(
                'alerts-filters',
                ('name', '=', namespace),
                ('severity', '=', alert['severity']),
Example #21
0
class DeviceInfoPlugin(Provider):
    @description("Returns list of available device classes")
    @returns(h.array(str))
    def get_classes(self):
        return ["disk", "network", "cpu"]

    @description("Returns list of devices from given class")
    @accepts(str)
    @returns(
        h.any_of(h.ref('disk-device'), h.ref('network-device'),
                 h.ref('cpu-device')))
    def get_devices(self, dev_class):
        method = "_get_class_{0}".format(dev_class)
        if hasattr(self, method):
            return getattr(self, method)()

        return None

    def _get_class_disk(self):
        result = []
        geom.scan()
        for child in geom.class_by_name('DISK').geoms:
            result.append({
                "path": os.path.join("/dev", child.name),
                "name": child.name,
                "mediasize": child.provider.mediasize,
                "description": child.provider.config['descr']
            })

        return result

    def _get_class_multipath(self):
        result = []
        geom.scan()
        cls = geom.class_by_name('MULTIPATH')
        if not cls:
            return []

        for child in cls.geoms:
            result.append({
                "path": os.path.join("/dev", child.name),
                "name": child.name,
                "mediasize": child.provider.mediasize,
                "members": [c.provider.name for c in child.consumers]
            })

        return result

    def _get_class_network(self):
        result = []
        for i in netif.list_interfaces().keys():
            if i.startswith('lo'):
                continue

            desc = get_sysctl(re.sub('(\w+)([0-9]+)', 'dev.\\1.\\2.%desc', i))
            result.append({'name': i, 'description': desc})

        return result

    def _get_class_cpu(self):
        pass
Example #22
0
    @query('alert')
    def query(self, filter=None, params=None):
        return self.datastore.query(
            'alerts', *(filter or []), **(params or {})
        )

    def dismiss(self, id):
        try:
            self.datastore.delete('alerts', id)
        except DatastoreException, e:
            raise TaskException(
                errno.EBADMSG,
                'Cannot delete alert: {0}'.format(str(e))
            )

    @accepts(h.ref('alert'))
    def emit(self, alert):
        alertprops = registered_alerts.get(alert['name'])
        if alertprops is None:
            raise RpcException(
                errno.ENOENT,
                "Alert {0} not registered".format(alert['name'])
            )

        # Try to find the first matching namespace
        emitters = None
        dot = alert['name'].split('.')
        for i in xrange(len(dot), 0, -1):
            namespace = '.'.join(dot[0:i])
            afilter = self.datastore.get_one(
                'alerts-filters', ('name', '=', namespace),
Example #23
0
                    'upgraded': is_upgraded(config),
                    'scan': config['scan'],
                    'properties': config['properties'],
                    'datasets': map(extend_dataset, flatten_datasets(config['root_dataset']))
                })

            return vol

        return self.datastore.query('volumes', *(filter or []), callback=extend, **(params or {}))

    @description("Finds volumes available for import")
    @accepts()
    @returns(h.array(
        h.object(properties={
            'id': str,
            'name': str,
            'topology': h.ref('zfs-topology'),
            'status': str
        })
    ))
    def find(self):
        result = []
        for pool in self.dispatcher.call_sync('zfs.pool.find'):
            topology = pool['groups']
            for vdev, _ in iterate_vdevs(topology):
                try:
                    vdev['path'] = self.dispatcher.call_sync(
                        'disks.partition_to_disk',
                        vdev['path']
                    )
                except RpcException:
                    pass
Example #24
0
                })

            return vol

        return self.datastore.query('volumes',
                                    *(filter or []),
                                    callback=extend,
                                    **(params or {}))

    @description("Finds volumes available for import")
    @accepts()
    @returns(
        h.array(
            h.object(
                properties={
                    'id': str,
                    'name': str,
                    'topology': h.ref('zfs-topology'),
                    'status': str
                })))
    def find(self):
        result = []
        for pool in self.dispatcher.call_sync('zfs.pool.find'):
            topology = pool['groups']
            for vdev, _ in iterate_vdevs(topology):
                try:
                    vdev['path'] = self.dispatcher.call_sync(
                        'disks.partition_to_disk', vdev['path'])
                except RpcException:
                    pass

            if self.datastore.exists('volumes', ('id', '=', pool['guid'])):
Example #25
0
            conns = filter(lambda c: c.pid == i.pid,
                           psutil.net_connections('inet'))
            conn = first_or_default(lambda c: c.laddr[1] == 548, conns)

            if not conn:
                continue

            result.append({
                'host': conn.laddr[0],
                'share': None,
                'user': i.username()
            })


@description("Adds new AFP share")
@accepts(h.ref('afp-share'))
class CreateAFPShareTask(Task):
    def describe(self, share):
        return "Creating AFP share {0}".format(share['id'])

    def verify(self, share):
        return ['service:afp']

    def run(self, share):
        self.datastore.insert('shares', share)
        self.dispatcher.call_sync('etcd.generation.generate_group', 'afp')
        self.dispatcher.call_sync('services.ensure_started', 'afp')
        self.dispatcher.call_sync('services.reload', 'afp')
        self.dispatcher.dispatch_event('shares.afp.changed', {
            'operation': 'create',
            'ids': [share['id']]
Example #26
0
    def get_boot_pool(self):
        name = self.configstore.get('system.boot_pool_name')
        zfs = libzfs.ZFS()
        return zfs.get(name).__getstate__()

    @accepts(str)
    @returns(h.array(str))
    def get_disks(self, name):
        try:
            zfs = libzfs.ZFS()
            pool = zfs.get(name)
            return pool.disks
        except libzfs.ZFSException, err:
            raise RpcException(errno.EFAULT, str(err))

    @returns(h.object())
    def get_capabilities(self):
        return {
            'vdev_types': {
                'disk': {
                    'min_devices': 1,
                    'max_devices': 1
                },
                'mirror': {
                    'min_devices': 2
                },
                'raidz1': {
                    'min_devices': 2
                },
                'raidz2': {
                    'min_devices': 3
Example #27
0
        disk = self.datastore.get_by_id('disks', id)
        acc_level = getattr(AcousticLevel, disk.get('acoustic_level', 'DISABLED')).value
        powermgmt = disk.get('apm_mode', 0)
        system('/usr/local/sbin/ataidle', '-P', str(powermgmt), '-A', str(acc_level), disk['path'])

        if disk.get('standby_mode'):
            standby_mode = str(disk['standby_mode'])
            gevent.spawn_later(60, lambda: system(
                '/usr/local/sbin/ataidle',
                '-I',
                standby_mode,
                disk['path']
            ))


@accepts(str, str, h.object())
class DiskGPTFormatTask(Task):
    def describe(self, disk, fstype, params=None):
        return "Formatting disk {0}".format(os.path.basename(disk))

    def verify(self, disk, fstype, params=None):
        if not get_disk_by_path(disk):
            raise VerifyException(errno.ENOENT, "Disk {0} not found".format(disk))

        if fstype not in ['freebsd-zfs']:
            raise VerifyException(errno.EINVAL, "Unsupported fstype {0}".format(fstype))

        return ['disk:{0}'.format(disk)]

    def run(self, disk, fstype, params=None):
        if params is None:
Example #28
0
class RouteProvider(Provider):
    @query('network-route')
    def query(self, filter=None, params=None):
        return self.datastore.query('network.routes', *(filter or []), **(params or {}))


@description("Provides access to static host entries database")
class HostsProvider(Provider):
    @query('network-host')
    def query(self, filter=None, params=None):
        return self.datastore.query('network.hosts', *(filter or []), **(params or {}))


@description("Updates global network configuration settings")
@accepts(h.ref('network-config'))
class NetworkConfigureTask(Task):
    def verify(self, settings):
        return ['system']

    def run(self, settings):
        node = ConfigNode('network', self.dispatcher.configstore)
        node.update(settings)

        try:
            self.dispatcher.call_sync('networkd.configuration.configure_network')
            self.dispatcher.call_sync('etcd.generation.generate_group', 'network')
        except RpcException, e:
            raise TaskException(errno.ENXIO, 'Cannot reconfigure interface: {0}'.format(str(e)))

Example #29
0
            if certificate.get('csr'):
                certificate['csr_path'] = os.path.join(
                    cert_path, '{0}.csr'.format(certificate['name']))

            return certificate

        return self.datastore.query('crypto.certificates',
                                    *(filter or []),
                                    callback=extend,
                                    **(params or {}))


@accepts(
    h.all_of(
        h.ref('crypto-certificate'),
        h.required('signedby', 'name', 'country', 'state', 'city',
                   'organization', 'email', 'common'),
    ))
class CertificateInternalCreateTask(Task):
    def verify(self, certificate):

        errors = []

        if self.datastore.exists('crypto.certificates',
                                 ('name', '=', certificate['name'])):
            errors.append(('name', errno.EEXIST,
                           'Certificate with given name already exists'))

        if not self.datastore.exists('crypto.certificates',
                                     ('id', '=', certificate['signedby'])):
            errors.append(('signedby', errno.EEXIST,
Example #30
0
            if not self.datastore.exists('groups', ('id', '=', i)):
                gid = i
                break

        if not gid:
            raise RpcException(errno.ENOSPC, 'No free GIDs available')

        return gid


@description("Create an user in the system")
@accepts(h.all_of(
    h.ref('user'),
    h.required('username', 'group'),
    h.forbidden('builtin', 'logged-in', 'sessions'),
    h.object({'password': {'type': 'string'}}),
    h.any_of(
        h.required('password'),
        h.required('unixhash', 'smbhash'),
        h.required('password_disabled')),
))
class UserCreateTask(Task):
    def describe(self, user):
        return "Adding user {0}".format(user['username'])

    def verify(self, user):

        errors = []

        for code, message in check_unixname(user['username']):
            errors.append(('name', code, message))
Example #31
0
def _init(dispatcher, plugin):
    # Register Schemas
    plugin.register_schema_definition('update', {
        'type': 'object',
        'properties': {
            'train': {'type': 'string'},
            'check_auto': {'type': 'boolean'},
            'update_server': {'type': 'string', 'readOnly': True},
        },
    })

    plugin.register_schema_definition('update-progress', h.object(properties={
        'operation': h.enum(str, ['DOWNLOADING', 'INSTALLING']),
        'details': str,
        'indeterminate': bool,
        'percent': int,
        'reboot': bool,
        'pkg_name': str,
        'pkg_version': str,
        'filename': str,
        'filesize': int,
        'num_files_done': int,
        'num_files_total': int,
        'error': bool,
        'finished': bool,
    }))

    plugin.register_schema_definition('update-ops', {
        'type': 'object',
        'properties': {
            'new_name': {'type': 'string'},
            'previous_version': {'type': 'string'},
            'operation': {
                'type': 'string',
                'enum': ['delete', 'install', 'upgrade']
            },
            'new_version': {'type': 'string'},
            'previous_name': {'type': 'string'},
        }
    })

    plugin.register_schema_definition('update-info', {
        'type': 'object',
        'properties': {
            'notes': {'type': 'object'},
            'notice': {'type': 'string'},
            'changelog': {'type': 'string'},
            'operations': {'$ref': 'update-ops'},
        }
    })

    plugin.register_schema_definition('update-train', {
        'type': 'object',
        'properties': {
            'name': {'type': 'string'},
            'description': {'type': 'string'},
            'sequence': {'type': 'string'},
            'current': {'type': 'boolean'},
        }
    })

    # Register providers
    plugin.register_provider("update", UpdateProvider)

    # Register task handlers
    plugin.register_task_handler("update.configure", UpdateConfigureTask)
    plugin.register_task_handler("update.check", CheckUpdateTask)
    plugin.register_task_handler("update.download", DownloadUpdateTask)
    plugin.register_task_handler("update.manual", UpdateManualTask)
    plugin.register_task_handler("update.update", UpdateApplyTask)
    plugin.register_task_handler("update.verify", UpdateVerifyTask)

    # Register Event Types
    plugin.register_event_type('update.in_progress', schema=h.ref('update-progress'))
    plugin.register_event_type('update.changed')

    # Register reources
    plugin.register_resource(Resource(update_resource_string), ['system'])

    # Get the Update Cache (if any) at system boot (and hence in init here)
    generate_update_cache(dispatcher)
Example #32
0
class UpdateProvider(Provider):
    @accepts()
    @returns(str)
    def is_update_available(self):
        temp_updateAvailable = update_cache.get('updateAvailable', timeout=1)
        if temp_updateAvailable is not None:
            return temp_updateAvailable
        elif update_cache.is_valid('updateAvailable'):
            return temp_updateAvailable
        else:
            raise RpcException(
                errno.EBUSY,
                ('Update Availability flag is invalidated, an Update Check'
                 ' might be underway. Try again in some time.'))

    @accepts()
    @returns(h.array(str))
    def obtain_changelog(self):
        temp_changelog = update_cache.get('changelog', timeout=1)
        if temp_changelog is not None:
            return temp_changelog
        elif update_cache.is_valid('changelog'):
            return temp_changelog
        else:
            raise RpcException(
                errno.EBUSY, ('Changelog list is invalidated, an Update Check '
                              'might be underway. Try again in some time.'))

    @accepts()
    @returns(h.array(h.ref('update-ops')))
    def get_update_ops(self):
        temp_updateOperations = update_cache.get('updateOperations', timeout=1)
        if temp_updateOperations is not None:
            return temp_updateOperations
        elif update_cache.is_valid('updateOperations'):
            return temp_updateOperations
        else:
            raise RpcException(
                errno.EBUSY,
                ('Update Operations Dict is invalidated, an Update Check '
                 'might be underway. Try again in some time.'))

    @accepts()
    @returns(h.any_of(
        h.ref('update-info'),
        None,
    ))
    def update_info(self):
        if not update_cache.is_valid('updateAvailable'):
            raise RpcException(
                errno.EBUSY,
                ('Update Availability flag is invalidated, an Update Check'
                 ' might be underway. Try again in some time.'))
        updateAvailable = update_cache.get('updateAvailable', timeout=1)
        if not updateAvailable:
            return None
        updateOperations = update_cache.get('updateOperations', timeout=1)
        updateNotes = update_cache.get('updateNotes', timeout=1)
        updateNotice = update_cache.get('updateNotice', timeout=1)
        changelog = update_cache.get('changelog', timeout=1)
        return {
            'changelog': changelog,
            'notes': updateNotes,
            'notice': updateNotice,
            'operations': updateOperations,
        }

    @returns(h.array(h.ref('update-train')))
    def trains(self):
        conf = Configuration.Configuration()
        conf.LoadTrainsConfig()
        trains = conf.AvailableTrains() or {}

        seltrain = self.dispatcher.configstore.get('update.train')

        data = []
        for name in trains.keys():
            if name in conf._trains:
                train = conf._trains.get(name)
            else:
                train = Train.Train(name)
            data.append({
                'name': train.Name(),
                'description': train.Description(),
                'sequence': train.LastSequence(),
                'current': True if name == seltrain else False,
            })
        return data

    @accepts()
    @returns(str)
    def get_current_train(self):
        conf = Configuration.Configuration()
        conf.LoadTrainsConfig()
        return conf.CurrentTrain()

    @accepts()
    @returns(h.ref('update'))
    def get_config(self):
        return {
            'train': self.dispatcher.configstore.get('update.train'),
            'check_auto': self.dispatcher.configstore.get('update.check_auto'),
            'update_server': Configuration.Configuration().UpdateServerURL(),
        }
Example #33
0
    def configure_disk(self, id):
        disk = self.datastore.get_by_id('disks', id)
        acc_level = getattr(AcousticLevel,
                            disk.get('acoustic_level', 'DISABLED')).value
        powermgmt = disk.get('apm_mode', 0)
        system('/usr/local/sbin/ataidle', '-P', str(powermgmt), '-A',
               str(acc_level), disk['path'])

        if disk.get('standby_mode'):
            standby_mode = str(disk['standby_mode'])
            gevent.spawn_later(
                60, lambda: system('/usr/local/sbin/ataidle', '-I',
                                   standby_mode, disk['path']))


@accepts(str, str, h.object())
class DiskGPTFormatTask(Task):
    def describe(self, disk, fstype, params=None):
        return "Formatting disk {0}".format(os.path.basename(disk))

    def verify(self, disk, fstype, params=None):
        if not get_disk_by_path(disk):
            raise VerifyException(errno.ENOENT,
                                  "Disk {0} not found".format(disk))

        if fstype not in ['freebsd-zfs']:
            raise VerifyException(errno.EINVAL,
                                  "Unsupported fstype {0}".format(fstype))

        return ['disk:{0}'.format(disk)]
Example #34
0
            'webui_http_port': self.configstore.get(
                'service.nginx.http.port',
            ),
            'webui_http_redirect_https': self.configstore.get(
                'service.nginx.http.redirect_https',
            ),
            'webui_https_certificate': self.configstore.get(
                'service.nginx.https.certificate',
            ),
            'webui_https_port': self.configstore.get(
                'service.nginx.https.port',
            ),
        }


@accepts(h.ref('system-general'))
class SystemGeneralConfigureTask(Task):

    def describe(self):
        return "System General Settings Configure"

    def verify(self, props):
        return ['system']

    def run(self, props):
        if 'hostname' in props:
            netif.set_hostname(props['hostname'])

        if 'language' in props:
            self.configstore.set('system.language', props['language'])
Example #35
0
                result.append(p.metadata['method'])

        return result

    @description("Returns list of clients connected to particular share")
    def get_connected_clients(self, share_name):
        share = self.datastore.get_by_id('shares', share_name)
        if not share:
            raise RpcException(errno.ENOENT, 'Share not found')

        return self.dispatcher.call_sync('shares.{0}.get_connected_clients'.format(share['type']), share_name)


@description("Creates new share")
@accepts(h.all_of(
    h.ref('share'),
    h.required('id', 'type', 'target')
))
class CreateShareTask(Task):
    def verify(self, share):
        return ['system']

    def run(self, share):
        self.join_subtasks(self.run_subtask('share.{0}.create'.format(share['type']), share))


@description("Updates existing share")
@accepts(str, h.ref('share'))
class UpdateShareTask(Task):
    def verify(self, name, updated_fields):
        share = self.datastore.get_by_id('shares', name)
        if not share:
Example #36
0
                    cert_path, '{0}.key'.format(certificate['name']))
                # Load and dump private key to make sure its in desired format
                # This is code ported from 9.3 and must be reviewed as it may very well be useless
                certificate['privatekey'] = export_privatekey(certificate['privatekey'])

            if certificate.get('csr'):
                certificate['csr_path'] = os.path.join(
                    cert_path, '{0}.csr'.format(certificate['name']))

            return certificate

        return self.datastore.query('crypto.certificates', *(filter or []), callback=extend, **(params or {}))


@accepts(h.all_of(
    h.ref('crypto-certificate'),
    h.required('signedby', 'name', 'country', 'state', 'city', 'organization', 'email', 'common'),
))
class CertificateInternalCreateTask(Task):
    def verify(self, certificate):

        errors = []

        if self.datastore.exists('crypto.certificates', ('name', '=', certificate['name'])):
            errors.append(('name', errno.EEXIST, 'Certificate with given name already exists'))

        if not self.datastore.exists('crypto.certificates', ('id', '=', certificate['signedby'])):
            errors.append(('signedby', errno.EEXIST, 'Signing certificate does not exists'))

        if '"' in certificate['name']:
            errors.append(
                ('name', errno.EINVAL, 'You cannot issue a certificate with a `"` in its name'))
Example #37
0
    except SubprocessException as e:
        # sysctl module compatibility
        raise OSError(str(e.err))


@description("Provides access to OS tunables")
class TunablesProvider(Provider):
    @query('tunable')
    def query(self, filter=None, params=None):
        return self.datastore.query('tunables', *(filter or []),
                                    **(params or {}))


@description("Adds Tunable")
@accepts(h.all_of(
    h.ref('tunable'),
    h.required('var', 'value', 'type'),
))
class TunableCreateTask(Task):
    def describe(self, tunable):
        return "Creating Tunable {0}".format(tunable['var'])

    def verify(self, tunable):

        errors = []
        if self.datastore.exists('tunables', ('var', '=', tunable['var'])):
            errors.append(
                ('var', errno.EEXIST, 'This variable already exists.'))

        if '"' in tunable['value'] or "'" in tunable['value']:
            errors.append(('value', errno.EINVAL, 'Quotes are not allowed'))
Example #38
0
        system('sysctl', '{0}={1}'.format(name, str(value)))
    except SubprocessException as e:
        # sysctl module compatibility
        raise OSError(str(e.err))


@description("Provides access to OS tunables")
class TunablesProvider(Provider):
    @query('tunable')
    def query(self, filter=None, params=None):
        return self.datastore.query('tunables', *(filter or []), **(params or {}))


@description("Adds Tunable")
@accepts(h.all_of(
    h.ref('tunable'),
    h.required('var', 'value', 'type'),
))
class TunableCreateTask(Task):
    def describe(self, tunable):
        return "Creating Tunable {0}".format(tunable['var'])

    def verify(self, tunable):

        errors = []
        if self.datastore.exists('tunables', ('var', '=', tunable['var'])):
            errors.append(('var', errno.EEXIST, 'This variable already exists.'))

        if '"' in tunable['value'] or "'" in tunable['value']:
            errors.append(('value', errno.EINVAL, 'Quotes are not allowed'))

        if tunable['type'] in ('LOADER', 'RC') and not VAR_LOADER_RC_RE.match(tunable['var']):
Example #39
0
    @query('network-route')
    def query(self, filter=None, params=None):
        return self.datastore.query('network.routes', *(filter or []),
                                    **(params or {}))


@description("Provides access to static host entries database")
class HostsProvider(Provider):
    @query('network-host')
    def query(self, filter=None, params=None):
        return self.datastore.query('network.hosts', *(filter or []),
                                    **(params or {}))


@description("Updates global network configuration settings")
@accepts(h.ref('network-config'))
class NetworkConfigureTask(Task):
    def verify(self, settings):
        return ['system']

    def run(self, settings):
        node = ConfigNode('network', self.dispatcher.configstore)
        node.update(settings)

        try:
            self.dispatcher.call_sync(
                'networkd.configuration.configure_network')
            self.dispatcher.call_sync('etcd.generation.generate_group',
                                      'network')
        except RpcException, e:
            raise TaskException(
Example #40
0
            if mail['auth']:
                server.login(mail['user'], mail['pass'])
            server.sendmail(mail['from'], to, msg)
            server.quit()
        except smtplib.SMTPAuthenticationError as e:
            raise RpcException(errno.EACCES, 'Authentication error: {0} {1}'.format(
                e.smtp_code, e.smtp_error))
        except Exception as e:
            logger.error('Failed to send email: {0}'.format(str(e)), exc_info=True)
            raise RpcException(errno.EFAULT, 'Email send error: {0}'.format(str(e)))
        except:
            raise RpcException(errno.EFAULT, 'Unexpected error')


@accepts(h.ref('mail'))
class MailConfigureTask(Task):

    def verify(self, mail):
        return []

    def run(self, mail):
        node = ConfigNode('mail', self.dispatcher.configstore)
        node.update(mail)

        try:
            self.dispatcher.call_sync('etcd.generation.generate_group', 'mail')
        except RpcException, e:
            raise TaskException(
                errno.ENXIO, 'Cannot reconfigure mail: {0}'.format(str(e))
            )
Example #41
0
from dispatcher.rpc import SchemaHelper as h
from lib.system import system, SubprocessException

logger = logging.getLogger('NTPPlugin')


@description("Provides access to NTP Servers configuration")
class NTPServersProvider(Provider):
    @query('ntp-server')
    def query(self, filter=None, params=None):
        return self.datastore.query('ntpservers', *(filter or []), **(params or {}))


@description("Adds new NTP Server")
@accepts(h.all_of(
    h.ref('ntp-server'),
    h.required('address'),
), bool)
class NTPServerCreateTask(Task):
    def describe(self, ntp):
        return "Creating NTP Server {0}".format(ntp['address'])

    def verify(self, ntp, force=False):

        errors = []

        try:
            system('ntpdate', '-q', ntp['address'])
        except SubprocessException:
            if not force:
                errors.append((
                    'address',
Example #42
0
            server.quit()
        except smtplib.SMTPAuthenticationError as e:
            raise RpcException(
                errno.EACCES,
                'Authentication error: {0} {1}'.format(e.smtp_code,
                                                       e.smtp_error))
        except Exception as e:
            logger.error('Failed to send email: {0}'.format(str(e)),
                         exc_info=True)
            raise RpcException(errno.EFAULT,
                               'Email send error: {0}'.format(str(e)))
        except:
            raise RpcException(errno.EFAULT, 'Unexpected error')


@accepts(h.ref('mail'))
class MailConfigureTask(Task):
    def verify(self, mail):
        return []

    def run(self, mail):
        node = ConfigNode('mail', self.dispatcher.configstore)
        node.update(mail)

        try:
            self.dispatcher.call_sync('etcd.generation.generate_group', 'mail')
        except RpcException, e:
            raise TaskException(errno.ENXIO,
                                'Cannot reconfigure mail: {0}'.format(str(e)))

Example #43
0
        conf = Configuration.Configuration()
        conf.LoadTrainsConfig()
        return conf.CurrentTrain()

    @accepts()
    @returns(h.ref('update'))
    def get_config(self):
        return {
            'train': self.dispatcher.configstore.get('update.train'),
            'check_auto': self.dispatcher.configstore.get('update.check_auto'),
            'update_server': Configuration.Configuration().UpdateServerURL(),
        }


@description("Set the System Updater Cofiguration Settings")
@accepts(h.ref('update'))
class UpdateConfigureTask(Task):
    def describe(self):
        return "System Updater Configure Settings"

    def verify(self, props):
        # TODO: Fix this verify's resource allocation as unique task
        train_to_set = props.get('train')
        conf = Configuration.Configuration()
        conf.LoadTrainsConfig()
        trains = conf.AvailableTrains() or []
        if trains:
            trains = trains.keys()
        if train_to_set not in trains:
            raise VerifyException(
                errno.ENOENT, '{0} is not a valid train'.format(train_to_set))
Example #44
0
class MailProvider(Provider):
    @returns(h.ref('mail'))
    def get_config(self):
        return ConfigNode('mail', self.configstore)

    @accepts(h.ref('mail-message'), h.ref('mail'))
    def send(self, mailmessage, mail=None):

        if mail is None:
            mail = ConfigNode('mail', self.configstore).__getstate__()
        if not mail.get('server') or not mail.get('port'):
            raise RpcException(
                errno.EINVAL,
                'You must provide an outgoing server and port when sending mail',
            )

        to = mailmessage.get('to')
        attachments = mailmessage.get('attachments')
        subject = mailmessage.get('subject')
        extra_headers = mailmessage.get('extra_headers')

        if not to:
            to = self.dispatcher.call_sync('users.query',
                                           [('username', '=', 'root')],
                                           {'single': True})
            if to and to.get('email'):
                to = [to['email']]

        if attachments:
            msg = MIMEMultipart()
            msg.preamble = mailmessage['message']
            map(lambda attachment: msg.attach(attachment), attachments)
        else:
            msg = MIMEText(mailmessage['message'], _charset='utf-8')
        if subject:
            msg['Subject'] = subject

        msg['From'] = mailmessage['from'] if mailmessage.get(
            'from') else mail['from']
        msg['To'] = ', '.join(to)
        msg['Date'] = formatdate()

        local_hostname = socket.gethostname()
        version = self.dispatcher.call_sync('system.info.version').split(
            '-')[0].lower()

        msg['Message-ID'] = "<{0}-{1}.{2}@{3}>".format(
            version,
            datetime.utcnow().strftime("%Y%m%d.%H%M%S.%f"),
            base64.urlsafe_b64encode(os.urandom(3)), local_hostname)

        if not extra_headers:
            extra_headers = {}
        for key, val in extra_headers.items():
            if key in msg:
                msg.replace_header(key, val)
            else:
                msg[key] = val
        msg = msg.as_string()

        try:
            if mail['encryption'] == 'SSL':
                klass = smtplib.SMTP_SSL
            else:
                klass = smtplib.SMTP
            server = klass(mail['server'],
                           mail['port'],
                           timeout=300,
                           local_hostname=local_hostname)
            if mail['encryption'] == 'TLS':
                server.starttls()

            if mail['auth']:
                server.login(mail['user'], mail['pass'])
            server.sendmail(mail['from'], to, msg)
            server.quit()
        except smtplib.SMTPAuthenticationError as e:
            raise RpcException(
                errno.EACCES,
                'Authentication error: {0} {1}'.format(e.smtp_code,
                                                       e.smtp_error))
        except Exception as e:
            logger.error('Failed to send email: {0}'.format(str(e)),
                         exc_info=True)
            raise RpcException(errno.EFAULT,
                               'Email send error: {0}'.format(str(e)))
        except:
            raise RpcException(errno.EFAULT, 'Unexpected error')
Example #45
0
def _init(dispatcher, plugin):
    # Register Schemas
    plugin.register_schema_definition(
        'update', {
            'type': 'object',
            'properties': {
                'train': {
                    'type': 'string'
                },
                'check_auto': {
                    'type': 'boolean'
                },
                'update_server': {
                    'type': 'string',
                    'readOnly': True
                },
            },
        })

    plugin.register_schema_definition(
        'update-progress',
        h.object(
            properties={
                'operation': h.enum(str, ['DOWNLOADING', 'INSTALLING']),
                'details': str,
                'indeterminate': bool,
                'percent': int,
                'reboot': bool,
                'pkg_name': str,
                'pkg_version': str,
                'filename': str,
                'filesize': int,
                'num_files_done': int,
                'num_files_total': int,
                'error': bool,
                'finished': bool,
            }))

    plugin.register_schema_definition(
        'update-ops', {
            'type': 'object',
            'properties': {
                'new_name': {
                    'type': 'string'
                },
                'previous_version': {
                    'type': 'string'
                },
                'operation': {
                    'type': 'string',
                    'enum': ['delete', 'install', 'upgrade']
                },
                'new_version': {
                    'type': 'string'
                },
                'previous_name': {
                    'type': 'string'
                },
            }
        })

    plugin.register_schema_definition(
        'update-info', {
            'type': 'object',
            'properties': {
                'notes': {
                    'type': 'object'
                },
                'notice': {
                    'type': 'string'
                },
                'changelog': {
                    'type': 'string'
                },
                'operations': {
                    '$ref': 'update-ops'
                },
            }
        })

    plugin.register_schema_definition(
        'update-train', {
            'type': 'object',
            'properties': {
                'name': {
                    'type': 'string'
                },
                'description': {
                    'type': 'string'
                },
                'sequence': {
                    'type': 'string'
                },
                'current': {
                    'type': 'boolean'
                },
            }
        })

    # Register providers
    plugin.register_provider("update", UpdateProvider)

    # Register task handlers
    plugin.register_task_handler("update.configure", UpdateConfigureTask)
    plugin.register_task_handler("update.check", CheckUpdateTask)
    plugin.register_task_handler("update.download", DownloadUpdateTask)
    plugin.register_task_handler("update.manual", UpdateManualTask)
    plugin.register_task_handler("update.update", UpdateApplyTask)
    plugin.register_task_handler("update.verify", UpdateVerifyTask)

    # Register Event Types
    plugin.register_event_type('update.in_progress',
                               schema=h.ref('update-progress'))
    plugin.register_event_type('update.changed')

    # Register reources
    plugin.register_resource(Resource(update_resource_string), ['system'])

    # Get the Update Cache (if any) at system boot (and hence in init here)
    generate_update_cache(dispatcher)
Example #46
0
        try:
            if type(rc_scripts) is unicode:
                system("/usr/sbin/service", rc_scripts, 'onerestart')

            if type(rc_scripts) is list:
                for i in rc_scripts:
                    system("/usr/sbin/service", i, 'onerestart')
        except SubprocessException, e:
            pass


@description("Provides functionality to start, stop, restart or reload service")
@accepts(
    str,
    h.enum(str, ['start', 'stop', 'restart', 'reload'])
)
class ServiceManageTask(Task):
    def describe(self, name, action):
        return "{0}ing service {1}".format(action.title(), name)

    def verify(self, name, action):
        if not self.datastore.exists('service_definitions', ('name', '=', name)):
            raise VerifyException(errno.ENOENT, 'Service {0} not found'.format(name))

        return ['system']

    def run(self, name, action):
        service = self.datastore.get_one('service_definitions', ('name', '=', name))
        rc_scripts = service['rcng'].get('rc-scripts')
        try: