New version of salt-formula from Saltstack
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

248 行
6.5KB

  1. from __future__ import absolute_import
  2. # Let's not allow PyLint complain about string substitution
  3. # pylint: disable=W1321,E1321
  4. # Import python libs
  5. import logging
  6. # Import Salt libs
  7. import salt.returners
  8. # Import third party libs
  9. try:
  10. import psycopg2
  11. import psycopg2.extras
  12. HAS_POSTGRES = True
  13. except ImportError:
  14. HAS_POSTGRES = False
  15. __virtualname__ = 'saltresource'
  16. LOG = logging.getLogger(__name__)
  17. def __virtual__():
  18. if not HAS_POSTGRES:
  19. return False, 'Could not import saltresource module; psycopg2 is not installed.'
  20. return __virtualname__
  21. def _get_options(ret=None):
  22. '''
  23. Get the postgres options from salt.
  24. '''
  25. defaults = {'host': '127.0.0.1',
  26. 'user': 'salt',
  27. 'passwd': 'salt',
  28. 'db': 'salt',
  29. 'port': '5432'}
  30. _options = {}
  31. for key, default in defaults.items():
  32. _options[key] = __salt__['config.get']('%s.%s' % (__virtualname__, key), default)
  33. return _options
  34. def _get_conn(ret=None):
  35. '''
  36. Return a postgres connection.
  37. '''
  38. _options = _get_options(ret)
  39. host = _options.get('host')
  40. user = _options.get('user')
  41. passwd = _options.get('passwd')
  42. datab = _options.get('db')
  43. port = _options.get('port')
  44. return psycopg2.connect(
  45. host=host,
  46. user=user,
  47. password=passwd,
  48. database=datab,
  49. port=port)
  50. def _close_conn(conn):
  51. '''
  52. Close the Postgres connection
  53. '''
  54. conn.commit()
  55. conn.close()
  56. def graph_data(*args, **kwargs):
  57. '''
  58. Returns graph data for visualization app
  59. CLI Examples:
  60. .. code-block:: bash
  61. salt '*' saltresource.graph_data
  62. '''
  63. conn = _get_conn()
  64. cur_dict = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
  65. cur_dict.execute('SELECT host, service, status FROM salt_resources')
  66. resources_db = [dict(res) for res in cur_dict]
  67. db_dict = {}
  68. for resource in resources_db:
  69. host = resource.get('host')
  70. service = '.'.join(resource.get('service').split('.')[:2])
  71. status = resource.get('status')
  72. if db_dict.get(host, None):
  73. if db_dict[host].get(service, None):
  74. service_data = db_dict[host][service]
  75. service_data.append(status)
  76. else:
  77. db_dict[host][service] = [status]
  78. else:
  79. db_dict[host] = {service: []}
  80. graph = []
  81. for host, services in db_dict.items():
  82. for service, statuses in services.items():
  83. status = 'unknown'
  84. if 'failed' in statuses:
  85. status = 'failed'
  86. elif 'success' in statuses and not ('failed' in statuses or 'unknown' in statuses):
  87. status = 'success'
  88. datum = {'host': host, 'service': service, 'status': status}
  89. graph.append(datum)
  90. _close_conn(conn)
  91. return {'graph': graph}
  92. def host_data(host, **kwargs):
  93. '''
  94. Returns data describing single host
  95. CLI Examples:
  96. .. code-block:: bash
  97. salt-call saltresource.host_data '<minion_id>'
  98. '''
  99. conn = _get_conn()
  100. cur_dict = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
  101. sql = 'SELECT host, service, resource_id, last_ret, status FROM salt_resources WHERE host=%s'
  102. cur_dict.execute(sql, (host,))
  103. resources_db = [dict(res) for res in cur_dict]
  104. db_dict = {}
  105. for resource in resources_db:
  106. host = resource.get('host')
  107. service = '.'.join(resource.get('service').split('.')[:2])
  108. status = resource.get('status')
  109. if db_dict.get(host, None):
  110. if db_dict[host].get(service, None):
  111. service_data = db_dict[host][service]
  112. service_data.append(status)
  113. else:
  114. db_dict[host][service] = [status]
  115. else:
  116. db_dict[host] = {service: []}
  117. graph = []
  118. for host, services in db_dict.items():
  119. for service, statuses in services.items():
  120. status = 'unknown'
  121. if 'failed' in statuses:
  122. status = 'failed'
  123. elif 'success' in statuses and not ('failed' in statuses or 'unknown' in statuses):
  124. status = 'success'
  125. resources = [{'service': r.get('service', ''), 'resource_id': r.get('resource_id', ''), 'last_ret': r.get('last_ret', None), 'status': r.get('status', '')}
  126. for r
  127. in resources_db
  128. if r.get('service', '').startswith(service)]
  129. datum = {'host': host, 'service': service, 'status': status, 'resources': resources}
  130. graph.append(datum)
  131. _close_conn(conn)
  132. return {'graph': graph}
  133. def sync_db(*args, **kwargs):
  134. conn = _get_conn()
  135. cur = conn.cursor()
  136. resources_sql = '''
  137. CREATE TABLE IF NOT EXISTS salt_resources (
  138. id varchar(255) NOT NULL UNIQUE,
  139. resource_id varchar(255) NOT NULL,
  140. host varchar(255) NOT NULL,
  141. service varchar(255) NOT NULL,
  142. module varchar(50) NOT NULL,
  143. fun varchar(50) NOT NULL,
  144. status varchar(50) NOT NULL,
  145. options json NULL,
  146. last_ret text NULL,
  147. alter_time TIMESTAMP WITH TIME ZONE DEFAULT now()
  148. );
  149. '''
  150. cur.execute(resources_sql)
  151. conn.commit()
  152. resources_meta_sql = '''
  153. CREATE TABLE IF NOT EXISTS salt_resources_meta (
  154. id varchar(255) NOT NULL UNIQUE,
  155. options json NULL,
  156. alter_time TIMESTAMP WITH TIME ZONE DEFAULT now()
  157. );
  158. '''
  159. cur.execute(resources_meta_sql)
  160. _close_conn(conn)
  161. return True
  162. def flush_db(*args, **kwargs):
  163. conn = _get_conn()
  164. cur = conn.cursor()
  165. result = True
  166. resources_sql = 'DELETE FROM salt_resources'
  167. try:
  168. cur.execute(resources_sql)
  169. conn.commit()
  170. except Exception as e:
  171. LOG.warning(repr(e))
  172. result = False
  173. resources_meta_sql = 'DELETE FROM salt_resources_meta'
  174. try:
  175. cur.execute(resources_meta_sql)
  176. _close_conn(conn)
  177. except Exception as e:
  178. LOG.warning(repr(e))
  179. result = False
  180. return result
  181. def destroy_db(*args, **kwargs):
  182. conn = _get_conn()
  183. cur = conn.cursor()
  184. resources_sql = 'DROP TABLE IF EXISTS salt_resources;'
  185. cur.execute(resources_sql)
  186. conn.commit()
  187. resources_meta_sql = 'DROP TABLE IF EXISTS salt_resources_meta;'
  188. cur.execute(resources_meta_sql)
  189. _close_conn(conn)
  190. return True