vFW and vDNS support added to azure-plugin
[multicloud/azure.git] / azure / aria / aria-extension-cloudify / src / aria / aria / core.py
1 # Licensed to the Apache Software Foundation (ASF) under one or more
2 # contributor license agreements.  See the NOTICE file distributed with
3 # this work for additional information regarding copyright ownership.
4 # The ASF licenses this file to You under the Apache License, Version 2.0
5 # (the "License"); you may not use this file except in compliance with
6 # the License.  You may obtain a copy of the License at
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15
16 """
17 ARIA core module.
18 """
19
20 from . import exceptions
21 from .parser import consumption
22 from .parser.loading.location import UriLocation
23 from .orchestrator import topology
24
25
26 class Core(object):
27
28     def __init__(self,
29                  model_storage,
30                  resource_storage,
31                  plugin_manager):
32         self._model_storage = model_storage
33         self._resource_storage = resource_storage
34         self._plugin_manager = plugin_manager
35
36     @property
37     def model_storage(self):
38         return self._model_storage
39
40     @property
41     def resource_storage(self):
42         return self._resource_storage
43
44     @property
45     def plugin_manager(self):
46         return self._plugin_manager
47
48     def validate_service_template(self, service_template_path):
49         self._parse_service_template(service_template_path)
50
51     def create_service_template(self, service_template_path, service_template_dir,
52                                 service_template_name):
53         context = self._parse_service_template(service_template_path)
54         service_template = context.modeling.template
55         service_template.name = service_template_name
56         self.model_storage.service_template.put(service_template)
57         self.resource_storage.service_template.upload(
58             entry_id=str(service_template.id), source=service_template_dir)
59         return service_template.id
60
61     def delete_service_template(self, service_template_id):
62         service_template = self.model_storage.service_template.get(service_template_id)
63         if service_template.services:
64             raise exceptions.DependentServicesError(
65                 'Can\'t delete service template `{0}` - service template has existing services'
66                 .format(service_template.name))
67
68         self.model_storage.service_template.delete(service_template)
69         self.resource_storage.service_template.delete(entry_id=str(service_template.id))
70
71     def create_service(self, service_template_id, inputs, service_name=None):
72         service_template = self.model_storage.service_template.get(service_template_id)
73
74         storage_session = self.model_storage._all_api_kwargs['session']
75         # setting no autoflush for the duration of instantiation - this helps avoid dependency
76         # constraints as they're being set up
77         with storage_session.no_autoflush:
78             topology_ = topology.Topology()
79             service = topology_.instantiate(
80                 service_template, inputs=inputs, plugins=self.model_storage.plugin.list())
81             topology_.coerce(service, report_issues=True)
82
83             topology_.validate(service)
84             topology_.satisfy_requirements(service)
85             topology_.coerce(service, report_issues=True)
86
87             topology_.validate_capabilities(service)
88             topology_.assign_hosts(service)
89             topology_.configure_operations(service)
90             topology_.coerce(service, report_issues=True)
91             if topology_.dump_issues():
92                 raise exceptions.InstantiationError('Failed to instantiate service template `{0}`'
93                                                     .format(service_template.name))
94
95         storage_session.flush()  # flushing so service.id would auto-populate
96         service.name = service_name or '{0}_{1}'.format(service_template.name, service.id)
97         self.model_storage.service.put(service)
98         return service
99
100     def delete_service(self, service_id, force=False):
101         service = self.model_storage.service.get(service_id)
102
103         active_executions = [e for e in service.executions if e.is_active()]
104         if active_executions:
105             raise exceptions.DependentActiveExecutionsError(
106                 'Can\'t delete service `{0}` - there is an active execution for this service. '
107                 'Active execution ID: {1}'.format(service.name, active_executions[0].id))
108
109         if not force:
110             available_nodes = [str(n.id) for n in service.nodes.itervalues() if n.is_available()]
111             if available_nodes:
112                 raise exceptions.DependentAvailableNodesError(
113                     'Can\'t delete service `{0}` - there are available nodes for this service. '
114                     'Available node IDs: {1}'.format(service.name, ', '.join(available_nodes)))
115
116         self.model_storage.service.delete(service)
117
118     @staticmethod
119     def _parse_service_template(service_template_path):
120         context = consumption.ConsumptionContext()
121         context.presentation.location = UriLocation(service_template_path)
122         # Most of the parser uses the topology package in order to manipulate the models.
123         # However, here we use the Consumer mechanism, but this should change in the future.
124         consumption.ConsumerChain(
125             context,
126             (
127                 consumption.Read,
128                 consumption.Validate,
129                 consumption.ServiceTemplate
130             )).consume()
131         if context.validation.dump_issues():
132             raise exceptions.ParsingError('Failed to parse service template')
133         return context