Asterisk AMI API UpdateConfig Action Issue

Hello, I am attempting to use the Asterisk Manager API to update a configuration file using the UpdateConfig Action. When doing so I am repeatedly getting an error response of “Message: Save of config failed”. Below is a PHP code snippet and if anyone can add some suggestions as to what may be going wrong it would greatly appreciated. On a side note I regularly use the AMI API for other functions so I know that it is working.

// Login
$socket = fsockopen($domain, 5038, $errno, $errstr, 30);
fputs($socket, “Action: Login\r\n”);
fputs($socket, “Username: “.$username.”\r\n”);
fputs($socket, “Secret: “.$secret.”\r\n\r\n”);
$wrets = fread($socket, 8192);
echo $wrets;

// Update Config
fputs($socket, “Action: UpdateConfig\r\n”);
fputs($socket, “Reload: no\r\n”); // No for testing but will be Yes.
fputs($socket, “Srcfilename: pjsip.auth.conf\r\n”);
fputs($socket, “Dstfilename: /tmp/pjsip.test.conf\r\n”); // Just a temp location to see if things work
fputs($socket, “Action-000000: update\r\n”);
fputs($socket, “Cat-000000: 10000-auth\r\n”);
fputs($socket, “Var-000000: password\r\n”);
fputs($socket, “Value-000000: 1234\r\n\r\n”);
$wrets = fread($socket, 8192);
echo $wrets;

// Logoff
fputs($socket, “Action: Logoff\r\n\r\n”);
$wrets = fread($socket, 8192);
fclose($socket);
echo $wrets;

Try to save your destination file in /etc/asterisk.

I havent use UpdateConfig action, but did you make sure it is not permision issue ?

Thanks for the ideas guys. Its not the path or permissions but good thinking.

Most likely @ambiorixg12 is right, but I’ll use the Asterisk source code to back me up a bit on that assertion.

If we look at the relevant bits of action_updateconfig, which handles the UpdateConfig action, you’ll see that the function that actually saves the configuration changes is ast_config_text_file_save2, the result of which - if non-zero - causes the error message you’re getting back from AMI:

	res = ast_config_text_file_save2(dfn, cfg, "Manager", preserve_effective_context);
	ast_config_destroy(cfg);
	if (res) {
		astman_send_error(s, m, "Save of config failed");
		return 0;
	}

Now, there’s actually a lot of ways this can fail. However, if you’re providing a valid config file name, and if that file exists in the expected configuration file directory path, then the most likely failure is a permissions issue. That aside, the Asterisk CLI should be dumping out an ERROR message indicating exactly why the configuration file can’t be saved. Most likely, one of the following:

ast_log(LOG_ERROR, "Unable to write to directory %s (%s)\n", dn, strerror(errno));

or

ast_log(LOG_ERROR, "Unable to write %s (%s)\n", fn, strerror(errno));

So - do you see anything on the CLI when the AMI action fails? If so, which ERROR message do you see? If not, can you provide the CLI output - with VERBOSE set to 5? That should give enough information to figure out why the action is failing.

1 Like

Great explanation @mjordan I hope we can get more feedbacks like that, from the Asterisk core developer team

Hi Guys, it did turn out to be a permission issue. I really appreciate all your expertise with this matter.

Hey guys,

I might be facing a similar issue trying to send of an UpdateConfig action to update pjsip.endpoint.conf.

I get back a Response: ‘Success’ in the response with the corresponding actionID.

But when i go into the CLI and cat out the file the update has not been made.

This is my action string

Action: UpdateConfig
SrcFilename: pjsip.endpoint.conf
DstFilename: pjsip.endpoint.conf
Reload: Yes
PreserveEffectiveContext: true
Action-000000: Update
Cat-000000: 101
Var-000000: ice_support
Value-000000: yes

Weirdly if i change the DstFilename to say… pjsip.endpoint2.conf it succesfully creates that second file with all the content from pjsip.endpoint.conf and the updated line.

permissions seem ok:

-rw-rw-r–. 1 asterisk asterisk 3491 Aug 1 15:19 /etc/asterisk/pjsip.endpoint.conf

Wondering if anyone had any suggestions

What version of asterisk and what permissions are set for the AMI user?
Can you paste the endpoint here (with sensitive info removed) and any templates it may reference? I’m assuming there’s at least an aor with the same name yes? Any other objects with the same name? Can you paste them here as well?
What happens if you set
Options-000000: catfilter='type=endpoint'

Thanks for responding.

Im on Asterisk 18.16.0

in manager config my user permissions are:

[admin]
secret = ******
permit=0.0.0.0/0.0.0.0
permit=127.0.0.1/255.255.255.0
read = system,call,log,verbose,command,agent,user,config,command,dtmf,reporting,cdr,dialplan,originate,message
write = system,call,log,verbose,command,agent,user,config,command,dtmf,reporting,cdr,dialplan,originate,message
writetimeout = 5000

One of the example endpoints that im trying to edit in pjsip.endpoint.conf are

