Compare commits

...

15 Commits

Author SHA1 Message Date
Timothée Floure 15d962bdf8
Rebase CI environment on alpine linux
continuous-integration/drone/push Build is passing Details
2022-05-22 12:05:15 +02:00
Timothée Floure f7fa25c2e5
Update bamboo and minor mix deps; fix synthax error in user module
continuous-integration/drone/push Build is passing Details
2022-05-21 18:47:56 +02:00
Timothée Floure 190b0827a2
Replace sr.ht builds by internal drone CI
continuous-integration/drone/push Build is failing Details
2022-05-21 18:38:33 +02:00
Timothée Floure 3f3c835598
VirtualMachineHosting* -> VirtualMachine* 2021-04-12 15:53:49 +02:00
Timothée Floure 11270fc7b1
VM dashboard - do not crash on missing configuration 2021-04-12 15:48:49 +02:00
Timothée Floure 82c12bd234
Rename from RecycledCloud / management to Meta 2021-04-12 15:44:12 +02:00
Timothée Floure 8e5ba0269f
Release 0.4.0 2021-04-09 11:38:38 +02:00
Timothée Floure 4a370a9952
Cleanup VM dashboard 2021-04-09 11:36:33 +02:00
Timothée Floure 65c9c07297
Wrap Odoo auth in try block 2021-04-07 17:24:21 +02:00
Timothée Floure 7e6439be67
Wire initial VM management frontend 2021-04-07 17:23:48 +02:00
Timothée Floure 053d5a3320
Fix mapping of lists in ONE Records, import both VM and VM_POOL
subrecords
2021-03-05 16:09:04 +01:00
Timothée Floure ae52442bd6
Add initial OpenNebula XML-RPC Api Integration 2021-02-11 14:34:40 +01:00
Timothée Floure 6938d7083c
Add credo linter 2021-02-08 15:26:00 +01:00
Timothée Floure 42d44160b5
Fix minor typo in captcha description, release v0.3.1 2021-02-03 13:56:00 +01:00
Timothée Floure 2250c87c6f
CI: fetch LDAP environment container before running tests 2021-02-03 13:18:18 +01:00
166 changed files with 7659 additions and 311 deletions

View File

@ -1,33 +0,0 @@
image: alpine/edge
packages:
- elixir
- postgresql
- postgresql-contrib
- docker
artifacts:
- management/_build/prod/rel/recycledcloud.tar.gz
sources:
- https://code.recycled.cloud/e-Durable/management.git
tasks:
- setup: |
sudo service postgresql setup
sudo service postgresql start
sudo service docker start
cd management
mix local.hex --force
mix local.rebar --force
mix deps.get
- build: |
cd management
MIX_ENV=test mix deps.compile
MIX_ENV=test mix compile
- test: |
cd management
CALL_CONTAINER_RUNTIME_AS_ROOT=1 LDAP_WAIT_LOOPS=100 MIX_ENV=test mix test
- release: |
cd management
MIX_ENV=prod mix compile
MIX_ENV=prod mix phx.digest
MIX_ENV=prod mix release
cd _build/prod/rel
tar cvzf recycledcloud.tar.gz recycledcloud/

35
.drone.yml Normal file
View File

@ -0,0 +1,35 @@
---
kind: pipeline
name: default
steps:
- name: build-release
image: alpine:3.15
environment:
MIX_ENV: prod
commands:
- apk add elixir git make gcc libc-dev
- mix local.hex --force
- mix local.rebar --force
- mix deps.get
- mix compile
- mix phx.digest
- mix release
- cd _build/prod/rel
- tar czf "meta-$(git describe --exact-match --tags $(git log -n1 --pretty='%h') || git rev-parse HEAD).tar.gz" meta/
- name: publish-release-archive
image: alpine:3.15
environment:
LFTP_PASSWORD:
from_secret: ssh_password
commands:
- apk add lftp openssh-client git
- cd _build/prod/rel
- mkdir ~/.ssh
- ssh-keyscan static.recycled.cloud > ~/.ssh/known_hosts
- lftp "sftp://artifacts:$LFTP_PASSWORD@static.recycled.cloud" -e "cd htdocs; put meta-$(git describe --exact-match --tags $(git log -n1 --pretty='%h') || git rev-parse HEAD).tar.gz; bye"
---
kind: secret
name: ssh_password
data: qdcw1yGdz1iDaGmovTD7Afj1piyjcZ/H4NXNKPpmUWgagBvA

View File

@ -1,3 +1,17 @@
# meta 0.5.0, not yet release
* Rename app from Recycled Cloud / management to Meta
# management 0.4.0, 2021-04-09
* Initial VM dashboard
* Various typo fixes and error catching.
# management 0.3.1, 2021-02-03
* Allow forgery on the support request form
* Fix minor typo in captcha description
# management 0.3.0, 2021-02-03
* Add minimal captcha module

View File

