Rework SSH management

Related: PROD-12618 (PROD:12618)

Change-Id: I772b578e1189ccdc8c38e268dce3c5e865fae124
diff --git a/_modules/maasng.py b/_modules/maasng.py
index c08d5db..5189597 100644
--- a/_modules/maasng.py
+++ b/_modules/maasng.py
@@ -1115,7 +1115,8 @@
                 **data).read())
         else:
             data['vid'] = str(vlan)
-            json_res = json.loads(maas.post(u'api/2.0/fabrics/{0}/vlans/'.format(fabric_id), None, **data).read())
+            json_res = json.loads(maas.post(
+                u'api/2.0/fabrics/{0}/vlans/'.format(fabric_id), None, **data).read())
     except Exception as inst:
         LOG.debug("create_vlan_in_fabric data:{}".format(data))
         try:
@@ -1145,8 +1146,8 @@
     ret = 'not_exist'
     subnets = list_subnets(sort_by='cidr')
     if cidr in subnets.keys():
-         LOG.debug("Requested subnet cidr:{} already exist".format(cidr))
-         ret = 'update'
+        LOG.debug("Requested subnet cidr:{} already exist".format(cidr))
+        ret = 'update'
     return ret
 
 
@@ -1164,7 +1165,7 @@
 
     fabric_id = get_fabricid(fabric)
     result = {}
