Beispiel #1
0
 def get_unique_instance(type):
     # We'll use numeric identifiers for instances
     id = 1
     while str(id) in RoleSettings.get_instances(type):
         id += 1
     log.debug1("Generating unique instance %s" % str(id))
     return str(id)
Beispiel #2
0
    def installPackages(self):
        """install packages"""
        log.debug1("%s.installPackages()", self._log_prefix)

        # are there any groups or packages to install?
        if len(self._settings["packages"]) < 1:
            log.debug1("No groups or packages to install")
            yield None
            return

        # There is a bug in DNF where it will return exit code 1 if
        # all of the packages requested are @group and their contents
        # already installed. There's a hacky workaround by adding a
        # non-@group package to the command-line, so we'll add rolekit

        dnf_install = [ "dnf", "-y", "install", "rolekit" ] + \
                       self._settings["packages"]
        result = yield async.subprocess_future(dnf_install)

        if result.status:
            # If the subprocess returned non-zero, raise an exception
            raise RolekitError(COMMAND_FAILED, "%d" % result.status)

        # Completed successfully
        yield None
Beispiel #3
0
    def __decommission_async(self, force, sender):
        # Make sure we are in the proper state
        self.assert_state(READY_TO_START, ERROR)

        # Log
        log.debug1("%s.decommission(%s)", self._log_prefix, force)

        # Change state to decommissioning
        self.change_state(DECOMMISSIONING)

        # Call do_decommission
        try:
            yield async.call_future(self.do_decommission_async(force=force,
                                                               sender=sender))
        except Exception as e:
            self.change_state(ERROR, error=str(e), write=True)
            if not force:
                raise

        # Uninstall firewall
        self.uninstallFirewall()

        # Remove extension unit files
        self.cleanup_targets()

        # Remove the instance
        self.__remove_instance()
Beispiel #4
0
 def PropertiesChanged(self, interface_name, changed_properties,
                       invalidated_properties):
     interface_name = dbus_to_python(interface_name)
     changed_properties = dbus_to_python(changed_properties)
     invalidated_properties = dbus_to_python(invalidated_properties)
     log.debug1("PropertiesChanged('%s', '%s', '%s')",
                interface_name, changed_properties, invalidated_properties)
Beispiel #5
0
    def Set(self, interface_name, property_name, new_value, sender=None):
        interface_name = dbus_to_python(interface_name)
        property_name = dbus_to_python(property_name)
        new_value = dbus_to_python(new_value)
        log.debug1("%s.Set('%s', '%s', '%s')", self._log_prefix,
                   interface_name, property_name, new_value)

        if interface_name != DBUS_INTERFACE_ROLE:
            raise dbus.exceptions.DBusException(
                "org.freedesktop.DBus.Error.UnknownInterface: "
                "RolekitD does not implement %s" % interface_name)

        if property_name in self._exported_rw_properties:
            if not hasattr(self, "__check_%s", property_name):
                raise RolekitError(MISSING_CHECK, property_name)
            x = getattr(self, "__check_%s", property_name)
            x(new_value)
            self._settings.set(property_name, new_value)
            self._settings.write()
            self.PropertiesChanged(interface_name,
                                   { property_name: new_value }, [ ])
        elif property_name in self._exported_ro_properties:
            raise dbus.exceptions.DBusException(
                "org.freedesktop.DBus.Error.PropertyReadOnly: "
                "Property '%s' is read-only" % property_name)
        else:
            raise dbus.exceptions.DBusException(
                "org.freedesktop.DBus.Error.AccessDenied: "
                "Property '%s' does not exist" % property_name)
Beispiel #6
0
    def Introspect(self, sender=None):
        log.debug1("%s.Introspect()" % self._log_prefix)

        data = super(DBusRole, self).Introspect(self.path,
                                                self.busname.get_bus())
        return dbus_introspection_add_properties(self, data,
                                                 DBUS_INTERFACE_ROLE)
Beispiel #7
0
def main():
    args = parse_cmdline()

    setup_logging(args)
    log.debug1("Arguments: %s" % sys.argv)

    # Read the password from stdin
    user_pass = input(False)

    # Check for valid database and user names
    # We restrict this to having only letters, numbers
    # and underscores, for safety against SQL injection
    identifier = re.compile(r"^[^\d\W]\w*\Z")

    if not identifier.match(args.user):
        log.error("The user name was not a valid identifier.")
        sys.exit(1)

    # Connect to the local database via 'peer'
    conn = psycopg2.connect(database=args.database)
    conn.autocommit = True
    log.info1("Connected to local database '%s'" % args.database)
    cur = conn.cursor()


    # Construct the SQL statement
    sql_msg = ("ALTER ROLE %s WITH ENCRYPTED PASSWORD" %
               (args.user) + " %(pwd)s;")
    log.info1("Executing: %s" % sql_msg)
    log.debug10("Password: [%s]", user_pass)

    # Submit the request
    cur.execute(sql_msg, {'pwd': user_pass})

    sys.exit(0)
