clustercfg: extract cfssl handling to separate function
diff --git a/cluster/clustercfg/ca.py b/cluster/clustercfg/ca.py
index e4973db..06f03f3 100644
--- a/cluster/clustercfg/ca.py
+++ b/cluster/clustercfg/ca.py
@@ -1,3 +1,4 @@
+# encoding: utf-8
 import json
 import logging
 import os
@@ -89,6 +90,22 @@
         with open(self._cert) as f:
             return f.read()
 
+    def _cfssl_call(self, args, obj=None, stdin=None):
+        p = subprocess.Popen(['cfssl'] + args,
+                             stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+                             stderr=subprocess.PIPE)
+        if obj:
+            stdin = json.dumps(stdin)
+
+        outs, errs = p.communicate(stdin.encode())
+        if p.returncode != 0:
+            raise Exception(
+                'cfssl failed. stderr: %r, stdout: %r, code: %r' % (
+                    errs, outs, p.returncode))
+
+        out = json.loads(outs)
+        return out
+
     def _init_ca(self):
         if self.ss.exists(self._secret_key):
             return
@@ -97,11 +114,7 @@
         ca_csr['CN'] = self.cn
 
         logger.info("{}: Generating CA...".format(self))
-        p = subprocess.Popen(['cfssl', 'gencert', '-initca', '-'],
-                             stdin=subprocess.PIPE, stdout=subprocess.PIPE,
-                             stderr=subprocess.PIPE)
-        outs, errs = p.communicate(json.dumps(ca_csr).encode())
-        out = json.loads(outs)
+        out = self._cfssl_call(['gencert', '-initca', '-'], obj=ca_csr)
 
         f = self.ss.open(self._secret_key, 'w')
         f.write(out['key'])
@@ -132,11 +145,8 @@
         }
         cfg.update(_ca_config)
         logger.info("{}: Generating key/CSR for {}".format(self, hosts))
-        p = subprocess.Popen(['cfssl', 'genkey', '-'],
-                             stdin=subprocess.PIPE, stdout=subprocess.PIPE,
-                             stderr=subprocess.PIPE)
-        outs, errs = p.communicate(json.dumps(cfg).encode())
-        out = json.loads(outs)
+        out = self._cfssl_call(['genkey', '-'], obj=cfg)
+
         key, csr = out['key'], out['csr']
         if save is not None:
             logging.info("{}: Saving new key to secret {}".format(self, save))
@@ -150,12 +160,8 @@
         logging.info("{}: Signing CSR".format(self))
         ca = self._cert
         cakey = self.ss.plaintext(self._secret_key)
-        p = subprocess.Popen(['cfssl', 'sign', '-ca=' + ca, '-ca-key=' + cakey,
-                              '-profile=client-server', '-'],
-                             stdin=subprocess.PIPE, stdout=subprocess.PIPE,
-                             stderr=subprocess.PIPE)
-        outs, errs = p.communicate(csr.encode())
-        out = json.loads(outs)
+        out = self._cfssl_call(['sign', '-ca=' + ca, '-ca-key=' + cakey,
+                                '-profile=client-server', '-'], stdin=csr)
         cert = out['cert']
         if save is not None:
             name = os.path.join(self.cdir, save)