Project

General

Profile

Editing Server Settings via XMPP

Avatar?id=6023&size=32x32

Artur Hefczyc TigaseTeam
Added about 3 years ago

Almost every application written has some way you can change how it behaves.  Some are more difficult to change than others, being locked behind options and run commands.  Others, like Tigase, offer a number of ways you can configure the software allowing the user to choose the most convenient way to change settings.  One method available it by sending XMPP stanzas to the server which can be sent from any client connected with an administrator account.  This can be useful if you want to change settings on the server on the fly without having to restart the server and sending potentially thousands of users offline!

The ability to send XMPP stanzas to edit server configuration requires no configuration, and is ready to work out of the box.  Once the server is up and running, administrator accounts can send XMPP Stanzas to send ad-hoc commands.  First, let”s look at how you can find out what commands are available.  This stanza can be sent to any running component on the server, and will list available commands:

<iq type=“get” to=“basic-conf@example.com” id=“aae8a”>
  <query xmlns=“http://jabber.org/protocol/disco#items”node=“http://jabber.org/protocol/commands”/>
</iq>

The result will be a list of commands that are applicable to basic-conf, which is the basic configuration of the server.  The returned list will be a number of ‘item’ stanzas, where the node is the XML Namespace.  However in this case, we want to update an item’s configuration, so the node we are interested in is:

<item node="comp-repo-item-update" name="Update item configuration" jid="basic-conf@example.com"/>

To proceed with this command, we send a “set” iq stanza to basic-conf, with the appropriate command:

<iq type="set" to="basic-conf@example.com" id="aad5a">
  <command xmlns="http://jabber.org/protocol/commands" node="comp-repo-item-update"/>
</iq>

The server now responds with a very long list of options, as it will list every available option for many components such as, AMP, S2S, C2S, BOSH and others.  A field type XML is returned with a list of options.  Some are shown here, but it is truncated.

<iq from="basic-conf@example.com" type="result" id="aad5a" to="user1@example.com/mobile">
  <command xmlns="http://jabber.org/protocol/commands" status="executing" node="comp-repo-item-update">
    <x xmlns="jabber:x:data" type="form">
      <field type="list-single" label="List of items" var="item-list">
        <value>basic-conf/component-id</value>
        <option label="basic-conf/component-id">
          <value>basic-conf/component-id</value>
        </option>
        <option label="basic-conf/logging/.level">
          <value>basic-conf/logging/.level</value>
        </option>
        <option label="message-router/max-queue-size">
          <value>message-router/max-queue-size</value>
        </option>
        <option label="bosh/connections/tls/use">
          <value>bosh/connections/tls/use</value>
        </option>
        <option label="c2s/traffic-throttling">
          <value>c2s/traffic-throttling</value>
        </option>
        <option label="eventbus/component-id">
          <value>eventbus/component-id</value>
        </option>
        <option label="message-archive/tags-support">
          <value>message-archive/tags-support</value>
        </option>
     </field>
    </x>
    <actions execute="complete">
      <complete/>
    </actions>
  </command>
</iq>

As you can see, options are broken into component/option for organization.  Some options may be available for multiple components, so you will see many instances of /admins which can define admins in addition to ones specified in sess-man for certain components, /component-id, which will change the name of the component, or /scripts-dir which lists a specific directory for scripts for that component.  Let's say for example, you want a more verbose output for logs when looking at the basic-conf component of Tigase. This can be helpful for determining how the component is running, and what it is doing. In this case we want to set the logging level for basic-conf to INFO:

<iq type="set" to="basic-conf@example.com" id="aad6a">
  <command xmlns="http://jabber.org/protocol/commands" node="comp-repo-item-update">
    <x xmlns="jabber:x:data" type="submit">
      <field type="list-single" var="item-list">
        <value>basic-conf/logging/.level</value>
      </field>
    </x>
  </command>
</iq>

Once the command is sent, we will receive a form XML stanza with the options that are currently set:

<iq from="basic-conf@example.com" type="result" id="aad6a" to="user1@example.com/mobile">
<command xmlns="http://jabber.org/protocol/commands" status="executing" node="comp-repo-item-update">
<x xmlns="jabber:x:data" type="form">
<field type="fixed" var="Component name">
<value>basic-conf</value>
</field>
<field type="fixed" var="Property node name">
<value>logging</value>
</field>
<field type="fixed" var="Property key name">
<value>.level</value>
</field>
<field type="fixed" var=" ">
<value> </value>
</field>
<field var="Propety value \[S\]">
<value>CONFIG</value>
</field>
<field var="Owner">
<value>user1@example.com</value>
</field>
<field var="Administrators">
<value/>
</field>
<field type="hidden" var="command-marker">
<value>command-marker</value>
</field>
<field type="hidden" var="item-list">
<value>basic-conf/logging/.level</value>
</field>
<field type="hidden" var="notify-cluster">
<value>true</value>
</field>
</x>
<actions execute="complete">
<complete/>
</actions>
</command>
</iq>

Although we want to change just one option, the entire form needs to be sent back, we’re going to send back the form, but with the logging level set to INFO.

<iq type="set" to="basic-conf@example.com" id="ab26a">
<command xmlns="http://jabber.org/protocol/commands" node="comp-repo-item-update">
<x xmlns="jabber:x:data" type="submit">
<field type="fixed" var="Component name">
<value>basic-conf</value>
</field>
<field type="fixed" var="Property node name">
<value>logging</value>
</field>
<field type="fixed" var="Property key name">
<value>.level</value>
</field>
<field type="fixed" var=" ">
<value> </value>
</field>
<field type="text-single" var="Propety value \[S\]">
<value>INFO</value>
</field>
<field type="text-single" var="Owner">
<value>user1@example.com</value>
</field>
<field type="text-single" var="Administrators">
<value></value>
</field>
<field type="hidden" var="command-marker">
<value>command-marker</value>
</field>
<field type="hidden" var="item-list">
<value>basic-conf/logging/.level</value>
</field>
<field type="hidden" var="notify-cluster">
<value>true</value>
</field>
</x>
</command>
</iq>

If the settings are applied correctly, the server will send back an Operation successful field:

<iq from="basic-conf@example.com" type="result" id="ab26a" to="user1@example.com/mobile">
<command xmlns="http://jabber.org/protocol/commands" status="completed" node="comp-repo-item-update">
<x xmlns="jabber:x:data" type="result">
<field type="fixed" var="Note">
<value>Operation successful</value>
</field>
</x>
</command>
</iq>

Although this may be a more involved procedure, you can see by this exchange, you can send XMPP stanzas to various components to configure the server without needed anything more than a client.  As we’ve seen basic server configuration can be manipulated by addressing the basic-conf component (basic-conf@example.com).  However configuration of other components may also be set in the same fashion by addressing muc configuration by addressing the muc component (muc@example.com), pubsub configuration by addressing the pubsub component (pubsub@example.com) and so on.  Any setting change can follow this exchange of stanzas more or less the same.  Nearly any setting can be changed in this manner from any XMPP client.  These changes are immediate and there is no need to interrupt a connected user's experience!  However, keep in mind that resetting the server may lose some of these settings, so you may wish to change settings in the init.properties file as well to keep them permanent.