Beispiel #8
0
    def _signal_receiver(self, *args, **kwargs):
        _args = []
        for arg in args:
            _args.append(dbus_to_python(arg))
        args = _args
        if not "member" in kwargs:
            return
        signal = kwargs["member"]
        interface = kwargs["interface"]

        if interface != DBUS_INTERFACE or signal != "NotifyUnitFailed" or len(args) != 2:
            return

        log.debug1("NotifyUnitFailed('%s', '%s')", args[0], args[1])

        for obj in self._roles:
            if obj.get_name() != args[0]:
                continue
            instances = obj.get_instances()
            for instance_name in instances:
                if instance_name != args[1]:
                    continue
                instance = instances[instance_name]
                if instance._settings["state"] == RUNNING:
                    state = target_unit_state(instance.target_unit)
                    if state != "active":
                        instance.change_state(ERROR, write=True)
Beispiel #9
0
 def getAllRoleInstances(self, sender=None):
     """ return the list of all role instances """
     log.debug1("getAllRoleInstances()")
     ret_list = []
     for obj in self._roles:
         for instance in obj.get_instances().values():
             ret_list.append(instance)
     return ret_list
Beispiel #10
0
 def getNamedRole(self, name, sender=None):
     """ return the role with the name, otherwise raise error """
     name = dbus_to_python(name)
     log.debug1("getNamedRole('%s')", name)
     for obj in self._roles:
         if obj.get_name() == name:
             return obj
     raise RolekitError(INVALID_ROLE, name)
Beispiel #11
0
 def getNamedInstance(self, name, sender=None):
     """ return the role with the name, otherwise raise error """
     name = dbus_to_python(name)
     log.debug1("%s.getNamedInstance('%s')", self._log_prefix, name)
     instance_escaped_name = dbus_label_escape(name)
     if instance_escaped_name in self._instances:
         return self._instances[instance_escaped_name]
     raise RolekitError(INVALID_INSTANCE, name)
Beispiel #12
0
    def __redeploy_async(self, values, sender):
        values = dbus_to_python(values)

        # Make sure we are in the proper state
        self.assert_state(READY_TO_START, ERROR)

        # Log
        log.debug1("%s.redeploy(%s)", self._log_prefix, values)

        # Check values
        try:
            self.check_values(values)
        except Exception as e:
            # checking of values failed, set state to error
            self.change_state(ERROR, error=str(e), write=True)
            raise

        try:
            # Change to redeploying state
            self.change_state(REDEPLOYING)

            # Uninstall firewall
            self.uninstallFirewall()

            # Copy _DEFAULTS to self._settings
            self.copy_defaults()

            # Install package groups and packages
            log.debug9("TRACE: Installing packages")
            yield async.call_future(self.installPackages())

            # Install firewall
            self.installFirewall()

            # Call do_redeploy_async
            log.debug9("TRACE: Performing role-specific redeployment")
            yield async.call_future(self.do_redeploy_async(values, sender))

            # Continue only after successful deployment:
            # Apply values to self._settings
            log.debug9("TRACE: role-specific redeployment complete, applying values")
            self.apply_values(values)

            # Change to ready to start state
            self.change_state(READY_TO_START, write=True)

            # Attempt to start the newly-deployed role
            # We do this because many role-installers will conclude by
            # starting anyway and we want to ensure that our role mechanism
            # is in sync with them.
            log.debug9("TRACE: Starting %s" % self.get_name())
            yield async.call_future(self.__start_async(sender))

        except Exception as e:
            # Something failed, set state to error
            self.change_state(ERROR, error=str(e), write=True)
            raise
Beispiel #13
0
 def __job_removed_handler(self, job_id, job_path, unit, result):
     """SYSTEMD_MANAGER_INTERFACE.JobRemoved signal handler"""
     log.debug1("systemd JobRemoved signal: %s" %
                repr((job_id, job_path, unit, result)))
     if job_path in self.__pending_jobs:
         self.__job_results[unit] = result
         self.__pending_jobs.remove(job_path)
         if len(self.__pending_jobs) == 0:
             self.__future.set_result(self.__job_results)
