Commit 62addd15 authored by Spiros Koulouzis's avatar Spiros Koulouzis

fixed hyperleger inventory

parent 11370fde
...@@ -84,13 +84,13 @@ def handle_delivery(message): ...@@ -84,13 +84,13 @@ def handle_delivery(message):
tosca_helper = ToscaHelper(sure_tosca_base_url, tosca_template_path) tosca_helper = ToscaHelper(sure_tosca_base_url, tosca_template_path)
# nodes_to_deploy = tosca_helper.get_application_nodes() # nodes_to_deploy = tosca_helper.get_application_nodes()
nodes_pairs = tosca_helper.get_deployment_node_pairs() nodes = tosca_helper.get_deployment_node_pipeline()
deployService = DeployService(semaphore_base_url=semaphore_base_url, semaphore_username=semaphore_username, deployService = DeployService(semaphore_base_url=semaphore_base_url, semaphore_username=semaphore_username,
semaphore_password=semaphore_password, vms=tosca_helper.get_vms()) semaphore_password=semaphore_password, vms=tosca_helper.get_vms())
try: try:
for node_pair in nodes_pairs: for node in nodes:
updated_node = deployService.deploy(node_pair) updated_node = deployService.deploy(node)
if isinstance(updated_node, list): if isinstance(updated_node, list):
for node in updated_node: for node in updated_node:
tosca_template_dict = tosca_helper.set_node(node,tosca_template_dict) tosca_template_dict = tosca_helper.set_node(node,tosca_template_dict)
......
pika==1.1.0 pika==1.1.0
names==0.3.0 names==0.3.0
networkx==2.4 networkx==2.4
requests==2.23.0 # requests==2.23.0
wheel==0.34.2 wheel==0.34.2
pyyaml==5.3.1 pyyaml==5.3.1
matplotlib==3.2.1 # matplotlib==3.2.1
# ansible==2.9.6 ansible==2.9.11
certifi==2020.4.5.1 # certifi==2020.4.5.1
six==1.14.0 six==1.14.0
python_dateutil==2.8.1 python_dateutil==2.8.1
setuptools==46.1.3 # setuptools==46.1.3
urllib3==1.25.8 # urllib3==1.25.8
kubernetes==11.0.0 kubernetes==11.0.0
\ No newline at end of file
import base64 import base64
import configparser
import logging import logging
from time import sleep from time import sleep
import datetime import datetime
...@@ -29,8 +30,7 @@ class AnsibleService: ...@@ -29,8 +30,7 @@ class AnsibleService:
self.repository_id = None self.repository_id = None
self.template_id = None self.template_id = None
def execute(self, nodes_pair, interface_type, vms, env_vars=None): def execute(self, application, interface_type, vms, env_vars=None):
application = nodes_pair[1]
name = application.name name = application.name
desired_state = None desired_state = None
tasks_outputs = {} tasks_outputs = {}
...@@ -43,7 +43,8 @@ class AnsibleService: ...@@ -43,7 +43,8 @@ class AnsibleService:
if desired_state: if desired_state:
now = datetime.datetime.now() now = datetime.datetime.now()
project_id = self.semaphore_helper.create_project(application.name + '_' + str(now)) project_id = self.semaphore_helper.create_project(application.name + '_' + str(now))
inventory_contents = yaml.dump(self.build_yml_inventory(vms), default_flow_style=False) inventory_dict = self.build_inventory(vms, application_name=application.name)
inventory_contents = yaml.dump(inventory_dict, default_flow_style=False)
private_key = self.get_private_key(vms) private_key = self.get_private_key(vms)
key_id = self.semaphore_helper.create_ssh_key(application.name, project_id, private_key) key_id = self.semaphore_helper.create_ssh_key(application.name, project_id, private_key)
inventory_id = self.semaphore_helper.create_inventory(application.name, project_id, key_id, inventory_id = self.semaphore_helper.create_inventory(application.name, project_id, key_id,
...@@ -59,17 +60,28 @@ class AnsibleService: ...@@ -59,17 +60,28 @@ class AnsibleService:
environment_id = None environment_id = None
if env_vars: if env_vars:
environment_id = self.semaphore_helper.create_environment(project_id, name, env_vars) environment_id = self.semaphore_helper.create_environment(project_id, name, env_vars)
arguments = None
if application.name == 'gluster_fs' or application.name == 'glusterfs' or application.name == 'tic':
if playbook_name == '003.setup_glusterfs_cluster.yml':
arguments = '["-u","vm_user"]'
if playbook_name == '013.mount_fs.yml':
master_ip = next(iter(
inventory_dict['all']['children']['swarm_manager_prime']['hosts'])) # outputs 'foo'
arguments = '["-u","vm_user","--extra-vars","gluster_cluster_host0=\'' + master_ip + '\' gluster_cluster_volume=\'gfs0\'"]'
task_id = self.run_task(name, project_id, key_id, git_url, inventory_id, playbook_name, task_id = self.run_task(name, project_id, key_id, git_url, inventory_id, playbook_name,
environment_id=environment_id) environment_id=environment_id, arguments=arguments)
if self.semaphore_helper.get_task(project_id, task_id).status != 'success': if self.semaphore_helper.get_task(project_id, task_id).status != 'success':
msg = ' ' msg = ' '
for out in self.semaphore_helper.get_task_outputs(project_id, task_id): for out in self.semaphore_helper.get_task_outputs(project_id, task_id):
msg = msg+' '+out.output msg = msg + ' ' + out.output
raise Exception('Task: '+playbook_name+' failed. '+self.semaphore_helper.get_task(project_id, task_id).status+' Output: '+msg) raise Exception(
'Task: ' + playbook_name + ' failed. ' + self.semaphore_helper.get_task(project_id,
task_id).status + ' Output: ' + msg)
tasks_outputs[task_id] = self.semaphore_helper.get_task_outputs(project_id, task_id) tasks_outputs[task_id] = self.semaphore_helper.get_task_outputs(project_id, task_id)
if 'configure' in interface and self.semaphore_helper.get_task(project_id, task_id).status == 'success' and 'resources' in inputs: if 'configure' in interface and self.semaphore_helper.get_task(project_id,
task_id).status == 'success' and 'resources' in inputs:
configure = interface['configure'] configure = interface['configure']
inputs = configure['inputs'] inputs = configure['inputs']
git_url = inputs['repository'] git_url = inputs['repository']
...@@ -91,29 +103,40 @@ class AnsibleService: ...@@ -91,29 +103,40 @@ class AnsibleService:
tasks_outputs[task_id] = self.semaphore_helper.get_task_outputs(project_id, task_id) tasks_outputs[task_id] = self.semaphore_helper.get_task_outputs(project_id, task_id)
return tasks_outputs return tasks_outputs
def build_yml_inventory(self, vms): def build_inventory(self, vms, application_name=None):
# loader = DataLoader() # loader = DataLoader()
# inventory = InventoryManager(loader=loader) # inventory = InventoryManager(loader=loader)
# variable_manager = VariableManager() # variable_manager = VariableManager()
vars = {}
# vars ['ansible_ssh_common_args'] = '"-o StrictHostKeyChecking=no"'
vars['ansible_ssh_user'] = vms[0].node_template.properties['user_name']
vars['ansible_python_interpreter'] = '/usr/bin/python3'
if application_name == 'gluster_fs' or application_name == 'glusterfs':
return self.build_glusterfs_inventory(vms, vars)
if application_name == 'tic':
return self.build_tic_inventory(vms, vars)
inventory = {} inventory = {}
all = {} all = {}
vars = {'ansible_ssh_common_args': '-o StrictHostKeyChecking=no'}
vars['ansible_ssh_user'] = vms[0].node_template.properties['user_name']
children = {} children = {}
for vm in vms: for vm in vms:
attributes = vm.node_template.attributes attributes = vm.node_template.attributes
role = attributes['role'] roles = []
roles.append(attributes['role'])
public_ip = attributes['public_ip'] public_ip = attributes['public_ip']
if role not in children: for role in roles:
hosts = {} if role not in children:
else: hosts = {}
hosts = children[role] else:
host = {} hosts = children[role]
host[public_ip] = vars
hosts['hosts'] = host host = {}
children[role] = hosts host[public_ip] = vars
# inventory.add_group(role) if 'hosts' in hosts:
# inventory.add_host(public_ip,group=role) hosts['hosts'][public_ip] = vars
else:
hosts['hosts'] = host
children[role] = hosts
all['children'] = children all['children'] = children
inventory['all'] = all inventory['all'] = all
return inventory return inventory
...@@ -122,12 +145,13 @@ class AnsibleService: ...@@ -122,12 +145,13 @@ class AnsibleService:
private_key = vms[0].node_template.attributes['user_key_pair']['keys']['private_key'] private_key = vms[0].node_template.attributes['user_key_pair']['keys']['private_key']
return base64.b64decode(private_key).decode('utf-8').replace(r'\n', '\n') return base64.b64decode(private_key).decode('utf-8').replace(r'\n', '\n')
def run_task(self, name, project_id, key_id, git_url, inventory_id, playbook_name, environment_id=None): def run_task(self, name, project_id, key_id, git_url, inventory_id, playbook_name, environment_id=None,
arguments=None):
logger.info('project_id: ' + str(project_id) + ' task name: ' + str( logger.info('project_id: ' + str(project_id) + ' task name: ' + str(
name) + ' git url: ' + git_url + ' playbook: ' + playbook_name) name) + ' git url: ' + git_url + ' playbook: ' + playbook_name)
self.repository_id = self.semaphore_helper.create_repository(name, project_id, key_id, git_url) self.repository_id = self.semaphore_helper.create_repository(name, project_id, key_id, git_url)
template_id = self.semaphore_helper.create_template(project_id, key_id, inventory_id, self.repository_id, template_id = self.semaphore_helper.create_template(project_id, key_id, inventory_id, self.repository_id,
playbook_name) playbook_name, arguments)
task_id = self.semaphore_helper.execute_task(project_id, template_id, playbook_name, task_id = self.semaphore_helper.execute_task(project_id, template_id, playbook_name,
environment_id=environment_id) environment_id=environment_id)
task = self.semaphore_helper.get_task(project_id, task_id) task = self.semaphore_helper.get_task(project_id, task_id)
...@@ -140,3 +164,67 @@ class AnsibleService: ...@@ -140,3 +164,67 @@ class AnsibleService:
last_status = this_status last_status = this_status
sleep(6) sleep(6)
return task_id return task_id
def build_glusterfs_inventory(self, vms, vars):
inventory = {}
all = {}
children = {}
for vm in vms:
attributes = vm.node_template.attributes
roles = []
roles.append('gfscluster')
public_ip = attributes['public_ip']
for role in roles:
if role not in children:
hosts = {}
else:
hosts = children[role]
if 'hosts' in hosts:
hosts['hosts'][public_ip] = vars
else:
host = {}
host[public_ip] = vars
hosts['hosts'] = host
children[role] = hosts
all['children'] = children
inventory['all'] = all
return inventory
def build_tic_inventory(self, vms, vars):
inventory = {}
all = {}
children = {}
for vm in vms:
attributes = vm.node_template.attributes
roles = []
if attributes['role'] == 'master':
roles.append('swarm_manager_prime')
roles.append('swarm_managers')
elif attributes['role'] == 'worker':
roles.append('swarm_workers')
public_ip = attributes['public_ip']
for role in roles:
if role not in children:
hosts = {}
else:
hosts = children[role]
if 'hosts' in hosts:
# if attributes['role'] == 'master':
hosts['hosts'] = {public_ip: vars}
# else:
# hosts['hosts'] = {public_ip: vars}
else:
host = {}
host[public_ip] = vars
# if role == 'swarm_manager_prime':
# host['fabric-manager'] = vars
# elif role == 'swarm_managers':
# host['fabric-manager'] = {}
# else:
# host['fabric-worker'] = vars
hosts['hosts'] = host
children[role] = hosts
all['children'] = children
inventory['all'] = all
return inventory
...@@ -29,24 +29,24 @@ class DeployService: ...@@ -29,24 +29,24 @@ class DeployService:
self.master_ip = vm.node_template.attributes['public_ip'] self.master_ip = vm.node_template.attributes['public_ip']
break break
def deploy(self,nodes_pair): def deploy(self, application):
target = nodes_pair[0] # target = nodes_pair[0]
source = nodes_pair[1] # source = nodes_pair[1]
interface_types = tosca_helper.get_interface_types(source) interface_types = tosca_helper.get_interface_types(application)
if interface_types: if interface_types:
ansible_service = AnsibleService(self.semaphore_base_url, self.semaphore_username, self.semaphore_password) ansible_service = AnsibleService(self.semaphore_base_url, self.semaphore_username, self.semaphore_password)
env_vars = self.get_env_vars(nodes_pair) env_vars = self.get_env_vars(application)
if 'Standard' in interface_types: if 'Standard' in interface_types:
task_outputs = ansible_service.execute(nodes_pair, 'Standard', self.vms, env_vars=env_vars) task_outputs = ansible_service.execute(application, 'Standard', self.vms, env_vars=env_vars)
source = self.set_attributes(task_outputs,source) application = self.set_attributes(task_outputs, application)
if 'Kubernetes' in interface_types: if 'Kubernetes' in interface_types:
task_outputs = ansible_service.execute(nodes_pair, 'Kubernetes', self.vms, env_vars=env_vars) task_outputs = ansible_service.execute(application, 'Kubernetes', self.vms, env_vars=env_vars)
source = self.set_attributes(task_outputs,source) application = self.set_attributes(task_outputs, application)
return source return application
def get_env_vars(self, nodes_pair): def get_env_vars(self, source):
target = nodes_pair[0] # target = nodes_pair[0]
source = nodes_pair[1] # source = nodes_pair[1]
env_vars = {'K8s_NAMESPACE': 'default'} env_vars = {'K8s_NAMESPACE': 'default'}
if source.node_template.type == 'tosca.nodes.QC.Container.Application.Docker': if source.node_template.type == 'tosca.nodes.QC.Container.Application.Docker':
env_vars['DOCKER_IMAGE'] = source.node_template.artifacts['image']['file'] env_vars['DOCKER_IMAGE'] = source.node_template.artifacts['image']['file']
...@@ -65,6 +65,8 @@ class DeployService: ...@@ -65,6 +65,8 @@ class DeployService:
source = self.set_kubernetes_attributes(source=source,task_outputs=task_outputs) source = self.set_kubernetes_attributes(source=source,task_outputs=task_outputs)
if source.node_template.type == 'tosca.nodes.QC.Container.Application.Docker': if source.node_template.type == 'tosca.nodes.QC.Container.Application.Docker':
source = self.set_docker_attributes(source=source, task_outputs=task_outputs) source = self.set_docker_attributes(source=source, task_outputs=task_outputs)
if source.node_template.type == 'tosca.nodes.QC.Application.TIC':
source = self.set_tic_attributes(source=source, task_outputs=task_outputs)
# lst = list(nodes_pair) # lst = list(nodes_pair)
# lst[1] = source # lst[1] = source
# nodes_pair = tuple(lst) # nodes_pair = tuple(lst)
...@@ -175,3 +177,13 @@ class DeployService: ...@@ -175,3 +177,13 @@ class DeployService:
attributes['service_url'] = service_url attributes['service_url'] = service_url
logger.info('source.node_template.attributes: ' + str(attributes)) logger.info('source.node_template.attributes: ' + str(attributes))
return source return source
def set_tic_attributes(self, source, task_outputs):
attributes = source.node_template.attributes
if 'service_urls' not in source.node_template.attributes:
service_urls = []
attributes['service_urls'] = service_urls
for port in ['8090','9000','9090']:
service_urls.append('http://' + self.master_ip + ':' + str(port))
attributes['service_urls'] = service_urls
return source
...@@ -5,6 +5,8 @@ import urllib.request ...@@ -5,6 +5,8 @@ import urllib.request
from sure_tosca_client import Configuration, ApiClient, NodeTemplate from sure_tosca_client import Configuration, ApiClient, NodeTemplate
from sure_tosca_client.api import default_api from sure_tosca_client.api import default_api
import networkx as nx
import matplotlib.pyplot as plt
class ToscaHelper: class ToscaHelper:
...@@ -38,22 +40,30 @@ class ToscaHelper: ...@@ -38,22 +40,30 @@ class ToscaHelper:
def get_application_nodes(self): def get_application_nodes(self):
return self.tosca_client.get_node_templates(self.doc_id, type_name='tosca.nodes.QC.Application') return self.tosca_client.get_node_templates(self.doc_id, type_name='tosca.nodes.QC.Application')
def get_deployment_node_pairs(self): def get_deployment_node_pipeline(self):
nodes_to_deploy = self.get_application_nodes() nodes_to_deploy = self.get_application_nodes()
nodes_pairs = [] G = nx.DiGraph()
sorted_nodes = []
for node in nodes_to_deploy: for node in nodes_to_deploy:
related_nodes = self.tosca_client.get_related_nodes(self.doc_id,node.name) related_nodes = self.tosca_client.get_related_nodes(self.doc_id,node.name)
for related_node in related_nodes: for related_node in related_nodes:
# We need to deploy the docker orchestrator on the VMs not the topology. G.add_edge(node.name, related_node.name)
# But the topology is directly connected to the orchestrator not the VMs. # # We need to deploy the docker orchestrator on the VMs not the topology.
# So we explicitly get the VMs # # But the topology is directly connected to the orchestrator not the VMs.
# I don't like this solution but I can't think of something better. # # So we explicitly get the VMs
if related_node.node_template.type == 'tosca.nodes.QC.VM.topology': # # I don't like this solution but I can't think of something better.
vms = self.get_vms() # if related_node.node_template.type == 'tosca.nodes.QC.VM.topology':
related_node = vms # vms = self.get_vms()
pair = (related_node, node) # related_node = vms
nodes_pairs.append(pair) # pair = (related_node, node)
return nodes_pairs # nodes_pairs.append(pair)
sorted_graph = sorted(G.in_degree, key=lambda x: x[1], reverse=True)
for node_tuple in sorted_graph:
node_name = node_tuple[0]
for node in nodes_to_deploy:
if node.name == node_name:
sorted_nodes.append(node)
return sorted_nodes
@classmethod @classmethod
def service_is_up(cls, url): def service_is_up(cls, url):
......
...@@ -48,7 +48,7 @@ class TestDeployer(unittest.TestCase): ...@@ -48,7 +48,7 @@ class TestDeployer(unittest.TestCase):
self.assertIsNotNone(tosca_helper.doc_id) self.assertIsNotNone(tosca_helper.doc_id)
nodes_to_deploy = tosca_helper.get_application_nodes() nodes_to_deploy = tosca_helper.get_application_nodes()
self.assertIsNotNone(nodes_to_deploy) self.assertIsNotNone(nodes_to_deploy)
nodes_pairs = tosca_helper.get_deployment_node_pairs() nodes_pairs = tosca_helper.get_deployment_node_pipeline()
self.assertIsNotNone(nodes_pairs) self.assertIsNotNone(nodes_pairs)
username = 'admin' username = 'admin'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment