From c454fb83b95185aefc28ac55d9e3859c591f4602 Mon Sep 17 00:00:00 2001 From: Mike Fedosin Date: Tue, 18 Apr 2017 13:29:12 +0300 Subject: [PATCH] Add architecture documentation Change-Id: I52868375cbf82a9f4b320d3a9d5229c63d13ca96 --- doc/source/architecture.rst | 95 +- doc/source/images/glare-architecture.png | Bin 0 -> 41233 bytes .../images_src/glare-architecture.graphml | 876 ++++++++++++++++++ tox.ini | 1 + 4 files changed, 970 insertions(+), 2 deletions(-) create mode 100644 doc/source/images/glare-architecture.png create mode 100644 doc/source/images_src/glare-architecture.graphml diff --git a/doc/source/architecture.rst b/doc/source/architecture.rst index 3837742..15738b6 100644 --- a/doc/source/architecture.rst +++ b/doc/source/architecture.rst @@ -1,2 +1,93 @@ -Architecture -============ +.. + Copyright 2017 - Nokia Networks + All Rights Reserved. + + Licensed 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. + +================== +Basic architecture +================== + +OpenStack Glare has a client-server architecture that provides a Unified REST API, +which then transfers control to the appropriate artifact type. The API consists of + * *Router*, that converts WSGI requests into appropriate Glare API methods; + * *Deserializer*, that parses parameters from user input and performs initial + validation checks; + * *Controller*, which is responsible for interactions with Glare Engine; + * *Serializer*, that prepares information for responses (inserts status code, + content-type, response content length, and so on). + +But before the requests reach the API they have to pass trough the set of +middlewares, and each performs some actions over Request or Response objects. +For example, *Auth* middleware checks that authentication token provided in request +header is valid by sending auth requests to Identity service, obtains user +information and injects it in Request object as a context objects; +*Fault middleware*, on the other hand, is responsible for converting inner +Glare exceptions to appropriate http error codes. + +Almost all business logic is provided by Glare *Engine*. It is responsible +for *Policy* checking, when operator may define what operations users may execute, +based on their contexts; for sending broadcast *Notifications* about performed +actions; then it is *Access Control*, when Engine checks if user has rights to +modify desired artifact; and finally – *Locking*, that is used to prevent race +conditions during artifact updates, when the artifact is locked until the +modification operation is finished. + +All the file (Blob data) operations are performed using +*glance_store* library, which is responsible for interaction with external +storage back ends and (or) local filesystem(s). The glance_store library +provides a uniform interface to access the backend stores. Also there is +an adapter layer *Store Manager* between Engine and glance_store that is +responsible for converting glance_store exceptions and adding some additional +logic, like sha256 calculation. + +All database operations are organized with artifact types. Each type installed +in the system must implement Glare Artifact Type Interface (GATI) and use +appropriate data types to describe its attributes. + +Glare uses several data types from a declarative framework *oslo.versionedobjects*: +Integer, Float, String, Boolean, which complemented with the following home-grown +data types: + * Version — specifies the version of the artifact in ‘SemVer’ format and + implements comparison operations. + * Dependency — sets a reference to another artifact. At the request of the + ‘dependency’ field, Glare will get the dependent artifact meta-information. + * Blob — specifies a binary object. When a user assigns a value to this field, + data will be automatically redirected to one of the connected storages. + * List and Dict — define complex data structures such as Lists and Dictionaries + of primitive types respectively. + +*Base artifact type* is an abstract class that has a reference implementation +of GATI. It contains only common fields, like "id", "name", "version", +"created_at”, "owner", and so on. + +Each artifact type is inherited from the Base and adds some additional fields. +For example, for Image artifact type there were added "container_format" and +"disk_format" string fields, for Heat Template it was "nested_templates" Blob +Dictionary. + +*Validators* are objects that can be attached to a filed to perform additional +checks. For example, if validator MinLen(1) is attached to a string field it +checks that the string value is non empty. Validator ForbiddenChars("/", ",") +validates that there shouldn't be slashes and commas in the string. + +Glare uses a central *Database* that is shared amongst all +the components in the system and is sql-based by default. Other types +of database backends are somewhat supported and used by operators +but are not extensively tested upstream. + +.. figure:: ./images/glare-architecture.png + :figwidth: 100% + :align: center + +.. centered:: Image 1. OpenStack Glare Architecture diff --git a/doc/source/images/glare-architecture.png b/doc/source/images/glare-architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..64b491f6ab16e018453dc9dfb3b3d72d9af9ba53 GIT binary patch literal 41233 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 literal 0 HcmV?d00001 diff --git a/doc/source/images_src/glare-architecture.graphml b/doc/source/images_src/glare-architecture.graphml new file mode 100644 index 0000000..283cc79 --- /dev/null +++ b/doc/source/images_src/glare-architecture.graphml @@ -0,0 +1,876 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Glare Service + + + + + + + + + + Folder 6 + + + + + + + + + + + + + + + + + + + Middlewares + + + + + + + + + + Folder 1 + + + + + + + + + + + + + + + + Auth Middleware + + + + + + + + + + + + + + + + + Fault Middleware + + + + + + + + + + + + + + + + + + + + + + API + + + + + + + + + + Folder 2 + + + + + + + + + + + + + + + + Router + + + + + + + + + + + + + + + + + Deserializer + + + + + + + + + + + + + + + + + Controller + + + + + + + + + + + + + + + + + Serializer + + + + + + + + + + + + + + + + + + + Engine + + + + + + + + + + + + + + + + + + + + Utils + + + + + + + + + + Folder 3 + + + + + + + + + + + + + + + + PolicyEnforcer + + + + + + + + + + + + + + + + + Notifier + + + + + + + + + + + + + + + + + Access Control + + + + + + + + + + + + + + + + + Locking + + + + + + + + + + + + + + + + + + + + + + Store + + + + + + + + + + Folder 4 + + + + + + + + + + + + + + + + Store Manager + + + + + + + + + + + + + + + + + glance_store + + + + + + + + + + + + + + + + + + + + + + Objects + + + + + + + + + + Folder 5 + + + + + + + + + + + + + + + + Fields + + + + + + + + + + + + + + + + + Validators + + + + + + + + + + + + + + + + + Base Artifact + + + + + + + + + + + + + + + + + Images + + + + + + + + + + + + + + + + + Heat Templates + + + + + + + + + + + + + + + + + + + DB api + + + + + + + + + + + + + + + + + oslo.vo Base + + + + + + + + + + + + + + + + + + + + + + + Cloud storages + + + + + + + + + + Folder 7 + + + + + + + + + + + + + + + + Swift + + + + + + + + + + + + + + + + + Ceph + + + + + + + + + + + + + + + + + + + + Database + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tox.ini b/tox.ini index 9664bff..451c75d 100644 --- a/tox.ini +++ b/tox.ini @@ -51,6 +51,7 @@ commands = oslopolicy-sample-generator --namespace=glare --output-file=etc/policy.yaml.sample [testenv:docs] +basepython = python2.7 commands = python setup.py build_sphinx [testenv:bandit]