diff --git a/bootstrap/playbooks/solar.yaml b/bootstrap/playbooks/solar.yaml index 81347ce8..3c8181ad 100644 --- a/bootstrap/playbooks/solar.yaml +++ b/bootstrap/playbooks/solar.yaml @@ -51,3 +51,4 @@ tasks: - file: path=/var/lib/solar/repositories state=directory - file: src=/vagrant/resources dest=/var/lib/solar/repositories/resources state=link + - file: src=/vagrant/templates dest=/var/lib/solar/repositories/templates state=link diff --git a/solar/cli/resource.py b/solar/cli/resource.py index 3ae5adb8..47045977 100644 --- a/solar/cli/resource.py +++ b/solar/cli/resource.py @@ -134,8 +134,7 @@ def clear_all(): @resource.command() @click.argument('name') -@click.argument( - 'base_path', type=click.Path(exists=True, resolve_path=True)) +@click.argument('base_path') @click.argument('args', nargs=-1) def create(args, base_path, name): args_parsed = {} diff --git a/solar/core/resource/repository.py b/solar/core/resource/repository.py index 702a1c70..29344309 100644 --- a/solar/core/resource/repository.py +++ b/solar/core/resource/repository.py @@ -17,12 +17,18 @@ from collections import defaultdict import errno import os +import re import semver import shutil + +from enum import Enum from solar import utils +RES_TYPE = Enum("Resource Types", 'Normal Virtual') + + class RepositoryException(Exception): pass @@ -66,22 +72,29 @@ class Repository(object): def _list_source_contents(self, source): for pth in os.listdir(source): single_path = os.path.join(source, pth) - if os.path.exists(os.path.join(single_path, 'meta.yaml')): - yield pth, single_path + if pth.endswith('.yaml'): + pth = pth[:-5] + yield RES_TYPE.Virtual, pth, single_path + elif os.path.exists(os.path.join(single_path, 'meta.yaml')): + yield RES_TYPE.Normal, pth, single_path else: if not os.path.isdir(single_path): continue for single in os.listdir(single_path): - try: - semver.parse(single) - except ValueError: + if single.endswith('.yaml'): fp = os.path.join(single_path, single) - raise RepositoryException("Invalid repository" - "content: %r" % fp) + yield RES_TYPE.Virtual, pth, fp else: - fp = os.path.join(single_path, single) - if os.path.exists(os.path.join(fp, 'meta.yaml')): - yield pth, fp + try: + semver.parse(single) + except ValueError: + fp = os.path.join(single_path, single) + raise RepositoryException("Invalid repository" + "content: %r" % fp) + else: + fp = os.path.join(single_path, single) + if os.path.exists(os.path.join(fp, 'meta.yaml')): + yield RES_TYPE.Normal, pth, fp @classmethod def repo_path(cls, repo_name): @@ -105,8 +118,11 @@ class Repository(object): def _add_contents(self, source, overwrite=False): cnts = self._list_source_contents(source) - for single_name, single_path in cnts: - self.add_single(single_name, single_path, overwrite) + for res_type, single_name, single_path in cnts: + if res_type is RES_TYPE.Normal: + self.add_single(single_name, single_path, overwrite) + else: + self.add_single_vr(single_name, single_path, overwrite) def add_single(self, name, source, overwrite=False): try: @@ -129,6 +145,32 @@ class Repository(object): shutil.rmtree(target_path) shutil.copytree(source, target_path, symlinks=True) + def add_single_vr(self, name, source, overwrite=False): + # with open(source, 'rb') as f: + # parsed = yaml.safe_load(f.read()) + # version = parsed.get('version', '1.0.0') + version = '1.0.0' + with open(source, 'rb') as f: + data = f.read() + regex = re.compile('^version.*\:(?P.+)') + m = regex.search(data) + if m: + v_file = m.group("version") + if v_file: + version = v_file + target_dir = os.path.join(self.fpath, name, version) + target_path = os.path.join(target_dir, "{}.yaml".format(name)) + os.makedirs(target_dir) + try: + shutil.copy(source, target_path) + except OSError as e: + if e.errno != errno.EEXIST: + raise + if not overwrite: + raise + shutil.rm(target_dir) + shutil.copy(source, target_path) + def remove(self): shutil.rmtree(self.fpath) @@ -280,3 +322,11 @@ class Repository(object): def parse(cls, spec): spec = cls._parse_spec(spec) return Repository(spec['repo']), spec + + def is_virtual(self, spec): + return os.path.exists(self.get_virtual_path(spec)) + + def get_virtual_path(self, spec): + spec = self._parse_spec(spec) + p = self.get_path(spec) + return os.path.join(p, "{}.yaml".format(spec['resource_name'])) diff --git a/solar/core/resource/virtual_resource.py b/solar/core/resource/virtual_resource.py index d2dcc3b5..d9548570 100644 --- a/solar/core/resource/virtual_resource.py +++ b/solar/core/resource/virtual_resource.py @@ -14,17 +14,19 @@ # under the License. from collections import defaultdict -import os from StringIO import StringIO from jinja2 import Environment from jinja2 import meta + +import os import yaml from solar.core.log import log from solar.core import provider from solar.core.resource import load as load_resource from solar.core.resource import load_by_tags +from solar.core.resource.repository import Repository from solar.core.resource import Resource from solar.events.api import add_event from solar.events.controls import Dep @@ -45,8 +47,27 @@ def create(name, spec, args=None, tags=None, virtual_resource=None): if isinstance(spec, provider.BaseProvider): spec = spec.directory - if is_virtual(spec): - template = _compile_file(name, spec, args) + # fullpath + # TODO: (jnowak) find a better way to code this part + if spec.startswith('/'): + if os.path.isfile(spec): + template = _compile_file(name, spec, args) + yaml_template = yaml.load(StringIO(template)) + rs = create_virtual_resource(name, yaml_template, tags) + else: + r = create_resource(name, + spec, + args=args, + tags=tags, + virtual_resource=virtual_resource) + rs = [r] + return rs + + repo, parsed_spec = Repository.parse(spec) + + if repo.is_virtual(spec): + path = repo.get_virtual_path(spec) + template = _compile_file(name, path, args) yaml_template = yaml.load(StringIO(template)) rs = create_virtual_resource(name, yaml_template, tags) else: @@ -126,10 +147,6 @@ def _get_template(name, content, kwargs, inputs): return template -def is_virtual(path): - return os.path.isfile(path) - - def create_resources(resources, tags=None): created_resources = [] for r in resources: @@ -141,7 +158,11 @@ def create_resources(resources, tags=None): tags = r.get('tags', []) new_resources = create(resource_name, spec, args=args, tags=tags) created_resources += new_resources - if not is_virtual(spec): + is_virtual = False + if not spec.startswith('/'): + repo, parsed_spec = Repository.parse(spec) + is_virtual = repo.is_virtual(spec) + if not is_virtual: if node: node = load_resource(node) r = new_resources[0] diff --git a/templates/controller.yaml b/templates/controller/1.0.0/controller.yaml similarity index 100% rename from templates/controller.yaml rename to templates/controller/1.0.0/controller.yaml diff --git a/templates/glance.yaml b/templates/glance/1.0.0/glance.yaml similarity index 100% rename from templates/glance.yaml rename to templates/glance/1.0.0/glance.yaml diff --git a/templates/glance_base.yaml b/templates/glance_base/1.0.0/glance_base.yaml similarity index 100% rename from templates/glance_base.yaml rename to templates/glance_base/1.0.0/glance_base.yaml diff --git a/templates/glance_db.yaml b/templates/glance_db/1.0.0/glance_db.yaml similarity index 100% rename from templates/glance_db.yaml rename to templates/glance_db/1.0.0/glance_db.yaml diff --git a/templates/glance_registry.yaml b/templates/glance_registry/1.0.0/glance_registry.yaml similarity index 100% rename from templates/glance_registry.yaml rename to templates/glance_registry/1.0.0/glance_registry.yaml diff --git a/templates/haproxy.yaml b/templates/haproxy/1.0.0/haproxy.yaml similarity index 100% rename from templates/haproxy.yaml rename to templates/haproxy/1.0.0/haproxy.yaml diff --git a/templates/keystone_api.yaml b/templates/keystone_api/1.0.0/keystone_api.yaml similarity index 100% rename from templates/keystone_api.yaml rename to templates/keystone_api/1.0.0/keystone_api.yaml diff --git a/templates/keystone_base.yaml b/templates/keystone_base/1.0.0/keystone_base.yaml similarity index 100% rename from templates/keystone_base.yaml rename to templates/keystone_base/1.0.0/keystone_base.yaml diff --git a/templates/mos_repos.yaml b/templates/mos_repos/1.0.0/mos_repos.yaml similarity index 100% rename from templates/mos_repos.yaml rename to templates/mos_repos/1.0.0/mos_repos.yaml diff --git a/templates/nodes.yaml b/templates/nodes/1.0.0/nodes.yaml similarity index 100% rename from templates/nodes.yaml rename to templates/nodes/1.0.0/nodes.yaml diff --git a/templates/nodes_network.yaml b/templates/nodes_network/1.0.0/nodes_network.yaml similarity index 100% rename from templates/nodes_network.yaml rename to templates/nodes_network/1.0.0/nodes_network.yaml diff --git a/templates/nodes_with_transports.yaml b/templates/nodes_with_transports/1.0.0/nodes_with_transports.yaml similarity index 100% rename from templates/nodes_with_transports.yaml rename to templates/nodes_with_transports/1.0.0/nodes_with_transports.yaml diff --git a/templates/not_provisioned_nodes.yaml b/templates/not_provisioned_nodes/1.0.0/not_provisioned_nodes.yaml similarity index 100% rename from templates/not_provisioned_nodes.yaml rename to templates/not_provisioned_nodes/1.0.0/not_provisioned_nodes.yaml diff --git a/templates/openstack_base.yaml b/templates/openstack_base/1.0.0/openstack_base.yaml similarity index 100% rename from templates/openstack_base.yaml rename to templates/openstack_base/1.0.0/openstack_base.yaml diff --git a/templates/profile.yaml b/templates/profile/1.0.0/profile.yaml similarity index 100% rename from templates/profile.yaml rename to templates/profile/1.0.0/profile.yaml diff --git a/templates/seed_node.yaml b/templates/seed_node/1.0.0/seed_node.yaml similarity index 100% rename from templates/seed_node.yaml rename to templates/seed_node/1.0.0/seed_node.yaml diff --git a/templates/sources.yaml b/templates/sources/1.0.0/sources.yaml similarity index 100% rename from templates/sources.yaml rename to templates/sources/1.0.0/sources.yaml