Beispiel #14
0
 def _check_property(self, prop, value):
     try:
         super(Role, self)._check_property(prop, value)
     except RolekitError as e:
         if e.code == MISSING_CHECK:
             log.debug1("Unvalidated property: %s" % prop)
         else:
             log.debug1("Property %s did not validate" % prop)
             raise
Beispiel #15
0
    def start(self):
        """ starts rolekit """
        log.debug1("start()")

        try:
            os.makedirs(ETC_ROLEKIT_ROLES)
        except OSError as e:
            if e.errno == errno.EEXIST:
                if not os.path.isdir(ETC_ROLEKIT_ROLES):
                    log.fatal("'%s' is not a directory.", e.strerror)
            else:
                log.fatal("Failed to create '%s': %s", e.strerror)
                raise
        else:
            log.info1("Created missing '%s'.", ETC_ROLEKIT_ROLES)

        path = ROLEKIT_ROLES

        if not os.path.exists(path) or not os.path.isdir(path):
            log.error("Role directory '%s' does not exist.", path)
            return

        for name in sorted(os.listdir(path)):
            directory = "%s/%s" % (path, name)
            if not os.path.isdir(directory):
                continue

            if not os.path.exists(os.path.join(directory, "role.py")):
                continue

            log.debug1("Loading role '%s'", name)
            escaped_name = dbus_label_escape(name)

            try:
                if os.path.exists(os.path.join(directory, "role.py")):
                    mod = imp.load_source(name, "%s/role.py" % directory)

                    # get Role from module
                    role = getattr(mod, "Role")

                    # create role object that contains the role instance class
                    obj = DBusRole(role, name, directory, self.busname,
                                    "%s/%s" % (DBUS_PATH_ROLES, escaped_name),
                                   persistent=self.persistent)

                    if obj in self._roles:
                        log.error("Duplicate role '%s'", obj.get_name())
                    else:
                        self._roles.append(obj)
            except RolekitError as msg:
                log.error("Failed to load role '%s': %s", name, msg)
                continue
            except Exception as msg:
                log.error("Failed to load role '%s':", name)
                log.exception()
                continue
Beispiel #16
0
        def GetAll(self, interface_name, sender=None):
            interface_name = dbus_to_python(interface_name)
            log.debug1("GetAll('%s')", interface_name)

            if interface_name != DBUS_INTERFACE:
                raise dbus.exceptions.DBusException(
                    "org.freedesktop.DBus.Error.UnknownInterface: " "roled does not implement %s" % interface_name
                )

            return {"version": self._get_property("version"), "roles": self._get_property("roles")}
Beispiel #17
0
 def getAllRoleInstancesByState(self, state, sender=None):
     """ return the list of all roles instances that are in a particular state """
     state = dbus_to_python(state)
     log.debug1("getAllRoleInstancesByState('%s')", state)
     ret_list = []
     for obj in self._roles:
         for instance in obj.get_instances().values():
             if instance.get_state() == state:
                 ret_list.append(instance)
     return ret_list
Beispiel #18
0
    def resetError(self, sender=None):
        """resets error state in a role"""
        # Make sure we are in the proper state
        self.assert_state(ERROR)

        # Log
        log.debug1("%s.resetError()", self._log_prefix)

        # Change to state updating
        self.change_state(READY_TO_START, write=True)
Beispiel #19
0
    def __stop_async(self, sender):
        self.assert_state(RUNNING)
        log.debug1("%s.stop()", self._log_prefix)

        try:
            self.change_state(STOPPING)
            yield async.call_future(self.do_stop_async(sender))
            self.change_state(READY_TO_START, write=True)
        except:
            self.change_state(ERROR, write=True)
            raise
Beispiel #20
0
        def Get(self, interface_name, property_name, sender=None):
            # get a property
            interface_name = dbus_to_python(interface_name)
            property_name = dbus_to_python(property_name)
            log.debug1("Get('%s', '%s')", interface_name, property_name)

            if interface_name != DBUS_INTERFACE:
                raise dbus.exceptions.DBusException(
                    "org.freedesktop.DBus.Error.UnknownInterface: " "roled does not implement %s" % interface_name
                )

            return self._get_property(property_name)
Beispiel #21
0
    def __deploy_async(self, name, values):
        values = dbus_to_python(values)
        name = dbus_to_python(name)
        log.debug1("role.%s.deploy('%s', %s)", self._escaped_name, name, values)

        # limit role instances to max instances per role
        if len(self._instances) >= self._role._MAX_INSTANCES:
            raise RolekitError(TOO_MANY_INSTANCES, "> %d" % self._role._MAX_INSTANCES)

        # TODO: lock

        # create name if empty
        if not name:
            id = 1
            while str(id) in self._instances:
                id += 1
            name = str(id)

        # create escaped name and check if it is already in use
        instance_escaped_name = dbus_label_escape(name)
        if instance_escaped_name in self._instances:
            raise RolekitError(NAME_CONFLICT, instance_escaped_name)

        settings = RoleSettings(self._name, name)
        try:
            settings.read()
        except ValueError as e:
            raise RolekitError(NAME_CONFLICT, settings.filename)
        except IOError as e:
            pass
        else:
            raise RolekitError(NAME_CONFLICT, settings.filename)

        # create role
        role = self._role(
            self,
            name,
            self._name,
            self._directory,
            settings,
            self._path,
            "%s/%s/%s" % (DBUS_PATH_ROLES, self._escaped_name, instance_escaped_name),
            persistent=self.persistent,
        )
        self._instances[instance_escaped_name] = role
        self.InstanceAdded(instance_escaped_name)

        # TODO: unlock

        # deploy role, lock in role now
        result = yield async.call_future(role.deploy_async(values))
        yield result
Beispiel #22
0
    def GetAll(self, interface_name, sender=None):
        interface_name = dbus_to_python(interface_name)
        log.debug1("%s.GetAll('%s')", self._log_prefix, interface_name)

        if interface_name != DBUS_INTERFACE_ROLE:
            raise dbus.exceptions.DBusException(
                "org.freedesktop.DBus.Error.UnknownInterface: "
                "RolekitD does not implement %s" % interface_name)

        ret = dbus.Dictionary(signature = "sv")
        for x in [ "name", "DEFAULTS" ]:
            ret[x] = self.get_dbus_property(x)
        return ret
Beispiel #23
0
    def Get(self, interface_name, property_name, sender=None):
        # get a property
        interface_name = dbus_to_python(interface_name)
        property_name = dbus_to_python(property_name)
        log.debug1("%s.Get('%s', '%s')", self._log_prefix, interface_name,
                   property_name)

        if interface_name != DBUS_INTERFACE_ROLE_INSTANCE:
            raise dbus.exceptions.DBusException(
                "org.freedesktop.DBus.Error.UnknownInterface: "
                "RolekitD does not implement %s" % interface_name)

        return self.get_dbus_property(self, property_name)
Beispiel #24
0
def target_unit_state(target_unit):
    with SystemdJobHandler() as job_handler:
        job_path = job_handler.manager.GetUnit(target_unit)
        bus = slip.dbus.SystemBus()
        obj = bus.get_object(SYSTEMD_MANAGER_NAME, job_path)
        props = dbus.Interface(
            obj, dbus_interface='org.freedesktop.DBus.Properties')
        systemd_state = dbus_to_python(props.Get(SYSTEMD_UNIT_INTERFACE,
                                       "ActiveState"))
        rolekit_state = map_systemd_state(systemd_state);
        log.debug1("Detected systemd state %s" % rolekit_state)
        return rolekit_state
    raise RolekitError(COMMAND_FAILED, "Could not get role state.")
Beispiel #25
0
    def __redeploy_async(self, values, sender):
        values = dbus_to_python(values)

        # Make sure we are in the proper state
        self.assert_state(READY_TO_START, ERROR)

        # Log
        log.debug1("%s.redeploy(%s)", self._log_prefix, values)

        # Check values
        try:
            self.check_values(values)
        except:
            # checking of values failed, set state to error
            self.change_state(ERROR, write=True)
            raise

        try:
            # Change to redeploying state
            self.change_state(REDEPLOYING)


            # Copy _DEFAULTS to self._settings
            self.copy_defaults()

            # Call do_redeploy_async
            yield async.call_future(self.do_redeploy_async(values, sender))

            # Continue only after successful deployment:
            # Apply values to self._settings
            try:
                self.apply_values(values)
            except:
                # applying of values failed, set state to error
                self.change_state(ERROR, write=True)
                raise

            # Change to ready to start state
            self.change_state(READY_TO_START, write=True)

            # Attempt to start the newly-deployed role
            # We do this because many role-installers will conclude by
            # starting anyway and we want to ensure that our role mechanism
            # is in sync with them.
            yield async.call_future(self.__start_async(sender))

        except:
            # Something failed, set state to error
            self.change_state(ERROR, write=True)
            raise
