# 1.2+ Config export, backup and rollback

**URL:** <https://forum.genieacs.com/t/1-2-config-export-backup-and-rollback/722>\
**Category:** Uncategorized\
**Created:** [April 21, 2020, 8:21am UTC](https://forum.genieacs.com/t/1-2-config-export-backup-and-rollback/722 "2020-04-21T08:21:29Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![KGcasa](https://avatars.discourse-cdn.com/v4/letter/k/f4b2a3/32.png) [@KGcasa](https://forum.genieacs.com/u/KGcasa)\
**Post date:** [April 21, 2020, 8:21am UTC](https://forum.genieacs.com/t/1-2-config-export-backup-and-rollback/722/1 "2020-04-21T08:21:29Z")

</div>

Is there a way to rollback the config that is entered via the Admin | Config page to a known good config, or at least the previous config?

Surely there should be a way to checkpoint the config and perform a rollback ?

At the very least how about providing a way to export the config to a text file as a form of backup that can then be imported to restore the config to its previous state?

---

<div class="post-metadata">

**Author:** ![gunter](https://avatars.discourse-cdn.com/v4/letter/g/e480ec/32.png) [@gunter](https://forum.genieacs.com/u/gunter)\
**Post date:** [April 25, 2020, 7:48pm UTC](https://forum.genieacs.com/t/1-2-config-export-backup-and-rollback/722/2 "2020-04-25T19:48:43Z")

</div>

There isn’t a built-in export/import function but the API exposes everything you need to do this. This is what I wrote to manage my configs from dev to production with git being used for version control. Just be careful if you’re using this to sync systems. If you’ve deleted a parameter it will still exist on the destination server and needs to be manually removed.

```
#!/bin/python
# export/import genieACS 1.2 configuration files using the UI API
# PGunter 20200122

import requests, json, os, getopt, sys, re

# Globals
apiURL = "http://localhost:3000/"
baseDIR = "/opt/genieacs/local/configs"

# List of configuration sections to operate on
configs = ["config","permissions","presets","provisions","users","variables","virtualParameters"]

def exportConfigs(webSession):
   for config in configs:
      # Create directories to save configuration files if they don't exist
      path = baseDIR + "/" + config
      if not os.path.exists(path):
         os.makedirs(path)

      URL = apiURL + "api/" + config + "/"
      # Download complete config
      request = webSession.get(URL)
      data = json.loads(request.content)
      for item in data:
         # Save each config item into a seperate file
         name = item["_id"]
         file = path + "/" + name + ".json"
         # JSON dump to disk
         with open(file, 'w') as json_file:
            json.dump(item, json_file)

def importConfigs(webSession):
   for config in configs:
      path = baseDIR + "/" + config
      for filename in os.listdir(path):
         # Walk the configuration directories looking for JSON files
         if filename.endswith(".json"):
            file = path + "/" + filename
            with open(file, "r") as json_file:
               conf = json.load(json_file)
            # Extract _id from the JSON file
            id = conf['_id']
            # Remove _id from the JSON object. Required by GenieACS API
            del conf['_id']
            # Build URL e.g. http://localhost:3000/api/presets/inform
            URL = apiURL + "api/" + config + "/" + id
            # Upload JSON file
            request = webSession.put(URL, json = conf)
            if str(request.status_code) != "200":
               # Display error if we don't receive a 200 OK response
               print str(request.status_code) + ": Failed to upload " + file

def usage():
   print "usage: configMgr [--password <password>] --import | --export"
   print "Options:"
   print "-e, --export Save configruation files to /opt/genieacs/local/configs"
   print "-i, --import Load configruation files from /opt/genieacs/local/configs"
   print "-p, --password admin password for the GenieACS UI"
   print   

def main():
   # variables
   if len(sys.argv) <= 1:
      usage()
      sys.exit(1)
   try:
      opts, args = getopt.getopt(sys.argv[1:], "heip:", ["help", "export", "import", "password="])
   except getopt.GetoptError as err:
      # print help information and exit:
      print str(err)
      usage()
      sys.exit(2)
   apiPassword = "admin"
   apiAction = ""
   for o, a in opts:
      if o in ("-h", "--help"):
         usage()
         sys.exit()
      if o in ("-p", "--password"):
         apiPassword = a
      if o in ("-e", "--export"):
         apiAction = "export"
      if o in ("-i", "--import"):
         apiAction = "import"

   # Check which action to run
   if apiAction in ["export", "import"]:
      # Login to GenieACS UI and save session
      apiSession = requests.Session()
      URL = apiURL + "login"
      request = apiSession.post(URL, json={"username": "admin", "password": apiPassword})
      # Check request successful
      if str(request.status_code) != "200":
         # Display error if we don't receive a 200 OK response
         print ("Unable to login to GenieACS. Error %d: %s"% (request.status_code, request.text))
         sys.exit(2)

      # Which action
      if apiAction == "export":
         print "Exporting GenieACS configuration"
         exportConfigs(apiSession)
      elif apiAction == "import":
         print "Importing GenieACS configuration"
         importConfigs(apiSession)

   else:
        print "Unknown action"
        usage()

if __name__ == " __main__":
   main()
```

---

<div class="post-metadata">

**Author:** ![KGcasa](https://avatars.discourse-cdn.com/v4/letter/k/f4b2a3/32.png) [@KGcasa](https://forum.genieacs.com/u/KGcasa)\
**Post date:** [April 25, 2020, 11:43pm UTC](https://forum.genieacs.com/t/1-2-config-export-backup-and-rollback/722/3 "2020-04-25T23:43:00Z")

</div>

Thank you, that is very helpful, I will give it a try.

Is this portable across python 2.7 and 3.x ?

---

<div class="post-metadata">

**Author:** ![gunter](https://avatars.discourse-cdn.com/v4/letter/g/e480ec/32.png) [@gunter](https://forum.genieacs.com/u/gunter)\
**Post date:** [April 26, 2020, 1:56am UTC](https://forum.genieacs.com/t/1-2-config-export-backup-and-rollback/722/4 "2020-04-26T01:56:09Z")

</div>

I’m using RHEL7 boxes for GenieACS so I’ve only been using this with python 2.7.  
That said I’ve just tested against python 3.6 and the only issue that I found was the print statements needed to be put in brackets  
eg  
\< print(str(request.status\_code) + ": Failed to upload " + file)  
—  
\> print str(request.status\_code) + ": Failed to upload " + file

---

<div class="post-metadata">

**Author:** ![KGcasa](https://avatars.discourse-cdn.com/v4/letter/k/f4b2a3/32.png) [@KGcasa](https://forum.genieacs.com/u/KGcasa)\
**Post date:** [April 26, 2020, 11:15pm UTC](https://forum.genieacs.com/t/1-2-config-export-backup-and-rollback/722/5 "2020-04-26T23:15:00Z")

</div>

Thank you.

My current test platform has python 2.7.

I get the following error.

 ![image](https://canada1.discourse-cdn.com/flex035/uploads/genieacs/original/1X/4baf912dbe58c94bb53d29f6ca17e0b4d14a7174.jpeg)

---

<div class="post-metadata">

**Author:** ![gunter](https://avatars.discourse-cdn.com/v4/letter/g/e480ec/32.png) [@gunter](https://forum.genieacs.com/u/gunter)\
**Post date:** [April 27, 2020, 10:50pm UTC](https://forum.genieacs.com/t/1-2-config-export-backup-and-rollback/722/6 "2020-04-27T22:50:56Z")

</div>

Are you sure the GenieACS UI is running? Are you running the script on the GenieACS server? Look at the last line on your screen grab. Connection refused…

---

<div class="post-metadata">

**Author:** ![KGcasa](https://avatars.discourse-cdn.com/v4/letter/k/f4b2a3/32.png) [@KGcasa](https://forum.genieacs.com/u/KGcasa)\
**Post date:** [April 27, 2020, 11:44pm UTC](https://forum.genieacs.com/t/1-2-config-export-backup-and-rollback/722/7 "2020-04-27T23:44:14Z")

</div>

Thank you.

Yes, the UI is running. The problem seems to be related to the container plumbing.

I made this change to the script:

> ##apiURL = “[http://localhost:3000/](http://localhost:3000/)”  
> apiURL = “[http://192.16.90.160:3000/](http://192.16.90.160:3000/)”

Now I don’t get the connection error, but it fails with “[Errno 110] Connection timeout” instead of “[Errno 111] Connection refused”.

I am seeking help from the docker experts in my team.

---

<div class="post-metadata">

**Author:** ![KGcasa](https://avatars.discourse-cdn.com/v4/letter/k/f4b2a3/32.png) [@KGcasa](https://forum.genieacs.com/u/KGcasa)\
**Post date:** [April 28, 2020, 7:33am UTC](https://forum.genieacs.com/t/1-2-config-export-backup-and-rollback/722/8 "2020-04-28T07:33:01Z")

</div>

OK, several problems sorted out to get the script running (see below) but now the usage is not quite as expected.

The ‘import’ action effectively merges the config with whatever is already present instead of replacing it.  
Is this your intention?

In my case I am aiming for the ‘import’ action to completely replace the config on the target system.

Fixes for my context:

1. Helps to use the correct IP address, I had a typo in the hard-coded address

2. The list of Mongo tables included ‘variables’ and this would crash with a permissions problem, removing it solved the problem.

3. Hard-coded directory path required sudo permissions to create. Created and modified the permissions from comamnd-line with sudo.

With these changes the script runs. I am uncertain of the implications of not including the ‘variables’ table. Any thoughts?

---

<div class="post-metadata">

**Author:** ![BoroKosa](https://yyz1.discourse-cdn.com/flex035/user_avatar/forum.genieacs.com/borokosa/32/1544_2.png) [@BoroKosa](https://forum.genieacs.com/u/BoroKosa)\
**Post date:** [September 28, 2023, 3:30pm UTC](https://forum.genieacs.com/t/1-2-config-export-backup-and-rollback/722/9 "2023-09-28T15:30:19Z")

</div>

I think the best way to backup configurations and scripts is with Mongodump utility. For example:  
mongodump --db=genieacs --collection=config --gzip  
backups all your config. It can be easily restored with:  
mongorestore --drop --gzip /root/dump/genieacs/config.bson.gz

This backup can be done also for presets, provisions, users, virtualParameters

---

<div class="post-metadata">

**Author:** ![Felipe](https://yyz1.discourse-cdn.com/flex035/user_avatar/forum.genieacs.com/felipe/32/1949_2.png) [@Felipe](https://forum.genieacs.com/u/Felipe)\
**Post date:** [September 29, 2023, 11:14am UTC](https://forum.genieacs.com/t/1-2-config-export-backup-and-rollback/722/10 "2023-09-29T11:14:14Z")

</div>

mongodump restore passwords too?

---

<div class="post-metadata">

**Author:** ![akcoder](https://yyz1.discourse-cdn.com/flex035/user_avatar/forum.genieacs.com/akcoder/32/11_2.png) [@akcoder](https://forum.genieacs.com/u/akcoder)\
**Post date:** [September 29, 2023, 5:59pm UTC](https://forum.genieacs.com/t/1-2-config-export-backup-and-rollback/722/11 "2023-09-29T17:59:47Z")

</div>

Which passwords? The passwords created for users of GenieACS? Yes, those are included in the backup. Plaintext passwords for users are not stored in GenieACS, they are hashed.

---

<div class="post-metadata">

**Author:** ![Felipe](https://yyz1.discourse-cdn.com/flex035/user_avatar/forum.genieacs.com/felipe/32/1949_2.png) [@Felipe](https://forum.genieacs.com/u/Felipe)\
**Post date:** [September 29, 2023, 7:57pm UTC](https://forum.genieacs.com/t/1-2-config-export-backup-and-rollback/722/12 "2023-09-29T19:57:48Z")

</div>

I mean passwords that were setted in any parameter, like SSID, PPPoE, etc…

If I did a mongodump and after restore, the passwords will be there? It works?

---

<div class="post-metadata">

**Author:** ![akcoder](https://yyz1.discourse-cdn.com/flex035/user_avatar/forum.genieacs.com/akcoder/32/11_2.png) [@akcoder](https://forum.genieacs.com/u/akcoder)\
**Post date:** [September 29, 2023, 8:48pm UTC](https://forum.genieacs.com/t/1-2-config-export-backup-and-rollback/722/13 "2023-09-29T20:48:52Z")

</div>

Yes