-    vlan=str(vlan)
+    vlan = str(vlan)
     data = {
         "cidr": cidr,
         "name": name,
@@ -1175,12 +1176,14 @@
     maas = _create_maas_client()
     # FIXME: vlan definition not work in 2.3.3-6498-ge4db91d.
     LOG.warning("Ignoring parameter vlan:{}".format(vlan))
-    data.pop('vlan','')
+    data.pop('vlan', '')
     try:
         if update:
-            json_res = json.loads(maas.put(u"api/2.0/subnets/{0}/".format(subnet_id), **data).read())
+            json_res = json.loads(
+                maas.put(u"api/2.0/subnets/{0}/".format(subnet_id), **data).read())
         else:
-            json_res = json.loads(maas.post(u"api/2.0/subnets/", None, **data).read())
+            json_res = json.loads(
+                maas.post(u"api/2.0/subnets/", None, **data).read())
     except Exception as inst:
         LOG.debug("create_subnet data:{}".format(data))
         try:
@@ -1194,7 +1197,8 @@
         return result
     LOG.debug("create_subnet:{}".format(json_res))
     result["new"] = "Subnet {0} with CIDR {1}" \
-                    "and gateway {2} was created".format(name, cidr, gateway_ip)
+                    "and gateway {2} was created".format(
+                        name, cidr, gateway_ip)
 
     return result
 
@@ -1592,7 +1596,7 @@
         :param labels:    The label lists for which to import resources.
     """
 
-    result = { "result" : True, 'name' : bs_url, 'changes' : None }
+    result = {"result": True, 'name': bs_url, 'changes': None}
 
     data = {
         "os": os,
@@ -1619,7 +1623,7 @@
     # at least simple retry ;(
     json_res = False
     poll_time = 5
-    for i in range(0,5):
+    for i in range(0, 5):
         try:
             json_res = json.loads(
                 maas.post(u'api/2.0/boot-sources/{0}/selections/'.format(bs_id), None,
@@ -1647,7 +1651,8 @@
         ret = boot_resources_import(action='import', wait=True)
         if ret is dict:
             return ret
-    result["comment"] = "boot-source selection for {0} was created".format(bs_url)
+    result["comment"] = "boot-source selection for {0} was created".format(
+        bs_url)
     result["new"] = data
 
     return result
@@ -1820,3 +1825,65 @@
     return ret
 
 # END RACK CONTROLLERS SECTION
+# SSHKEYS
+
+
+def list_sshkeys():
+    """
+    Get list of all sshkeys
+
+    CLI Example:
+
+    .. code-block:: bash
+
+        salt 'maas-node' maasng.list_sshkeys
+        salt-call maasng.list_sshkeys
+    """
+    ssh = {}
+    maas = _create_maas_client()
+    json_res = json.loads(maas.get(u'api/2.0/account/prefs/sshkeys/').read())
+    LOG.info(json_res)
+    for item in json_res:
+        ssh[item["key"]] = item
+    return ssh
+
+
+def add_sshkey(sshkey):
+    """
+    Add SSH key for user to MAAS.
+
+    CLI Example:
+
+    .. code-block:: bash
+
+        salt 'maas-node' maasng.add_sshkey sshkey
+        salt-call maasng.add_sshkey sshkey
+    """
+    data = {
+        "key": sshkey,
+    }
+    result = {}
+    maas = _create_maas_client()
+
+    maas.post(u"/api/2.0/account/prefs/sshkeys/", None, **data).read()
+    result["new"] = "SSH Key {0} was added.".format(sshkey)
+
+    return result
+
+
+def get_sshkey(sshkey):
+    """
+    Get start ip for ip range
+
+    CLI Example:
+
+    .. code-block:: bash
+
+        salt 'maas-node' maasng.get_sshkey sshkey
+        salt-call maasng.get_sshkey sshkey
+    """
+    try:
+        return list_sshkeys()[sshkey]
+    except KeyError:
+        return {"error": "SSH key not found on MaaS server"}
+# END SSHKEYS
diff --git a/_states/maasng.py b/_states/maasng.py
index b71c9d9..0275465 100644
--- a/_states/maasng.py
+++ b/_states/maasng.py
@@ -352,7 +352,8 @@
 
     if __opts__['test']:
         ret['result'] = None
-        ret['comment'] = 'Vlan {0} will be updated for {1}'.format(vlan, fabric)
+        ret['comment'] = 'Vlan {0} will be updated for {1}'.format(
+            vlan, fabric)
         return ret
     # Check, that vlan  already defined
     _rez = __salt__['maasng.check_vlan_in_fabric'](fabric=fabric,
@@ -498,7 +499,7 @@
 
     changes = __salt__['maasng.create_iprange'](type_range=type_range,
                                                 start_ip=start_ip,
-                                                end_ip=end_ip,subnet=subnet, comment=comment)
+                                                end_ip=end_ip, subnet=subnet, comment=comment)
     ret["changes"] = changes
     if "error" in changes:
         ret['comment'] = "State execution failed for iprange {0}".format(name)
@@ -599,3 +600,47 @@
         return ret
 
     return ret
+
+
+def sshkey_present(name, sshkey):
+    """
+
+    :param name: Name of user
+    :param sshkey: SSH key for MAAS user
+
+    """
+
+    ret = {'name': name,
+           'changes': {},
+           'result': True,
+           'comment': 'Module function maasng.ssshkey_present executed'}
+
+    # Check, that subnet already defined
+    _rez = __salt__['maasng.get_sshkey'](sshkey)
+    if 'key' in _rez.keys():
+        if _rez["key"] == sshkey:
+            ret['comment'] = 'SSH key {0} already exist for user {1}.'.format(
+                sshkey, name)
+            return ret
+
+    if __opts__['test']:
+        ret['result'] = None
+        ret['comment'] = 'SSH  key {0} will be add it to MAAS for user {1}'.format(
+            sshkey, name)
+
+        return ret
+
+    changes = __salt__['maasng.add_sshkey'](sshkey=sshkey)
+    ret['comment'] = 'SSH-key {0} ' \
+        'has been added for user {1}'.format(sshkey, name)
+
+    ret['changes'] = changes
+
+    if "error" in changes:
+        ret['comment'] = "State execution failed for sshkey: {0}".format(
+            sshkey)
+        ret['result'] = False
+        ret['changes'] = changes
+        return ret
+
+    return ret
diff --git a/maas/region.sls b/maas/region.sls
index 684fda4..1226b5d 100644
--- a/maas/region.sls
+++ b/maas/region.sls
@@ -411,13 +411,16 @@
 #  - onlyif: /bin/false
 #  {%- endif %}
 
-
 {%- if region.get('sshprefs', False)  %}
-maas_sshprefs:
-  module.run:
-  - name: maas.process_sshprefs
+{%- for sshkey in region.sshprefs %}
+{%- set idx = loop.index %}
+maas_sshkey_{{ idx }}:
+  maasng.sshkey_present:
+  - name: {{ region.admin.username }}
+  - sshkey: {{ sshkey }}
   - require:
     - cmd: maas_login_admin
+{% endfor %}
 {%- endif %}
 
 {%- endif %}