You are making this to hard on yourself :). Don't manage port mapping
instances, manage the desired state.


//Staticly define the data for demonstration purposes. In production, I
fetch the data from another server.
let portForwards = [{"InternalClient":"192.168.1.
113","PortMappingDescription":" to 9308

let basePath = "InternetGatewayDevice.WANDevice.*.WANConnectionDevice.1.WAN
declare(basePath + ".[]", null, {path: 0}); // Tell Genie we want to delete
everything, this won't actually happen unless the instances don't match up
(i.e. an instance was deleted)

for (let forward of portForwards) {
    const path = basePath + '.[' + Object.keys(forward).map(function (key)
{ return key + ':' + forward[key]; }).join(',') + ']';

    log("\r\n\r\nPortForwards - Updating - " + path + "\r\n\r\n", forward);

    for (let key of Object.keys(forward)) {
        declare(path, {path: 1}, {path: 1});

What will happen here is on the first run of this script, the port mapping
will be created. On subsequent runs, in Genie's internal state it will
first delete all object instances, but then see that the desired state at
the end is to have a single port mapping, with a name of "
 to 9308 (UDP)", protocol of UDP, etc. And so no change will be made.

If on subsequent runs, you change any of the parameters, the previous
instance will be deleted, and a new instance will be created with the given

Make sense?


On Fri, Apr 13, 2018 at 5:33 AM, George Chelidze <> wrote:

> Hi,
> As you know PortMapping object's location depends on instances for
> WANDevice, WANConnectionDevice and WANIPConnection nodes. So in general
> it's:
> InternetGatewayDevice.WANDevice.{i}.WANConnectionDevice.{i}.
> WANIPConnection.{i}.PortMapping
> In practice, it can be as simple as
> InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.
> WANIPConnection.1.PortMapping,
> or with the same success, it can be
> InternetGatewayDevice.WANDevice.5.WANConnectionDevice.1.
> WANIPConnection.3.PortMapping
> depending on vendor's implementation. You never know what instances are
> used, when do they change (if ever), so you have to query a device.
> To be able to manage this table through API, you have to:
> A) Find actual instances used. For this, I use the following preset
> called WANIPConnectionPortMapping:
> let wanIPConnectionPortMapping =
> "InternetGatewayDevice.WANDevice.1.WANConnectionDevice.1.
> WANIPConnection.1.PortMapping";
> let portMappings =
> declare("InternetGatewayDevice.WANDevice.*.WANConnectionDevice.*.
> WANIPConnection.*.PortMapping",
> {path:});
> if (portMappings.size) {
>   for (let portMapping of portMappings) {
>     wanIPConnectionPortMapping = portMapping.path;
>     break;
>   }
> }
> return {writable: false, value: [wanIPConnectionPortMapping,
> "xsd:string"]};
> As a result, I can read VirtualParameters.WANIPConnectionPortMapping,
> which contains the actual path (the first one) currently used, and use
> it for further API calls.
> B) If it's possible to create a VirtualParameter which contains a
> writable table, it will be possible to perform whatever operations is
> required directly on this parameter (table) without taking care about
> instances used, which will simplify the whole process. Another benefit
> would be to use this parameter in summary_parameters.yml to display the
> table (as far as I understand it's not possible to use any kind of
> wildcards/regexp in summary_parameters.yml).
> So to summarize, my question is regarding second approach (B): Is it
> possible to create a writable virtual parameter which contains a table
> (not a primitive like xsd:string, xsd:unsignedInt, etc). If yes, a
> simple example would be great. If not, we have a workaround as described
> in point A, however it's not clear how to describe this table in
> summary_parameters.yml. Any suggestions?
> Regards,
> George Chelidze
> _______________________________________________
> Users mailing list
Users mailing list

Reply via email to