Beispiel #26
0
    def __init__(self, role, name, directory, *args, **kwargs):
        """The DBUS_INTERFACE_ROLE implementation

        :param role: RoleBase descendant
        :param name: Role name
        :param directory: FIXME: unused???
        :param path: (Implicit in *args) FIXME: unused???
        """
        super(DBusRole, self).__init__(*args, **kwargs)
        self._path = args[0]
        self._role = role
        self._name = name
        self._escaped_name = dbus_label_escape(name)
        self._directory = directory
        self._instances = {}

        # create instances for stored instance settings

        path = "%s/%s" % (ETC_ROLEKIT_ROLES, self._name)
        if os.path.exists(path) and os.path.isdir(path):
            for name in sorted(os.listdir(path)):
                if not name.endswith(".json"):
                    continue
                instance = name[:-5]
                log.debug1("Loading '%s' instance '%s'", self._name, instance)

                settings = RoleSettings(self._name, instance)
                try:
                    settings.read()
                except ValueError as e:
                    log.error("Failed to load '%s' instance '%s': %s", self._name, instance, e)
                    continue

                instance_escaped_name = dbus_label_escape(instance)
                if instance_escaped_name in self._instances:
                    raise RolekitError(NAME_CONFLICT, instance_escaped_name)

                role = self._role(
                    self,
                    instance,
                    self._name,
                    self._directory,
                    settings,
                    self._path,
                    "%s/%s/%s" % (DBUS_PATH_ROLES, self._escaped_name, instance_escaped_name),
                    persistent=self.persistent,
                )
                self._instances[instance_escaped_name] = role

        self.timeout_restart()
Beispiel #27
0
    def restart(self, reply_handler, error_handler, sender=None):
        """restart role"""
        # Make sure we are in the proper state
        self.assert_state(RUNNING)

        # Log
        log.debug1("%s.restart()", self._log_prefix)

        # Stop
        self.stop(reply_handler, error_handler, sender)

        # Start if state is ready to start
        self.assert_state(READY_TO_START)
        self.start(reply_handler, error_handler, sender)
Beispiel #28
0
    def stop_services_async(self):
        """stop_services_async"""
        log.debug1("%s.stop_services_async()", self._log_prefix)

        with SystemdJobHandler() as job_handler:
            target_unit = "role-%s-%s.target" % (self._type, self.get_name())
            job_path = job_handler.manager.StopUnit(target_unit, "replace")
            job_handler.register_job(job_path)

            job_results = yield job_handler.all_jobs_done_future()

        if any([x for x in job_results.values() if x not in ("skipped", "done")]):
            details = ", ".join(["%s: %s" % item for item in job_results.items()])
            raise RolekitError(COMMAND_FAILED, "Stopping services failed: %s" % details)
Beispiel #29
0
        def Set(self, interface_name, property_name, new_value, sender=None):
            interface_name = dbus_to_python(interface_name)
            property_name = dbus_to_python(property_name)
            new_value = dbus_to_python(new_value)
            log.debug1("Set('%s', '%s', '%s')", interface_name, property_name, new_value)
            self.accessCheck(sender)

            if interface_name != DBUS_INTERFACE:
                raise dbus.exceptions.DBusException(
                    "org.freedesktop.DBus.Error.UnknownInterface: " "roled does not implement %s" % interface_name
                )

            raise dbus.exceptions.DBusException(
                "org.freedesktop.DBus.Error.AccessDenied: " "Property '%s' is not settable" % property_name
            )
Beispiel #30
0
        def GetAll(self, interface_name, sender=None):
            interface_name = dbus_to_python(interface_name)
            log.debug1("config.GetAll('%s')", interface_name)

            if interface_name != DBUS_INTERFACE_ROLE_INSTANCE:
                raise dbus.exceptions.DBusException(
                    "org.freedesktop.DBus.Error.UnknownInterface: "
                    "RolekitD does not implement %s" % interface_name)

            ret = { }
            for name in self._DEFAULTS:
                ret[name] = self.get_dbus_property(self, name)
            # lasterror is not in _DEFAULTS, but in _settings
            ret["lasterror"] = self.get_dbus_property(self, "lasterror")
            return ret