@ -1,6 +1,6 @@
# Recycled Cloud Management Interface
# Recycled Cloud Management Interface (Meta)
[![builds.sr.ht status](https://builds.sr.ht/~fnux.svg?search=recycledcloud-management)](https://builds.sr.ht/~fnux?search=recycledcloud-management)
[![builds.sr.ht status](https://builds.sr.ht/~fnux.svg?search=recycledcloud-meta)](https://builds.sr.ht/~fnux?search=recycledcloud-meta)
This repository tracks the initial work for a web interface atop the recycled
cloud. It is written in [Elixir](https://elixir-lang.org/), making use of the
@ -18,6 +18,7 @@ cloud. It is written in [Elixir](https://elixir-lang.org/), making use of the
* Authentication is based on José Valim and Aaron Renner's
[Phx.Gen.Auth](https://hex.pm/packages/phx_gen_auth), adapted for LDAP-backed
authentication.
* You can run the linter with `mix credo`.
## Getting Started

View File

@ -7,17 +7,17 @@
# General application configuration
use Mix.Config
config :recycledcloud,
namespace: RecycledCloud,
ecto_repos: [RecycledCloud.Repo],
config :meta,
namespace: Meta,
ecto_repos: [Meta.Repo],
enable_registration: true
# Configures the endpoint
config :recycledcloud, RecycledCloudWeb.Endpoint,
config :meta, MetaWeb.Endpoint,
url: [host: "localhost"],
secret_key_base: "bm4MGjSLcEbL3HEDg2H0LlcJ5d3nIkogyd/PpGW1iXdEbKbtM0N8Ct4Jh/PbsnoS",
render_errors: [view: RecycledCloudWeb.ErrorView, accepts: ~w(html json), layout: false],
pubsub_server: RecycledCloud.PubSub,
render_errors: [view: MetaWeb.ErrorView, accepts: ~w(html json), layout: false],
pubsub_server: Meta.PubSub,
live_view: [signing_salt: "kTyyWZd5"]
# Configures Elixir's Logger

View File

@ -1,10 +1,10 @@
use Mix.Config
# Configure your database
config :recycledcloud, RecycledCloud.Repo,
config :meta, Meta.Repo,
username: "postgres",
password: "postgres",
database: "recycledcloud_dev",
database: "meta_dev",
hostname: "localhost",
show_sensitive_data_on_connection_error: true,
pool_size: 10
@ -15,7 +15,7 @@ config :recycledcloud, RecycledCloud.Repo,
# The watchers configuration can be used to run external
# watchers to your application. For example, we use it
# with webpack to recompile .js and .css sources.
config :recycledcloud, RecycledCloudWeb.Endpoint,
config :meta, MetaWeb.Endpoint,
http: [port: 4000],
debug_errors: true,
code_reloader: true,
@ -47,13 +47,13 @@ config :recycledcloud, RecycledCloudWeb.Endpoint,
# different ports.
# Watch static and templates for browser reloading.
config :recycledcloud, RecycledCloudWeb.Endpoint,
config :meta, MetaWeb.Endpoint,
live_reload: [
patterns: [
~r"priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$",
~r"priv/gettext/.*(po)$",
~r"lib/recycledcloud_web/(live|views)/.*(ex)$",
~r"lib/recycledcloud_web/templates/.*(eex)$"
~r"lib/meta_web/(live|views)/.*(ex)$",
~r"lib/meta_web/templates/.*(eex)$"
]
]
@ -68,11 +68,11 @@ config :phoenix, :stacktrace_depth, 20
config :phoenix, :plug_init_mode, :runtime
# Send emails to local memory for development.
config :recycledcloud, RecycledCloud.Mailer,
config :meta, Meta.Mailer,
adapter: Bamboo.LocalAdapter
# LDAP configuration
config :recycledcloud, :ldap,
config :meta, :ldap,
server: "127.0.0.1",
port: 3089,
ssl: false,
@ -82,7 +82,7 @@ config :recycledcloud, :ldap,
default_group_gid: 1000
## Odoo API credentials
config :recycledcloud, :odoo,
config :meta, :odoo,
server: "https://odoo.staging.e-durable.ch",
database: "e-Durable",
user: "user",

View File

@ -9,7 +9,7 @@ use Mix.Config
# manifest is generated by the `mix phx.digest` task,
# which you should run after static files are built and
# before starting your production server.
config :recycledcloud, RecycledCloudWeb.Endpoint,
config :meta, MetaWeb.Endpoint,
url: [host: "example.com", port: 80],
cache_static_manifest: "priv/static/cache_manifest.json"
@ -21,7 +21,7 @@ config :logger, level: :info
# To get SSL working, you will need to add the `https` key
# to the previous section and set your `:url` port to 443:
#
# config :recycledcloud, RecycledCloudWeb.Endpoint,
# config :meta, MetaWeb.Endpoint,
# ...
# url: [host: "example.com", port: 443],
# https: [
@ -45,7 +45,7 @@ config :logger, level: :info
# We also recommend setting `force_ssl` in your endpoint, ensuring
# no data is ever sent via http, always redirecting to https:
#
# config :recycledcloud, RecycledCloudWeb.Endpoint,
# config :meta, MetaWeb.Endpoint,
# force_ssl: [hsts: true]
#
# Check `Plug.SSL` for all available options in `force_ssl`.

View File

@ -10,7 +10,7 @@ database_url =
For example: ecto://USER:PASS@HOST/DATABASE
"""
config :recycledcloud, RecycledCloud.Repo,
config :meta, Meta.Repo,
# ssl: true,
url: database_url,
pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10")
@ -22,7 +22,7 @@ secret_key_base =
You can generate one by calling: mix phx.gen.secret
"""
config :recycledcloud, RecycledCloudWeb.Endpoint,
config :meta, MetaWeb.Endpoint,
http: [
port: String.to_integer(System.get_env("PORT") || "4000"),
transport_options: [socket_opts: [:inet6]]
@ -34,7 +34,7 @@ config :recycledcloud, RecycledCloudWeb.Endpoint,
# If you are doing OTP releases, you need to instruct Phoenix
# to start each relevant endpoint:
#
config :recycledcloud, RecycledCloudWeb.Endpoint, server: true
config :meta, MetaWeb.Endpoint, server: true
#
# Then you can assemble a release by calling `mix release`.
# See `mix help release` for more information.

View File

@ -8,16 +8,16 @@ config :bcrypt_elixir, :log_rounds, 1
# The MIX_TEST_PARTITION environment variable can be used
# to provide built-in test partitioning in CI environment.
# Run `mix help test` for more information.
config :recycledcloud, RecycledCloud.Repo,
config :meta, Meta.Repo,
username: "postgres",
password: "postgres",
database: "recycledcloud_test#{System.get_env("MIX_TEST_PARTITION")}",
database: "meta_test#{System.get_env("MIX_TEST_PARTITION")}",
hostname: "localhost",
pool: Ecto.Adapters.SQL.Sandbox
# We don't run a server during test. If one is required,
# you can enable the server option below.
config :recycledcloud, RecycledCloudWeb.Endpoint,
config :meta, MetaWeb.Endpoint,
http: [port: 4002],
server: false
@ -25,7 +25,7 @@ config :recycledcloud, RecycledCloudWeb.Endpoint,
config :logger, level: :warn
# LDAP configuration
config :recycledcloud, :ldap,
config :meta, :ldap,
server: "127.0.0.1",
port: 3089,
ssl: false,
@ -34,5 +34,5 @@ config :recycledcloud, :ldap,
bind_pw: "admin"
# Send emails to local memory for testing.
config :recycledcloud, RecycledCloud.Mailer,
config :meta, Meta.Mailer,
adapter: Bamboo.LocalAdapter

View File

@ -1,6 +1,6 @@
defmodule RecycledCloud do
defmodule Meta do
@moduledoc """
RecycledCloud keeps the contexts that define your domain
Meta keeps the contexts that define your domain
and business logic.
Contexts are also responsible for managing your data, regardless

View File

@ -1,11 +1,11 @@
defmodule RecycledCloud.Accounts do
defmodule Meta.Accounts do
@moduledoc """
The Accounts context.
"""
import Ecto.Query, warn: false
alias RecycledCloud.Repo
alias RecycledCloud.Accounts.{User, Key, UserToken, UserNotifier}
alias Meta.Repo
alias Meta.Accounts.{User, Key, UserToken, UserNotifier}
## Database getters

View File

@ -1,4 +1,4 @@
defmodule RecycledCloud.Accounts.Key do
defmodule Meta.Accounts.Key do
use Ecto.Schema
import Ecto.Changeset
@ -6,7 +6,7 @@ defmodule RecycledCloud.Accounts.Key do
field :comment, :string
field :value, :string
field :fingerprint, :string
belongs_to :user, RecycledCloud.Accounts.User
belongs_to :user, Meta.Accounts.User
timestamps()
end

View File

@ -1,10 +1,10 @@
defmodule RecycledCloud.Accounts.User do
defmodule Meta.Accounts.User do
use Ecto.Schema
import Ecto.Changeset
require Logger
alias RecycledCloud.{LDAP,Accounts}
alias RecycledCloud.Accounts.User
alias RecycledCloud.Repo
alias Meta.{LDAP,Accounts}
alias Meta.Accounts.User
alias Meta.Repo
@min_password_lenght 6
@max_password_lenght 80
@ -74,7 +74,7 @@ defmodule RecycledCloud.Accounts.User do
defp create_ldap_user(%User{} = user) do
# TODO: read dn template from conf, gid_number
conf = Application.get_env(:recycledcloud, :ldap)
conf = Application.get_env(:meta, :ldap)
basetree = conf |> Keyword.get(:base_dn)
default_group_gid = conf |> Keyword.get(:default_group_gid, 1000)
@ -156,7 +156,7 @@ defmodule RecycledCloud.Accounts.User do
user
|> cast(attrs, [:username, :password, :email, :dn, :captcha])
|> RecycledCloud.Captcha.validate(expected_captcha_result)
|> Meta.Captcha.validate(expected_captcha_result)
|> validate_username()
|> validate_email()
|> validate_password()
@ -266,7 +266,7 @@ defmodule RecycledCloud.Accounts.User do
def set_password(%User{dn: nil} = _user, _), do: {:error, "User DN must be set"}
def set_password(_, nil), do: {:error, "Password cannot be nil"}
def set_password(%User{dn: dn} = _user, new_password) when
byte_size(new_password) > 0do
byte_size(new_password) do
query = fn ldap_conn ->
:eldap.modify_password(
ldap_conn,

View File

@ -1,5 +1,5 @@
defmodule RecycledCloud.Accounts.UserNotifier do
alias RecycledCloud.Mailer
defmodule Meta.Accounts.UserNotifier do
alias Meta.Mailer
import Bamboo.Email
defp deliver(to, body) do

View File

@ -1,4 +1,4 @@
defmodule RecycledCloud.Accounts.UserToken do
defmodule Meta.Accounts.UserToken do
use Ecto.Schema
import Ecto.Query
@ -16,7 +16,7 @@ defmodule RecycledCloud.Accounts.UserToken do
field :token, :binary
field :context, :string
field :sent_to, :string
belongs_to :user, RecycledCloud.Accounts.User
belongs_to :user, Meta.Accounts.User
timestamps(updated_at: false)
end
@ -28,7 +28,7 @@ defmodule RecycledCloud.Accounts.UserToken do
"""
def build_session_token(user) do
token = :crypto.strong_rand_bytes(@rand_size)
{token, %RecycledCloud.Accounts.UserToken{token: token, context: "session", user_id: user.id}}
{token, %Meta.Accounts.UserToken{token: token, context: "session", user_id: user.id}}
end
@doc """
@ -63,7 +63,7 @@ defmodule RecycledCloud.Accounts.UserToken do
hashed_token = :crypto.hash(@hash_algorithm, token)
{Base.url_encode64(token, padding: false),
%RecycledCloud.Accounts.UserToken{
%Meta.Accounts.UserToken{
token: hashed_token,
context: context,
sent_to: sent_to,
@ -123,17 +123,17 @@ defmodule RecycledCloud.Accounts.UserToken do
Returns the given token with the given context.
"""
def token_and_context_query(token, context) do
from RecycledCloud.Accounts.UserToken, where: [token: ^token, context: ^context]
from Meta.Accounts.UserToken, where: [token: ^token, context: ^context]
end
@doc """
Gets all tokens for the given user for the given contexts.
"""
def user_and_contexts_query(user, :all) do
from t in RecycledCloud.Accounts.UserToken, where: t.user_id == ^user.id
from t in Meta.Accounts.UserToken, where: t.user_id == ^user.id
end
def user_and_contexts_query(user, [_ | _] = contexts) do
from t in RecycledCloud.Accounts.UserToken, where: t.user_id == ^user.id and t.context in ^contexts
from t in Meta.Accounts.UserToken, where: t.user_id == ^user.id and t.context in ^contexts
end
end

View File

@ -1,4 +1,4 @@
defmodule RecycledCloud.Application do
defmodule Meta.Application do
# See https://hexdocs.pm/elixir/Application.html
# for more information on OTP Applications
@moduledoc false
@ -8,31 +8,31 @@ defmodule RecycledCloud.Application do
def start(_type, _args) do
children = [
# Start the Ecto repository
RecycledCloud.Repo,
Meta.Repo,
# Start the Telemetry supervisor
RecycledCloudWeb.Telemetry,
MetaWeb.Telemetry,
# Start the PubSub system
{Phoenix.PubSub, name: RecycledCloud.PubSub},
{Phoenix.PubSub, name: Meta.PubSub},
# Start the Endpoint (http/https)
RecycledCloudWeb.Endpoint,
MetaWeb.Endpoint,
# Starts LDAP connection pool
RecycledCloud.LDAP,
Meta.LDAP,
# Starts Odoo client
RecycledCloud.Odoo
# Start a worker by calling: RecycledCloud.Worker.start_link(arg)
# {RecycledCloud.Worker, arg}
Meta.Odoo
# Start a worker by calling: Meta.Worker.start_link(arg)
# {Meta.Worker, arg}
]
# See https://hexdocs.pm/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: RecycledCloud.Supervisor]
opts = [strategy: :one_for_one, name: Meta.Supervisor]
Supervisor.start_link(children, opts)
end
# Tell Phoenix to update the endpoint configuration
# whenever the application is updated.
def config_change(changed, _new, removed) do
RecycledCloudWeb.Endpoint.config_change(changed, removed)
MetaWeb.Endpoint.config_change(changed, removed)
:ok
end
end

View File

@ -1,6 +1,6 @@
defmodule RecycledCloud.Billing.Invoice do
alias RecycledCloud.Billing.{Partner, Invoice}
alias RecycledCloud.Odoo
defmodule Meta.Billing.Invoice do
alias Meta.Billing.{Partner, Invoice}
alias Meta.Odoo
use Ecto.Schema

View File

@ -1,8 +1,8 @@
defmodule RecycledCloud.Billing.Partner do
alias RecycledCloud.Accounts.User
alias RecycledCloud.Billing.Partner
alias RecycledCloud.Odoo
alias RecycledCloud.Repo
defmodule Meta.Billing.Partner do
alias Meta.Accounts.User
alias Meta.Billing.Partner
alias Meta.Odoo
alias Meta.Repo
import Ecto.Changeset
use Ecto.Schema

View File

@ -1,4 +1,4 @@
defmodule RecycledCloud.Captcha do
defmodule Meta.Captcha do
# We can't use a graphical-only captcha library such as
# https://hex.pm/packages/captcha since it would break accessibility for
# blind people. Let's make it simple maths instead!

View File

@ -1,4 +1,4 @@
defmodule RecycledCloud.LDAP do
defmodule Meta.LDAP do
require Logger
use GenServer
@ -54,7 +54,7 @@ defmodule RecycledCloud.LDAP do
###
def search(ldap_conn, field, value, search_timeout \\ 1000) do
base_dn = Application.get_env(:recycledcloud, :ldap) |> Keyword.get(:base_dn)
base_dn = Application.get_env(:meta, :ldap) |> Keyword.get(:base_dn)
opts = [
{:base, to_charlist(base_dn)},
{:scope, :eldap.wholeSubtree()},
@ -89,7 +89,7 @@ defmodule RecycledCloud.LDAP do
defp internal_execute_query(query, ldap_conn), do: query.(ldap_conn)
defp bind(ldap_conn) do
conf = Application.get_env(:recycledcloud, :ldap, [])
conf = Application.get_env(:meta, :ldap, [])
dn = conf |> Keyword.get(:bind_dn)
pw = conf |> Keyword.get(:bind_pw)
@ -98,7 +98,7 @@ defmodule RecycledCloud.LDAP do
# The method is used by the RC.LDAPTestEnvironment module.
def connect do
conf = Application.get_env(:recycledcloud, :ldap, [])
conf = Application.get_env(:meta, :ldap, [])
host = Keyword.get(conf, :server, "localhost") |> String.to_charlist
opts = [

View File

@ -1,5 +1,5 @@
defmodule RecycledCloud.Mailer do
use Bamboo.Mailer, otp_app: :recycledcloud
defmodule Meta.Mailer do
use Bamboo.Mailer, otp_app: :meta
import Bamboo.Email
@from "no-reply@recycled.cloud"

View File

@ -1,4 +1,4 @@
defmodule RecycledCloud.Odoo do
defmodule Meta.Odoo do
use GenServer
require Logger
@ -8,7 +8,7 @@ defmodule RecycledCloud.Odoo do
# Odoo 14.0 API is documented at https://www.odoo.com/documentation/14.0/webservices/odoo.html
defp get_odoo_config(key) do
Application.get_env(:recycledcloud, :odoo, []) |> Keyword.get(key)
Application.get_env(:meta, :odoo, []) |> Keyword.get(key)
end
defp post!(call, endpoint) do
@ -32,12 +32,15 @@ defmodule RecycledCloud.Odoo do
nil
]
auth_response = %XMLRPC.MethodCall{method_name: "authenticate", params: auth_params}
|> post!(@common_endpoint)
case auth_response do
{:ok, false} -> {:error, "Could not authenticate against Odoo."}
{:ok, uid} -> {:ok, uid}
{:error, err} -> {:error, err}
try do
auth_response = %XMLRPC.MethodCall{method_name: "authenticate", params: auth_params}
|> post!(@common_endpoint)
case auth_response do
{:ok, false} -> {:error, "Could not authenticate against Odoo."}
{:ok, uid} -> {:ok, uid}
{:error, err} -> {:error, err}
end
rescue e -> {:error, e}
end
end

91
lib/meta/opennebula.ex Normal file
View File

@ -0,0 +1,91 @@
defmodule Meta.OpenNebula do
@moduledoc """
The OpenNebula context and XML-RPC Interface.
See http://docs.opennebula.io/5.12/integration/system_interfaces/api.html for details.
"""
alias Meta.OpenNebula.{VM, VMPool}
require Logger
# OpenNebula daemon.
@endpoint "/RPC2"
defp get_opennebula_config(key, default \\ nil) do
Application.get_env(:meta, :opennebula, []) |> Keyword.get(key, default)
end
def get_locations() do
get_opennebula_config(:locations, [])
|> Enum.map(fn m -> Map.get(m, :name) end)
end
def get_location_config(name) do
get_opennebula_config(:locations)
|> Enum.find(fn m -> Map.get(m, :name) == name end)
end
##
# Related to XML-RPC calls
defp post(url, request) do
opts = []
headers = []
body = request |> XMLRPC.encode!
query = HTTPoison.post(url, body, headers, opts)
case query do
{:ok, response} ->
case response.body |> XMLRPC.decode! do
%{fault_code: _, fault_string: err} -> {:error, err}
%{param: [false, err | _]} -> {:error, err}
%{param: [true, result | _]} -> {:ok, result}
end
{:error, %HTTPoison.Error{id: nil, reason: reason}} ->
Logger.warn("Error querying OpenNebula: #{inspect(reason)}")
{:error, reason}
end
end
def query(location, method, params) do
user = Map.get(get_location_config(location), :user)
password = Map.get(get_location_config(location), :password)
auth_string = "#{user}:#{password}"
request = %XMLRPC.MethodCall{
method_name: method,
params: [auth_string | params]
}
address = get_location_config(location) |> Map.get(:xmlrpc_address)
post(address <> @endpoint, request)
end
##
# Public / external calls.
def get_vm(location, id), do: VM.get(id).(location)
def get_vms_for_user(location, username) do
call = VMPool.get(%{
filter_flag: :all,
range_start: :infinite,
range_end: :infinite,
state_filter: VM.state_for(:any_except_done),
kv_filter: ""
})
case call.(location) do
{:ok, %{VM: vms}} ->
Enum.filter(vms,
fn vm -> List.to_string(Map.get(vm, :UNAME)) == username end)
{:error, _err} -> %{}
end
end
def get_vms_for_user(username) do
get_locations()
|> Enum.map(fn l -> %{l => get_vms_for_user(l, username)} end)
|> Enum.reduce(%{}, &Map.merge/2)
end
end

View File

@ -0,0 +1,99 @@
defmodule Meta.OpenNebula.Schema do
@moduledoc """
Helpers used to process OpenNebula's XSD schema.
,.
/,,;';;. ,;;;.. ,,;. '
.','' `::;:' ``;;;;' `..'
` ,,/' ,,//
Here be dragons! We import the records from Erlang header files (.hrl)
generated by erlsom as macros in the Records module. The only way I found to
programatically call a macro (apply/3 only works with functions) is by
playing around with the AST to template said call...
I'm not fond of this as it makes things more complex than I would like them
to be, but likely the easiest way to user erlsom's data binder from elixir
(and it's not *that* bad). The ideal would be to generate elixir structs from
source XSD files, but it would take much more work.
Heavily inspired from Gary Poster's:
http://codesinger.blogspot.com/2015/12/elixir-erlang-records-and-erlsom-xml.html
I stole the dragon art from ASCII.co.uk.
"""
require Logger
alias Meta.OpenNebula.Schema
alias Meta.OpenNebula.Schema.Records
@opennebula_release "5.12"
##
# Data-binding: access and extract XSD models.
defp get_raw(type, object) do
priv_dir = :code.priv_dir(:meta) |> to_string
{data_dir, extension} = case type do
:xsd -> {"xsd-src", ".xsd"}
:hrl -> {"xsd-records", ".hrl"}
end
raw_path = [priv_dir, "opennebula", @opennebula_release, data_dir, object <> extension]
raw_path |> Path.join()
end
def get_xsd_for(object), do: get_raw(:xsd, object)
def get_hrl_for(object), do: get_raw(:hrl, object)
def generate_model_for(object) do
{:ok, model} = object
|> get_xsd_for()
|> :erlsom.compile_xsd_file()
model
end
##
# Data-binding: transform erlsom records to Elixir maps.
def scan(raw, object_type) do
{:ok, data, _rest} = :erlsom.scan(raw, Records.get_model_for(object_type))
data
end
defp transform_value({k, l}) when is_list(l) do
{k, Enum.map(l, fn v -> map_record(v) end)}
end
defp transform_value({k, v}), do: {k, map_record(v)}
# Here be dragons! See moduledoc.
def map_record(data) when is_tuple(data) do
schema = elem(data, 0)
if schema in Keyword.keys(Schema.Records.__info__(:macros)) do
call = quote do
require Meta.OpenNebula.Schema.Records
Meta.OpenNebula.Schema.Records."XSD"(:data)
end
replace = fn
:XSD, {model, data} -> {model, {model, data}}
:data, {model, data} -> {data, {model, data}}
node, stubs -> {node, stubs}
end
{{inserted, _raw}, []} = call
|> Macro.prewalk({schema, Macro.escape(data)}, replace)
|> Code.eval_quoted()
Enum.into(inserted, Map.new, &transform_value/1)
else
Logger.debug("Ignoring unknown OpenNebula Model #{schema}.")
data
end
end
def map_record(data = [first | _rest]) when is_integer(first), do:
List.to_string(data)
def map_record(:undefined), do: nil
def map_record(data), do: data
end

View File

@ -0,0 +1,33 @@
defmodule Meta.OpenNebula.Schema.Records do
@moduledoc """
Here we define XSD template into something we can play with (Records).
Records are not usually used in elixir except for integrating with erlang
code - which is what we're doing right now: the records are defined in .hrl
(erlang headers) by erlsom.
See Meta.OpenNebula.Schema module for details.
"""
require Record
alias Meta.OpenNebula.Schema
@models %{
"vm" => Schema.generate_model_for("vm"),
"vm_pool" => Schema.generate_model_for("vm_pool")
}
def get_model_for(object), do: Map.get(@models, object)
extract = fn name, acc -> Record.extract_all(from: Schema.get_hrl_for(name)) ++ acc end
sources = ["vm", "vm_pool"]
|> Enum.reduce([], extract)
|> Enum.sort_by(fn {name, _} -> name end)
|> Enum.dedup_by(fn {name, _} -> name end)
#IO.inspect sources |> Enum.dedup_by(fn {, _} -> name end)
for {name, record} <- sources do
Record.defrecord name, record
end
end

195
lib/meta/opennebula/vm.ex Normal file
View File

@ -0,0 +1,195 @@
defmodule Meta.OpenNebula.VM do
@moduledoc """
OpenNebula VM: http://docs.opennebula.io/5.12/integration/system_interfaces/api.html#one-vm-info
"""
alias Meta.OpenNebula, as: ONE
alias Meta.OpenNebula.Schema
@states [
{:any, -2},
{:any_except_done, -1},
{:init, 0},
{:pending, 1},
{:hold, 2},
{:active, 3},
{:stopped, 4},
{:suspended, 5},
{:done, 6},
{:failure, 7},
{:poweroff, 8},
{:undeployed, 9},
{:cloning, 10},
{:cloning_failure, 11}
]
@lcm_states [
{:LCM_INIT , 0},
{:PROLOG , 1},
{:BOOT , 2},
{:RUNNING , 3},
{:MIGRATE , 4},
{:SAVE_STOP , 5},
{:SAVE_SUSPEND , 6},
{:SAVE_MIGRATE , 7},
{:PROLOG_MIGRATE , 8},
{:PROLOG_RESUME , 9},
{:EPILOG_STOP , 10},
{:EPILOG , 11},
{:SHUTDOWN , 12},
{:CLEANUP_RESUBMIT , 15},
{:UNKNOWN , 16},
{:HOTPLUG , 17},
{:SHUTDOWN_POWEROFF , 18},
{:BOOT_UNKNOWN , 19},
{:BOOT_POWEROFF , 20},
{:BOOT_SUSPENDED , 21},
{:BOOT_STOPPED , 22},
{:CLEANUP_DELETE , 23},
{:HOTPLUG_SNAPSHOT , 24},
{:HOTPLUG_NIC , 25},
{:HOTPLUG_SAVEAS , 26},
{:HOTPLUG_SAVEAS_POWEROFF , 27},
{:HOTPLUG_SAVEAS_SUSPENDED , 28},
{:SHUTDOWN_UNDEPLOY , 29},
{:EPILOG_UNDEPLOY , 30},
{:PROLOG_UNDEPLOY , 31},
{:BOOT_UNDEPLOY , 32},
{:HOTPLUG_PROLOG_POWEROFF , 33},
{:HOTPLUG_EPILOG_POWEROFF , 34},
{:BOOT_MIGRATE , 35},
{:BOOT_FAILURE , 36},
{:BOOT_MIGRATE_FAILURE , 37},
{:PROLOG_MIGRATE_FAILURE , 38},
{:PROLOG_FAILURE , 39},
{:EPILOG_FAILURE , 40},
{:EPILOG_STOP_FAILURE , 41},
{:EPILOG_UNDEPLOY_FAILURE , 42},
{:PROLOG_MIGRATE_POWEROFF , 43},
{:PROLOG_MIGRATE_POWEROFF_FAILURE, 44},
{:PROLOG_MIGRATE_SUSPEND , 45},
{:PROLOG_MIGRATE_SUSPEND_FAILURE , 46},
{:BOOT_UNDEPLOY_FAILURE , 47},
{:BOOT_STOPPED_FAILURE , 48},
{:PROLOG_RESUME_FAILURE , 49},
{:PROLOG_UNDEPLOY_FAILURE , 50},
{:DISK_SNAPSHOT_POWEROFF , 51},
{:DISK_SNAPSHOT_REVERT_POWEROFF , 52},
{:DISK_SNAPSHOT_DELETE_POWEROFF , 53},
{:DISK_SNAPSHOT_SUSPENDED , 54},
{:DISK_SNAPSHOT_REVERT_SUSPENDED , 55},
{:DISK_SNAPSHOT_DELETE_SUSPENDED , 56},
{:DISK_SNAPSHOT , 57},
{:DISK_SNAPSHOT_DELETE , 59},
{:PROLOG_MIGRATE_UNKNOWN , 60},
{:PROLOG_MIGRATE_UNKNOWN_FAILURE , 61},
]
@actions [
"terminate-hard",
"terminate",
"undeploy-hard",
"undeploy",
"poweroff-hard",
"poweroff",
"reboot-hard",
"reboot",
"hold",
"release",
"stop",
"suspend",
"resume",
"resched",
"unresched"
]
@events [
{:NONE_ACTION , 0},
{:MIGRATE_ACTION , 1},
{:LIVE_MIGRATE_ACTION , 2},
{:SHUTDOWN_ACTION , 3},
{:SHUTDOWN_HARD_ACTION , 4},
{:UNDEPLOY_ACTION , 5},
{:UNDEPLOY_HARD_ACTION , 6},
{:HOLD_ACTION , 7},
{:RELEASE_ACTION , 8},
{:STOP_ACTION , 9},
{:SUSPEND_ACTION , 10},
{:RESUME_ACTION , 11},
{:BOOT_ACTION , 12},
{:DELETE_ACTION , 13},
{:DELETE_RECREATE_ACTION , 14},
{:REBOOT_ACTION , 15},
{:REBOOT_HARD_ACTION , 16},
{:RESCHED_ACTION , 17},
{:UNRESCHED_ACTION , 18},
{:POWEROFF_ACTION , 19},
{:POWEROFF_HARD_ACTION , 20},
{:DISK_ATTACH_ACTION , 21},
{:DISK_DETACH_ACTION , 22},
{:NIC_ATTACH_ACTION , 23},
{:NIC_DETACH_ACTION , 24},
{:DISK_SNAPSHOT_CREATE_ACTION , 25},
{:DISK_SNAPSHOT_DELETE_ACTION , 26},
{:TERMINATE_ACTION , 27},
{:TERMINATE_HARD_ACTION , 28},
{:DISK_RESIZE_ACTION , 29},
{:DEPLOY_ACTION , 30},
{:CHOWN_ACTION , 31},
{:CHMOD_ACTION , 32},
{:UPDATECONF_ACTION , 33},
{:RENAME_ACTION , 34},
{:RESIZE_ACTION , 35},
{:UPDATE_ACTION , 36},
{:SNAPSHOT_CREATE_ACTION , 37},
{:SNAPSHOT_DELETE_ACTION , 38},
{:SNAPSHOT_REVERT_ACTION , 39},
{:DISK_SAVEAS_ACTION , 40},
{:DISK_SNAPSHOT_REVERT_ACTION , 41},
{:RECOVER_ACTION , 42},
{:RETRY_ACTION , 43},
{:MONITOR_ACTION , 44},
{:DISK_SNAPSHOT_RENAME_ACTION , 45},
{:ALIAS_ATTACH_ACTION , 46},
{:ALIAS_DETACH_ACTION , 47},
]
defp find(table, state) when is_integer(state) do
case Enum.find(table, fn {_atom, value} -> value == state end) do
{atom, _value} -> atom
nil -> nil
end
end
def state_for(state) when is_atom(state), do: @states |> Keyword.get(state)
def state_for(state) when is_integer(state), do: find(@states, state)
def lcm_state_for(state) when is_integer(state), do: find(@lcm_states, state)
def event_for(event) when is_integer(event) do
case Enum.find(@events, fn {_atom, value} -> value == event end) do
{atom, _value} -> atom
nil -> nil
end
end
def get(id) do
fn location ->
case ONE.query(location, "one.vm.info", [id]) do
{:ok, raw} ->
data = raw
|> Schema.scan("vm")
|> Schema.map_record
{:ok, data}
{:error, err} -> {:error, err}
end
end
end
def execute(vm_id, action) when action in @actions do
fn location ->
case ONE.query(location, "one.vm.action", [action, vm_id]) do
{:ok, _raw} -> :ok
{:error, err} -> {:error, err}
end
end
end
end

View File

@ -0,0 +1,55 @@
defmodule Meta.OpenNebula.VMPool do
@moduledoc """
OpenNebula VM Pool: http://docs.opennebula.io/5.12/integration/system_interfaces/api.html#one-vmpool-info
"""
alias Meta.OpenNebula, as: ONE
alias Meta.OpenNebula.Schema
# Filters ressourses.
# (user) ID >= 0 matches an user's resources.
@filter_flags [
{:user_primary_group, -4},
{:user, -3},
{:all, -2},
{:user_and_groups, -1}
]
def get(%{filter_flag: filter_flag} = params) when is_atom(filter_flag) do
params
|> Map.put(:filter_flag, Keyword.get(@filter_flags, filter_flag))
|> get()
end
def get(%{range_start: :infinite} = params) do
params |> Map.put(:range_start, -1) |> get()
end
def get(%{range_end: :infinite} = params) do
params |> Map.put(:range_end, -1) |> get()
end
def get(%{state_filter: state} = params) when is_atom(state) do
params |> Map.put(:state_filter, ONE.VM.state_for(state)) |> get()
end
def get(%{
filter_flag: filter_flag,
range_start: range_start,
range_end: range_end,
state_filter: state,
kv_filter: kv_filter
}) do
fn location ->
params = [filter_flag, range_start, range_end, state, kv_filter]
case ONE.query(location, "one.vmpool.info", params) do
{:ok, raw} ->
data = raw
|> Schema.scan("vm_pool")
|> Schema.map_record
{:ok, data}
{:error, err} -> {:error, err}
end
end
end
end

View File

@ -1,5 +1,5 @@
defmodule RecycledCloud.Release do
@app :recycledcloud
defmodule Meta.Release do
@app :meta
def migrate do
load_app()

5
lib/meta/repo.ex Normal file
View File

@ -0,0 +1,5 @@
defmodule Meta.Repo do
use Ecto.Repo,
otp_app: :meta,
adapter: Ecto.Adapters.Postgres
end

View File

@ -1,11 +1,11 @@
defmodule RecycledCloud.SupportRequest do
defmodule Meta.SupportRequest do
use Ecto.Schema
import Ecto.Changeset
import Bamboo.Email
alias RecycledCloud.SupportRequest
alias RecycledCloud.Mailer
alias RecycledCloud.Captcha
alias Meta.SupportRequest
alias Meta.Mailer
alias Meta.Captcha
embedded_schema do
field :name, :string
@ -26,8 +26,8 @@ defmodule RecycledCloud.SupportRequest do
end
def send(%SupportRequest{} = request) do
admin_email = Application.get_env(:recycledcloud, :admin_email)
host = Application.get_env(:recycledcloud, RecycledCloudWeb.Endpoint)
admin_email = Application.get_env(:meta, :admin_email)
host = Application.get_env(:meta, MetaWeb.Endpoint)
|> Keyword.get(:url, [])
|> Keyword.get(:host, "localhost")

View File

@ -1,12 +1,12 @@
defmodule RecycledCloudWeb do
defmodule MetaWeb do
@moduledoc """
The entrypoint for defining your web interface, such
as controllers, views, channels and so on.
This can be used in your application as:
use RecycledCloudWeb, :controller
use RecycledCloudWeb, :view
use MetaWeb, :controller
use MetaWeb, :view
The definitions below will be executed for every view,
controller, etc, so keep them short and clean, focused
@ -19,19 +19,19 @@ defmodule RecycledCloudWeb do
def controller do
quote do
use Phoenix.Controller, namespace: RecycledCloudWeb
use Phoenix.Controller, namespace: MetaWeb
import Plug.Conn
import RecycledCloudWeb.Gettext
alias RecycledCloudWeb.Router.Helpers, as: Routes
import MetaWeb.Gettext
alias MetaWeb.Router.Helpers, as: Routes
end
end
def view do
quote do
use Phoenix.View,
root: "lib/recycledcloud_web/templates",
namespace: RecycledCloudWeb
root: "lib/meta_web/templates",
namespace: MetaWeb
# Import convenience functions from controllers
import Phoenix.Controller,
@ -54,7 +54,7 @@ defmodule RecycledCloudWeb do
def channel do
quote do
use Phoenix.Channel
import RecycledCloudWeb.Gettext
import MetaWeb.Gettext
end
end
@ -66,9 +66,9 @@ defmodule RecycledCloudWeb do
# Import basic rendering functionality (render, render_layout, etc)
import Phoenix.View
import RecycledCloudWeb.ErrorHelpers
import RecycledCloudWeb.Gettext
alias RecycledCloudWeb.Router.Helpers, as: Routes
import MetaWeb.ErrorHelpers
import MetaWeb.Gettext
alias MetaWeb.Router.Helpers, as: Routes
end
end

View File

@ -1,8 +1,8 @@
defmodule RecycledCloudWeb.UserSocket do
defmodule MetaWeb.UserSocket do
use Phoenix.Socket
## Channels
# channel "room:*", RecycledCloudWeb.RoomChannel
# channel "room:*", MetaWeb.RoomChannel
# Socket params are passed from the client and can
# be used to verify and authenticate a user. After
@ -27,7 +27,7 @@ defmodule RecycledCloudWeb.UserSocket do
# Would allow you to broadcast a "disconnect" event and terminate
# all active sockets and channels for a given user:
#
# RecycledCloudWeb.Endpoint.broadcast("user_socket:#{user.id}", "disconnect", %{})
# MetaWeb.Endpoint.broadcast("user_socket:#{user.id}", "disconnect", %{})
#
# Returning `nil` makes this socket anonymous.
@impl true

View File

@ -1,8 +1,8 @@
defmodule RecycledCloudWeb.BillingController do
use RecycledCloudWeb, :controller
defmodule MetaWeb.BillingController do
use MetaWeb, :controller
alias RecycledCloud.Billing.{Partner, Invoice}
alias RecycledCloud.Repo
alias Meta.Billing.{Partner, Invoice}
alias Meta.Repo
def current_partner(conn) do
user = conn.assigns.current_user

View File

@ -0,0 +1,7 @@
defmodule MetaWeb.PageController do
use MetaWeb, :controller
def index(conn, _params) do
render(conn, "index.html")
end
end

View File

@ -1,8 +1,8 @@
defmodule RecycledCloudWeb.SupportController do
use RecycledCloudWeb, :controller
defmodule MetaWeb.SupportController do
use MetaWeb, :controller
alias RecycledCloud.SupportRequest
alias RecycledCloud.Captcha
alias Meta.SupportRequest
alias Meta.Captcha
def new(conn, _params) do
{captcha_text, captcha_result} = Captcha.generate()

View File

@ -1,9 +1,9 @@
defmodule RecycledCloudWeb.UserAuth do
defmodule MetaWeb.UserAuth do
import Plug.Conn
import Phoenix.Controller
alias RecycledCloud.Accounts
alias RecycledCloudWeb.Router.Helpers, as: Routes
alias Meta.Accounts
alias MetaWeb.Router.Helpers, as: Routes
# Make the remember me cookie valid for 60 days.
# If you want bump or reduce this value, also change
@ -75,7 +75,7 @@ defmodule RecycledCloudWeb.UserAuth do
user_token && Accounts.delete_session_token(user_token)
if live_socket_id = get_session(conn, :live_socket_id) do
RecycledCloudWeb.Endpoint.broadcast(live_socket_id, "disconnect", %{})
MetaWeb.Endpoint.broadcast(live_socket_id, "disconnect", %{})
end
conn

View File

@ -1,7 +1,7 @@
defmodule RecycledCloudWeb.UserConfirmationController do
use RecycledCloudWeb, :controller
defmodule MetaWeb.UserConfirmationController do
use MetaWeb, :controller
alias RecycledCloud.Accounts
alias Meta.Accounts
def new(conn, _params) do
render(conn, "new.html")

View File

@ -1,7 +1,7 @@
defmodule RecycledCloudWeb.UserKeysController do
use RecycledCloudWeb, :controller
defmodule MetaWeb.UserKeysController do
use MetaWeb, :controller
alias RecycledCloud.Accounts
alias Meta.Accounts
def index(conn, %{"username" => username}) do
case Accounts.get_user_by_username(username) do

View File

@ -1,13 +1,13 @@
defmodule RecycledCloudWeb.UserRegistrationController do
use RecycledCloudWeb, :controller
defmodule MetaWeb.UserRegistrationController do
use MetaWeb, :controller
alias RecycledCloud.Captcha
alias RecycledCloud.Accounts
alias RecycledCloud.Accounts.User
alias RecycledCloudWeb.UserAuth
alias Meta.Captcha
alias Meta.Accounts
alias Meta.Accounts.User
alias MetaWeb.UserAuth
defp is_registration_enabled?() do
Application.get_env(:recycledcloud, :enable_registration)
Application.get_env(:meta, :enable_registration)
end
def new(conn, _params) do

View File

@ -1,7 +1,7 @@
defmodule RecycledCloudWeb.UserResetPasswordController do
use RecycledCloudWeb, :controller
defmodule MetaWeb.UserResetPasswordController do
use MetaWeb, :controller
alias RecycledCloud.Accounts
alias Meta.Accounts
plug :get_user_by_reset_password_token when action in [:edit, :update]

View File

@ -1,8 +1,8 @@
defmodule RecycledCloudWeb.UserSessionController do
use RecycledCloudWeb, :controller
defmodule MetaWeb.UserSessionController do
use MetaWeb, :controller
alias RecycledCloud.Accounts
alias RecycledCloudWeb.UserAuth
alias Meta.Accounts
alias MetaWeb.UserAuth
def new(conn, _params) do
render(conn, "new.html", error_message: nil)

View File

@ -1,8 +1,8 @@
defmodule RecycledCloudWeb.UserSettingsController do
use RecycledCloudWeb, :controller
defmodule MetaWeb.UserSettingsController do
use MetaWeb, :controller
alias RecycledCloud.Accounts
alias RecycledCloudWeb.UserAuth
alias Meta.Accounts
alias MetaWeb.UserAuth
plug :assign_email_and_password_changesets

View File

@ -0,0 +1,59 @@
defmodule MetaWeb.VirtualMachineController do
use MetaWeb, :controller
alias Meta.OpenNebula, as: ONE
def index(conn, _params) do
username = conn.assigns.current_user.username
vms = ONE.get_vms_for_user(username)
render(conn, "index.html", vms: vms)
end
# def start(conn, %{"id" => id}) do
# case VM.execute(String.to_integer(id), "resume") do
# :ok ->
# conn
# |> put_flash(:info, "Start request sent to VMM.")
# |> redirect(to: Routes.virtual_machine_hosting_path(conn, :index))
# {:error, err} ->
# conn
# |> put_flash(:error, "Something went wrong: #{inspect(err)}")
# |> redirect(to: Routes.virtual_machine_hosting_path(conn, :index))
# end
# end
#
# def stop(conn, %{"id" => id}) do
# case VM.execute(String.to_integer(id), "poweroff") do
# :ok ->
# conn
# |> put_flash(:stop, "Stop request sent to VMM.")
# |> redirect(to: Routes.virtual_machine_hosting_path(conn, :index))
# {:error, err} ->
# conn
# |> put_flash(:error, "Something went wrong: #{inspect(err)}")
# |> redirect(to: Routes.virtual_machine_hosting_path(conn, :index))
# end
# end
def show(conn, %{"location" => location, "id" => id}) do
case ONE.get_vm(location, String.to_integer(id)) do
{:error, err} ->
conn
|> put_flash(:error, "Could not fetch VM details: #{inspect(err)}")
|> redirect(to: Routes.virtual_machine_hosting_path(conn, :index))
{:ok, vm} ->
owner = vm |> Map.get(:UNAME) |> List.to_string
if owner == conn.assigns.current_user.username do
conn
|> assign(:location, location)
|> assign(:vm, vm)
|> render("show.html")
else
conn
|> put_flash(:error, "You are not the owner of this machine.")
|> redirect(to: Routes.virtual_machine_hosting_path(conn, :index))
end
end
end
end

View File

@ -1,16 +1,16 @@
defmodule RecycledCloudWeb.Endpoint do
use Phoenix.Endpoint, otp_app: :recycledcloud
defmodule MetaWeb.Endpoint do
use Phoenix.Endpoint, otp_app: :meta
# The session will be stored in the cookie and signed,
# this means its contents can be read but not tampered with.
# Set :encryption_salt if you would also like to encrypt it.
@session_options [
store: :cookie,
key: "_recycledcloud_key",
key: "_meta_key",
signing_salt: "6k95bz+m"
]
socket "/socket", RecycledCloudWeb.UserSocket,
socket "/socket", MetaWeb.UserSocket,
websocket: true,
longpoll: false
@ -20,7 +20,7 @@ defmodule RecycledCloudWeb.Endpoint do
# when deploying your static files in production.
plug Plug.Static,
at: "/",
from: :recycledcloud,
from: :meta,
gzip: false,
only: ~w(css fonts images js favicon.ico robots.txt)
@ -30,7 +30,7 @@ defmodule RecycledCloudWeb.Endpoint do
socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket
plug Phoenix.LiveReloader
plug Phoenix.CodeReloader
plug Phoenix.Ecto.CheckRepoStatus, otp_app: :recycledcloud
plug Phoenix.Ecto.CheckRepoStatus, otp_app: :meta
end
plug Plug.RequestId
@ -44,5 +44,5 @@ defmodule RecycledCloudWeb.Endpoint do
plug Plug.MethodOverride
plug Plug.Head
plug Plug.Session, @session_options
plug RecycledCloudWeb.Router
plug MetaWeb.Router
end

View File

@ -1,11 +1,11 @@
defmodule RecycledCloudWeb.Gettext do
defmodule MetaWeb.Gettext do
@moduledoc """
A module providing Internationalization with a gettext-based API.
By using [Gettext](https://hexdocs.pm/gettext),
your module gains a set of macros for translations, for example:
import RecycledCloudWeb.Gettext
import MetaWeb.Gettext
# Simple translation
gettext("Here is the string to translate")
@ -20,5 +20,5 @@ defmodule RecycledCloudWeb.Gettext do
See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage.
"""
use Gettext, otp_app: :recycledcloud
use Gettext, otp_app: :meta
end

View File

@ -1,7 +1,7 @@
defmodule RecycledCloudWeb.Router do
use RecycledCloudWeb, :router
defmodule MetaWeb.Router do
use MetaWeb, :router
import RecycledCloudWeb.UserAuth
import MetaWeb.UserAuth
pipeline :browser do
plug :accepts, ["html"]
@ -12,6 +12,14 @@ defmodule RecycledCloudWeb.Router do
plug :fetch_current_user
end
pipeline :browser_with_forgery do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_flash
plug :put_secure_browser_headers
plug :fetch_current_user
end
pipeline :api do
plug :accepts, ["json"]
end
@ -20,13 +28,22 @@ defmodule RecycledCloudWeb.Router do
plug :accepts, ["text"]
end
scope "/", RecycledCloudWeb do
scope "/", MetaWeb do
pipe_through :browser
get "/", PageController, :index
get "/support/new", SupportController, :new
end
scope "/", RecycledCloudWeb do
scope "/", MetaWeb do
pipe_through :browser_with_forgery
# The static recycled.cloud website POST this endpoint, which basically is
# Cross-Site Request Forgery (hence browser_with_forgery pipeline).
post "/support/new", SupportController, :create
end
scope "/", MetaWeb do
pipe_through :plain
get "/keys/:username", UserKeysController, :index
@ -34,7 +51,7 @@ defmodule RecycledCloudWeb.Router do
## Authentication routes
scope "/", RecycledCloudWeb do
scope "/", MetaWeb do
pipe_through [:browser, :redirect_if_user_is_authenticated]
get "/users/register", UserRegistrationController, :new
@ -45,12 +62,9 @@ defmodule RecycledCloudWeb.Router do
post "/users/reset_password", UserResetPasswordController, :create
get "/users/reset_password/:token", UserResetPasswordController, :edit
put "/users/reset_password/:token", UserResetPasswordController, :update
get "/support/new", SupportController, :new
post "/support/new", SupportController, :create
end
scope "/", RecycledCloudWeb do
scope "/", MetaWeb do
pipe_through [:browser, :require_authenticated_user]
get "/users/settings", UserSettingsController, :edit
@ -60,9 +74,12 @@ defmodule RecycledCloudWeb.Router do
get "/users/settings/keys/:key_id/delete", UserKeysController, :delete
get "/billing", BillingController, :index
post "/billing/partner/update", BillingController, :update
get "/hosting/vm", VirtualMachineController, :index
get "/hosting/vm/:location/:id", VirtualMachineController, :show
end
scope "/", RecycledCloudWeb do
scope "/", MetaWeb do
pipe_through [:browser]
get "/users/log_out", UserSessionController, :delete
@ -74,7 +91,7 @@ defmodule RecycledCloudWeb.Router do
# In-memory mailer for development purposes only.
# See https://hexdocs.pm/bamboo/Bamboo.SentEmailViewerPlug.html for details.
if RecycledCloud.env() == :dev do
if Meta.env() == :dev do
forward "/outbox", Bamboo.SentEmailViewerPlug
end
end

View File

@ -1,4 +1,4 @@
defmodule RecycledCloudWeb.Telemetry do
defmodule MetaWeb.Telemetry do
use Supervisor
import Telemetry.Metrics
@ -31,11 +31,11 @@ defmodule RecycledCloudWeb.Telemetry do
),
# Database Metrics
summary("recycledcloud.repo.query.total_time", unit: {:native, :millisecond}),
summary("recycledcloud.repo.query.decode_time", unit: {:native, :millisecond}),
summary("recycledcloud.repo.query.query_time", unit: {:native, :millisecond}),
summary("recycledcloud.repo.query.queue_time", unit: {:native, :millisecond}),
summary("recycledcloud.repo.query.idle_time", unit: {:native, :millisecond}),
summary("meta.repo.query.total_time", unit: {:native, :millisecond}),
summary("meta.repo.query.decode_time", unit: {:native, :millisecond}),
summary("meta.repo.query.query_time", unit: {:native, :millisecond}),
summary("meta.repo.query.queue_time", unit: {:native, :millisecond}),
summary("meta.repo.query.idle_time", unit: {:native, :millisecond}),
# VM Metrics
summary("vm.memory.total", unit: {:byte, :kilobyte}),
@ -49,7 +49,7 @@ defmodule RecycledCloudWeb.Telemetry do
[
# A module, function and arguments to be invoked periodically.
# This function must call :telemetry.execute/3 and a metric must be added above.
# {RecycledCloudWeb, :count_users, []}
# {MetaWeb, :count_users, []}
]
end
end

View File

@ -6,13 +6,25 @@
<li><%= link "Settings", to: Routes.user_settings_path(@conn, :edit) %></li>
<li><%= link "Billing", to: Routes.billing_path(@conn, :index) %></li>
<li><%= link "Log out", to: Routes.user_session_path(@conn, :delete), method: :delete %></li>
<hr />
<!--
<li><%= link "Web Hosting", to: Routes.page_path(@conn, :index) %></li>
<li><%= link "Name Service", to: Routes.page_path(@conn, :index) %></li>
<li><%= link "Storage Services", to: Routes.page_path(@conn, :index) %></li>
-->
<li><%= link "Virtual Machines", to: Routes.virtual_machine_path(@conn, :index) %></li>
<% else %>
<li><%= link "Log in", to: Routes.user_session_path(@conn, :new) %></li>
<li><%= link "Register", to: Routes.user_registration_path(@conn, :new) %></li>
<% end %>
<hr />
<li>
<a href="https://status.recycled.cloud">
Infrastructure status
</a>
</li>
<a href="https://recycled.cloud">
Back to recycled.cloud &crarr;
</a>
</li>
</ul>

View File

@ -4,7 +4,7 @@
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>RecycledCloud · Management</title>
<title>Meta · Management</title>
<link rel="stylesheet" href="<%= Routes.static_path(@conn, "/css/app.css") %>"/>
</head>
<body>
@ -15,7 +15,7 @@
<img id="nav-logo" src="<%= Routes.static_path(@conn, "/images/cloud.svg") %>"></img>
<p class="nav-notice">
<small>
management v<%= RecycledCloud.version() %> | <%= RecycledCloud.env() %> | <a href="https://code.recycled.cloud/e-Durable/management">sources</a>
meta v<%= Meta.version() %> | <%= Meta.env() %> | <a href="https://code.recycled.cloud/e-Durable/management">sources</a>
</small>
</p>
</div>

View File

@ -23,8 +23,8 @@
<br />
<p>
Can you answer the following expression to confirm you are not basic
robot?
Can you answer the following expression to confirm you are
not a basic robot?
<br />

View File

@ -23,7 +23,7 @@
<br />
<p>
Can you answer the following expression to confirm you are not basic robot?
Can you answer the following expression to confirm you are not a basic robot?
<br />

View File

@ -0,0 +1,40 @@
<h1>Virtual Machines</h1>
<p>This page list all the Virtual Machines linked to your account. Note that
SSH keys are not (yet) synced with OpenNebula: you'll have to add your key in
<i><%= @current_user.username %> (top-right) > Settings > Add SSH Key</i> in
OpenNebula for every location you want to use.</p>
<%= for location <- Map.keys(@vms) do %>
<h2>Location: <%= location %></h2>
<p>
You can access the OpenNebula dashboard with your LDAP credentials at:
<a href="<%= Map.get(ONE.get_location_config(location), :public_address) %>">
<%= Map.get(ONE.get_location_config(location), :public_address) %>
</a>
</p>
<table>
<thead>
<tr>
<th style="width: 15%;">ID</th>
<th style="width: 40%;">Name</th>
<th style="width: 30%;">State</th>
<th style="width: 15%">Actions</th>
</tr>
</thead>
<tbody>
<%= for vm <- Map.get(@vms, location) do %>
<tr>
<td><%= location %>#<%= Map.get(vm, :ID) %></td>
<td><%= Map.get(vm, :NAME) %></td>
<td><%= render_state(vm) %></td>
<td>
<%= link "Show history »", to: Routes.virtual_machine_path(@conn, :show, location, Map.get(vm, :ID)) %>
</td>
</tr>
<% end %>
</tbody>
</table>
<% end %>

View File

@ -0,0 +1,30 @@
<h1>VM <%= @location %>#<%= Map.get(@vm, :ID) %> - <%= Map.get(@vm, :NAME) %></h1>
<p>
This VM is located in the <%= @location %> location, its state is <%=
render_state(@vm) %>. The OpenNebula dashboard can be accessed at
<a href="<%= Map.get(ONE.get_location_config(@location), :public_address) %>">
<%= Map.get(ONE.get_location_config(@location), :public_address) %>
</a>.
</p>
<h2>History</h2>
<table>
<thead>
<tr>
<th>Time</th>
<th>Action</th>
<th>Host</th>
</tr>
</thead>
<tbody>
<%= for entry <- @vm |> Map.get(:HISTORY_RECORDS) |> Map.get(:HISTORY) do %>
<tr>
<td><%= DateTime.from_unix!(Map.get(entry, :STIME)) %></td>
<td><%= VM.event_for(Map.get(entry, :ACTION)) %></td>
<td><%= Map.get(entry, :HOSTNAME) %></td>
</tr>
<% end %>
</tbody>
</table>

View File

@ -0,0 +1,3 @@
defmodule MetaWeb.BillingView do
use MetaWeb, :view
end

View File

@ -1,4 +1,4 @@
defmodule RecycledCloudWeb.ErrorHelpers do
defmodule MetaWeb.ErrorHelpers do
@moduledoc """
Conveniences for translating and building error messages.
"""
@ -39,9 +39,9 @@ defmodule RecycledCloudWeb.ErrorHelpers do
# should be written to the errors.po file. The :count option is
# set by Ecto and indicates we should also apply plural rules.
if count = opts[:count] do
Gettext.dngettext(RecycledCloudWeb.Gettext, "errors", msg, msg, count, opts)
Gettext.dngettext(MetaWeb.Gettext, "errors", msg, msg, count, opts)
else
Gettext.dgettext(RecycledCloudWeb.Gettext, "errors", msg, opts)
Gettext.dgettext(MetaWeb.Gettext, "errors", msg, opts)
end
end
end

View File

@ -1,5 +1,5 @@
defmodule RecycledCloudWeb.ErrorView do
use RecycledCloudWeb, :view
defmodule MetaWeb.ErrorView do
use MetaWeb, :view
# If you want to customize a particular status code
# for a certain format, you may uncomment below.

View File

@ -0,0 +1,3 @@
defmodule MetaWeb.LayoutView do
use MetaWeb, :view
end

View File

@ -0,0 +1,3 @@
defmodule MetaWeb.PageView do
use MetaWeb, :view
end

View File

@ -0,0 +1,3 @@
defmodule MetaWeb.SupportView do
use MetaWeb, :view
end

View File

@ -0,0 +1,3 @@
defmodule MetaWeb.UserConfirmationView do
use MetaWeb, :view
end

View File

@ -0,0 +1,3 @@
defmodule MetaWeb.UserRegistrationView do
use MetaWeb, :view
end

View File

@ -0,0 +1,3 @@
defmodule MetaWeb.UserResetPasswordView do
use MetaWeb, :view
end

View File

@ -0,0 +1,3 @@
defmodule MetaWeb.UserSessionView do
use MetaWeb, :view
end

View File

@ -0,0 +1,3 @@
defmodule MetaWeb.UserSettingsView do
use MetaWeb, :view
end

View File

@ -0,0 +1,16 @@
defmodule MetaWeb.VirtualMachineView do
use MetaWeb, :view
alias Meta.OpenNebula, as: ONE
alias Meta.OpenNebula.VM
def render_state(vm) do
state = Map.get(vm, :STATE) |> VM.state_for
if state == :active do
lcm_state = Map.get(vm, :LCM_STATE) |> VM.lcm_state_for
raw("#{state} (<b>#{lcm_state}</b>)")
else
raw("#{state}")
end
end
end

View File

@ -0,0 +1,43 @@
defmodule Mix.Tasks.GenerateOpenNebulaRecords do
use Mix.Task
@moduledoc """
Generate erlang records from OpenNebula's XSD templates. Inspired from
http://codesinger.blogspot.com/2015/12/elixir-erlang-records-and-erlsom-xml.html
"""
@opennebula_release "5.12"
@shortdoc "Generate erlang records from OpenNebula's XSD templates"
def run(_) do
priv_dir = to_string(:code.priv_dir(:meta))
xsd_dir = Path.join([priv_dir, "opennebula", @opennebula_release, "xsd-src"])
hrl_dir = Path.join([priv_dir, "opennebula", @opennebula_release, "xsd-records"])
files = xsd_dir
|> File.ls!()
|> Enum.filter(fn filename -> String.ends_with?(filename, ".xsd") end)
|> Enum.sort()
# Delete existing hrl headers.
if File.exists?(hrl_dir) do
File.rm_rf!(hrl_dir)
end
File.mkdir_p(hrl_dir)
for xsd_filename <- files do
hrl_filename = String.replace_trailing(xsd_filename, ".xsd", ".hrl")
xsd_file = Path.join([xsd_dir, xsd_filename]) |> String.to_charlist
hrl_file = Path.join([hrl_dir, hrl_filename]) |> String.to_charlist
IO.write "> Processing #{xsd_filename}... "
try do
:erlsom.write_xsd_hrl_file(xsd_file, hrl_file, [])
IO.puts "OK"
catch
e -> IO.puts "Error: #{inspect(e)}"
end
end
end
end

0
lib/opennebula.ex Normal file
View File

View File

@ -1,5 +0,0 @@
defmodule RecycledCloud.Repo do
use Ecto.Repo,
otp_app: :recycledcloud,
adapter: Ecto.Adapters.Postgres
end

View File

@ -1,7 +0,0 @@
defmodule RecycledCloudWeb.PageController do
use RecycledCloudWeb, :controller
def index(conn, _params) do
render(conn, "index.html")
end
end

View File

@ -1,3 +0,0 @@
defmodule RecycledCloudWeb.BillingView do
use RecycledCloudWeb, :view
end

View File

@ -1,3 +0,0 @@
defmodule RecycledCloudWeb.LayoutView do
use RecycledCloudWeb, :view
end

View File

@ -1,3 +0,0 @@
defmodule RecycledCloudWeb.PageView do
use RecycledCloudWeb, :view
end

View File

@ -1,3 +0,0 @@
defmodule RecycledCloudWeb.SupportView do
use RecycledCloudWeb, :view
end

View File

@ -1,3 +0,0 @@
defmodule RecycledCloudWeb.UserConfirmationView do
use RecycledCloudWeb, :view
end

View File

@ -1,3 +0,0 @@
defmodule RecycledCloudWeb.UserRegistrationView do
use RecycledCloudWeb, :view
end

View File

@ -1,3 +0,0 @@
defmodule RecycledCloudWeb.UserResetPasswordView do
use RecycledCloudWeb, :view
end

View File

@ -1,3 +0,0 @@
defmodule RecycledCloudWeb.UserSessionView do
use RecycledCloudWeb, :view
end

View File

@ -1,3 +0,0 @@
defmodule RecycledCloudWeb.UserSettingsView do
use RecycledCloudWeb, :view
end

20
mix.exs
View File

@ -1,10 +1,10 @@
defmodule RecycledCloud.MixProject do
defmodule Meta.MixProject do
use Mix.Project
def project do
[
app: :recycledcloud,
version: "0.3.0",
app: :meta,
version: "0.4.0",
elixir: "~> 1.7",
elixirc_paths: elixirc_paths(Mix.env()),
compilers: [:phoenix, :gettext] ++ Mix.compilers(),
@ -12,7 +12,7 @@ defmodule RecycledCloud.MixProject do
aliases: aliases(),
deps: deps(),
releases: [
recycledcloud: [
meta: [
include_executables_for: [:unix],
applications: [runtime_tools: :permanent],
include_erts: true,
@ -27,7 +27,7 @@ defmodule RecycledCloud.MixProject do
# Type `mix help compile.app` for more information.
def application do
[
mod: {RecycledCloud.Application, []},
mod: {Meta.Application, []},
extra_applications: [:logger, :runtime_tools, :eldap]
]
end
@ -54,14 +54,14 @@ defmodule RecycledCloud.MixProject do
{:jason, "~> 1.0"},
{:plug_cowboy, "~> 2.0"},
{:phx_gen_auth, "~> 0.6", only: [:dev], runtime: false},
{:bamboo, "~> 1.6"},
# FIXME: See https://github.com/fewlinesco/bamboo_smtp/issues/143
{:bamboo_smtp, git: "https://github.com/Fnux/bamboo_smtp.git"},
# FIXME: See https://github.com/gen-smtp/gen_smtp/issues/234
{:bamboo, "~> 2.2"},
{:bamboo_smtp, "~> 4.1"},
{:ranch, "~> 1.7.1", override: true},
{:xmlrpc, "~> 1.4"},
{:httpoison, "~> 1.8"},
{:the_big_username_blacklist, "~> 0.1"}
{:the_big_username_blacklist, "~> 0.1"},
{:credo, "~> 1.5", only: [:dev, :test], runtime: false},
{:erlsom, "~> 1.5"}
]
end

View File

@ -1,47 +1,49 @@
%{
"bamboo": {:hex, :bamboo, "1.6.0", "adfb583bef028923aae6f22deaea6667290561da1246058556ecaeb0fec5a175", [:mix], [{:hackney, ">= 1.13.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "454e67feacbc9b6e00553ce1d2fba003c861e0035600d59b09d6159985b17f9b"},
"bamboo_smtp": {:git, "https://github.com/Fnux/bamboo_smtp.git", "bdc911bb82963e548f7189ad10670107b24bb28b", []},
"bcrypt_elixir": {:hex, :bcrypt_elixir, "2.3.0", "6cb662d5c1b0a8858801cf20997bd006e7016aa8c52959c9ef80e0f34fb60b7a", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "2c81d61d4f6ed0e5cf7bf27a9109b791ff216a1034b3d541327484f46dd43769"},
"certifi": {:hex, :certifi, "2.5.3", "70bdd7e7188c804f3a30ee0e7c99655bc35d8ac41c23e12325f36ab449b70651", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm", "ed516acb3929b101208a9d700062d520f3953da3b6b918d866106ffa980e1c10"},
"comeonin": {:hex, :comeonin, "5.3.2", "5c2f893d05c56ae3f5e24c1b983c2d5dfb88c6d979c9287a76a7feb1e1d8d646", [:mix], [], "hexpm", "d0993402844c49539aeadb3fe46a3c9bd190f1ecf86b6f9ebd71957534c95f04"},
"bamboo": {:hex, :bamboo, "2.2.0", "f10a406d2b7f5123eb1f02edfa043c259db04b47ab956041f279eaac776ef5ce", [:mix], [{:hackney, ">= 1.15.2", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.4", [hex: :mime, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "8c3b14ba7d2f40cb4be04128ed1e2aff06d91d9413d38bafb4afccffa3ade4fc"},
"bamboo_smtp": {:hex, :bamboo_smtp, "4.1.0", "ba547be4146ae592f63af05c6c7b7b5195b2b6ca57eeea9d80070b38eacd528b", [:mix], [{:bamboo, "~> 2.2.0", [hex: :bamboo, repo: "hexpm", optional: false]}, {:gen_smtp, "~> 1.1.1", [hex: :gen_smtp, repo: "hexpm", optional: false]}], "hexpm", "cb1a2856ab0507d10df609428314aa5e18231e8b1801a5bc6e42f319eeb50ad9"},
"bcrypt_elixir": {:hex, :bcrypt_elixir, "2.3.1", "5114d780459a04f2b4aeef52307de23de961b69e13a5cd98a911e39fda13f420", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "42182d5f46764def15bf9af83739e3bf4ad22661b1c34fc3e88558efced07279"},
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"},
"certifi": {:hex, :certifi, "2.9.0", "6f2a475689dd47f19fb74334859d460a2dc4e3252a3324bd2111b8f0429e7e21", [:rebar3], [], "hexpm", "266da46bdb06d6c6d35fde799bcb28d36d985d424ad7c08b5bb48f5b5cdd4641"},
"comeonin": {:hex, :comeonin, "5.3.3", "2c564dac95a35650e9b6acfe6d2952083d8a08e4a89b93a481acb552b325892e", [:mix], [], "hexpm", "3e38c9c2cb080828116597ca8807bb482618a315bfafd98c90bc22a821cc84df"},
"connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"},
"cowboy": {:hex, :cowboy, "2.8.0", "f3dc62e35797ecd9ac1b50db74611193c29815401e53bac9a5c0577bd7bc667d", [:rebar3], [{:cowlib, "~> 2.9.1", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "4643e4fba74ac96d4d152c75803de6fad0b3fa5df354c71afdd6cbeeb15fac8a"},
"cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"},
"cowboy_telemetry": {:hex, :cowboy_telemetry, "0.3.1", "ebd1a1d7aff97f27c66654e78ece187abdc646992714164380d8a041eda16754", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3a6efd3366130eab84ca372cbd4a7d3c3a97bdfcfb4911233b035d117063f0af"},
"cowlib": {:hex, :cowlib, "2.9.1", "61a6c7c50cf07fdd24b2f45b89500bb93b6686579b069a89f88cb211e1125c78", [:rebar3], [], "hexpm", "e4175dc240a70d996156160891e1c62238ede1729e45740bdd38064dad476170"},
"db_connection": {:hex, :db_connection, "2.3.1", "4c9f3ed1ef37471cbdd2762d6655be11e38193904d9c5c1c9389f1b891a3088e", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm", "abaab61780dde30301d840417890bd9f74131041afd02174cf4e10635b3a63f5"},
"cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"},
"credo": {:hex, :credo, "1.6.4", "ddd474afb6e8c240313f3a7b0d025cc3213f0d171879429bf8535d7021d9ad78", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "c28f910b61e1ff829bffa056ef7293a8db50e87f2c57a9b5c3f57eee124536b7"},
"db_connection": {:hex, :db_connection, "2.4.2", "f92e79aff2375299a16bcb069a14ee8615c3414863a6fef93156aee8e86c2ff3", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4fe53ca91b99f55ea249693a0229356a08f4d1a7931d8ffa79289b145fe83668"},
"decimal": {:hex, :decimal, "1.9.0", "83e8daf59631d632b171faabafb4a9f4242c514b0a06ba3df493951c08f64d07", [:mix], [], "hexpm", "b1f2343568eed6928f3e751cf2dffde95bfaa19dd95d09e8a9ea92ccfd6f7d85"},
"ecto": {:hex, :ecto, "3.5.5", "48219a991bb86daba6e38a1e64f8cea540cded58950ff38fbc8163e062281a07", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "98dd0e5e1de7f45beca6130d13116eae675db59adfa055fb79612406acf6f6f1"},
"ecto_sql": {:hex, :ecto_sql, "3.5.3", "1964df0305538364b97cc4661a2bd2b6c89d803e66e5655e4e55ff1571943efd", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.5.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.3.0 or ~> 0.4.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d2f53592432ce17d3978feb8f43e8dc0705e288b0890caf06d449785f018061c"},
"elixir_make": {:hex, :elixir_make, "0.6.2", "7dffacd77dec4c37b39af867cedaabb0b59f6a871f89722c25b28fcd4bd70530", [:mix], [], "hexpm", "03e49eadda22526a7e5279d53321d1cced6552f344ba4e03e619063de75348d9"},
"ecto": {:hex, :ecto, "3.8.3", "5e681d35bc2cbb46dcca1e2675837c7d666316e5ada14eca6c9c609b6232817c", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "af92dd7815967bcaea0daaaccf31c3b23165432b1c7a475d84144efbc703d105"},
"ecto_sql": {:hex, :ecto_sql, "3.8.2", "d7d44bc8d45ba9c85485952710c80408632a7336eb811b045e791718d11ddb5b", [:mix], [{:db_connection, "~> 2.5 or ~> 2.4.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.8.1", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0 or ~> 0.16.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7b9b03d64360d6cc05dc263500a43c11740b5fd4552244c27efad358e98c75b3"},
"elixir_make": {:hex, :elixir_make, "0.6.3", "bc07d53221216838d79e03a8019d0839786703129599e9619f4ab74c8c096eac", [:mix], [], "hexpm", "f5cbd651c5678bcaabdbb7857658ee106b12509cd976c2c2fca99688e1daf716"},
"erlsom": {:hex, :erlsom, "1.5.0", "c5a5cdd0ee0e8dca62bcc4b13ff08da24fdefc16ccd8b25282a2fda2ba1be24a", [:rebar3], [], "hexpm", "55a9dbf9cfa77fcfc108bd8e2c4f9f784dea228a8f4b06ea10b684944946955a"},
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
"gen_smtp": {:hex, :gen_smtp, "1.0.1", "cc3de2898d9136ff02dc78fc8193d4fc997824fc793f5bbbada79ccde94581be", [:rebar3], [{:hut, "1.3.0", [hex: :hut, repo: "hexpm", optional: false]}, {:ranch, "1.6.2", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "341a98dc4dafad9cc1e4426e4988e45b31d3f235fa637408f7579a9b598c0ab6"},
"gettext": {:hex, :gettext, "0.18.2", "7df3ea191bb56c0309c00a783334b288d08a879f53a7014341284635850a6e55", [:mix], [], "hexpm", "f9f537b13d4fdd30f3039d33cb80144c3aa1f8d9698e47d7bcbcc8df93b1f5c5"},
"hackney": {:hex, :hackney, "1.17.0", "717ea195fd2f898d9fe9f1ce0afcc2621a41ecfe137fae57e7fe6e9484b9aa99", [:rebar3], [{:certifi, "~>2.5", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "64c22225f1ea8855f584720c0e5b3cd14095703af1c9fbc845ba042811dc671c"},
"httpoison": {:hex, :httpoison, "1.8.0", "6b85dea15820b7804ef607ff78406ab449dd78bed923a49c7160e1886e987a3d", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "28089eaa98cf90c66265b6b5ad87c59a3729bea2e74e9d08f9b51eb9729b3c3a"},
"gen_smtp": {:hex, :gen_smtp, "1.1.1", "bf9303c31735100631b1d708d629e4c65944319d1143b5c9952054f4a1311d85", [:rebar3], [{:hut, "1.3.0", [hex: :hut, repo: "hexpm", optional: false]}, {:ranch, ">= 1.7.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "51bc50cc017efd4a4248cbc39ea30fb60efa7d4a49688986fafad84434ff9ab7"},
"gettext": {:hex, :gettext, "0.19.1", "564953fd21f29358e68b91634799d9d26989f8d039d7512622efb3c3b1c97892", [:mix], [], "hexpm", "10c656c0912b8299adba9b061c06947511e3f109ab0d18b44a866a4498e77222"},
"hackney": {:hex, :hackney, "1.18.1", "f48bf88f521f2a229fc7bae88cf4f85adc9cd9bcf23b5dc8eb6a1788c662c4f6", [:rebar3], [{:certifi, "~>2.9.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a4ecdaff44297e9b5894ae499e9a070ea1888c84afdd1fd9b7b2bc384950128e"},
"httpoison": {:hex, :httpoison, "1.8.1", "df030d96de89dad2e9983f92b0c506a642d4b1f4a819c96ff77d12796189c63e", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "35156a6d678d6d516b9229e208942c405cf21232edd632327ecfaf4fd03e79e0"},
"hut": {:hex, :hut, "1.3.0", "71f2f054e657c03f959cf1acc43f436ea87580696528ca2a55c8afb1b06c85e7", [:"erlang.mk", :rebar, :rebar3], [], "hexpm", "7e15d28555d8a1f2b5a3a931ec120af0753e4853a4c66053db354f35bf9ab563"},
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
"jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"},
"jason": {:hex, :jason, "1.3.0", "fa6b82a934feb176263ad2df0dbd91bf633d4a46ebfdffea0c8ae82953714946", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "53fc1f51255390e0ec7e50f9cb41e751c260d065dcba2bf0d08dc51a4002c2ac"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
"mime": {:hex, :mime, "1.5.0", "203ef35ef3389aae6d361918bf3f952fa17a09e8e43b5aa592b93eba05d0fb8d", [:mix], [], "hexpm", "55a94c0f552249fc1a3dd9cd2d3ab9de9d3c89b559c2bd01121f824834f24746"},
"mime": {:hex, :mime, "1.6.0", "dabde576a497cef4bbdd60aceee8160e02a6c89250d6c0b29e56c0dfb00db3d2", [:mix], [], "hexpm", "31a1a8613f8321143dde1dafc36006a17d28d02bdfecb9e95a880fa7aabd19a7"},
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},
"parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"},
"phoenix": {:hex, :phoenix, "1.5.7", "2923bb3af924f184459fe4fa4b100bd25fa6468e69b2803dfae82698269aa5e0", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.13", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.1.2 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "774cd64417c5a3788414fdbb2be2eb9bcd0c048d9e6ad11a0c1fd67b7c0d0978"},
"phoenix_ecto": {:hex, :phoenix_ecto, "4.2.1", "13f124cf0a3ce0f1948cf24654c7b9f2347169ff75c1123f44674afee6af3b03", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 2.15", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "478a1bae899cac0a6e02be1deec7e2944b7754c04e7d4107fc5a517f877743c0"},
"phoenix": {:hex, :phoenix, "1.5.13", "d4e0805ec0973bed80d67302631130fb47d75b1a0b7335a0b23c4432b6ce55ee", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.13 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.1.2 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "1a7c4f1900e6e60bb60ae6680e48418e3f7c360d58bcb9f812487b6d0d281a0f"},
"phoenix_ecto": {:hex, :phoenix_ecto, "4.4.0", "0672ed4e4808b3fbed494dded89958e22fb882de47a97634c0b13e7b0b5f7720", [:mix], [{:ecto, "~> 3.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "09864e558ed31ee00bd48fcc1d4fc58ae9678c9e81649075431e69dbabb43cc1"},
"phoenix_html": {:hex, :phoenix_html, "2.14.3", "51f720d0d543e4e157ff06b65de38e13303d5778a7919bcc696599e5934271b8", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "efd697a7fff35a13eeeb6b43db884705cba353a1a41d127d118fda5f90c8e80f"},
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.3.0", "f35f61c3f959c9a01b36defaa1f0624edd55b87e236b606664a556d6f72fd2e7", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "02c1007ae393f2b76ec61c1a869b1e617179877984678babde131d716f95b582"},
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.0.0", "a1ae76717bb168cdeb10ec9d92d1480fec99e3080f011402c0a2d68d47395ffb", [:mix], [], "hexpm", "c52d948c4f261577b9c6fa804be91884b381a7f8f18450c5045975435350f771"},
"phx_gen_auth": {:hex, :phx_gen_auth, "0.6.0", "4ffbfa5b34ad8178c3dfcb996fed776df425903595cbc8d56a9ae5bc53136810", [:mix], [{:phoenix, "~> 1.5.2", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "9a801c0f0bc251d8d91d62cecba0ebb6a90b8580fa8843029d931d15164e6ad9"},
"plug": {:hex, :plug, "1.11.0", "f17217525597628298998bc3baed9f8ea1fa3f1160aa9871aee6df47a6e4d38e", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2d9c633f0499f9dc5c2fd069161af4e2e7756890b81adcbb2ceaa074e8308876"},
"plug_cowboy": {:hex, :plug_cowboy, "2.4.1", "779ba386c0915027f22e14a48919a9545714f849505fa15af2631a0d298abf0f", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d72113b6dff7b37a7d9b2a5b68892808e3a9a752f2bf7e503240945385b70507"},
"plug_crypto": {:hex, :plug_crypto, "1.2.0", "1cb20793aa63a6c619dd18bb33d7a3aa94818e5fd39ad357051a67f26dfa2df6", [:mix], [], "hexpm", "a48b538ae8bf381ffac344520755f3007cc10bd8e90b240af98ea29b69683fc2"},
"postgrex": {:hex, :postgrex, "0.15.8", "f5e782bbe5e8fa178d5e3cd1999c857dc48eda95f0a4d7f7bd92a50e84a0d491", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "698fbfacea34c4cf22c8281abeb5cf68d99628d541874f085520ab3b53d356fe"},
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.3.3", "3a53772a6118d5679bf50fc1670505a290e32a1d195df9e069d8c53ab040c054", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "766796676e5f558dbae5d1bdb066849673e956005e3730dfd5affd7a6da4abac"},
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.1", "ba04e489ef03763bf28a17eb2eaddc2c20c6d217e2150a61e3298b0f4c2012b5", [:mix], [], "hexpm", "81367c6d1eea5878ad726be80808eb5a787a23dee699f96e72b1109c57cdd8d9"},
"phx_gen_auth": {:hex, :phx_gen_auth, "0.7.0", "2e10e9527b6b71abbfbb4601c7dc4aa4fb9f2db6f9a6be457c468b7f2b0f6319", [:mix], [{:phoenix, "~> 1.5.2", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "b9dc3e3b866e67c5db8f00f4a2adb28fc8636e794f78600e35aba0e55bdac209"},
"plug": {:hex, :plug, "1.13.6", "187beb6b67c6cec50503e940f0434ea4692b19384d47e5fdfd701e93cadb4cc2", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "02b9c6b9955bce92c829f31d6284bf53c591ca63c4fb9ff81dfd0418667a34ff"},
"plug_cowboy": {:hex, :plug_cowboy, "2.5.2", "62894ccd601cf9597e2c23911ff12798a8a18d237e9739f58a6b04e4988899fe", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "ea6e87f774c8608d60c8d34022a7d073bd7680a0a013f049fc62bf35efea1044"},
"plug_crypto": {:hex, :plug_crypto, "1.2.2", "05654514ac717ff3a1843204b424477d9e60c143406aa94daf2274fdd280794d", [:mix], [], "hexpm", "87631c7ad914a5a445f0a3809f99b079113ae4ed4b867348dd9eec288cecb6db"},
"postgrex": {:hex, :postgrex, "0.16.3", "fac79a81a9a234b11c44235a4494d8565303fa4b9147acf57e48978a074971db", [:mix], [{:connection, "~> 1.1", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "aeaae1d2d1322da4e5fe90d241b0a564ce03a3add09d7270fb85362166194590"},
"ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm", "451d8527787df716d99dc36162fca05934915db0b6141bbdac2ea8d3c7afc7d7"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
"telemetry": {:hex, :telemetry, "0.4.2", "2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm", "2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"},
"telemetry_metrics": {:hex, :telemetry_metrics, "0.6.0", "da9d49ee7e6bb1c259d36ce6539cd45ae14d81247a2b0c90edf55e2b50507f7b", [:mix], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5cfe67ad464b243835512aa44321cee91faed6ea868d7fb761d7016e02915c3d"},
"telemetry": {:hex, :telemetry, "0.4.3", "a06428a514bdbc63293cd9a6263aad00ddeb66f608163bdec7c8995784080818", [:rebar3], [], "hexpm", "eb72b8365ffda5bed68a620d1da88525e326cb82a75ee61354fc24b844768041"},
"telemetry_metrics": {:hex, :telemetry_metrics, "0.6.1", "315d9163a1d4660aedc3fee73f33f1d355dcc76c5c3ab3d59e76e3edf80eef1f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7be9e0871c41732c233be71e4be11b96e56177bf15dde64a8ac9ce72ac9834c6"},
"telemetry_poller": {:hex, :telemetry_poller, "0.5.1", "21071cc2e536810bac5628b935521ff3e28f0303e770951158c73eaaa01e962a", [:rebar3], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4cab72069210bc6e7a080cec9afffad1b33370149ed5d379b81c7c5f0c663fd4"},
"the_big_username_blacklist": {:hex, :the_big_username_blacklist, "0.1.2", "a2622f06a26279c9cd5216ada872c2dceb63bc2ade5c8714df0de65a24aa985c", [:mix], [], "hexpm", "9f411601209758d4a5ef9e247a1e7b908c0cd05e78171f51f07e68b7afb038fe"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
"xmlrpc": {:hex, :xmlrpc, "1.4.1", "e69711f5a15b297c6c27dd833726a6a0cf06bab9130ac6039b8031510a3af497", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:erlsom, "~> 1.4", [hex: :erlsom, repo: "hexpm", optional: false]}], "hexpm", "4680ce0e452f80ce69f405429fa35ecfbd5a385fe882a7f2666702da3cd173a7"},
"xmlrpc": {:hex, :xmlrpc, "1.4.2", "e38c3666e3d2e1a93ed830e3dc56a3faf86680b2ac36d9979aa61234b4116db6", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:erlsom, "~> 1.4", [hex: :erlsom, repo: "hexpm", optional: false]}], "hexpm", "8145f2d285c45b68ae2bbdaebfa021f6f6a7abe8e2dbe07e0708ca13ea26133a"},
}

View File

@ -0,0 +1,127 @@
%% HRL file generated by ERLSOM
%%
%% It is possible (and in some cases necessary) to change the name of
%% the record fields.
%%
%% It is possible to add default values, but be aware that these will
%% only be used when *writing* an xml document.
-ifndef(ERLSOM_ANY_ATTRIB_TYPES).
-define(ERLSOM_ANY_ATTRIB_TYPES, true).
-type anyAttrib() :: {{string(), %% name of the attribute
string()}, %% namespace
string()}. %% value
-type anyAttribs() :: [anyAttrib()] | undefined.
-endif.
-ifndef(ERLSOM_QNAME_TYPES).
-define(ERLSOM_QNAME_TYPES, true).
%% xsd:QName values are translated to #qname{} records.
-record(qname, {uri :: string(),
localPart :: string(),
prefix :: string(),
mappedPrefix :: string()}).
-endif.
-record('HISTORY', {anyAttribs :: anyAttribs(),
'OID' :: integer(),
'SEQ' :: integer(),
'HOSTNAME' :: string(),
'HID' :: integer(),
'CID' :: integer(),
'STIME' :: integer(),
'ETIME' :: integer(),
'VM_MAD' :: string(),
'TM_MAD' :: string(),
'DS_ID' :: integer(),
'PSTIME' :: integer(),
'PETIME' :: integer(),
'RSTIME' :: integer(),
'RETIME' :: integer(),
'ESTIME' :: integer(),
'EETIME' :: integer(),
'ACTION' :: integer(),
'UID' :: integer(),
'GID' :: integer(),
'REQUEST_ID' :: string(),
'VM' :: 'HISTORY/VM'()}).
-type 'HISTORY'() :: #'HISTORY'{}.
-record('HISTORY/VM', {anyAttribs :: anyAttribs(),
'ID' :: integer(),
'UID' :: integer(),
'GID' :: integer(),
'UNAME' :: string(),
'GNAME' :: string(),
'NAME' :: string(),
'PERMISSIONS' :: 'HISTORY/VM/PERMISSIONS'() | undefined,
'LAST_POLL' :: integer(),
'STATE' :: integer(),
'LCM_STATE' :: integer(),
'PREV_STATE' :: integer(),
'PREV_LCM_STATE' :: integer(),
'RESCHED' :: integer(),
'STIME' :: integer(),
'ETIME' :: integer(),
'DEPLOY_ID' :: string(),
'MONITORING' :: string(),
'TEMPLATE' :: string(),
'USER_TEMPLATE' :: string(),
'HISTORY_RECORDS' :: string(),
'SNAPSHOTS' :: ['HISTORY/VM/SNAPSHOTS'()] | undefined}).
-type 'HISTORY/VM'() :: #'HISTORY/VM'{}.
-record('HISTORY/VM/SNAPSHOTS', {anyAttribs :: anyAttribs(),
'ALLOW_ORPHANS' :: string(),
'CURRENT_BASE' :: integer(),
'DISK_ID' :: integer(),
'NEXT_SNAPSHOT' :: integer(),
'SNAPSHOT' :: ['HISTORY/VM/SNAPSHOTS/SNAPSHOT'()] | undefined}).
-type 'HISTORY/VM/SNAPSHOTS'() :: #'HISTORY/VM/SNAPSHOTS'{}.
-record('HISTORY/VM/SNAPSHOTS/SNAPSHOT', {anyAttribs :: anyAttribs(),
'ACTIVE' :: string() | undefined,
'CHILDREN' :: string() | undefined,
'DATE' :: integer(),
'ID' :: integer(),
'NAME' :: string() | undefined,
'PARENT' :: integer(),
'SIZE' :: integer()}).
-type 'HISTORY/VM/SNAPSHOTS/SNAPSHOT'() :: #'HISTORY/VM/SNAPSHOTS/SNAPSHOT'{}.
-record('HISTORY/VM/PERMISSIONS', {anyAttribs :: anyAttribs(),
'OWNER_U' :: integer(),
'OWNER_M' :: integer(),
'OWNER_A' :: integer(),
'GROUP_U' :: integer(),
'GROUP_M' :: integer(),
'GROUP_A' :: integer(),
'OTHER_U' :: integer(),
'OTHER_M' :: integer(),
'OTHER_A' :: integer()}).
-type 'HISTORY/VM/PERMISSIONS'() :: #'HISTORY/VM/PERMISSIONS'{}.
-record('HISTORY_RECORDS', {anyAttribs :: anyAttribs(),
'HISTORY_RECORDS/SEQ1' :: 'HISTORY_RECORDS/SEQ1'() | undefined}).
-type 'HISTORY_RECORDS'() :: #'HISTORY_RECORDS'{}.
-record('HISTORY_RECORDS/SEQ1', {anyAttribs :: anyAttribs(),
'HISTORY' :: ['HISTORY'()] | undefined}).
-type 'HISTORY_RECORDS/SEQ1'() :: #'HISTORY_RECORDS/SEQ1'{}.

View File

@ -0,0 +1,50 @@
%% HRL file generated by ERLSOM
%%
%% It is possible (and in some cases necessary) to change the name of
%% the record fields.
%%
%% It is possible to add default values, but be aware that these will
%% only be used when *writing* an xml document.
-ifndef(ERLSOM_ANY_ATTRIB_TYPES).
-define(ERLSOM_ANY_ATTRIB_TYPES, true).
-type anyAttrib() :: {{string(), %% name of the attribute
string()}, %% namespace
string()}. %% value
-type anyAttribs() :: [anyAttrib()] | undefined.
-endif.
-ifndef(ERLSOM_QNAME_TYPES).
-define(ERLSOM_QNAME_TYPES, true).
%% xsd:QName values are translated to #qname{} records.
-record(qname, {uri :: string(),
localPart :: string(),
prefix :: string(),
mappedPrefix :: string()}).
-endif.
-record('ACL_POOL', {anyAttribs :: anyAttribs(),
'ACL_POOL/SEQ1' :: 'ACL_POOL/SEQ1'() | undefined}).
-type 'ACL_POOL'() :: #'ACL_POOL'{}.
-record('ACL_POOL/SEQ1', {anyAttribs :: anyAttribs(),
'ACL' :: ['ACL_POOL/SEQ1/ACL'()] | undefined}).
-type 'ACL_POOL/SEQ1'() :: #'ACL_POOL/SEQ1'{}.
-record('ACL_POOL/SEQ1/ACL', {anyAttribs :: anyAttribs(),
'ID' :: integer(),
'USER' :: string(),
'RESOURCE' :: string(),
'RIGHTS' :: string(),
'ZONE' :: string(),
'STRING' :: string()}).
-type 'ACL_POOL/SEQ1/ACL'() :: #'ACL_POOL/SEQ1/ACL'{}.

View File

@ -0,0 +1,56 @@
%% HRL file generated by ERLSOM
%%
%% It is possible (and in some cases necessary) to change the name of
%% the record fields.
%%
%% It is possible to add default values, but be aware that these will
%% only be used when *writing* an xml document.
-ifndef(ERLSOM_ANY_ATTRIB_TYPES).
-define(ERLSOM_ANY_ATTRIB_TYPES, true).
-type anyAttrib() :: {{string(), %% name of the attribute
string()}, %% namespace
string()}. %% value
-type anyAttribs() :: [anyAttrib()] | undefined.
-endif.
-ifndef(ERLSOM_QNAME_TYPES).
-define(ERLSOM_QNAME_TYPES, true).
%% xsd:QName values are translated to #qname{} records.
-record(qname, {uri :: string(),
localPart :: string(),
prefix :: string(),
mappedPrefix :: string()}).
-endif.
-record('CLUSTER', {anyAttribs :: anyAttribs(),
'ID' :: integer(),
'NAME' :: string(),
'HOSTS' :: 'CLUSTER/HOSTS'(),
'DATASTORES' :: 'CLUSTER/DATASTORES'(),
'VNETS' :: 'CLUSTER/VNETS'(),
'TEMPLATE' :: string()}).
-type 'CLUSTER'() :: #'CLUSTER'{}.
-record('CLUSTER/VNETS', {anyAttribs :: anyAttribs(),
'ID' :: [integer()] | undefined}).
-type 'CLUSTER/VNETS'() :: #'CLUSTER/VNETS'{}.
-record('CLUSTER/DATASTORES', {anyAttribs :: anyAttribs(),
'ID' :: [integer()] | undefined}).
-type 'CLUSTER/DATASTORES'() :: #'CLUSTER/DATASTORES'{}.
-record('CLUSTER/HOSTS', {anyAttribs :: anyAttribs(),
'ID' :: [integer()] | undefined}).
-type 'CLUSTER/HOSTS'() :: #'CLUSTER/HOSTS'{}.

View File

@ -0,0 +1,89 @@
%% HRL file generated by ERLSOM
%%
%% It is possible (and in some cases necessary) to change the name of
%% the record fields.
%%
%% It is possible to add default values, but be aware that these will
%% only be used when *writing* an xml document.
-ifndef(ERLSOM_ANY_ATTRIB_TYPES).
-define(ERLSOM_ANY_ATTRIB_TYPES, true).
-type anyAttrib() :: {{string(), %% name of the attribute
string()}, %% namespace
string()}. %% value
-type anyAttribs() :: [anyAttrib()] | undefined.
-endif.
-ifndef(ERLSOM_QNAME_TYPES).
-define(ERLSOM_QNAME_TYPES, true).
%% xsd:QName values are translated to #qname{} records.
-record(qname, {uri :: string(),
localPart :: string(),
prefix :: string(),
mappedPrefix :: string()}).
-endif.
-record('DATASTORE', {anyAttribs :: anyAttribs(),
'ID' :: integer(),
'UID' :: integer(),
'GID' :: integer(),
'UNAME' :: string(),
'GNAME' :: string(),
'NAME' :: string(),
'PERMISSIONS' :: 'DATASTORE/PERMISSIONS'() | undefined,
'DS_MAD' :: string(),
'TM_MAD' :: string(),
'BASE_PATH' :: string(),
'TYPE' :: integer(),
'DISK_TYPE' :: integer(),
'STATE' :: integer(),
'CLUSTERS' :: 'DATASTORE/CLUSTERS'(),
'TOTAL_MB' :: integer(),
'FREE_MB' :: integer(),
'USED_MB' :: integer(),
'IMAGES' :: 'DATASTORE/IMAGES'(),
'TEMPLATE' :: 'DATASTORE/TEMPLATE'()}).
-type 'DATASTORE'() :: #'DATASTORE'{}.
-record('DATASTORE/TEMPLATE', {anyAttribs :: anyAttribs(),
'VCENTER_DC_NAME' :: string() | undefined,
'VCENTER_DC_REF' :: string() | undefined,
'VCENTER_DS_NAME' :: string() | undefined,
'VCENTER_DS_REF' :: string() | undefined,
'VCENTER_HOST' :: string() | undefined,
'VCENTER_INSTANCE_ID' :: string() | undefined,
'#any' :: any()}).
-type 'DATASTORE/TEMPLATE'() :: #'DATASTORE/TEMPLATE'{}.
-record('DATASTORE/IMAGES', {anyAttribs :: anyAttribs(),
'ID' :: [integer()] | undefined}).
-type 'DATASTORE/IMAGES'() :: #'DATASTORE/IMAGES'{}.
-record('DATASTORE/CLUSTERS', {anyAttribs :: anyAttribs(),
'ID' :: [integer()] | undefined}).
-type 'DATASTORE/CLUSTERS'() :: #'DATASTORE/CLUSTERS'{}.
-record('DATASTORE/PERMISSIONS', {anyAttribs :: anyAttribs(),
'OWNER_U' :: integer(),
'OWNER_M' :: integer(),
'OWNER_A' :: integer(),
'GROUP_U' :: integer(),
'GROUP_M' :: integer(),
'GROUP_A' :: integer(),
'OTHER_U' :: integer(),
'OTHER_M' :: integer(),
'OTHER_A' :: integer()}).
-type 'DATASTORE/PERMISSIONS'() :: #'DATASTORE/PERMISSIONS'{}.

View File

@ -0,0 +1,65 @@
%% HRL file generated by ERLSOM
%%
%% It is possible (and in some cases necessary) to change the name of
%% the record fields.
%%
%% It is possible to add default values, but be aware that these will
%% only be used when *writing* an xml document.
-ifndef(ERLSOM_ANY_ATTRIB_TYPES).
-define(ERLSOM_ANY_ATTRIB_TYPES, true).
-type anyAttrib() :: {{string(), %% name of the attribute
string()}, %% namespace
string()}. %% value
-type anyAttribs() :: [anyAttrib()] | undefined.
-endif.
-ifndef(ERLSOM_QNAME_TYPES).
-define(ERLSOM_QNAME_TYPES, true).
%% xsd:QName values are translated to #qname{} records.
-record(qname, {uri :: string(),
localPart :: string(),
prefix :: string(),
mappedPrefix :: string()}).
-endif.
-record('DOCUMENT', {anyAttribs :: anyAttribs(),
'ID' :: integer(),
'UID' :: integer(),
'GID' :: integer(),
'UNAME' :: string(),
'GNAME' :: string(),
'NAME' :: string(),
'TYPE' :: string(),
'PERMISSIONS' :: 'DOCUMENT/PERMISSIONS'() | undefined,
'LOCK' :: 'DOCUMENT/LOCK'() | undefined,
'TEMPLATE' :: string()}).
-type 'DOCUMENT'() :: #'DOCUMENT'{}.
-record('DOCUMENT/LOCK', {anyAttribs :: anyAttribs(),
'LOCKED' :: integer(),
'OWNER' :: integer(),
'TIME' :: integer(),
'REQ_ID' :: integer()}).
-type 'DOCUMENT/LOCK'() :: #'DOCUMENT/LOCK'{}.
-record('DOCUMENT/PERMISSIONS', {anyAttribs :: anyAttribs(),
'OWNER_U' :: integer(),
'OWNER_M' :: integer(),
'OWNER_A' :: integer(),
'GROUP_U' :: integer(),
'GROUP_M' :: integer(),
'GROUP_A' :: integer(),
'OTHER_U' :: integer(),
'OTHER_M' :: integer(),
'OTHER_A' :: integer()}).
-type 'DOCUMENT/PERMISSIONS'() :: #'DOCUMENT/PERMISSIONS'{}.

View File

@ -0,0 +1,201 @@
%% HRL file generated by ERLSOM
%%
%% It is possible (and in some cases necessary) to change the name of
%% the record fields.
%%
%% It is possible to add default values, but be aware that these will
%% only be used when *writing* an xml document.
-ifndef(ERLSOM_ANY_ATTRIB_TYPES).
-define(ERLSOM_ANY_ATTRIB_TYPES, true).
-type anyAttrib() :: {{string(), %% name of the attribute
string()}, %% namespace
string()}. %% value
-type anyAttribs() :: [anyAttrib()] | undefined.
-endif.
-ifndef(ERLSOM_QNAME_TYPES).
-define(ERLSOM_QNAME_TYPES, true).
%% xsd:QName values are translated to #qname{} records.
-record(qname, {uri :: string(),
localPart :: string(),
prefix :: string(),
mappedPrefix :: string()}).
-endif.
-record('GROUP', {anyAttribs :: anyAttribs(),
'ID' :: integer(),
'NAME' :: string(),
'TEMPLATE' :: string(),
'USERS' :: 'GROUP/USERS'(),
'ADMINS' :: 'GROUP/ADMINS'(),
'DATASTORE_QUOTA' :: 'GROUP/DATASTORE_QUOTA'() | undefined,
'NETWORK_QUOTA' :: 'GROUP/NETWORK_QUOTA'() | undefined,
'VM_QUOTA' :: 'GROUP/VM_QUOTA'() | undefined,
'IMAGE_QUOTA' :: 'GROUP/IMAGE_QUOTA'() | undefined,
'DEFAULT_GROUP_QUOTAS' :: 'GROUP/DEFAULT_GROUP_QUOTAS'()}).
-type 'GROUP'() :: #'GROUP'{}.
-record('GROUP/DEFAULT_GROUP_QUOTAS', {anyAttribs :: anyAttribs(),
'DATASTORE_QUOTA' :: 'GROUP/DEFAULT_GROUP_QUOTAS/DATASTORE_QUOTA'() | undefined,
'NETWORK_QUOTA' :: 'GROUP/DEFAULT_GROUP_QUOTAS/NETWORK_QUOTA'() | undefined,
'VM_QUOTA' :: 'GROUP/DEFAULT_GROUP_QUOTAS/VM_QUOTA'() | undefined,
'IMAGE_QUOTA' :: 'GROUP/DEFAULT_GROUP_QUOTAS/IMAGE_QUOTA'() | undefined}).
-type 'GROUP/DEFAULT_GROUP_QUOTAS'() :: #'GROUP/DEFAULT_GROUP_QUOTAS'{}.
-record('GROUP/DEFAULT_GROUP_QUOTAS/IMAGE_QUOTA', {anyAttribs :: anyAttribs(),
'IMAGE' :: ['GROUP/DEFAULT_GROUP_QUOTAS/IMAGE_QUOTA/IMAGE'()] | undefined}).
-type 'GROUP/DEFAULT_GROUP_QUOTAS/IMAGE_QUOTA'() :: #'GROUP/DEFAULT_GROUP_QUOTAS/IMAGE_QUOTA'{}.
-record('GROUP/DEFAULT_GROUP_QUOTAS/IMAGE_QUOTA/IMAGE', {anyAttribs :: anyAttribs(),
'ID' :: string(),
'RVMS' :: string(),
'RVMS_USED' :: string()}).
-type 'GROUP/DEFAULT_GROUP_QUOTAS/IMAGE_QUOTA/IMAGE'() :: #'GROUP/DEFAULT_GROUP_QUOTAS/IMAGE_QUOTA/IMAGE'{}.
-record('GROUP/DEFAULT_GROUP_QUOTAS/VM_QUOTA', {anyAttribs :: anyAttribs(),
'VM' :: 'GROUP/DEFAULT_GROUP_QUOTAS/VM_QUOTA/VM'() | undefined}).
-type 'GROUP/DEFAULT_GROUP_QUOTAS/VM_QUOTA'() :: #'GROUP/DEFAULT_GROUP_QUOTAS/VM_QUOTA'{}.
-record('GROUP/DEFAULT_GROUP_QUOTAS/VM_QUOTA/VM', {anyAttribs :: anyAttribs(),
'CPU' :: string(),
'CPU_USED' :: string(),
'MEMORY' :: integer(),
'MEMORY_USED' :: integer(),
'RUNNING_CPU' :: string(),
'RUNNING_CPU_USED' :: string(),
'RUNNING_MEMORY' :: integer(),
'RUNNING_MEMORY_USED' :: integer(),
'RUNNING_VMS' :: integer(),
'RUNNING_VMS_USED' :: integer(),
'SYSTEM_DISK_SIZE' :: string(),
'SYSTEM_DISK_SIZE_USED' :: string(),
'VMS' :: integer(),
'VMS_USED' :: integer()}).
-type 'GROUP/DEFAULT_GROUP_QUOTAS/VM_QUOTA/VM'() :: #'GROUP/DEFAULT_GROUP_QUOTAS/VM_QUOTA/VM'{}.
-record('GROUP/DEFAULT_GROUP_QUOTAS/NETWORK_QUOTA', {anyAttribs :: anyAttribs(),
'NETWORK' :: ['GROUP/DEFAULT_GROUP_QUOTAS/NETWORK_QUOTA/NETWORK'()] | undefined}).
-type 'GROUP/DEFAULT_GROUP_QUOTAS/NETWORK_QUOTA'() :: #'GROUP/DEFAULT_GROUP_QUOTAS/NETWORK_QUOTA'{}.
-record('GROUP/DEFAULT_GROUP_QUOTAS/NETWORK_QUOTA/NETWORK', {anyAttribs :: anyAttribs(),
'ID' :: string(),
'LEASES' :: string(),
'LEASES_USED' :: string()}).
-type 'GROUP/DEFAULT_GROUP_QUOTAS/NETWORK_QUOTA/NETWORK'() :: #'GROUP/DEFAULT_GROUP_QUOTAS/NETWORK_QUOTA/NETWORK'{}.
-record('GROUP/DEFAULT_GROUP_QUOTAS/DATASTORE_QUOTA', {anyAttribs :: anyAttribs(),
'DATASTORE' :: ['GROUP/DEFAULT_GROUP_QUOTAS/DATASTORE_QUOTA/DATASTORE'()] | undefined}).
-type 'GROUP/DEFAULT_GROUP_QUOTAS/DATASTORE_QUOTA'() :: #'GROUP/DEFAULT_GROUP_QUOTAS/DATASTORE_QUOTA'{}.
-record('GROUP/DEFAULT_GROUP_QUOTAS/DATASTORE_QUOTA/DATASTORE', {anyAttribs :: anyAttribs(),
'ID' :: string(),
'IMAGES' :: string(),
'IMAGES_USED' :: string(),
'SIZE' :: string(),
'SIZE_USED' :: string()}).
-type 'GROUP/DEFAULT_GROUP_QUOTAS/DATASTORE_QUOTA/DATASTORE'() :: #'GROUP/DEFAULT_GROUP_QUOTAS/DATASTORE_QUOTA/DATASTORE'{}.
-record('GROUP/IMAGE_QUOTA', {anyAttribs :: anyAttribs(),
'IMAGE' :: ['GROUP/IMAGE_QUOTA/IMAGE'()] | undefined}).
-type 'GROUP/IMAGE_QUOTA'() :: #'GROUP/IMAGE_QUOTA'{}.
-record('GROUP/IMAGE_QUOTA/IMAGE', {anyAttribs :: anyAttribs(),
'ID' :: string(),
'RVMS' :: string(),
'RVMS_USED' :: string()}).
-type 'GROUP/IMAGE_QUOTA/IMAGE'() :: #'GROUP/IMAGE_QUOTA/IMAGE'{}.
-record('GROUP/VM_QUOTA', {anyAttribs :: anyAttribs(),
'VM' :: 'GROUP/VM_QUOTA/VM'() | undefined}).
-type 'GROUP/VM_QUOTA'() :: #'GROUP/VM_QUOTA'{}.
-record('GROUP/VM_QUOTA/VM', {anyAttribs :: anyAttribs(),
'CPU' :: string(),
'CPU_USED' :: string(),
'MEMORY' :: integer(),
'MEMORY_USED' :: integer(),
'RUNNING_CPU' :: string(),
'RUNNING_CPU_USED' :: string(),
'RUNNING_MEMORY' :: integer(),
'RUNNING_MEMORY_USED' :: integer(),
'RUNNING_VMS' :: integer(),
'RUNNING_VMS_USED' :: integer(),
'SYSTEM_DISK_SIZE' :: string(),
'SYSTEM_DISK_SIZE_USED' :: string(),
'VMS' :: integer(),
'VMS_USED' :: integer()}).
-type 'GROUP/VM_QUOTA/VM'() :: #'GROUP/VM_QUOTA/VM'{}.
-record('GROUP/NETWORK_QUOTA', {anyAttribs :: anyAttribs(),
'NETWORK' :: ['GROUP/NETWORK_QUOTA/NETWORK'()] | undefined}).
-type 'GROUP/NETWORK_QUOTA'() :: #'GROUP/NETWORK_QUOTA'{}.
-record('GROUP/NETWORK_QUOTA/NETWORK', {anyAttribs :: anyAttribs(),
'ID' :: string(),
'LEASES' :: string(),
'LEASES_USED' :: string()}).
-type 'GROUP/NETWORK_QUOTA/NETWORK'() :: #'GROUP/NETWORK_QUOTA/NETWORK'{}.
-record('GROUP/DATASTORE_QUOTA', {anyAttribs :: anyAttribs(),
'DATASTORE' :: ['GROUP/DATASTORE_QUOTA/DATASTORE'()] | undefined}).
-type 'GROUP/DATASTORE_QUOTA'() :: #'GROUP/DATASTORE_QUOTA'{}.
-record('GROUP/DATASTORE_QUOTA/DATASTORE', {anyAttribs :: anyAttribs(),
'ID' :: string(),
'IMAGES' :: string(),
'IMAGES_USED' :: string(),
'SIZE' :: string(),
'SIZE_USED' :: string()}).
-type 'GROUP/DATASTORE_QUOTA/DATASTORE'() :: #'GROUP/DATASTORE_QUOTA/DATASTORE'{}.
-record('GROUP/ADMINS', {anyAttribs :: anyAttribs(),
'ID' :: [integer()] | undefined}).
-type 'GROUP/ADMINS'() :: #'GROUP/ADMINS'{}.
-record('GROUP/USERS', {anyAttribs :: anyAttribs(),
'ID' :: [integer()] | undefined}).
-type 'GROUP/USERS'() :: #'GROUP/USERS'{}.

View File

@ -0,0 +1,219 @@
%% HRL file generated by ERLSOM
%%
%% It is possible (and in some cases necessary) to change the name of
%% the record fields.
%%
%% It is possible to add default values, but be aware that these will
%% only be used when *writing* an xml document.
-ifndef(ERLSOM_ANY_ATTRIB_TYPES).
-define(ERLSOM_ANY_ATTRIB_TYPES, true).
-type anyAttrib() :: {{string(), %% name of the attribute
string()}, %% namespace
string()}. %% value
-type anyAttribs() :: [anyAttrib()] | undefined.
-endif.
-ifndef(ERLSOM_QNAME_TYPES).
-define(ERLSOM_QNAME_TYPES, true).
%% xsd:QName values are translated to #qname{} records.
-record(qname, {uri :: string(),
localPart :: string(),
prefix :: string(),
mappedPrefix :: string()}).
-endif.
-record('GROUP_POOL', {anyAttribs :: anyAttribs(),
choice :: 'GROUP_POOL/SEQ1'() | 'GROUP_POOL/SEQ1'() | 'GROUP_POOL/SEQ1'()}).
-type 'GROUP_POOL'() :: #'GROUP_POOL'{}.
-record('GROUP_POOL/SEQ1', {anyAttribs :: anyAttribs(),
choice :: [['GROUP_POOL/SEQ1/QUOTAS'()] | ['GROUP_POOL/SEQ1/GROUP'()]] | undefined,
'DEFAULT_GROUP_QUOTAS' :: 'GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS'()}).
-type 'GROUP_POOL/SEQ1'() :: #'GROUP_POOL/SEQ1'{}.
-record('GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS', {anyAttribs :: anyAttribs(),
'DATASTORE_QUOTA' :: 'GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/DATASTORE_QUOTA'() | undefined,
'NETWORK_QUOTA' :: 'GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/NETWORK_QUOTA'() | undefined,
'VM_QUOTA' :: 'GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/VM_QUOTA'() | undefined,
'IMAGE_QUOTA' :: 'GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/IMAGE_QUOTA'() | undefined}).
-type 'GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS'() :: #'GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS'{}.
-record('GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/IMAGE_QUOTA', {anyAttribs :: anyAttribs(),
'IMAGE' :: ['GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/IMAGE_QUOTA/IMAGE'()] | undefined}).
-type 'GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/IMAGE_QUOTA'() :: #'GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/IMAGE_QUOTA'{}.
-record('GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/IMAGE_QUOTA/IMAGE', {anyAttribs :: anyAttribs(),
'ID' :: string(),
'RVMS' :: string(),
'RVMS_USED' :: string()}).
-type 'GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/IMAGE_QUOTA/IMAGE'() :: #'GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/IMAGE_QUOTA/IMAGE'{}.
-record('GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/VM_QUOTA', {anyAttribs :: anyAttribs(),
'VM' :: 'GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/VM_QUOTA/VM'() | undefined}).
-type 'GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/VM_QUOTA'() :: #'GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/VM_QUOTA'{}.
-record('GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/VM_QUOTA/VM', {anyAttribs :: anyAttribs(),
'CPU' :: string(),
'CPU_USED' :: string(),
'MEMORY' :: string(),
'MEMORY_USED' :: string(),
'RUNNING_CPU' :: string(),
'RUNNING_CPU_USED' :: string(),
'RUNNING_MEMORY' :: string(),
'RUNNING_MEMORY_USED' :: string(),
'RUNNING_VMS' :: string(),
'RUNNING_VMS_USED' :: string(),
'SYSTEM_DISK_SIZE' :: string(),
'SYSTEM_DISK_SIZE_USED' :: string(),
'VMS' :: string(),
'VMS_USED' :: string()}).
-type 'GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/VM_QUOTA/VM'() :: #'GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/VM_QUOTA/VM'{}.
-record('GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/NETWORK_QUOTA', {anyAttribs :: anyAttribs(),
'NETWORK' :: ['GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/NETWORK_QUOTA/NETWORK'()] | undefined}).
-type 'GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/NETWORK_QUOTA'() :: #'GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/NETWORK_QUOTA'{}.
-record('GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/NETWORK_QUOTA/NETWORK', {anyAttribs :: anyAttribs(),
'ID' :: string(),
'LEASES' :: string(),
'LEASES_USED' :: string()}).
-type 'GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/NETWORK_QUOTA/NETWORK'() :: #'GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/NETWORK_QUOTA/NETWORK'{}.
-record('GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/DATASTORE_QUOTA', {anyAttribs :: anyAttribs(),
'DATASTORE' :: ['GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/DATASTORE_QUOTA/DATASTORE'()] | undefined}).
-type 'GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/DATASTORE_QUOTA'() :: #'GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/DATASTORE_QUOTA'{}.
-record('GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/DATASTORE_QUOTA/DATASTORE', {anyAttribs :: anyAttribs(),
'ID' :: string(),
'IMAGES' :: string(),
'IMAGES_USED' :: string(),
'SIZE' :: string(),
'SIZE_USED' :: string()}).
-type 'GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/DATASTORE_QUOTA/DATASTORE'() :: #'GROUP_POOL/SEQ1/DEFAULT_GROUP_QUOTAS/DATASTORE_QUOTA/DATASTORE'{}.
-record('GROUP_POOL/SEQ1/QUOTAS', {anyAttribs :: anyAttribs(),
'ID' :: integer(),
'DATASTORE_QUOTA' :: 'GROUP_POOL/SEQ1/QUOTAS/DATASTORE_QUOTA'() | undefined,
'NETWORK_QUOTA' :: 'GROUP_POOL/SEQ1/QUOTAS/NETWORK_QUOTA'() | undefined,
'VM_QUOTA' :: 'GROUP_POOL/SEQ1/QUOTAS/VM_QUOTA'() | undefined,
'IMAGE_QUOTA' :: 'GROUP_POOL/SEQ1/QUOTAS/IMAGE_QUOTA'() | undefined}).
-type 'GROUP_POOL/SEQ1/QUOTAS'() :: #'GROUP_POOL/SEQ1/QUOTAS'{}.
-record('GROUP_POOL/SEQ1/QUOTAS/IMAGE_QUOTA', {anyAttribs :: anyAttribs(),
'IMAGE' :: ['GROUP_POOL/SEQ1/QUOTAS/IMAGE_QUOTA/IMAGE'()] | undefined}).
-type 'GROUP_POOL/SEQ1/QUOTAS/IMAGE_QUOTA'() :: #'GROUP_POOL/SEQ1/QUOTAS/IMAGE_QUOTA'{}.
-record('GROUP_POOL/SEQ1/QUOTAS/IMAGE_QUOTA/IMAGE', {anyAttribs :: anyAttribs(),
'ID' :: string(),
'RVMS' :: string(),
'RVMS_USED' :: string()}).
-type 'GROUP_POOL/SEQ1/QUOTAS/IMAGE_QUOTA/IMAGE'() :: #'GROUP_POOL/SEQ1/QUOTAS/IMAGE_QUOTA/IMAGE'{}.
-record('GROUP_POOL/SEQ1/QUOTAS/VM_QUOTA', {anyAttribs :: anyAttribs(),
'VM' :: 'GROUP_POOL/SEQ1/QUOTAS/VM_QUOTA/VM'() | undefined}).
-type 'GROUP_POOL/SEQ1/QUOTAS/VM_QUOTA'() :: #'GROUP_POOL/SEQ1/QUOTAS/VM_QUOTA'{}.
-record('GROUP_POOL/SEQ1/QUOTAS/VM_QUOTA/VM', {anyAttribs :: anyAttribs(),
'CPU' :: string(),
'CPU_USED' :: string(),
'MEMORY' :: string(),
'MEMORY_USED' :: string(),
'RUNNING_CPU' :: string(),
'RUNNING_CPU_USED' :: string(),
'RUNNING_MEMORY' :: string(),
'RUNNING_MEMORY_USED' :: string(),
'RUNNING_VMS' :: string(),
'RUNNING_VMS_USED' :: string(),
'SYSTEM_DISK_SIZE' :: string(),
'SYSTEM_DISK_SIZE_USED' :: string(),
'VMS' :: string(),
'VMS_USED' :: string()}).
-type 'GROUP_POOL/SEQ1/QUOTAS/VM_QUOTA/VM'() :: #'GROUP_POOL/SEQ1/QUOTAS/VM_QUOTA/VM'{}.
-record('GROUP_POOL/SEQ1/QUOTAS/NETWORK_QUOTA', {anyAttribs :: anyAttribs(),
'NETWORK' :: ['GROUP_POOL/SEQ1/QUOTAS/NETWORK_QUOTA/NETWORK'()] | undefined}).
-type 'GROUP_POOL/SEQ1/QUOTAS/NETWORK_QUOTA'() :: #'GROUP_POOL/SEQ1/QUOTAS/NETWORK_QUOTA'{}.
-record('GROUP_POOL/SEQ1/QUOTAS/NETWORK_QUOTA/NETWORK', {anyAttribs :: anyAttribs(),
'ID' :: string(),
'LEASES' :: string(),
'LEASES_USED' :: string()}).
-type 'GROUP_POOL/SEQ1/QUOTAS/NETWORK_QUOTA/NETWORK'() :: #'GROUP_POOL/SEQ1/QUOTAS/NETWORK_QUOTA/NETWORK'{}.
-record('GROUP_POOL/SEQ1/QUOTAS/DATASTORE_QUOTA', {anyAttribs :: anyAttribs(),
'DATASTORE' :: ['GROUP_POOL/SEQ1/QUOTAS/DATASTORE_QUOTA/DATASTORE'()] | undefined}).
-type 'GROUP_POOL/SEQ1/QUOTAS/DATASTORE_QUOTA'() :: #'GROUP_POOL/SEQ1/QUOTAS/DATASTORE_QUOTA'{}.
-record('GROUP_POOL/SEQ1/QUOTAS/DATASTORE_QUOTA/DATASTORE', {anyAttribs :: anyAttribs(),
'ID' :: string(),
'IMAGES' :: string(),
'IMAGES_USED' :: string(),
'SIZE' :: string(),
'SIZE_USED' :: string()}).
-type 'GROUP_POOL/SEQ1/QUOTAS/DATASTORE_QUOTA/DATASTORE'() :: #'GROUP_POOL/SEQ1/QUOTAS/DATASTORE_QUOTA/DATASTORE'{}.
-record('GROUP_POOL/SEQ1/GROUP', {anyAttribs :: anyAttribs(),
'ID' :: integer(),
'NAME' :: string(),
'TEMPLATE' :: string(),
'USERS' :: 'GROUP_POOL/SEQ1/GROUP/USERS'(),
'ADMINS' :: 'GROUP_POOL/SEQ1/GROUP/ADMINS'()}).
-type 'GROUP_POOL/SEQ1/GROUP'() :: #'GROUP_POOL/SEQ1/GROUP'{}.
-record('GROUP_POOL/SEQ1/GROUP/ADMINS', {anyAttribs :: anyAttribs(),
'ID' :: [integer()] | undefined}).
-type 'GROUP_POOL/SEQ1/GROUP/ADMINS'() :: #'GROUP_POOL/SEQ1/GROUP/ADMINS'{}.
-record('GROUP_POOL/SEQ1/GROUP/USERS', {anyAttribs :: anyAttribs(),
'ID' :: [integer()] | undefined}).
-type 'GROUP_POOL/SEQ1/GROUP/USERS'() :: #'GROUP_POOL/SEQ1/GROUP/USERS'{}.

View File

@ -0,0 +1,81 @@
%% HRL file generated by ERLSOM
%%
%% It is possible (and in some cases necessary) to change the name of
%% the record fields.
%%
%% It is possible to add default values, but be aware that these will
%% only be used when *writing* an xml document.
-ifndef(ERLSOM_ANY_ATTRIB_TYPES).
-define(ERLSOM_ANY_ATTRIB_TYPES, true).
-type anyAttrib() :: {{string(), %% name of the attribute
string()}, %% namespace
string()}. %% value
-type anyAttribs() :: [anyAttrib()] | undefined.
-endif.
-ifndef(ERLSOM_QNAME_TYPES).
-define(ERLSOM_QNAME_TYPES, true).
%% xsd:QName values are translated to #qname{} records.
-record(qname, {uri :: string(),
localPart :: string(),
prefix :: string(),
mappedPrefix :: string()}).
-endif.
-record('HOOK', {anyAttribs :: anyAttribs(),
'ID' :: integer(),
'NAME' :: string(),
'TYPE' :: string(),
'TEMPLATE' :: 'HOOK/TEMPLATE'(),
'HOOKLOG' :: 'HOOK/HOOKLOG'() | undefined}).
-type 'HOOK'() :: #'HOOK'{}.
-record('HOOK/HOOKLOG', {anyAttribs :: anyAttribs(),
'HOOK_EXECUTION_RECORD' :: ['HOOK/HOOKLOG/HOOK_EXECUTION_RECORD'()] | undefined}).
-type 'HOOK/HOOKLOG'() :: #'HOOK/HOOKLOG'{}.
-record('HOOK/HOOKLOG/HOOK_EXECUTION_RECORD', {anyAttribs :: anyAttribs(),
choice :: [any()] | undefined,
'HOOK_ID' :: integer(),
'EXECUTION_ID' :: integer(),
'TIMESTAMP' :: integer(),
'ARGUMENTS' :: string(),
'EXECUTION_RESULT' :: 'HOOK/HOOKLOG/HOOK_EXECUTION_RECORD/EXECUTION_RESULT'(),
'REMOTE_HOST' :: string() | undefined,
'RETRY' :: string() | undefined,
choice1 :: [any()] | undefined}).
-type 'HOOK/HOOKLOG/HOOK_EXECUTION_RECORD'() :: #'HOOK/HOOKLOG/HOOK_EXECUTION_RECORD'{}.
-record('HOOK/HOOKLOG/HOOK_EXECUTION_RECORD/EXECUTION_RESULT', {anyAttribs :: anyAttribs(),
'COMMAND' :: string(),
'STDOUT' :: string(),
'STDERR' :: string(),
'CODE' :: string()}).
-type 'HOOK/HOOKLOG/HOOK_EXECUTION_RECORD/EXECUTION_RESULT'() :: #'HOOK/HOOKLOG/HOOK_EXECUTION_RECORD/EXECUTION_RESULT'{}.
-record('HOOK/TEMPLATE', {anyAttribs :: anyAttribs(),
choice :: [any()] | undefined,
'ARGUMENTS' :: string() | undefined,
'ARGUMENTS_STDIN' :: string() | undefined,
'CALL' :: string() | undefined,
'COMMAND' :: string(),
'REMOTE' :: string() | undefined,
'RESOURCE' :: string() | undefined,
'STATE' :: string() | undefined,
'LCM_STATE' :: string() | undefined,
choice1 :: [any()] | undefined}).
-type 'HOOK/TEMPLATE'() :: #'HOOK/TEMPLATE'{}.

View File

@ -0,0 +1,35 @@
%% HRL file generated by ERLSOM
%%
%% It is possible (and in some cases necessary) to change the name of
%% the record fields.
%%
%% It is possible to add default values, but be aware that these will
%% only be used when *writing* an xml document.
-ifndef(ERLSOM_ANY_ATTRIB_TYPES).
-define(ERLSOM_ANY_ATTRIB_TYPES, true).
-type anyAttrib() :: {{string(), %% name of the attribute
string()}, %% namespace
string()}. %% value
-type anyAttribs() :: [anyAttrib()] | undefined.
-endif.
-ifndef(ERLSOM_QNAME_TYPES).
-define(ERLSOM_QNAME_TYPES, true).
%% xsd:QName values are translated to #qname{} records.
-record(qname, {uri :: string(),
localPart :: string(),
prefix :: string(),
mappedPrefix :: string()}).
-endif.
-record('HOOK_MESSAGE', {anyAttribs :: anyAttribs(),
'HOOK_TYPE' :: string(),
'CALL' :: string(),
'CALL_INFO' :: ['CALL_INFO'()] | undefined}).
-type 'HOOK_MESSAGE'() :: #'HOOK_MESSAGE'{}.

View File

@ -0,0 +1,34 @@
%% HRL file generated by ERLSOM
%%
%% It is possible (and in some cases necessary) to change the name of
%% the record fields.
%%
%% It is possible to add default values, but be aware that these will
%% only be used when *writing* an xml document.
-ifndef(ERLSOM_ANY_ATTRIB_TYPES).
-define(ERLSOM_ANY_ATTRIB_TYPES, true).
-type anyAttrib() :: {{string(), %% name of the attribute
string()}, %% namespace
string()}. %% value
-type anyAttribs() :: [anyAttrib()] | undefined.
-endif.
-ifndef(ERLSOM_QNAME_TYPES).
-define(ERLSOM_QNAME_TYPES, true).
%% xsd:QName values are translated to #qname{} records.
-record(qname, {uri :: string(),
localPart :: string(),
prefix :: string(),
mappedPrefix :: string()}).
-endif.
-record('HOOK_MESSAGE', {anyAttribs :: anyAttribs(),
'ARGUMENTS' :: string(),
'HOOK_ID' :: integer()}).
-type 'HOOK_MESSAGE'() :: #'HOOK_MESSAGE'{}.

View File

@ -0,0 +1,165 @@
%% HRL file generated by ERLSOM
%%
%% It is possible (and in some cases necessary) to change the name of
%% the record fields.
%%
%% It is possible to add default values, but be aware that these will
%% only be used when *writing* an xml document.
-ifndef(ERLSOM_ANY_ATTRIB_TYPES).
-define(ERLSOM_ANY_ATTRIB_TYPES, true).
-type anyAttrib() :: {{string(), %% name of the attribute
string()}, %% namespace
string()}. %% value
-type anyAttribs() :: [anyAttrib()] | undefined.
-endif.
-ifndef(ERLSOM_QNAME_TYPES).
-define(ERLSOM_QNAME_TYPES, true).
%% xsd:QName values are translated to #qname{} records.
-record(qname, {uri :: string(),
localPart :: string(),
prefix :: string(),
mappedPrefix :: string()}).
-endif.
-record('HOST', {anyAttribs :: anyAttribs(),
'ID' :: integer(),
'NAME' :: string(),
'STATE' :: integer(),
'PREV_STATE' :: integer(),
'IM_MAD' :: string(),
'VM_MAD' :: string(),
'CLUSTER_ID' :: integer(),
'CLUSTER' :: string(),
'HOST_SHARE' :: 'HOST/HOST_SHARE'(),
'VMS' :: 'HOST/VMS'(),
'TEMPLATE' :: 'HOST/TEMPLATE'(),
'MONITORING' :: 'HOST/MONITORING'()}).
-type 'HOST'() :: #'HOST'{}.
-record('HOST/MONITORING', {anyAttribs :: anyAttribs(),
'TIMESTAMP' :: integer() | undefined,
'ID' :: integer() | undefined,
'CAPACITY' :: 'HOST/MONITORING/CAPACITY'() | undefined,
'SYSTEM' :: 'HOST/MONITORING/SYSTEM'() | undefined}).
-type 'HOST/MONITORING'() :: #'HOST/MONITORING'{}.
-record('HOST/MONITORING/SYSTEM', {anyAttribs :: anyAttribs(),
'NETRX' :: integer() | undefined,
'NETTX' :: integer() | undefined}).
-type 'HOST/MONITORING/SYSTEM'() :: #'HOST/MONITORING/SYSTEM'{}.
-record('HOST/MONITORING/CAPACITY', {anyAttribs :: anyAttribs(),
'FREE_CPU' :: integer(),
'FREE_MEMORY' :: integer(),
'USED_CPU' :: integer(),
'USED_MEMORY' :: integer()}).
-type 'HOST/MONITORING/CAPACITY'() :: #'HOST/MONITORING/CAPACITY'{}.
-record('HOST/TEMPLATE', {anyAttribs :: anyAttribs(),
choice :: [any()] | undefined,
'VCENTER_CCR_REF' :: string() | undefined,
'VCENTER_DS_REF' :: [string()] | undefined,
'VCENTER_HOST' :: string() | undefined,
'VCENTER_INSTANCE_ID' :: string() | undefined,
'VCENTER_NAME' :: string() | undefined,
'VCENTER_PASSWORD' :: string() | undefined,
'VCENTER_RESOURCE_POOL_INFO' :: [string()] | undefined,
'VCENTER_USER' :: string() | undefined,
'VCENTER_VERSION' :: string() | undefined,
choice1 :: [any()] | undefined}).
-type 'HOST/TEMPLATE'() :: #'HOST/TEMPLATE'{}.
-record('HOST/VMS', {anyAttribs :: anyAttribs(),
'ID' :: [integer()] | undefined}).
-type 'HOST/VMS'() :: #'HOST/VMS'{}.
-record('HOST/HOST_SHARE', {anyAttribs :: anyAttribs(),
'MEM_USAGE' :: integer(),
'CPU_USAGE' :: integer(),
'TOTAL_MEM' :: integer(),
'TOTAL_CPU' :: integer(),
'MAX_MEM' :: integer(),
'MAX_CPU' :: integer(),
'RUNNING_VMS' :: integer(),
'VMS_THREAD' :: integer(),
'DATASTORES' :: 'HOST/HOST_SHARE/DATASTORES'(),
'PCI_DEVICES' :: 'HOST/HOST_SHARE/PCI_DEVICES'(),
'NUMA_NODES' :: 'HOST/HOST_SHARE/NUMA_NODES'()}).
-type 'HOST/HOST_SHARE'() :: #'HOST/HOST_SHARE'{}.
-record('HOST/HOST_SHARE/NUMA_NODES', {anyAttribs :: anyAttribs(),
'NODE' :: ['HOST/HOST_SHARE/NUMA_NODES/NODE'()] | undefined}).
-type 'HOST/HOST_SHARE/NUMA_NODES'() :: #'HOST/HOST_SHARE/NUMA_NODES'{}.
-record('HOST/HOST_SHARE/NUMA_NODES/NODE', {anyAttribs :: anyAttribs(),
'CORE' :: ['HOST/HOST_SHARE/NUMA_NODES/NODE/CORE'()] | undefined,
'HUGEPAGE' :: ['HOST/HOST_SHARE/NUMA_NODES/NODE/HUGEPAGE'()] | undefined,
'MEMORY' :: 'HOST/HOST_SHARE/NUMA_NODES/NODE/MEMORY'(),
'NODE_ID' :: integer()}).
-type 'HOST/HOST_SHARE/NUMA_NODES/NODE'() :: #'HOST/HOST_SHARE/NUMA_NODES/NODE'{}.
-record('HOST/HOST_SHARE/NUMA_NODES/NODE/MEMORY', {anyAttribs :: anyAttribs(),
'DISTANCE' :: string(),
'FREE' :: integer(),
'TOTAL' :: integer(),
'USAGE' :: integer(),
'USED' :: integer()}).
-type 'HOST/HOST_SHARE/NUMA_NODES/NODE/MEMORY'() :: #'HOST/HOST_SHARE/NUMA_NODES/NODE/MEMORY'{}.
-record('HOST/HOST_SHARE/NUMA_NODES/NODE/HUGEPAGE', {anyAttribs :: anyAttribs(),
'FREE' :: integer(),
'PAGES' :: integer(),
'SIZE' :: integer(),
'USAGE' :: integer()}).
-type 'HOST/HOST_SHARE/NUMA_NODES/NODE/HUGEPAGE'() :: #'HOST/HOST_SHARE/NUMA_NODES/NODE/HUGEPAGE'{}.
-record('HOST/HOST_SHARE/NUMA_NODES/NODE/CORE', {anyAttribs :: anyAttribs(),
'CPUS' :: string(),
'DEDICATED' :: string(),
'FREE' :: integer(),
'ID' :: integer()}).
-type 'HOST/HOST_SHARE/NUMA_NODES/NODE/CORE'() :: #'HOST/HOST_SHARE/NUMA_NODES/NODE/CORE'{}.
-record('HOST/HOST_SHARE/PCI_DEVICES', {anyAttribs :: anyAttribs(),
'PCI' :: [string()] | undefined}).
-type 'HOST/HOST_SHARE/PCI_DEVICES'() :: #'HOST/HOST_SHARE/PCI_DEVICES'{}.
-record('HOST/HOST_SHARE/DATASTORES', {anyAttribs :: anyAttribs(),
'DISK_USAGE' :: integer(),
'FREE_DISK' :: integer(),
'MAX_DISK' :: integer(),
'USED_DISK' :: integer()}).
-type 'HOST/HOST_SHARE/DATASTORES'() :: #'HOST/HOST_SHARE/DATASTORES'{}.

View File

@ -0,0 +1,131 @@
%% HRL file generated by ERLSOM
%%
%% It is possible (and in some cases necessary) to change the name of
%% the record fields.
%%
%% It is possible to add default values, but be aware that these will
%% only be used when *writing* an xml document.
-ifndef(ERLSOM_ANY_ATTRIB_TYPES).
-define(ERLSOM_ANY_ATTRIB_TYPES, true).
-type anyAttrib() :: {{string(), %% name of the attribute
string()}, %% namespace
string()}. %% value
-type anyAttribs() :: [anyAttrib()] | undefined.
-endif.
-ifndef(ERLSOM_QNAME_TYPES).
-define(ERLSOM_QNAME_TYPES, true).
%% xsd:QName values are translated to #qname{} records.
-record(qname, {uri :: string(),
localPart :: string(),
prefix :: string(),
mappedPrefix :: string()}).
-endif.
-record('IMAGE', {anyAttribs :: anyAttribs(),
'ID' :: integer(),
'UID' :: integer(),
'GID' :: integer(),
'UNAME' :: string(),
'GNAME' :: string(),
'NAME' :: string(),
'LOCK' :: 'IMAGE/LOCK'() | undefined,
'PERMISSIONS' :: 'IMAGE/PERMISSIONS'() | undefined,
'TYPE' :: integer(),
'DISK_TYPE' :: integer(),
'PERSISTENT' :: integer(),
'REGTIME' :: integer(),
'SOURCE' :: string(),
'PATH' :: string(),
'FORMAT' :: string(),
'FS' :: string(),
'SIZE' :: integer(),
'STATE' :: integer(),
'RUNNING_VMS' :: integer(),
'CLONING_OPS' :: integer(),
'CLONING_ID' :: integer(),
'TARGET_SNAPSHOT' :: integer(),
'DATASTORE_ID' :: integer(),
'DATASTORE' :: string(),
'VMS' :: 'IMAGE/VMS'(),
'CLONES' :: 'IMAGE/CLONES'(),
'APP_CLONES' :: 'IMAGE/APP_CLONES'(),
'TEMPLATE' :: 'IMAGE/TEMPLATE'(),
'SNAPSHOTS' :: 'IMAGE/SNAPSHOTS'()}).
-type 'IMAGE'() :: #'IMAGE'{}.
-record('IMAGE/SNAPSHOTS', {anyAttribs :: anyAttribs(),
'ALLOW_ORPHANS' :: string(),
'CURRENT_BASE' :: integer(),
'NEXT_SNAPSHOT' :: string(),
'SNAPSHOT' :: ['IMAGE/SNAPSHOTS/SNAPSHOT'()] | undefined}).
-type 'IMAGE/SNAPSHOTS'() :: #'IMAGE/SNAPSHOTS'{}.
-record('IMAGE/SNAPSHOTS/SNAPSHOT', {anyAttribs :: anyAttribs(),
'CHILDREN' :: string() | undefined,
'ACTIVE' :: string() | undefined,
'DATE' :: integer(),
'ID' :: integer(),
'NAME' :: string() | undefined,
'PARENT' :: integer(),
'SIZE' :: integer()}).
-type 'IMAGE/SNAPSHOTS/SNAPSHOT'() :: #'IMAGE/SNAPSHOTS/SNAPSHOT'{}.
-record('IMAGE/TEMPLATE', {anyAttribs :: anyAttribs(),
choice :: [any()] | undefined,
'VCENTER_IMPORTED' :: string() | undefined,
choice1 :: [any()] | undefined}).
-type 'IMAGE/TEMPLATE'() :: #'IMAGE/TEMPLATE'{}.
-record('IMAGE/APP_CLONES', {anyAttribs :: anyAttribs(),
'ID' :: [integer()] | undefined}).
-type 'IMAGE/APP_CLONES'() :: #'IMAGE/APP_CLONES'{}.
-record('IMAGE/CLONES', {anyAttribs :: anyAttribs(),
'ID' :: [integer()] | undefined}).
-type 'IMAGE/CLONES'() :: #'IMAGE/CLONES'{}.
-record('IMAGE/VMS', {anyAttribs :: anyAttribs(),
'ID' :: [integer()] | undefined}).
-type 'IMAGE/VMS'() :: #'IMAGE/VMS'{}.
-record('IMAGE/PERMISSIONS', {anyAttribs :: anyAttribs(),
'OWNER_U' :: integer(),
'OWNER_M' :: integer(),
'OWNER_A' :: integer(),
'GROUP_U' :: integer(),
'GROUP_M' :: integer(),
'GROUP_A' :: integer(),
'OTHER_U' :: integer(),
'OTHER_M' :: integer(),
'OTHER_A' :: integer()}).
-type 'IMAGE/PERMISSIONS'() :: #'IMAGE/PERMISSIONS'{}.
-record('IMAGE/LOCK', {anyAttribs :: anyAttribs(),
'LOCKED' :: integer(),
'OWNER' :: integer(),
'TIME' :: integer(),
'REQ_ID' :: integer()}).
-type 'IMAGE/LOCK'() :: #'IMAGE/LOCK'{}.

View File

@ -0,0 +1,66 @@
%% HRL file generated by ERLSOM
%%
%% It is possible (and in some cases necessary) to change the name of
%% the record fields.
%%
%% It is possible to add default values, but be aware that these will
%% only be used when *writing* an xml document.
-ifndef(ERLSOM_ANY_ATTRIB_TYPES).
-define(ERLSOM_ANY_ATTRIB_TYPES, true).
-type anyAttrib() :: {{string(), %% name of the attribute
string()}, %% namespace
string()}. %% value
-type anyAttribs() :: [anyAttrib()] | undefined.
-endif.
-ifndef(ERLSOM_QNAME_TYPES).
-define(ERLSOM_QNAME_TYPES, true).
%% xsd:QName values are translated to #qname{} records.
-record(qname, {uri :: string(),
localPart :: string(),
prefix :: string(),
mappedPrefix :: string()}).
-endif.
-record('MARKETPLACE', {anyAttribs :: anyAttribs(),
'ID' :: integer(),
'UID' :: integer(),
'GID' :: integer(),
'UNAME' :: string(),
'GNAME' :: string(),
'NAME' :: string(),
'MARKET_MAD' :: string(),
'ZONE_ID' :: string(),
'TOTAL_MB' :: integer(),
'FREE_MB' :: integer(),
'USED_MB' :: integer(),
'MARKETPLACEAPPS' :: 'MARKETPLACE/MARKETPLACEAPPS'(),
'PERMISSIONS' :: 'MARKETPLACE/PERMISSIONS'() | undefined,
'TEMPLATE' :: string()}).
-type 'MARKETPLACE'() :: #'MARKETPLACE'{}.
-record('MARKETPLACE/PERMISSIONS', {anyAttribs :: anyAttribs(),
'OWNER_U' :: integer(),
'OWNER_M' :: integer(),
'OWNER_A' :: integer(),
'GROUP_U' :: integer(),
'GROUP_M' :: integer(),
'GROUP_A' :: integer(),
'OTHER_U' :: integer(),
'OTHER_M' :: integer(),
'OTHER_A' :: integer()}).
-type 'MARKETPLACE/PERMISSIONS'() :: #'MARKETPLACE/PERMISSIONS'{}.
-record('MARKETPLACE/MARKETPLACEAPPS', {anyAttribs :: anyAttribs(),
'ID' :: [integer()] | undefined}).
-type 'MARKETPLACE/MARKETPLACEAPPS'() :: #'MARKETPLACE/MARKETPLACEAPPS'{}.

Some files were not shown because too many files have changed in this diff Show More