Skip to content

Commit

Permalink
ns-api: add ns.migration
Browse files Browse the repository at this point in the history
  • Loading branch information
gsanchietti committed Nov 2, 2023
1 parent fd21977 commit 172b921
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 0 deletions.
2 changes: 2 additions & 0 deletions packages/ns-api/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ define Package/ns-api/install
$(INSTALL_DATA) ./files/ns.account.json $(1)/usr/share/rpcd/acl.d/
$(INSTALL_BIN) ./files/ns.backup $(1)/usr/libexec/rpcd/
$(INSTALL_DATA) ./files/ns.backup.json $(1)/usr/share/rpcd/acl.d/
$(INSTALL_BIN) ./files/ns.migration $(1)/usr/libexec/rpcd/
$(INSTALL_DATA) ./files/ns.migration.json $(1)/usr/share/rpcd/acl.d/
$(INSTALL_DIR) $(1)/lib/upgrade/keep.d
$(INSTALL_CONF) files/msmtp.keep $(1)/lib/upgrade/keep.d/msmtp
$(LN) /usr/bin/msmtp $(1)/usr/sbin/sendmail
Expand Down
68 changes: 68 additions & 0 deletions packages/ns-api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2651,3 +2651,71 @@ Example response:
}
}
```

## ns.migration

Manage migration from NS7

### list-devices

List existing devices:
```
api-clit ns.migration list-devices
```

Response example:
```json
{
"devices": [
{
"name": "eth0",
"hwaddr": "52:54:00:6a:50:bf"
},
{
"name": "eth1",
"hwaddr": "52:54:00:20:82:a6"
}
]
}
```

### upload

Upload a NS7 migration archive:
```
api-cli ns.migration upload --data '{"archive": "H4sIAAAAAAAAA+w9a3PbNr..."}'
```

This API can return a validation error if the given file is not a valid NS7 migration export archive.

Response example:
```json
{
"devices": [
{
"name": "enp1s0",
"hwaddr": "xx:yy:xx",
"ipaddr": "1.2.3.4",
"role": "green"
},
{
"name": "en1",
"hwaddr": "xx:zz:zz",
"ipaddr": "4.5.6.7",
"role": "red"
}
]
}
```

### migrate

Execute the migration:
```
api-cli ns.migration migrate
```

Response example:
```json
{"result": "success"}
```
93 changes: 93 additions & 0 deletions packages/ns-api/files/ns.migration
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#!/usr/bin/python3

#
# Copyright (C) 2023 Nethesis S.r.l.
# SPDX-License-Identifier: GPL-2.0-only
#

import base64
import json
import os
import shutil
import subprocess
import sys

from nethsec import utils

MIGRATE_DIR= '/tmp/migrate/'
MIGRATE_PATH = '/tmp/migrate/migration.tar.gz'


def restore_backup(passphrase=None):
try:
if passphrase is not None:
subprocess.run([
'/usr/bin/gpg',
'--decrypt',
'--batch',
'--passphrase', passphrase,
'--output', f'{BACKUP_PATH}.decrypted',
'--yes',
BACKUP_PATH
], check=True, capture_output=True)
shutil.move(f'{BACKUP_PATH}.decrypted', BACKUP_PATH)

# run sysupgrade to restore backup file
subprocess.run(['/sbin/sysupgrade', '-r', BACKUP_PATH], check=True, capture_output=True)

except subprocess.CalledProcessError as error:
if error.cmd[0] == '/usr/bin/gpg':
raise RuntimeError('decryption failed')
elif error.cmd[0] == '/sbin/sysupgrade':
raise RuntimeError('restore failed')


cmd = sys.argv[1]

if cmd == 'list':
print(json.dumps({
'upload': {
'archive': 'str',
},
'list-devices': {},
'migrate': { }
}))
elif cmd == 'call':
action = sys.argv[2]
if action == 'migrate':
try:
#FIXME: add -moldmac=newmac
#subprocess.run(['/usr/sbin/ns-import', MIGRATE_PATH], check=True, capture_output=True)
# return content
print(json.dumps({'result': 'success'}))
except RuntimeError as error:
print(json.dumps(utils.generic_error(error.args[0])))

elif action == 'upload':
try:
# decode input, write backup in default path
data = json.load(sys.stdin)
os.makedirs(MIGRATE_DIR, exist_ok=True)
# open(MIGRATION_PATH, 'wb').write(base64.b64decode(data['archive']))
# reboot takes a few seconds to complete, enough to send the response
print(json.dumps({'devices': [
{"name": "enp1s0", "hwaddr": "xx:yy:xx", "ipaddr": "1.2.3.4", "role": "green"},
{"name": "en1", "hwaddr": "xx:zz:zz", "ipaddr": "4.5.6.7", "role": "red"}
]}))
except RuntimeError as error:
print(json.dumps(utils.generic_error(error.args[0])))

elif action == 'list-devices':
ret = []
try:
data = json.loads(subprocess.run(["/sbin/ip", "--json", "link"], check=True, capture_output=True, text=True).stdout)
for i in data:
if i['ifname'] == "lo" or i['ifname'].startswith('br-') or i['ifname'].startswith('tun-') or i['ifname'].startswith('ifb-'):
continue
ret.append({'name': i['ifname'], 'hwaddr': i['address']})

print(json.dumps({'devices': ret}))
except KeyError as error:
print(error)
print(json.dumps(utils.validation_error('passphrase', 'required')))

13 changes: 13 additions & 0 deletions packages/ns-api/files/ns.migration.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"migration-manager": {
"description": "Manages migration",
"write": {},
"read": {
"ubus": {
"ns.migration": [
"*"
]
}
}
}
}

0 comments on commit 172b921

Please sign in to comment.