Beispiel #31
0
    def Introspect(self, sender=None):
        log.debug1("Introspect()")

        data = super(RoleD, self).Introspect(self.path, self.busname.get_bus())
        return dbus_introspection_add_properties(self, data, DBUS_INTERFACE)
Beispiel #32
0
 def InstanceRemoved(self, name):
     log.debug1("%s.InstanceRemoved('%s')", self._log_prefix, name)
Beispiel #33
0
    def __init__(self, role, name, directory, *args, **kwargs):
        """The DBUS_INTERFACE_ROLE implementation

        :param role: RoleBase descendant
        :param name: Role name
        :param directory: FIXME: unused???
        :param path: (Implicit in *args) FIXME: unused???
        """
        super(DBusRole, self).__init__(*args, **kwargs)
        self.busname = args[0]
        self.path = args[1]
        self._role = role
        self._name = name
        self._escaped_name = dbus_label_escape(name)
        self._log_prefix = "role.%s" % self._escaped_name
        self._directory = directory
        self._instances = {}

        # create instances for stored instance settings

        path = "%s/%s" % (ETC_ROLEKIT_ROLES, self.get_name())
        if os.path.exists(path) and os.path.isdir(path):
            for name in sorted(os.listdir(path)):
                if not name.endswith(".json"):
                    continue
                instance = name[:-5]
                log.debug1("Loading '%s' instance '%s'", self.get_name(),
                           instance)

                settings = RoleSettings(self.get_name(), instance)
                try:
                    settings.read()
                except ValueError as e:
                    log.error("Failed to load '%s' instance '%s': %s",
                              self.get_name(), instance, e)
                    continue

                instance_escaped_name = dbus_label_escape(instance)
                if instance_escaped_name in self._instances:
                    raise RolekitError(NAME_CONFLICT, instance_escaped_name)

                role = self._role(self,
                                  instance,
                                  self.get_name(),
                                  self._directory,
                                  settings,
                                  self.busname,
                                  "%s/%s/%s" %
                                  (DBUS_PATH_ROLES, self._escaped_name,
                                   instance_escaped_name),
                                  persistent=self.persistent)

                # During roled startup (the only time this function should be
                # called), if any role is in a transitional state, it can only
                # mean that roled was terminated while it was still supposed
                # to be doing something.
                # Always set the state to ERROR here if it's in a transitional state,
                # otherwise we won't be able to clean it up.
                if role._settings["state"] in TRANSITIONAL_STATES:
                    role.change_state(state=ERROR,
                                      write=True,
                                      error="roled terminated unexpectedly")

                self._instances[instance_escaped_name] = role

        self.timeout_restart()
Beispiel #34
0
 def restartServices(self):
     """restart services"""
     log.debug1("%s.restartServices()", self._log_prefix)
     raise NotImplementedError()
Beispiel #35
0
    def deploy_async(self, values, sender=None):
        """deploy role"""
        remove_instance = False

        values = dbus_to_python(values)

        # Make sure we are in the proper state
        self.assert_state(NASCENT)

        # Log
        log.debug1("%s.deploy(%s)", self._log_prefix, values)

        # Check values
        try:
            self.check_values(values)
        except Exception as e:
            # Check values failed, remove the instance again if verification
            # failed, set state to error, save it (will be visible in the
            # .old backup file).
            self.change_state(ERROR, error=str(e), write=True)

            # cleanup
            self.__remove_instance()
            raise

        try:
            # Change to deploying state
            self.change_state(DEPLOYING)

            # Copy _DEFAULTS to self._settings
            self.copy_defaults()

            # Install package groups and packages
            log.debug9("TRACE: Installing packages")
            yield async .call_future(self.installPackages())

            # Install firewall
            self.installFirewall()

            # Call do_deploy
            log.debug9("TRACE: Performing role-specific deployment")
            try:
                target = yield async .call_future(
                    self.do_deploy_async(values, sender))
            except RolekitError as e:
                if e.code == INVALID_VALUE:
                    # If we failed because the input values were incorrect,
                    # also remove the instance.
                    remove_instance = True
                raise

            # Continue only after successful deployment:
            # Apply values to self._settings
            log.debug9(
                "TRACE: role-specific deployment complete, applying values")
            self.apply_values(values)

            # Set up systemd target files
            log.debug9("TRACE: Creating systemd target files")
            self.create_target(target)

            # Change to ready to start state
            self.change_state(READY_TO_START, write=True)

            # In case this was a nextboot deployment, make sure to remove
            # the deferred role settings and systemd unit
            try:
                # Remove settings
                deferredsettings = "%s/%s/%s.json" % (
                    ETC_ROLEKIT_DEFERREDROLES, self.get_type(),
                    self.get_name())
                os.unlink(deferredsettings)

                # Remove systemd service unit
                deferredunit = "%s/deferred-role-deployment-%s-%s.service" % (
                    SYSTEMD_UNITS, self.get_type(), self.get_name())
                disable_units([deferredunit])
                os.unlink(deferredunit)
            except FileNotFoundError:
                # Files didn't exist; ignore that
                pass
            except PermissionError:
                # SELinux bug?
                log.fatal(
                    "ERROR: permission error attempting to delete %s or %s" %
                    (deferredsettings, deferredunit))
                # We'll continue anyway, since the service should be runnable at this point
                # The ConditionPathExists will prevent the service from trying to deploy
                # again

            # Tell systemd to reload the daemon configuration
            log.debug9("Reloading systemd units\n")
            with SystemdJobHandler() as job_handler:
                job_handler.manager.Reload()

            # Start monitoring the role
            self.monitor_unit()

            # Attempt to start the newly-deployed role
            # We do this because many role-installers will conclude by
            # starting anyway and we want to ensure that our role mechanism
            # is in sync with them.
            log.debug9("TRACE: Starting %s" % self.get_name())
            yield async .call_future(self.__start_async(sender))

        except Exception as e:
            # Something failed, set state to error
            self.change_state(ERROR, error=str(e), write=True)
            if remove_instance:
                self.__remove_instance()
            raise
