Commit a51e1087 authored by Spiros Koulouzis's avatar Spiros Koulouzis

get multiple VMs

parent 493da3df
...@@ -3,6 +3,7 @@ tosca_definitions_version: tosca_simple_yaml_1_0 ...@@ -3,6 +3,7 @@ tosca_definitions_version: tosca_simple_yaml_1_0
imports: imports:
- nodes: types/nodes.yaml - nodes: types/nodes.yaml
- capabilities: types/capabilities.yaml - capabilities: types/capabilities.yaml
- policies: types/policies.yaml
description: > description: >
TOSCA example TOSCA example
...@@ -16,8 +17,8 @@ topology_template: ...@@ -16,8 +17,8 @@ topology_template:
- service: - service:
node: mysql node: mysql
relationship: relationship:
type: tosca.relationships.ConnectsTo #type: tosca.relationships.ConnectsTo
#type: tosca.relationships.DependsOn type: tosca.relationships.DependsOn
artifacts: artifacts:
my_image: my_image:
file: wordpress:latest file: wordpress:latest
...@@ -48,6 +49,11 @@ topology_template: ...@@ -48,6 +49,11 @@ topology_template:
file: mysql:5.7 file: mysql:5.7
repository: docker_hub repository: docker_hub
policies:
- scalability:
type: tosca.policies.ARTICONF.Performance
targets: [ wordpress ]
......
...@@ -8,3 +8,17 @@ capability_types: ...@@ -8,3 +8,17 @@ capability_types:
some_properties: some_properties:
type: string type: string
required: no required: no
tosca.capabilities.ARTICONF.VM:
derived_from: tosca.capabilities.Compute
properties:
some_properties:
type: string
required: no
tosca.capabilities.ARTICONF.VM.topology:
derived_from: tosca.capabilities.Compute
properties:
some_properties:
type: string
required: no
...@@ -36,13 +36,13 @@ node_types: ...@@ -36,13 +36,13 @@ node_types:
relationship: tosca.relationships.HostedOn relationship: tosca.relationships.HostedOn
tosca.nodes.ARTICONF.Orchestrator: tosca.nodes.ARTICONF.Orchestrator:
derived_from: tosca.nodes.SoftwareComponent #derived_from: tosca.nodes.SoftwareComponent
description: a container orchestrator description: a container orchestrator
requirements: #requirements:
- host: #- host:
capability: tosca.capabilities.Container #capability: tosca.capabilities.Container
node: tosca.nodes.Compute #node: tosca.nodes.Compute
relationship: tosca.relationships.HostedOn #relationship: tosca.relationships.HostedOn
capabilities: capabilities:
host: host:
type: tosca.capabilities.ARTICONF.Orchestrator type: tosca.capabilities.ARTICONF.Orchestrator
...@@ -55,10 +55,84 @@ node_types: ...@@ -55,10 +55,84 @@ node_types:
requirements: requirements:
- host: - host:
capability: tosca.capabilities.Scalable capability: tosca.capabilities.Scalable
node: tosca.nodes.Compute node: tosca.nodes.ARTICONF.Compute
relationship: tosca.relationships.HostedOn relationship: tosca.relationships.HostedOn
interfaces: interfaces:
Standard: Standard:
create: interfaces/playbooks/kubernetes_install.yaml create: interfaces/playbooks/kubernetes_install.yaml
tosca.nodes.ARTICONF.Compute:
description: Base compute node
capabilities:
host:
type: tosca.capabilities.Compute
os:
type: tosca.capabilities.OperatingSystem
container:
type: tosca.capabilities.Container
node_cap:
type: tosca.capabilities.Node
tosca.nodes.ARTICONF.VM.Compute:
derived_from: tosca.nodes.ARTICONF.Compute
description: VM node
capabilities:
vm:
type: tosca.capabilities.ARTICONF.VM
properties:
num_cpus:
type: integer
required: true
mem_size:
type: integer
required: true
username:
type: string
required: true
password:
type: string
required: true
host_name:
type: string
required: false
role:
type: string
required: false
state:
type: string
required: false
interfaces:
Standard:
create: dumy.yaml
tosca.nodes.ARTICONF.VM.topology:
derived_from: tosca.nodes.ARTICONF.Compute
description: topology of VMs
requirements:
- vm:
capability: tosca.capabilities.ARTICONF.VM
node: tosca.nodes.ARTICONF.Compute
relationship: tosca.relationships.DependsOn
occurrences: [1, UNBOUNDED]
capabilities:
scalable:
type: tosca.capabilities.Scalable
topology:
type: tosca.capabilities.ARTICONF.VM.topology
occurrences: [1, 1]
properties:
provider:
type: string
required: true
name:
type: string
required: true
domain:
type: string
required: true
interfaces:
Standard:
create: dumy.yaml
tosca_definitions_version: tosca_simple_yaml_1_0
policy_types:
tosca.policies.ARTICONF.Performance:
derived_from: tosca.policies.Performance
description: QoS constraint
properties:
constraint_name:
type: string
description: the name of the constraint e.g. users_per_sec
required: false
min_value:
type: integer
required: false
description: the minimum acceptable value
max_value:
type: integer
required: false
description: the maximum acceptable value
...@@ -34,6 +34,7 @@ class BasicPlanner: ...@@ -34,6 +34,7 @@ class BasicPlanner:
# capable_node_name = '' # capable_node_name = ''
for node in self.template.nodetemplates: for node in self.template.nodetemplates:
node_templates = self.add_reqired_nods(node,None) node_templates = self.add_reqired_nods(node,None)
# missing_requirements = self.get_missing_requirements(node) # missing_requirements = self.get_missing_requirements(node)
# for req in missing_requirements: # for req in missing_requirements:
# for key in req: # for key in req:
...@@ -88,6 +89,7 @@ class BasicPlanner: ...@@ -88,6 +89,7 @@ class BasicPlanner:
if node.parent_type and node.parent_type.requirements: if node.parent_type and node.parent_type.requirements:
logging.info('Adding to : '+str(node.name) + ' parent requirements from: '+str(node.parent_type.type)) logging.info('Adding to : '+str(node.name) + ' parent requirements from: '+str(node.parent_type.type))
missing_requirements = missing_requirements + node.parent_type.requirements missing_requirements = missing_requirements + node.parent_type.requirements
logging.info(' missing_requirements: '+str(missing_requirements))
return missing_requirements return missing_requirements
...@@ -95,9 +97,12 @@ class BasicPlanner: ...@@ -95,9 +97,12 @@ class BasicPlanner:
candidate_nodes = {} candidate_nodes = {}
for tosca_node_type in self.all_nodes: for tosca_node_type in self.all_nodes:
if tosca_node_type.startswith('tosca.nodes') and 'capabilities' in self.all_nodes[tosca_node_type]: if tosca_node_type.startswith('tosca.nodes') and 'capabilities' in self.all_nodes[tosca_node_type]:
logging.debug(' Node: '+str(tosca_node_type))
for caps in self.all_nodes[tosca_node_type]['capabilities']: for caps in self.all_nodes[tosca_node_type]['capabilities']:
logging.debug(' '+str(self.all_nodes[tosca_node_type]['capabilities'][caps]['type'])+' == '+cap)
if self.all_nodes[tosca_node_type]['capabilities'][caps]['type'] == cap: if self.all_nodes[tosca_node_type]['capabilities'][caps]['type'] == cap:
candidate_nodes[tosca_node_type] = self.all_nodes[tosca_node_type] candidate_nodes[tosca_node_type] = self.all_nodes[tosca_node_type]
logging.debug(' candidate_node: '+str(tosca_node_type))
candidate_child_nodes = {} candidate_child_nodes = {}
for tosca_node_type in self.all_nodes: for tosca_node_type in self.all_nodes:
...@@ -113,7 +118,7 @@ class BasicPlanner: ...@@ -113,7 +118,7 @@ class BasicPlanner:
#Only return the nodes that have interfaces. This means that they are not "abstract" #Only return the nodes that have interfaces. This means that they are not "abstract"
for candidate_node_name in candidate_nodes: for candidate_node_name in candidate_nodes:
if 'interfaces' in candidate_nodes[candidate_node_name].keys(): if 'interfaces' in candidate_nodes[candidate_node_name].keys() and 'tosca.nodes.Root'!=candidate_node_name:
capable_nodes[candidate_node_name] = candidate_nodes[candidate_node_name] capable_nodes[candidate_node_name] = candidate_nodes[candidate_node_name]
return capable_nodes return capable_nodes
...@@ -172,43 +177,73 @@ class BasicPlanner: ...@@ -172,43 +177,73 @@ class BasicPlanner:
return NodeTemplate(name, nodetemplate_dict,node_type) return NodeTemplate(name, nodetemplate_dict,node_type)
def node_requered_once(self,node): def get_requirement_occurrences(self,req):
for node_type in node: if 'occurrences' in req:
if 'capabilities' in node[node_type]: return req['occurrences']
capabilities = node[node_type]['capabilities'] return None
for cap in capabilities:
if self.has_capability_max_one_occurrence(capabilities[cap]): def get_optimal_num_of_occurrences(self,node_type,min_max_occurrences):
return True max_occurrences = -1
return False min_occurrences = -1
if min_max_occurrences:
if isinstance(min_max_occurrences[1], int):
max_occurrences = int(min_max_occurrences[1])
if isinstance(min_max_occurrences[0], int):
min_occurrences = int(min_max_occurrences[0])
if max_occurrences and max_occurrences > -1 :
return max_occurrences
if max_occurrences and max_occurrences <= -1 and min_max_occurrences[1] == 'UNBOUNDED' and node_type =='tosca.nodes.ARTICONF.VM.Compute':
return 2
else:
return 1
def add_reqired_nods(self,node,node_templates): def add_reqired_nods(self,node,node_templates):
if not node_templates: if not node_templates:
node_templates = [] node_templates = []
missing_requirements = self.get_missing_requirements(node) missing_requirements = self.get_missing_requirements(node)
if not missing_requirements: if not missing_requirements:
logging.info('Node: '+node.name + ' of type: '+node.type +' has no requirements') logging.info('Node: '+node.name + ' of type: '+node.type +' has no requirements')
# return node_templates # return node_templates
capable_node_name = '' capable_node_name = ''
min_max_occurrences = []
for req in missing_requirements: for req in missing_requirements:
for key in req: for key in req:
logging.info('Looking for capability: '+req[key]['capability']+ ' for node: '+node.name ) min_max_occurrences = self.get_requirement_occurrences(req[key])
logging.info('Looking for capability: '+req[key]['capability']+ ' for node: '+node.name)
capable_node = self.get_node_types_by_capability(req[key]['capability']) capable_node = self.get_node_types_by_capability(req[key]['capability'])
if capable_node: if capable_node:
capable_node_type = next(iter(capable_node)) capable_node_type = next(iter(capable_node))
logging.info('Found : '+str(capable_node_type)) logging.info('Found: '+str(capable_node_type))
else: else:
logging.error('Did not find node with reuired capability: '+str(req[key]['capability'])) logging.error('Did not find node with reuired capability: '+str(req[key]['capability']))
if self.node_requered_once(capable_node) and not self.contains_node_type(node_templates,capable_node_type): occurrences = self.get_optimal_num_of_occurrences(capable_node_type,min_max_occurrences)
if not self.contains_node_type(node_templates,capable_node_type) and occurrences == 1:
capable_node_template = self.node_type_2_node_template(capable_node) capable_node_template = self.node_type_2_node_template(capable_node)
capable_node_name = capable_node_template.name capable_node_name = capable_node_template.name
node_templates.append(capable_node_template) node_templates.append(capable_node_template)
#recursively fulfill all requirements #recursively fulfill all requirements
self.add_reqired_nods(capable_node_template,node_templates) self.add_reqired_nods(capable_node_template,node_templates)
elif occurrences > 1:
logging.info('Creating: '+str(occurrences) + ' occurrences of '+capable_node_type)
for x in range(0, occurrences):
capable_node_template = self.node_type_2_node_template(capable_node)
capable_node_name = capable_node_template.name
logging.info('Adding : '+str(capable_node_template.name))
node_templates.append(capable_node_template)
#recursively fulfill all requirements
self.add_reqired_nods(capable_node_template,node_templates)
logging.info('Adding node: '+capable_node_name+ ' to ------------------: '+str(req))
for x in range(0, occurrences):
req[next(iter(req))]['node'] = capable_node_name req[next(iter(req))]['node'] = capable_node_name
node.requirements.append(req) node.requirements.append(req)
if not self.contains_node_type(node_templates,node): if not self.contains_node_type(node_templates,node):
node_templates.append(node) node_templates.append(node)
......
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