[100]
type=endpoint
aors=100
auth=100-auth
tos_audio=ef
tos_video=af41
cos_audio=5
cos_video=4
allow=g722,ulaw,alaw,gsm,g726,g723,g729,h264,mpeg4
context=from-internal
callerid=john <100>

dtmf_mode=rfc4733
direct_media=yes
mailboxes=100@device

mwi_subscribe_replaces_unsolicited=yes
aggregate_mwi=no
use_avpf=yes
rtcp_mux=yes
max_audio_streams=1
max_video_streams=1
bundle=yes
ice_support=yes
media_use_received_transport=yes
trust_id_inbound=yes
user_eq_phone=no
send_connected_line=yes
media_encryption=dtls
timers=yes
timers_min_se=90
media_encryption_optimistic=no
refer_blind_progress=yes
refer_blind_progress=yes
rtp_timeout=10
rtp_timeout_hold=300
rtp_keepalive=0
send_pai=yes
rtp_symmetric=yes
rewrite_contact=yes
force_rport=yes
language=en
one_touch_recording=on
record_on_feature=apprecord
record_off_feature=apprecord
dtls_verify=fingerprint
dtls_setup=actpass
dtls_rekey=0
dtls_cert_file=/etc/asterisk/keys/default.crt
dtls_private_key=/etc/asterisk/keys/default.key

also in pjsip.endpoint_custom.conf i have this template

endpoint_template
type = endpoint
media_encryption = dtls
dtls_verify = fingerprint
dtls_setup = actpass
dtls_rekey = 0
ice_support = yes
media_use_received_transport = yes
use_avpf = yes
rtcp_mux = yes
dtls_cert_file = /etc/asterisk/keys/default.crt
dtls_private_key = /etc/asterisk/keys/default.key

but seeing as there seems to be no other way to automatically assign endpoints a template when they’re created or have any sort of default endpoint settings im not using that template at the moment. With the amount of projects that my company will have using our PBX solution its too impractical to manually enter (endpoint_template) after each endpoint in pjsip.endpoint.conf or update extensions in the FreePBX gui.

So im attempting to programmatically update endpoints through the AMI

In pjsip.aor_custom.conf I have

[100]
type=aor
mailboxes=100@device

max_contacts=1
remove_existing=yes
maximum_expiration=7200
minimum_expiration=60
qualify_frequency=60

I just tried using your settings on 18.16.0 and it worked fine. Is it possible that in your original test, DstFilename had a leading or trailing space or something else that made it a different file? Have you looked in /etc/asterisk to see if a new file may have been created accidentally?

You mentioned that when you set DstFilename: pjsip.endpoint2.conf it writes pjsip.endpoint2.conf just fine. What happens if you then change SrcFilename to pjsip.endpoint2.conf? Can you read and write back to it?

@gjoseph

So i’ve got update actions working now through the AMI, but what my problem was is that i was calling FreePBX reload through their graphql API and whenever that is called… FreePBX overwrites any config files with the settings it knows.

Which was overwriting any updates to files I sent just before the reload.

So basically FreePBX gives you the ability to create endpoints but doesnt give you the ability to programatically change settings in those endpoints…
Asterisk does give you the ability to change endpoint settings but you can’t use that with FreePBX cause you work just gets overwritten

You can modify FreePBX default values with your own like for example

[defaultFreePBX]

user = friend

defaultFreePBX

user = peer

FreePBX has default endpoint settings? I had someone else say this was not possible.

Can you set these up in the GUI or through the graphql api once and then every endpoint from then on has them?

I need to either setup the defaults once then every future endpoint made needs to be through FreePBX’s graphql api programatically, it will be to impractical to manually edit any config files or go into the GUI to update any endpoints

Example I gave is for sip.conf, can be used with [extensions|sip|iax|…]_additional.conf

[original] folowed by open parenthis, plus sign, closing parenthis
value1 =
value2 =

so your valueX will replace those from FreePBX. Hope it’s more clear :wink:

Ohhh

so just reading in sip.conf theres this at the bottom:

;sip_custom_post.conf If you have extra parameters that are needed for a
;extension to work to for example, those go here. So you have extension
;1000 defined in your system you start by creating a line 1000 in this
;file. Then on the next line add the extra parameter that is needed.
;When the sip.conf is loaded it will append your additions to the end of
;that extension.
;
#include sip_custom_post.conf

so firstly i could create the extension with FreePBX graphql

Then use the AMI to put into the sip_custom_post.conf file

[$number] (+)
media_encryption=dtls
dtls_verify=fingerprint
dtls_setup=actpass
dtls_rekey=0
ice_support=yes
media_use_received_transport=yes
use_avpf=yes
rtcp_mux=yes

I hope this works thank you @tootai

https://docs.asterisk.org/Fundamentals/Asterisk-Configuration/Asterisk-Configuration-Files/Adding-to-an-existing-section/

Has information on how to use the (+) notation including special requirements for pjsip objects that may have the same name but different types. I.E. An endpoint and aor with the same name.

1 Like

And FreePBX won’t overwrite anything in the sip_custom_post.conf file?

Id also be curious to submit a pull request to FreePBX adding more query parameters into their addExtension graphql endpoint, that would be the better way to go about this entire situation