54ff7fb67d8ddd203882e4fa149ba5be438a2f3b
[osm/riftware.git] /
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))