Beispiel #36
0
    def updateFirewall(self):
        """update firewall"""
        log.debug1("%s.updateFirewall()", self._log_prefix)

        self.uninstallFirewall()
        self.installFirewall()
Beispiel #37
0
    def deploy_async(self, values, sender=None):
        """deploy role"""
        remove_instance = False

        values = dbus_to_python(values)

        # Make sure we are in the proper state
        self.assert_state(NASCENT)

        # Log
        log.debug1("%s.deploy(%s)", self._log_prefix, values)

        # Check values
        try:
            self.check_values(values)
        except:
            # Check values failed, remove the instance again if verification
            # failed, set state to error, save it (will be visible in the
            # .old backup file).
            self.change_state(ERROR, write=True)

            # cleanup
            self.__remove_instance()
            raise

        try:
            # Change to deploying state
            self.change_state(DEPLOYING)

            # Copy _DEFAULTS to self._settings
            self.copy_defaults()

            # Install package groups and packages
            log.debug9("TRACE: Installing packages")
            yield async.call_future(self.installPackages())

            # Install firewall
            self.installFirewall()

            # Call do_deploy
            log.debug9("TRACE: Performing role-specific deployment")
            try:
                target = yield async.call_future(self.do_deploy_async(values, sender))
            except RolekitError as e:
                if e.code == INVALID_VALUE:
                    # If we failed because the input values were incorrect,
                    # also remove the instance.
                    remove_instance = True
                raise

            # Continue only after successful deployment:
            # Apply values to self._settings
            log.debug9("TRACE: role-specific deployment complete, applying values")
            self.apply_values(values)

            # Set up systemd target files
            log.debug9("TRACE: Creating systemd target files")
            self.create_target(target)

            # Change to ready to start state
            self.change_state(READY_TO_START, write=True)

            # Attempt to start the newly-deployed role
            # We do this because many role-installers will conclude by
            # starting anyway and we want to ensure that our role mechanism
            # is in sync with them.
            log.debug9("TRACE: Starting %s" % self.name)
            yield async.call_future(self.__start_async(sender))

        except:
            # Something failed, set state to error
            self.change_state(ERROR, write=True)
            if remove_instance:
                self.__remove_instance()
            raise
