Change the copyright from GPL-3 to Apache-2.0
[osm/devops.git] / builds / vpe-router / lib / charms / router.py
1
2 import paramiko
3 import subprocess
4
5 from charmhelpers.core.hookenv import config
6
7
8 class NetNS(object):
9 def __init__(self, name):
10 pass
11
12 @classmethod
13 def create(cls, name):
14 # @TODO: Need to check if namespace exists already
15 try:
16 ip('netns', 'add', name)
17 except Exception as e:
18 raise Exception('could not create net namespace: %s' % e)
19
20 return cls(name)
21
22 def up(self, iface, cidr):
23 self.do('ip', 'link', 'set', 'dev', iface, 'up')
24 self.do('ip', 'address', 'add', cidr, 'dev', iface)
25
26 def add_iface(self, iface):
27 ip('link', 'set', 'dev', iface, 'netns', self.name)
28
29 def do(self, *cmd):
30 ip(*['netns', 'exec', self.name] + cmd)
31
32
33 def ip(*args):
34 return _run(['ip'] + list(args))
35
36
37 def _run(cmd, env=None):
38 if isinstance(cmd, str):
39 cmd = cmd.split() if ' ' in cmd else [cmd]
40
41 cfg = config()
42 if all(k in cfg for k in ['pass', 'vpe-router', 'user']):
43 router = cfg['vpe-router']
44 user = cfg['user']
45 passwd = cfg['pass']
46
47 if router and user and passwd:
48 return ssh(cmd, router, user, passwd)
49
50 p = subprocess.Popen(cmd,
51 env=env,
52 stdout=subprocess.PIPE,
53 stderr=subprocess.PIPE)
54 stdout, stderr = p.communicate()
55 retcode = p.poll()
56 if retcode > 0:
57 raise subprocess.CalledProcessError(returncode=retcode,
58 cmd=cmd,
59 output=stderr.decode("utf-8").strip())
60 return (''.join(stdout), ''.join(stderr))
61
62
63 def ssh(cmd, host, user, password=None):
64 ''' Suddenly this project needs to SSH to something. So we replicate what
65 _run was doing with subprocess using the Paramiko library. This is
66 temporary until this charm /is/ the VPE Router '''
67
68 cmds = ' '.join(cmd)
69 client = paramiko.SSHClient()
70 client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
71 client.connect(host, port=22, username=user, password=password)
72
73 stdin, stdout, stderr = client.exec_command(cmds)
74 retcode = stdout.channel.recv_exit_status()
75 client.close() # @TODO re-use connections
76 if retcode > 0:
77 output = stderr.read().strip()
78 raise subprocess.CalledProcessError(returncode=retcode, cmd=cmd,
79 output=output)
80 return (''.join(stdout), ''.join(stderr))