summaryrefslogtreecommitdiffstats
path: root/azure/aria/aria-extension-cloudify/src/aria/aria/core.py
diff options
context:
space:
mode:
Diffstat (limited to 'azure/aria/aria-extension-cloudify/src/aria/aria/core.py')
-rw-r--r--azure/aria/aria-extension-cloudify/src/aria/aria/core.py133
1 files changed, 133 insertions, 0 deletions
diff --git a/azure/aria/aria-extension-cloudify/src/aria/aria/core.py b/azure/aria/aria-extension-cloudify/src/aria/aria/core.py
new file mode 100644
index 0000000..e364f48
--- /dev/null
+++ b/azure/aria/aria-extension-cloudify/src/aria/aria/core.py
@@ -0,0 +1,133 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+ARIA core module.
+"""
+
+from . import exceptions
+from .parser import consumption
+from .parser.loading.location import UriLocation
+from .orchestrator import topology
+
+
+class Core(object):
+
+ def __init__(self,
+ model_storage,
+ resource_storage,
+ plugin_manager):
+ self._model_storage = model_storage
+ self._resource_storage = resource_storage
+ self._plugin_manager = plugin_manager
+
+ @property
+ def model_storage(self):
+ return self._model_storage
+
+ @property
+ def resource_storage(self):
+ return self._resource_storage
+
+ @property
+ def plugin_manager(self):
+ return self._plugin_manager
+
+ def validate_service_template(self, service_template_path):
+ self._parse_service_template(service_template_path)
+
+ def create_service_template(self, service_template_path, service_template_dir,
+ service_template_name):
+ context = self._parse_service_template(service_template_path)
+ service_template = context.modeling.template
+ service_template.name = service_template_name
+ self.model_storage.service_template.put(service_template)
+ self.resource_storage.service_template.upload(
+ entry_id=str(service_template.id), source=service_template_dir)
+ return service_template.id
+
+ def delete_service_template(self, service_template_id):
+ service_template = self.model_storage.service_template.get(service_template_id)
+ if service_template.services:
+ raise exceptions.DependentServicesError(
+ 'Can\'t delete service template `{0}` - service template has existing services'
+ .format(service_template.name))
+
+ self.model_storage.service_template.delete(service_template)
+ self.resource_storage.service_template.delete(entry_id=str(service_template.id))
+
+ def create_service(self, service_template_id, inputs, service_name=None):
+ service_template = self.model_storage.service_template.get(service_template_id)
+
+ storage_session = self.model_storage._all_api_kwargs['session']
+ # setting no autoflush for the duration of instantiation - this helps avoid dependency
+ # constraints as they're being set up
+ with storage_session.no_autoflush:
+ topology_ = topology.Topology()
+ service = topology_.instantiate(
+ service_template, inputs=inputs, plugins=self.model_storage.plugin.list())
+ topology_.coerce(service, report_issues=True)
+
+ topology_.validate(service)
+ topology_.satisfy_requirements(service)
+ topology_.coerce(service, report_issues=True)
+
+ topology_.validate_capabilities(service)
+ topology_.assign_hosts(service)
+ topology_.configure_operations(service)
+ topology_.coerce(service, report_issues=True)
+ if topology_.dump_issues():
+ raise exceptions.InstantiationError('Failed to instantiate service template `{0}`'
+ .format(service_template.name))
+
+ storage_session.flush() # flushing so service.id would auto-populate
+ service.name = service_name or '{0}_{1}'.format(service_template.name, service.id)
+ self.model_storage.service.put(service)
+ return service
+
+ def delete_service(self, service_id, force=False):
+ service = self.model_storage.service.get(service_id)
+
+ active_executions = [e for e in service.executions if e.is_active()]
+ if active_executions:
+ raise exceptions.DependentActiveExecutionsError(
+ 'Can\'t delete service `{0}` - there is an active execution for this service. '
+ 'Active execution ID: {1}'.format(service.name, active_executions[0].id))
+
+ if not force:
+ available_nodes = [str(n.id) for n in service.nodes.itervalues() if n.is_available()]
+ if available_nodes:
+ raise exceptions.DependentAvailableNodesError(
+ 'Can\'t delete service `{0}` - there are available nodes for this service. '
+ 'Available node IDs: {1}'.format(service.name, ', '.join(available_nodes)))
+
+ self.model_storage.service.delete(service)
+
+ @staticmethod
+ def _parse_service_template(service_template_path):
+ context = consumption.ConsumptionContext()
+ context.presentation.location = UriLocation(service_template_path)
+ # Most of the parser uses the topology package in order to manipulate the models.
+ # However, here we use the Consumer mechanism, but this should change in the future.
+ consumption.ConsumerChain(
+ context,
+ (
+ consumption.Read,
+ consumption.Validate,
+ consumption.ServiceTemplate
+ )).consume()
+ if context.validation.dump_issues():
+ raise exceptions.ParsingError('Failed to parse service template')
+ return context