Beispiel #38
0
    def uninstallFirewall(self):
        """uninstall firewall"""
        log.debug1("%s.uninstallFirewall()", self._log_prefix)

        # Removes the settings that have been added in the installFirewall call

        # get applied changes from installFirewall call
        if "firewall-changes" in self._settings:
            fw_changes = self._settings["firewall-changes"]
        else:
            # fallback if there was a severe error in deploy before or while
            # installing the firewall
            fw_changes = { }

        # only continue if there are any changes
        if len(fw_changes) < 1:
            return

        # create firewall client
        fw = FirewallClient()

        # for all zones
        for zone in fw_changes:
            z_perm = fw.config().getZoneByName(zone).getSettings()

            if "services" in fw_changes[zone]:
                services = fw_changes[zone]["services"]
                for service in services:
                    if "runtime" in services[service]:
                        try:
                            fw.removeService(zone, service)
                        except Exception as e:
                            if not "NOT_ENABLED" in str(e):
                                raise
                    if "permanent" in services[service]:
                        try:
                            z_perm.removeService(service)
                        except Exception as e:
                            if not "NOT_ENABLED" in str(e):
                                raise

            if "ports" in fw_changes[zone]:
                ports = fw_changes[zone]["ports"]
                for port_proto in ports:
                    port, proto = port_proto.split("/")
                    if "runtime" in ports[port_proto]:
                        try:
                            fw.removePort(zone, port, proto)
                        except Exception as e:
                            if not "NOT_ENABLED" in str(e):
                                raise
                    if "permanent" in ports[port_proto]:
                        try:
                            z_perm.removePort(port, proto)
                        except Exception as e:
                            if not "NOT_ENABLED" in str(e):
                                raise

            fw.config().getZoneByName(zone).update(z_perm)

        # clear fw_changes and save it in _settings
        fw_changes.clear()
        self._settings["firewall-changes"] = fw_changes
        self._settings.write()
Beispiel #39
0
 def StateChanged(self, state):
     log.debug1("%s.StateChanged('%s')", self._log_prefix, state)
Beispiel #40
0
    def installFirewall(self):
        """install firewall"""
        log.debug1("%s.installFirewall()", self._log_prefix)

        # are there any firewall settings to apply?
        if len(self._settings["firewall"]["services"]) + \
           len(self._settings["firewall"]["ports"]) < 1:
            return

        # create firewall client
        fw = FirewallClient()
        log.debug2("TRACE: Firewall client created")

        # Make sure firewalld is running by getting the
        # default zone
        try:
            default_zone = fw.getDefaultZone()
        except DBusException:
            # firewalld is not running
            log.error("Firewalld is not running or rolekit cannot access it")
            raise

        # save changes to the firewall
        try:
            fw_changes = self._settings["firewall-changes"]
        except KeyError:
            fw_changes = { }

        log.debug2("TRACE: Checking for zones: {}".format(self._settings))

        try:
            zones = self._settings["firewall_zones"]
        except KeyError:
            zones = []

        # if firewall_zones setting is empty, use default zone
        if len(zones) < 1:
            zones = [ default_zone ]

        log.debug2("TRACE: default zone {}".format(zones[0]))

        for zone in zones:
            log.debug2("TRACE: Processing zone {0}".format(zone))
            # get permanent zone settings, run-time settings do not need a
            # special treatment
            z_perm = fw.config().getZoneByName(zone).getSettings()

            for service in self._settings["firewall"]["services"]:
                try:
                    fw.addService(zone, service, 0)
                except Exception as e:
                    if not "ALREADY_ENABLED" in str(e):
                        raise
                else:
                    fw_changes.setdefault(zone, {}).setdefault("services", {}).setdefault(service, []).append("runtime")

                if not z_perm.queryService(service):
                    z_perm.addService(service)
                    fw_changes.setdefault(zone, {}).setdefault("services", {}).setdefault(service, []).append("permanent")

            for port_proto in self._settings["firewall"]["ports"]:
                port, proto = port_proto.split("/")

                try:
                    fw.addPort(zone, port, proto, 0)
                except Exception as e:
                    if not "ALREADY_ENABLED" in str(e):
                        raise
                else:
                    fw_changes.setdefault(zone, {}).setdefault("ports", {}).setdefault(port_proto, []).append("runtime")

                if not z_perm.queryPort(port, proto):
                    z_perm.addPort(port, proto)
                    fw_changes.setdefault(zone, {}).setdefault("ports", {}).setdefault(port_proto, []).append("permanent")

            fw.config().getZoneByName(zone).update(z_perm)

        self._settings["firewall-changes"] = fw_changes
        self._settings.write()
Beispiel #41
0
 def stop(self):
     """ stops rolekit """
     log.debug1("stop()")
Beispiel #42
0
 def PropertiesChanged(self, interface_name, changed_properties,
                       invalidated_properties):
     log.debug1("config.PropertiesChanged('%s', '%s', '%s')",
                interface_name, changed_properties,
                invalidated_properties)
Beispiel #43
0
    def getInstances(self, sender=None):
        """get role instances"""
        log.debug1("%s.getInstances()", self._log_prefix)

        return self._instances.values()