1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-16 22:50:10 +03:00

F #5387: add Vultr support into OneProvision (#1229)

This commit is contained in:
Alejandro Huertas Herrero 2021-05-19 12:24:19 +02:00 committed by GitHub
parent d67b1ae8b2
commit 7927c95553
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 1874 additions and 39 deletions

View File

@ -299,6 +299,8 @@ LIB_DIRS="$LIB_LOCATION/ruby \
$LIB_LOCATION/oneprovision/lib/terraform/providers/templates/google \
$LIB_LOCATION/oneprovision/lib/terraform/providers/templates/digitalocean \
$LIB_LOCATION/oneprovision/lib/terraform/providers/templates/packet \
$LIB_LOCATION/oneprovision/lib/terraform/providers/templates/vultr_metal \
$LIB_LOCATION/oneprovision/lib/terraform/providers/templates/vultr_virtual \
$LIB_LOCATION/oneprovision/lib/provision \
$LIB_LOCATION/oneprovision/lib/provision_template \
$LIB_LOCATION/oneprovision/lib/provider \
@ -501,6 +503,7 @@ VAR_DIRS="$VAR_LOCATION/remotes \
$VAR_LOCATION/remotes/auth/dummy \
$VAR_LOCATION/remotes/ipam/dummy \
$VAR_LOCATION/remotes/ipam/packet \
$VAR_LOCATION/remotes/ipam/vultr \
$VAR_LOCATION/remotes/ipam/aws"
SUNSTONE_DIRS="$SUNSTONE_LOCATION/routes \
@ -712,6 +715,7 @@ INSTALL_FILES=(
MARKETPLACE_DRIVER_DH_SCRIPTS:$VAR_LOCATION/remotes/market/dockerhub
IPAM_DRIVER_DUMMY_SCRIPTS:$VAR_LOCATION/remotes/ipam/dummy
IPAM_DRIVER_PACKET_SCRIPTS:$VAR_LOCATION/remotes/ipam/packet
IPAM_DRIVER_VULTR_SCRIPTS:$VAR_LOCATION/remotes/ipam/vultr
IPAM_DRIVER_EC2_SCRIPTS:$VAR_LOCATION/remotes/ipam/aws
NETWORK_FILES:$VAR_LOCATION/remotes/vnm
NETWORK_HOOKS_PRE_FILES:$VAR_LOCATION/remotes/vnm/hooks/pre
@ -786,6 +790,8 @@ INSTALL_ONEPROVISION_FILES=(
ONEPROVISION_LIB_GOOGLE_ERB_FILES:$LIB_LOCATION/oneprovision/lib/terraform/providers/templates/google
ONEPROVISION_LIB_DIGITALOCEAN_ERB_FILES:$LIB_LOCATION/oneprovision/lib/terraform/providers/templates/digitalocean
ONEPROVISION_LIB_PACKET_ERB_FILES:$LIB_LOCATION/oneprovision/lib/terraform/providers/templates/packet
ONEPROVISION_LIB_VULTR_METAL_ERB_FILES:$LIB_LOCATION/oneprovision/lib/terraform/providers/templates/vultr_metal
ONEPROVISION_LIB_VULTR_VIRTUAL_ERB_FILES:$LIB_LOCATION/oneprovision/lib/terraform/providers/templates/vultr_virtual
ONEPROVISION_LIB_PROVISION_FILES:$LIB_LOCATION/oneprovision/lib/provision
ONEPROVISION_LIB_RESOURCES_FILES:$LIB_LOCATION/oneprovision/lib/provision/resources
ONEPROVISION_LIB_PHYSICAL_R_FILES:$LIB_LOCATION/oneprovision/lib/provision/resources/physical
@ -992,7 +998,8 @@ RUBY_LIB_FILES="src/mad/ruby/ActionManager.rb \
src/vmm_mad/remotes/one/opennebula_driver.rb \
src/vmm_mad/remotes/packet/packet_driver.rb \
src/vnm_mad/remotes/elastic/aws_vnm.rb \
src/vnm_mad/remotes/elastic/packet_vnm.rb"
src/vnm_mad/remotes/elastic/packet_vnm.rb \
src/vnm_mad/remotes/elastic/vultr_vnm.rb"
#-------------------------------------------------------------------------------
# Ruby auth library files, to be installed under $LIB_LOCATION/ruby/opennebula
@ -1767,28 +1774,37 @@ NETWORK_ETC_FILES="src/vnm_mad/remotes/OpenNebulaNetwork.conf"
# IPAM dummy drivers to be installed under $REMOTES_LOCATION/ipam
#-------------------------------------------------------------------------------
IPAM_DRIVER_DUMMY_SCRIPTS="src/ipamm_mad/remotes/dummy/register_address_range \
src/ipamm_mad/remotes/dummy/unregister_address_range \
src/ipamm_mad/remotes/dummy/allocate_address \
src/ipamm_mad/remotes/dummy/get_address \
src/ipamm_mad/remotes/dummy/free_address"
src/ipamm_mad/remotes/dummy/unregister_address_range \
src/ipamm_mad/remotes/dummy/allocate_address \
src/ipamm_mad/remotes/dummy/get_address \
src/ipamm_mad/remotes/dummy/free_address"
#-------------------------------------------------------------------------------
# IPAM Packet drivers to be installed under $REMOTES_LOCATION/ipam
#-------------------------------------------------------------------------------
IPAM_DRIVER_PACKET_SCRIPTS="src/ipamm_mad/remotes/packet/register_address_range \
src/ipamm_mad/remotes/packet/unregister_address_range \
src/ipamm_mad/remotes/packet/allocate_address \
src/ipamm_mad/remotes/packet/get_address \
src/ipamm_mad/remotes/packet/free_address"
src/ipamm_mad/remotes/packet/unregister_address_range \
src/ipamm_mad/remotes/packet/allocate_address \
src/ipamm_mad/remotes/packet/get_address \
src/ipamm_mad/remotes/packet/free_address"
#-------------------------------------------------------------------------------
# IPAM Vultr drivers to be installed under $REMOTES_LOCATION/ipam
#-------------------------------------------------------------------------------
IPAM_DRIVER_VULTR_SCRIPTS="src/ipamm_mad/remotes/vultr/register_address_range \
src/ipamm_mad/remotes/vultr/unregister_address_range \
src/ipamm_mad/remotes/vultr/allocate_address \
src/ipamm_mad/remotes/vultr/get_address \
src/ipamm_mad/remotes/vultr/free_address"
#-------------------------------------------------------------------------------
# IPAM EC2 drivers to be installed under $REMOTES_LOCATION/ipam
#-------------------------------------------------------------------------------
IPAM_DRIVER_EC2_SCRIPTS="src/ipamm_mad/remotes/aws/register_address_range \
src/ipamm_mad/remotes/aws/unregister_address_range \
src/ipamm_mad/remotes/aws/allocate_address \
src/ipamm_mad/remotes/aws/get_address \
src/ipamm_mad/remotes/aws/free_address"
src/ipamm_mad/remotes/aws/unregister_address_range \
src/ipamm_mad/remotes/aws/allocate_address \
src/ipamm_mad/remotes/aws/get_address \
src/ipamm_mad/remotes/aws/free_address"
#-------------------------------------------------------------------------------
# Transfer Manager commands, to be installed under $LIB_LOCATION/tm_commands
@ -2515,7 +2531,10 @@ ONEPROVISION_LIB_PROVIDERS_FILES="src/oneprovision/lib/terraform/providers/aws.r
src/oneprovision/lib/terraform/providers/google.rb \
src/oneprovision/lib/terraform/providers/digitalocean.rb \
src/oneprovision/lib/terraform/providers/dummy.rb \
src/oneprovision/lib/terraform/providers/packet.rb"
src/oneprovision/lib/terraform/providers/packet.rb \
src/oneprovision/lib/terraform/providers/vultr.rb \
src/oneprovision/lib/terraform/providers/vultr_metal.rb \
src/oneprovision/lib/terraform/providers/vultr_virtual.rb"
ONEPROVISION_LIB_AWS_ERB_FILES="src/oneprovision/lib/terraform/providers/templates/aws/cluster.erb \
src/oneprovision/lib/terraform/providers/templates/aws/datastore.erb \
@ -2541,6 +2560,18 @@ ONEPROVISION_LIB_PACKET_ERB_FILES="src/oneprovision/lib/terraform/providers/temp
src/oneprovision/lib/terraform/providers/templates/packet/network.erb \
src/oneprovision/lib/terraform/providers/templates/packet/provider.erb"
ONEPROVISION_LIB_VULTR_METAL_ERB_FILES="src/oneprovision/lib/terraform/providers/templates/vultr_metal/cluster.erb \
src/oneprovision/lib/terraform/providers/templates/vultr_metal/datastore.erb \
src/oneprovision/lib/terraform/providers/templates/vultr_metal/host.erb \
src/oneprovision/lib/terraform/providers/templates/vultr_metal/network.erb \
src/oneprovision/lib/terraform/providers/templates/vultr_metal/provider.erb"
ONEPROVISION_LIB_VULTR_VIRTUAL_ERB_FILES="src/oneprovision/lib/terraform/providers/templates/vultr_virtual/cluster.erb \
src/oneprovision/lib/terraform/providers/templates/vultr_virtual/datastore.erb \
src/oneprovision/lib/terraform/providers/templates/vultr_virtual/host.erb \
src/oneprovision/lib/terraform/providers/templates/vultr_virtual/network.erb \
src/oneprovision/lib/terraform/providers/templates/vultr_virtual/provider.erb"
#-----------------------------------------------------------------------------
# Sunstone files
#-----------------------------------------------------------------------------
@ -2925,7 +2956,8 @@ DOCS_FILES="LICENSE LICENSE.onsla LICENSE.onsla-nc NOTICE README.md"
# Ruby VENDOR files
#-----------------------------------------------------------------------------
VENDOR_DIRS="share/vendor/ruby/gems/packethost"
VENDOR_DIRS="share/vendor/ruby/gems/packethost \
share/vendor/ruby/gems/vultr"
#-------------------------------------------------------------------------------
# Libvirt RelaxNG schemas

View File

@ -668,7 +668,7 @@ MARKET_MAD = [
IPAM_MAD = [
EXECUTABLE = "one_ipam",
ARGUMENTS = "-t 1 -i dummy,aws,packet"
ARGUMENTS = "-t 1 -i dummy,aws,packet,vultr"
]
#*******************************************************************************
@ -1068,6 +1068,7 @@ INHERIT_VNET_ATTR = "IP_LINK_CONF"
INHERIT_VNET_ATTR = "EXTERNAL_IP"
INHERIT_VNET_ATTR = "EXTERNAL"
INHERIT_VNET_ATTR = "AWS_ALLOCATION_ID"
INHERIT_VNET_ATTR = "VULTR_IP_ID"
INHERIT_VNET_ATTR = "GATEWAY"
INHERIT_VNET_ATTR = "VXLAN_MODE"
INHERIT_VNET_ATTR = "VXLAN_TEP"

View File

@ -0,0 +1,20 @@
# networking
## Description
Configures static IP address for network interface.
These changes are persistent.
## Requirements
No special requirements.
## Variables
All of the variables in this role are documented in the [defaults](defaults/main.yml) file.
## Todo list
None

View File

@ -0,0 +1,9 @@
################################################################################
# Mandatory
################################################################################
# The network device to configure
networking_iface: 'ens7'
# Netmask of the interface
networking_prefix: 20

View File

@ -0,0 +1,6 @@
---
- name: restart network
service:
name: network
state: restarted

View File

@ -0,0 +1,13 @@
---
- name: Configuration for bridge
template:
src: ifcfg.j2
dest: /etc/sysconfig/network-scripts/ifcfg-{{ networking_iface }}
notify: restart network
- name: Force all notified handlers to run now
meta: flush_handlers
- name: Refresh facts
setup:

View File

@ -0,0 +1,6 @@
DEVICE={{ networking_iface }}
BOOTPROTO=static
ONBOOT=yes
NM_CONTROLLED=no
IPADDR={{ private_ip }}
PREFIX={{ networking_prefix }}

View File

@ -0,0 +1,28 @@
---
- hosts: all
gather_facts: false
roles:
- python
- hosts: nodes
roles:
- networking
- ddc
- opennebula-repository
- { role: opennebula-node-kvm, when: oneprovision_hypervisor == 'kvm' or oneprovision_hypervisor == 'qemu' }
- { role: opennebula-node-firecracker, when: oneprovision_hypervisor == 'firecracker' }
- { role: opennebula-node-lxc, when: oneprovision_hypervisor == 'lxc' }
- opennebula-ssh
- role: iptables
iptables_base_rules_services:
- { protocol: 'tcp', port: 22 }
# TCP/179 bgpd (TODO: only needed on Route Refector(s))
- { protocol: 'tcp', port: 179 }
# TCP/8742 default VXLAN port on Linux (UDP/4789 default IANA)
- { protocol: 'udp', port: 8472 }
- update-replica
- role: frr
frr_iface: 'ens7'
# Use /20 for the internal management network address
frr_prefix_length: 20

View File

@ -0,0 +1,23 @@
name: 'vultr-amsterdam'
description: 'Edge cluster in Vultr Amsterdam'
provider: 'vultr_metal'
plain:
image: 'VULTR'
location_key: 'region'
provision_type: 'metal'
connection:
key: 'Vultr key'
region: 'ams'
inputs:
- name: 'vultr_os'
type: 'list'
options:
- '362'
- name: 'vultr_plan'
type: 'list'
options:
- 'vbm-8c-132gb'

View File

@ -0,0 +1,23 @@
name: 'vultr-chicago'
description: 'Edge cluster in Vultr Chicago'
provider: 'vultr_metal'
plain:
image: 'VULTR'
location_key: 'region'
provision_type: 'metal'
connection:
key: 'Vultr key'
region: 'ord'
inputs:
- name: 'vultr_os'
type: 'list'
options:
- '362'
- name: 'vultr_plan'
type: 'list'
options:
- 'vbm-8c-132gb'

View File

@ -0,0 +1,23 @@
name: 'vultr-san-francisco'
description: 'Edge cluster in Vultr San Francisco'
provider: 'vultr_metal'
plain:
image: 'VULTR'
location_key: 'region'
provision_type: 'metal'
connection:
key: 'Vultr key'
region: 'sjc'
inputs:
- name: 'vultr_os'
type: 'list'
options:
- '362'
- name: 'vultr_plan'
type: 'list'
options:
- 'vbm-8c-132gb'

View File

@ -0,0 +1,40 @@
---
# ---------------------------------------------------------------------------- #
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# ---------------------------------------------------------------------------- #
#-------------------------------------------------------------------------------
# datastores: Defines the storage area for the cluster using the SSH replication
# drivers. It creates the following datastores, using Replica driver:
# 1. Image datastore, ${cluster_name}-image
# 2. System datastore, ${cluster_name}-system
# 3. File datastore, ${cluster_name}-files
#
# Configuration/Input attributes:
# - replica_host: The host that will hold the cluster replicas and snapshots.
#-------------------------------------------------------------------------------
datastores:
- name: "${provision}-image"
type: 'image_ds'
ds_mad: 'fs'
tm_mad: 'ssh'
safe_dirs: "/var/tmp /tmp"
- name: "${provision}-system"
type: 'system_ds'
tm_mad: 'ssh'
safe_dirs: "/var/tmp /tmp"
replica_host: "use-first-host"

View File

@ -0,0 +1,20 @@
---
# ---------------------------------------------------------------------------- #
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# ---------------------------------------------------------------------------- #
image: 'OPENNEBULA-VULTR'
provider: 'vultr_metal'
provision_type: 'metal'

View File

@ -0,0 +1,53 @@
---
# ---------------------------------------------------------------------------- #
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# ---------------------------------------------------------------------------- #
inputs:
- name: 'number_hosts'
type: text
description: "Number of metal servers to create"
default: '1'
- name: 'number_public_ips'
type: text
description: 'Number of public IPs to get'
default: '1'
- name: 'dns'
type: text
description: 'Comma separated list of DNS servers for public network'
default: '1.1.1.1'
- name: 'vultr_plan'
type: text
description: "Vultr plan (device type)"
default: 'vc2-1c-1gb'
- name: 'vultr_os'
type: text
description: "Vultr host operating system"
default: '362'
- name: 'one_hypervisor'
type: list
description: "Virtualization technology for the cluster hosts"
options:
- 'kvm'
- 'firecracker'
- 'lxc'
default: 'kvm'
...

View File

@ -0,0 +1,41 @@
---
# ---------------------------------------------------------------------------- #
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# ---------------------------------------------------------------------------- #
networks:
- name: "${provision}-public"
vn_mad: 'elastic'
bridge: 'br0'
netrole: 'public'
dns: "${input.dns}"
provision:
count: "${input.number_public_ips}"
ar:
- provison_id: "${provision_id}"
size: '1'
vultr_ip_type: 'v4'
ipam_mad: 'vultr'
vntemplates:
- name: "${provision}-private"
vn_mad: 'vxlan'
phydev: 'ens7'
automatic_vlan_id: 'yes'
netrole: 'private'
vxlan_mode: 'evpn'
vxlan_tep: 'dev'
ip_link_conf: 'nolearning='
cluster_ids: "${cluster.0.id}"

View File

@ -0,0 +1,65 @@
---
# ---------------------------------------------------------------------------- #
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# ---------------------------------------------------------------------------- #
#-------------------------------------------------------------------------------
# This is the canonical description file for a cluster build with 'Vultr'
# resources using the KVM hypervisor.
# ------------------------------------------------------------------------------
name: 'vultr_metal-cluster'
extends:
- common.d/defaults.yml
- common.d/resources.yml
- common.d/hosts.yml
- vultr.d/datastores.yml
- vultr.d/fireedge.yml
- vultr.d/inputs.yml
- vultr.d/networks.yml
#-------------------------------------------------------------------------------
# playbook: Ansible playbook used for hosts configuration. Check
# ansible/vultr.yml for the specific roles applied.
#-------------------------------------------------------------------------------
playbook:
- vultr
#-------------------------------------------------------------------------------
# defaults: Common configuration attributes for provision objects
#--------------------------------------------------------------------------------
defaults:
provision:
provider_name: 'vultr_metal'
plan: "${input.vultr_plan}"
os: "${input.vultr_os}"
#-------------------------------------------------------------------------------
# cluster: Parameters for the OpenNebula cluster. Applies to all the Hosts
#--------------------------------------------------------------------------------
# name: of the cluster
# description: Additional information
# reserved_cpu: In percentage. It will be subtracted from the TOTAL CPU
# reserved_memory: In percentage. It will be subtracted from the TOTAL MEM
#--------------------------------------------------------------------------------
cluster:
name: "${provision}"
description: 'Vultr edge cluster'
datastores:
- 1
- 2
reserved_cpu: '0'
reserved_mem: '0'

View File

@ -0,0 +1,25 @@
name: 'vultr-amsterdam'
description: 'Edge cluster in Vultr Amsterdam'
provider: 'vultr_virtual'
plain:
image: 'VULTR'
location_key: 'region'
provision_type: 'virtual'
connection:
key: 'Vultr key'
region: 'ams'
inputs:
- name: 'vultr_os'
type: 'list'
options:
- '362'
- name: 'vultr_plan'
type: 'list'
options:
- 'vc2-1c-1gb'
- 'vc2-1c-2gb'
- 'vc2-1c-4gb'

View File

@ -0,0 +1,25 @@
name: 'vultr-london'
description: 'Edge cluster in Vultr London'
provider: 'vultr_virtual'
plain:
image: 'VULTR'
location_key: 'region'
provision_type: 'virtual'
connection:
key: 'Vultr key'
region: 'lhr'
inputs:
- name: 'vultr_os'
type: 'list'
options:
- '362'
- name: 'vultr_plan'
type: 'list'
options:
- 'vc2-1c-1gb'
- 'vc2-1c-2gb'
- 'vc2-1c-4gb'

View File

@ -0,0 +1,25 @@
name: 'vultr-chicago'
description: 'Edge cluster in Vultr Chicago'
provider: 'vultr_virtual'
plain:
image: 'VULTR'
location_key: 'region'
provision_type: 'virtual'
connection:
key: 'Vultr key'
region: 'ord'
inputs:
- name: 'vultr_os'
type: 'list'
options:
- '362'
- name: 'vultr_plan'
type: 'list'
options:
- 'vc2-1c-1gb'
- 'vc2-1c-2gb'
- 'vc2-1c-4gb'

View File

@ -0,0 +1,25 @@
name: 'vultr-san-francisco'
description: 'Edge cluster in Vultr San Francisco'
provider: 'vultr_virtual'
plain:
image: 'VULTR'
location_key: 'region'
provision_type: 'virtual'
connection:
key: 'Vultr key'
region: 'sjc'
inputs:
- name: 'vultr_os'
type: 'list'
options:
- '362'
- name: 'vultr_plan'
type: 'list'
options:
- 'vc2-1c-1gb'
- 'vc2-1c-2gb'
- 'vc2-1c-4gb'

View File

@ -0,0 +1,40 @@
---
# ---------------------------------------------------------------------------- #
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# ---------------------------------------------------------------------------- #
#-------------------------------------------------------------------------------
# datastores: Defines the storage area for the cluster using the SSH replication
# drivers. It creates the following datastores, using Replica driver:
# 1. Image datastore, ${cluster_name}-image
# 2. System datastore, ${cluster_name}-system
# 3. File datastore, ${cluster_name}-files
#
# Configuration/Input attributes:
# - replica_host: The host that will hold the cluster replicas and snapshots.
#-------------------------------------------------------------------------------
datastores:
- name: "${provision}-image"
type: 'image_ds'
ds_mad: 'fs'
tm_mad: 'ssh'
safe_dirs: "/var/tmp /tmp"
- name: "${provision}-system"
type: 'system_ds'
tm_mad: 'ssh'
safe_dirs: "/var/tmp /tmp"
replica_host: "use-first-host"

View File

@ -0,0 +1,20 @@
---
# ---------------------------------------------------------------------------- #
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# ---------------------------------------------------------------------------- #
image: 'OPENNEBULA-VULTR'
provider: 'vultr_virtual'
provision_type: 'virtual'

View File

@ -0,0 +1,52 @@
---
# ---------------------------------------------------------------------------- #
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# ---------------------------------------------------------------------------- #
inputs:
- name: 'number_hosts'
type: text
description: "Number of virtual servers to create"
default: '1'
- name: 'number_public_ips'
type: text
description: 'Number of public IPs to get'
default: '1'
- name: 'dns'
type: text
description: 'Comma separated list of DNS servers for public network'
default: '1.1.1.1'
- name: 'vultr_plan'
type: text
description: "Vultr plan (device type)"
default: 'vc2-1c-1gb'
- name: 'vultr_os'
type: text
description: "Vultr host operating system"
default: '362'
- name: 'one_hypervisor'
type: list
description: "Virtualization technology for the cluster hosts"
options:
- 'qemu'
- 'lxc'
default: 'lxc'
...

View File

@ -0,0 +1,41 @@
---
# ---------------------------------------------------------------------------- #
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# ---------------------------------------------------------------------------- #
networks:
- name: "${provision}-public"
vn_mad: 'elastic'
bridge: 'br0'
netrole: 'public'
dns: "${input.dns}"
provision:
count: "${input.number_public_ips}"
ar:
- provison_id: "${provision_id}"
size: '1'
vultr_ip_type: 'v4'
ipam_mad: 'vultr'
vntemplates:
- name: "${provision}-private"
vn_mad: 'vxlan'
phydev: 'ens7'
automatic_vlan_id: 'yes'
netrole: 'private'
vxlan_mode: 'evpn'
vxlan_tep: 'dev'
ip_link_conf: 'nolearning='
cluster_ids: "${cluster.0.id}"

View File

@ -0,0 +1,65 @@
---
# ---------------------------------------------------------------------------- #
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# ---------------------------------------------------------------------------- #
#-------------------------------------------------------------------------------
# This is the canonical description file for a cluster build with 'Vultr'
# resources using the KVM hypervisor.
# ------------------------------------------------------------------------------
name: 'vultr_virtual-cluster'
extends:
- common.d/defaults.yml
- common.d/resources.yml
- common.d/hosts.yml
- vultr.d/datastores.yml
- vultr.d/fireedge.yml
- vultr.d/inputs.yml
- vultr.d/networks.yml
#-------------------------------------------------------------------------------
# playbook: Ansible playbook used for hosts configuration. Check
# ansible/vultr.yml for the specific roles applied.
#-------------------------------------------------------------------------------
playbook:
- vultr
#-------------------------------------------------------------------------------
# defaults: Common configuration attributes for provision objects
#--------------------------------------------------------------------------------
defaults:
provision:
provider_name: 'vultr_virtual'
plan: "${input.vultr_plan}"
os: "${input.vultr_os}"
#-------------------------------------------------------------------------------
# cluster: Parameters for the OpenNebula cluster. Applies to all the Hosts
#--------------------------------------------------------------------------------
# name: of the cluster
# description: Additional information
# reserved_cpu: In percentage. It will be subtracted from the TOTAL CPU
# reserved_memory: In percentage. It will be subtracted from the TOTAL MEM
#--------------------------------------------------------------------------------
cluster:
name: "${provision}"
description: 'Vultr edge cluster'
datastores:
- 1
- 2
reserved_cpu: '0'
reserved_mem: '0'

View File

@ -0,0 +1,212 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
require 'json'
require 'net/http'
# Vultr error
class VultrError < StandardError
# Check if error is really an error
#
# @param error [Object] Error to check
#
# @return [Boolean] True if it is an error, false otherwise
def self.error?(error)
error.class == VultrError
end
end
# Ruby bindings to interact with Vultr provider
class Vultr
############################################################################
#
# This Vultr binding has been developed following methods specified here:
# https://www.vultr.com/api
#
############################################################################
# API base URL
BASE_URL = 'https://api.vultr.com/v2'
# API instances URL
INSTANCE_URL = "#{BASE_URL}/instances"
# API networks URL
NETWORK_URL = "#{BASE_URL}/reserved-ips"
# HTTP codes that are good
GOOD_CODES = [Net::HTTPOK, Net::HTTPNoContent, Net::HTTPCreated]
# Class constructor
#
# @param key [String] Vultr API key
def initialize(key)
@key = key
end
############################################################################
# Instances Methods
############################################################################
# Get instances information
#
# @param id [String] Instances ID
#
# @return [Hash, Error] hash with instance data if no error, error othwerise
def instance(id)
rc = get("#{INSTANCE_URL}/#{id}")
return rc if VultrError.error?(rc)
JSON.parse(rc)['instance']
end
# Attach Reserved IP to an Instance
#
# @param id [String] Instance ID
# @param nic_id [String] The Reserved IP id to attach to this Instance
#
# @return [nil, Error] nil if no error, error othwerise
def attach_nic(id, nic_id)
data = {}
data['instance_id'] = id
post("#{NETWORK_URL}/#{nic_id}/attach", data)
end
# Detach Reserved IP from an Instance
#
# @param id [String] Instance ID
# @param nic_id [String] The Reserved IP id to detach from this Instance
#
# @return [nil, Error] nil if no error, error othwerise
def detach_nic(id, nic_id)
data = {}
data['instance_id'] = id
post("#{NETWORK_URL}/#{nic_id}/detach", data)
end
############################################################################
# Network methods
############################################################################
# Create a new Reserved IP in a region
#
# @param region [String] Create the Reserved IP in this Region id
# @param ip_type [String] IP version, it can be v4 or v6
#
# @return [Hash, Error] Reserved IP hash if no error, error othwerise
def create_nic(region, ip_type = 'v4')
data = {}
data['region'] = region
data['ip_type'] = ip_type
rc = post(NETWORK_URL, data)
return rc if VultrError.error?(rc)
JSON.parse(rc)['reserved_ip']
end
# Delete aPrivate Network
#
# @param nic_id [String] The Network ID
#
# @return [nil, Error] nil if no error, error othwerise
def delete_nic(nic_id)
delete("#{NETWORK_URL}/#{nic_id}")
end
private
############################################################################
# HTTP methods
############################################################################
# Execute HTTP Get operation
#
# @param url [String] URL to call
#
# @return [Object, Error] Response if everything went well, error othwerise
def get(url)
req(url, :get)
end
# Execute HTTP Post operation
#
# @param url [String] URL to call
# @param data [JSON] Data to send in the request
#
# @return [Object, Error] Response if everything went well, error othwerise
def post(url, data)
req(url, :post, data)
end
# Execute HTTP Delete operation
#
# @param url [String] URL to call
#
# @return [object, error] response if everything went well, error othwerise
def delete(url)
req(url, :delete)
end
############################################################################
# Helpers
############################################################################
# Execute an HTTP request
#
# @param url [String] URL to call
# @param method [Symbol] HTTP method to use
# @param data [JSON] Data to send
#
# @return [object, error] response if everything went well, error othwerise
def req(url, method, data = nil)
uri = URI(url)
case method
when :get
req = Net::HTTP::Get.new(uri)
when :post
req = Net::HTTP::Post.new(uri)
when :delete
req = Net::HTTP::Delete.new(uri)
else
raise "Undefined method #{method}"
end
req['Accept'] = 'application/json'
req['Authorization'] = "Bearer #{@key}"
req.body = data.to_json if data
res = Net::HTTP.new(uri.hostname, uri.port)
res.use_ssl = true
response = res.request(req)
unless GOOD_CODES.include?(response.class)
return VultrError.new(JSON.parse(response.body)['error'])
end
response.body
end
end

View File

@ -0,0 +1,21 @@
#!/usr/bin/env ruby
# -------------------------------------------------------------------------- #
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
STDIN = `cat -`
exit(0)

View File

@ -0,0 +1,21 @@
#!/usr/bin/env ruby
# -------------------------------------------------------------------------- #
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
STDIN = `cat -`
exit(0)

View File

@ -0,0 +1,99 @@
#!/usr/bin/env ruby
# -------------------------------------------------------------------------- #
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
###############################################################################
# This script is used to get a free IP address (or set of IPs). The IP will be
# used by OpenNebula VMs and should not be allocated to any other host in the
# network.
#
# STDIN Input:
# - Base64 encoded XML with the AR description and the address request
#
# This scrit MUST output the leased IP range, if the "size" IPs cannot be
# assgined the sript must return -1, otherwise it must exit 0. The answer to
# OpenNebula needs to include the ADDRESS spec:
#
# ADDRESS = [ IP = "10.0.0.2", SIZE = 1 ]
#
################################################################################
ONE_LOCATION = ENV['ONE_LOCATION'] unless defined?(ONE_LOCATION)
if !ONE_LOCATION
RUBY_LIB_LOCATION ||= '/usr/lib/one/ruby'
GEMS_LOCATION ||= '/usr/share/one/gems'
else
RUBY_LIB_LOCATION ||= ONE_LOCATION + '/lib/ruby'
GEMS_LOCATION ||= ONE_LOCATION + '/share/gems'
end
# %%RUBYGEMS_SETUP_BEGIN%%
if File.directory?(GEMS_LOCATION)
real_gems_path = File.realpath(GEMS_LOCATION)
if !defined?(Gem) || Gem.path != [real_gems_path]
$LOAD_PATH.reject! {|l| l =~ /vendor_ruby/ }
# Suppress warnings from Rubygems
# https://github.com/OpenNebula/one/issues/5379
begin
verb = $VERBOSE
$VERBOSE = nil
require 'rubygems'
Gem.use_paths(real_gems_path)
ensure
$VERBOSE = verb
end
end
end
# %%RUBYGEMS_SETUP_END%%
$LOAD_PATH << RUBY_LIB_LOCATION
require 'base64'
require 'nokogiri'
begin
data = Nokogiri::XML(Base64.decode64(STDIN.read))
size = data.xpath('//ADDRESS/SIZE').text
ip = data.xpath('//AR/IP').text
if Integer(size) != 1
STDERR.puts 'Only IP requests of size 1 are supported'
exit(-1)
end
if ip.empty?
STDERR.puts 'Empty IP address in request'
exit(-1)
end
puts <<-EOF
ADDRESS = [
IP = "#{ip}",
SIZE = "1"
]
EOF
rescue StandardError => e
error_str = "ERROR MESSAGE --8<------\n"
error_str << e.to_s
error_str << "\nERROR MESSAGE ------>8--"
STDERR.puts error_str
exit(-1)
end

View File

@ -0,0 +1,204 @@
#!/usr/bin/env ruby
# -------------------------------------------------------------------------- #
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
###############################################################################
# This script is used to register a new IP network in the IPAM. The network may
# be selected by a pool of free networks or if an specific network is requested
# its availability maybe checked by the IPAM driver.
#
# The IPAM driver must return an OpenNebula AddressRange definition, potentially
# augmented with network specific variables to be used by VMs (e.g. GATEWAYS,
# MASK...)
#
# STDIN Input:
# - Base64 encoded XML with AR request
#
# XML format
# <IPAM_DRIVER_ACTION_DATA>
# <AR>
# <TYPE>Type of the Ip (public/global)</TYPE>
# <SIZE>Number of IPs to allocate</SIZE>
# <PROVISION_ID>ID</PROVISION_ID>
# </AR>
# </IPAM_DRIVER_ACTION_DATA>
#
# The response MUST include IPAM_MAD, TYPE, IP and SIZE attributes, example:
# - A basic network definition
# AR = [
# IPAM_MAD = "vultr",
# TYPE = "IP4",
# IP = "10.0.0.1",
# SIZE = "255",
# DEPLOY_ID = "..",
# ]
#
# - A complete network definition. Custom attributes (free form, key-value)
# can be added, named cannot be repeated.
# AR = [
# IPAM_MAD = "vultr",
# TYPE = "IP4",
# IP = "10.0.0.2",
# SIZE = "200",
# DEPLOY_ID = "..",
# NETWORK_ADDRESS = "10.0.0.0",
# NETWORK_MASK = "255.255.255.0",
# GATEWAY = "10.0.0.1",
# DNS = "10.0.0.1",
# IPAM_ATTR = "10.0.0.240",
# OTHER_IPAM_ATTR = ".mydoamin.com"
# ]
################################################################################
ONE_LOCATION = ENV['ONE_LOCATION'] unless defined?(ONE_LOCATION)
if !ONE_LOCATION
LIB_LOCATION ||= '/usr/lib/one'
VULTR_LOCATION ||= '/usr/lib/one/ruby/vendors/vultr/lib'
RUBY_LIB_LOCATION ||= '/usr/lib/one/ruby'
GEMS_LOCATION ||= '/usr/share/one/gems'
else
LIB_LOCATION ||= ONE_LOCATION + '/lib'
VULTR_LOCATION ||= ONE_LOCATION + '/lib/ruby/vendors/vultr/lib'
RUBY_LIB_LOCATION ||= ONE_LOCATION + '/lib/ruby'
GEMS_LOCATION ||= ONE_LOCATION + '/share/gems'
end
# %%RUBYGEMS_SETUP_BEGIN%%
if File.directory?(GEMS_LOCATION)
real_gems_path = File.realpath(GEMS_LOCATION)
if !defined?(Gem) || Gem.path != [real_gems_path]
$LOAD_PATH.reject! {|l| l =~ /vendor_ruby/ }
# Suppress warnings from Rubygems
# https://github.com/OpenNebula/one/issues/5379
begin
verb = $VERBOSE
$VERBOSE = nil
require 'rubygems'
Gem.use_paths(real_gems_path)
ensure
$VERBOSE = verb
end
end
end
# %%RUBYGEMS_SETUP_END%%
$LOAD_PATH << VULTR_LOCATION
$LOAD_PATH << RUBY_LIB_LOCATION
$LOAD_PATH << LIB_LOCATION + '/oneprovision/lib'
require 'base64'
require 'digest'
require 'ipaddr'
require 'nokogiri'
require 'opennebula'
require 'oneprovision'
require 'vultr'
IP_TYPE = %w[v4 v6]
DEFAULT_PRIVATE_CIDR = '172.16.0.0/12'
# IP Address Class
class IPAddr
# Add ^ operator to the IPAddr class
def ^(other)
clone.set(@addr ^ other.to_i)
end
end
begin
data = Nokogiri::XML(Base64.decode64(STDIN.read))
# --------------------------------------------------------------------------
# Get connection details for the provider
# --------------------------------------------------------------------------
provision_id = data.xpath('//AR/PROVISION_ID').text
if provision_id.empty?
STDERR.puts 'Missing provision id in address range'
exit(-1)
end
one = OpenNebula::Client.new
provision = OneProvision::Provision.new_with_id(provision_id, one)
rc = provision.info
if OpenNebula.is_error?(rc)
STDERR.puts rc.message
exit(-1)
end
provider = provision.provider
connect = provider.body['connection']
v_key = connect['key']
v_region = connect['region']
# --------------------------------------------------------------------------
# Connect to Vultr and allocate a new IP
# --------------------------------------------------------------------------
vultr = Vultr.new(v_key)
ip_type = data.xpath('//AR/VULTR_IP_TYPE').text
ip_size = Integer(data.xpath('//AR/SIZE').text)
if Integer(ip_size) != 1
STDERR.puts 'Only address ranges of size 1 are supported'
exit(-1)
end
if ip_type.empty?
ip_type = IP_TYPE[0]
elsif !IP_TYPE.include?(ip_type)
STDERR.puts "Type #{ip_type} not supported. " \
"Must be: #{IP_TYPE.join(', ')}"
exit(-1)
end
nic = vultr.create_nic(v_region, ip_type)
raise nic if VultrError.error?(nic)
eip = IPAddr.new(nic['subnet'])
ipgw = eip ^ 1
puts <<-EOF
AR = [
TYPE = "IP4",
IP = "#{nic['subnet']}",
SIZE = "#{ip_size}",
IPAM_MAD = "vultr",
GATEWAY = "#{ipgw}",
EXTERNAL_IP = "#{nic['subnet']}",
NETWORK_MASK = "255.255.255.254",
VULTR_IP_ID = "#{nic['id']}",
PROVISION_ID = "#{provision_id}"
]
EOF
rescue StandardError => e
error_str = "ERROR MESSAGE --8<------\n"
error_str << e.to_s
error_str << "\nERROR MESSAGE ------>8--"
STDERR.puts error_str
exit(-1)
end

View File

@ -0,0 +1,121 @@
#!/usr/bin/env ruby
# -------------------------------------------------------------------------- #
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
###############################################################################
# This script is used to unregister a new IP network in the IPAM.
#
# STDIN Input:
# - Base64 encoded XML with AR request
#
################################################################################
ONE_LOCATION = ENV['ONE_LOCATION'] unless defined?(ONE_LOCATION)
if !ONE_LOCATION
LIB_LOCATION ||= '/usr/lib/one'
VULTR_LOCATION ||= '/usr/lib/one/ruby/vendors/vultr/lib'
RUBY_LIB_LOCATION ||= '/usr/lib/one/ruby'
GEMS_LOCATION ||= '/usr/share/one/gems'
else
LIB_LOCATION ||= ONE_LOCATION + '/lib'
VULTR_LOCATION ||= '/usr/lib/one/ruby/vendors/vultr/lib'
RUBY_LIB_LOCATION ||= ONE_LOCATION + '/lib/ruby'
GEMS_LOCATION ||= ONE_LOCATION + '/share/gems'
end
# %%RUBYGEMS_SETUP_BEGIN%%
if File.directory?(GEMS_LOCATION)
real_gems_path = File.realpath(GEMS_LOCATION)
if !defined?(Gem) || Gem.path != [real_gems_path]
$LOAD_PATH.reject! {|l| l =~ /vendor_ruby/ }
# Suppress warnings from Rubygems
# https://github.com/OpenNebula/one/issues/5379
begin
verb = $VERBOSE
$VERBOSE = nil
require 'rubygems'
Gem.use_paths(real_gems_path)
ensure
$VERBOSE = verb
end
end
end
# %%RUBYGEMS_SETUP_END%%
$LOAD_PATH << VULTR_LOCATION
$LOAD_PATH << RUBY_LIB_LOCATION
$LOAD_PATH << LIB_LOCATION + '/oneprovision/lib'
require 'base64'
require 'nokogiri'
require 'opennebula'
require 'oneprovision'
require 'vultr'
begin
data = Nokogiri::XML(Base64.decode64(STDIN.read))
# --------------------------------------------------------------------------
# Get connection details for the provider
# --------------------------------------------------------------------------
provision_id = data.xpath('//AR/PROVISION_ID').text
if provision_id.empty?
STDERR.puts 'Missing provision id in address range'
exit(-1)
end
one = OpenNebula::Client.new
provision = OneProvision::Provision.new_with_id(provision_id, one)
rc = provision.info
if OpenNebula.is_error?(rc)
STDERR.puts rc.message
exit(-1)
end
provider = provision.provider
connect = provider.body['connection']
v_key = connect['key']
# --------------------------------------------------------------------------
# Connect to Vultr and delete the IP
# --------------------------------------------------------------------------
vultr = Vultr.new(v_key)
v_id = data.xpath('//AR/VULTR_IP_ID').text.to_s
if v_id.empty?
STDERR.puts 'Missing Vultr range ID'
exit(-1)
end
rc = vultr.delete_nic(v_id)
raise rc if VultrError.error?(rc)
exit(0)
rescue StandardError => e
error_str = "ERROR MESSAGE --8<------\n"
error_str << e.to_s
error_str << "\nERROR MESSAGE ------>8--"
STDERR.puts error_str
exit(-1)
end

View File

@ -264,7 +264,13 @@ module OneProvision
host = Resource.object('hosts')
host.info(h['id'])
c << "#{host.one['NAME']}\n"
h_vars = host.one['TEMPLATE/ANSIBLE_HOST_VARS']
if h_vars
c << "#{host.one['NAME']} #{h_vars}\n"
else
c << "#{host.one['NAME']}\n"
end
end
c << "\n"

View File

@ -11,7 +11,6 @@
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
require 'opennebula/document_json'
require 'opennebula/wait_ext'
@ -742,6 +741,14 @@ module OneProvision
# Add deployment ID
host.one.add_element('//TEMPLATE/PROVISION', 'DEPLOY_ID' => id)
# Read private IP if any
terraform = Terraform.singleton(@provider, {})
if terraform.respond_to? :add_host_vars
terraform.add_host_vars(host)
end
host.one.update(host.one.template_str)
h['name'] = name

View File

@ -19,6 +19,9 @@ require 'terraform/providers/digitalocean'
require 'terraform/providers/dummy'
require 'terraform/providers/google'
require 'terraform/providers/packet'
require 'terraform/providers/vultr'
require 'terraform/providers/vultr_metal'
require 'terraform/providers/vultr_virtual'
# Module OneProvision
module OneProvision

View File

@ -0,0 +1,23 @@
resource "vultr_startup_script" "device_<%= obj['ID'] %>" {
name = "install_root_ssh_keys"
script = "<%= obj['user_data'] %>"
}
resource "vultr_bare_metal_server" "device_<%= obj['ID'] %>" {
hostname = "<%= provision['HOSTNAME'] %>"
plan = "<%= provision['PLAN'] %>"
region = "<%= provision['REGION'] %>"
os_id = "<%= provision['OS'] %>"
script_id = vultr_startup_script.device_<%= obj['ID'] %>.id
tag = "OpenNebula - ONE_ID=<%= obj['ID'] %>"
activation_email = false
}
output "ip_<%= obj['ID'] %>" {
value = vultr_instance.device_<%= obj['ID'] %>.main_ip
}
output "device_id_<%= obj['ID'] %>" {
value = vultr_instance.device_<%= obj['ID'] %>.id
}

View File

@ -0,0 +1,14 @@
terraform {
required_providers {
vultr = {
source = "vultr/vultr"
version = "2.2.0"
}
}
}
provider "vultr" {
api_key = "<%= conn['KEY'] %>"
}

View File

@ -0,0 +1,5 @@
resource "vultr_private_network" "device_<%= obj['ID'] %>" {
description = "BGP Network"
region = "<%= provision['REGION'] %>"
}

View File

@ -0,0 +1,24 @@
resource "vultr_startup_script" "device_<%= obj['ID'] %>" {
name = "install_root_ssh_keys"
script = "<%= obj['user_data'] %>"
}
resource "vultr_instance" "device_<%= obj['ID'] %>" {
hostname = "<%= provision['HOSTNAME'] %>"
plan = "<%= provision['PLAN'] %>"
region = "<%= provision['REGION'] %>"
os_id = "<%= provision['OS'] %>"
script_id = vultr_startup_script.device_<%= obj['ID'] %>.id
tag = "OpenNebula - ONE_ID=<%= obj['ID'] %>"
activation_email = false
private_network_ids = [vultr_private_network.device_<%= c['ID'] %>.id]
}
output "ip_<%= obj['ID'] %>" {
value = vultr_instance.device_<%= obj['ID'] %>.main_ip
}
output "device_id_<%= obj['ID'] %>" {
value = vultr_instance.device_<%= obj['ID'] %>.id
}

View File

@ -0,0 +1,14 @@
terraform {
required_providers {
vultr = {
source = "vultr/vultr"
version = "2.2.0"
}
}
}
provider "vultr" {
api_key = "<%= conn['KEY'] %>"
}

View File

@ -0,0 +1,95 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
ONE_LOCATION = ENV['ONE_LOCATION'] unless defined?(ONE_LOCATION)
if !ONE_LOCATION
VULTR_LOCATION ||= '/usr/lib/one/ruby/vendors/vultr/lib'
else
VULTR_LOCATION ||= ONE_LOCATION + '/lib/ruby/vendors/vultr/lib'
end
$LOAD_PATH << VULTR_LOCATION
require 'vultr'
require 'terraform/terraform'
# Module OneProvision
module OneProvision
# Vultr Terraform Provider
class Vultr < Terraform
KEYS = %w[key region]
# Class constructor
#
# @param provider [Provider]
# @param state [String] Terraform state in base64
# @param conf [String] Terraform config state in base64
def initialize(provider, state, conf)
# Credentials are not stored in a file
@file_credentials = false
super
end
# Get user data to add into the VM
#
# @param ssh_key [String] SSH keys to add
def user_data(ssh_key)
user_data = "#! /bin/bash\n"
user_data << "mkdir ~/.ssh\n"
ssh_key.split("\n").each do |key|
user_data << "echo #{key} >> ~/.ssh/authorized_keys\n"
end
user_data << "chmod 700 ~/.ssh\n"
user_data << 'chmod 644 ~/.ssh/authorized_keys'
Base64.strict_encode64(user_data)
end
# Add configuration variables to host template
#
# @param host [OneProvision::Host] Host information
def add_host_vars(host)
host.one.add_element(
'//TEMPLATE',
'ANSIBLE_HOST_VARS' => "private_ip=#{private_ip(host)}"
)
end
private
# Get private IP of an instance
#
# @param host [OneProvision::Host] Host information
#
# @return [String] Instance private IP
def private_ip(host)
v = ::Vultr.new(@provider.connection['KEY'])
i = v.instance(host.one['TEMPLATE/PROVISION/DEPLOY_ID'])
raise OneProvisionLoopException i if ::VultrError.error?(i)
i['internal_ip']
end
end
end

View File

@ -0,0 +1,46 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
require 'terraform/providers/vultr'
# Module OneProvision
module OneProvision
# Vultr Metal Terraform Provider
class VultrMetal < Vultr
# OpenNebula - Terraform equivalence
TYPES = {
:cluster => '',
:datastore => '',
:host => 'vultr_bare_metal_server',
:network => ''
}
# Class constructor
#
# @param provider [Provider]
# @param state [String] Terraform state in base64
# @param conf [String] Terraform config state in base64
def initialize(provider, state, conf)
@dir = "#{PROVIDERS_LOCATION}/templates/vultr_metal"
super
end
end
end

View File

@ -0,0 +1,46 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
require 'terraform/providers/vultr'
# Module OneProvision
module OneProvision
# Vultr Virtual Terraform Provider
class VultrVirtual < Vultr
# OpenNebula - Terraform equivalence
TYPES = {
:cluster => 'vultr_private_network',
:datastore => '',
:host => 'vultr_instance',
:network => ''
}
# Class constructor
#
# @param provider [Provider]
# @param state [String] Terraform state in base64
# @param conf [String] Terraform config state in base64
def initialize(provider, state, conf)
@dir = "#{PROVIDERS_LOCATION}/templates/vultr_virtual"
super
end
end
end

View File

@ -46,7 +46,13 @@ module OneProvision
class Terraform
# Providers that are currently available
PROVIDERS = %w[aws digitalocean google packet dummy]
PROVIDERS = %w[aws
digitalocean
dummy
google
packet
vultr_metal
vultr_virtual]
# Class constructor
#
@ -77,6 +83,10 @@ module OneProvision
tf_class = DigitalOcean
when 'dummy'
tf_class = Dummy
when 'vultr_metal'
tf_class = VultrMetal
when 'vultr_virtual'
tf_class = VultrVirtual
else
raise OneProvisionLoopException,
"Unknown provider: #{provider.body['provider']}"
@ -101,6 +111,8 @@ module OneProvision
keys = DigitalOcean::KEYS
when 'dummy'
return true
when 'vultr_metal', 'vultr_virtual'
keys = Vultr::KEYS
else
raise OneProvisionLoopException,
"Unknown provider: #{provider['provider']}"

View File

@ -101,7 +101,7 @@ class AWSProvider
# Unassign a public_ip from an instance
# @param ip [String] not used for AWS
# @param external [String] the public ip
def unassign(ip, external)
def unassign(ip, external, _opts = {})
filter = [{ :name => 'public-ip', :values => [external] }]
aws_ip = @ec2.describe_addresses({ :filters => filter }).addresses[0]

View File

@ -74,7 +74,8 @@ class ElasticDriver < VNMMAD::VNMDriver
next if attach_nic_id && attach_nic_id != nic[:nic_id]
cmds.add :ip, "route add #{nic[:ip]}/32 dev #{nic[:bridge]} ||:"
cmds.add :ip, "neighbour add proxy #{nic[:gateway]} dev #{nic[:bridge]}"
cmds.add :ip,
"neighbour add proxy #{nic[:gateway]} dev #{nic[:bridge]}"
provider.activate(cmds, nic) if provider.respond_to? :activate
end
@ -95,15 +96,18 @@ class ElasticDriver < VNMMAD::VNMDriver
process_all do |nic|
next if attach_nic_id && attach_nic_id != nic[:nic_id]
cmds.add :ip, "route del #{nic[:ip]}/32 dev #{nic[:bridge]} | true"
cmds.add :ip, "neighbour del proxy #{nic[:gateway]} dev #{nic[:bridge]} | true"
cmds.add :ip,
"route del #{nic[:ip]}/32 dev #{nic[:bridge]} | true"
cmds.add :ip,
"neighbour del proxy #{nic[:gateway]} " \
"dev #{nic[:bridge]} | true"
provider.deactivate(cmds, nic) if provider.respond_to? :deactivate
# TODO: MUST check if bridge is empty. Move to remote_clean
#next if nic[:parent_nic] || nic[:conf][:keep_empty_bridge]
# next if nic[:parent_nic] || nic[:conf][:keep_empty_bridge]
#
#cmds.add :ip, "link delete #{nic[:bridge]} | true"
# cmds.add :ip, "link delete #{nic[:bridge]} | true"
end
cmds.run_remote(@ssh)
@ -126,7 +130,9 @@ class ElasticDriver < VNMMAD::VNMDriver
next if attach_nic_id && attach_nic_id != nic[:nic_id]
# pass aws_allocation_id if present
opts = { :alloc_id => nic[:aws_allocation_id] }
# pass vultr_ip_id if present
opts = { :alloc_id => nic[:aws_allocation_id],
:vultr_id => nic[:vultr_ip_id] }
break false \
unless provider.assign(nic[:ip], nic[:external_ip], opts) == 0
@ -154,7 +160,10 @@ class ElasticDriver < VNMMAD::VNMDriver
@vm.each_nic_all do |nic|
next if attach_nic_id && attach_nic_id != nic[:nic_id]
provider.unassign(nic[:ip], nic[:external_ip])
# pass vultr_ip_id if present
opts = { :vultr_id => nic[:vultr_ip_id] }
provider.unassign(nic[:ip], nic[:external_ip], opts)
end
end
@ -169,6 +178,9 @@ class ElasticDriver < VNMMAD::VNMDriver
when 'packet'
require 'packet_vnm'
PacketProvider.new(provider, host)
when 'vultr_virtual', 'vultr_metal'
require 'vultr_vnm'
VultrProvider.new(provider, host)
else
nil
end
@ -179,7 +191,5 @@ class ElasticDriver < VNMMAD::VNMDriver
nil
end
private
end
# rubocop:enable Naming/FileName

View File

@ -68,7 +68,10 @@ class PacketProvider
0
rescue Packet::Error => e
# potential VM poweroff(itself) + resume
return 0 if e.message == '{"errors"=>["Address has already been taken"]}'
if e.message == '{"errors"=>["Address has already been taken"]}'
return 0
end
OpenNebula.log_error("Error assiging #{external}:#{e.message}")
1
@ -77,7 +80,7 @@ class PacketProvider
1
end
def unassign(_ip, external)
def unassign(_ip, external, _opts = {})
dev = @client.get_device(@deploy_id)
ip = dev.ip_addresses.select do |i|
@ -92,17 +95,21 @@ class PacketProvider
end
def activate(cmds, nic)
cmds.add :iptables, "-t nat -A POSTROUTING -s #{nic[:ip]} -j SNAT"\
" --to-source #{nic[:external_ip]}"
cmds.add :iptables, "-t nat -A PREROUTING -d #{nic[:external_ip]} -j DNAT"\
" --to-destination #{nic[:ip]}"
cmds.add :iptables,
"-t nat -A POSTROUTING -s #{nic[:ip]} -j SNAT " \
"--to-source #{nic[:external_ip]}"
cmds.add :iptables,
"-t nat -A PREROUTING -d #{nic[:external_ip]} -j DNAT " \
"--to-destination #{nic[:ip]}"
end
def deactivate(cmds, nic)
cmds.add :iptables, "-t nat -D POSTROUTING -s #{nic[:ip]} -j SNAT"\
" --to-source #{nic[:external_ip]}"
cmds.add :iptables, "-t nat -D PREROUTING -d #{nic[:external_ip]} -j DNAT"\
" --to-destination #{nic[:ip]}"
cmds.add :iptables,
"-t nat -D POSTROUTING -s #{nic[:ip]} -j SNAT " \
"--to-source #{nic[:external_ip]}"
cmds.add :iptables,
"-t nat -D PREROUTING -d #{nic[:external_ip]} -j DNAT " \
"--to-destination #{nic[:ip]}"
end
end

View File

@ -0,0 +1,124 @@
# -------------------------------------------------------------------------- #
# Copyright 2002-2021, OpenNebula Project, OpenNebula Systems #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); you may #
# not use this file except in compliance with the License. You may obtain #
# a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
#--------------------------------------------------------------------------- #
#
ONE_LOCATION = ENV['ONE_LOCATION'] unless defined?(ONE_LOCATION)
if !ONE_LOCATION
LIB_LOCATION ||= '/usr/lib/one'
RUBY_LIB_LOCATION ||= '/usr/lib/one/ruby'
GEMS_LOCATION ||= '/usr/share/one/gems'
VULTR_LOCATION ||= '/usr/lib/one/ruby/vendors/vultr/lib'
else
LIB_LOCATION ||= ONE_LOCATION + '/lib'
RUBY_LIB_LOCATION ||= ONE_LOCATION + '/lib/ruby'
GEMS_LOCATION ||= ONE_LOCATION + '/share/gems'
VULTR_LOCATION ||= ONE_LOCATION + '/lib/ruby/vendors/vultr/lib'
end
# %%RUBYGEMS_SETUP_BEGIN%%
if File.directory?(GEMS_LOCATION)
real_gems_path = File.realpath(GEMS_LOCATION)
if !defined?(Gem) || Gem.path != [real_gems_path]
$LOAD_PATH.reject! {|l| l =~ /vendor_ruby/ }
# Suppress warnings from Rubygems
# https://github.com/OpenNebula/one/issues/5379
begin
verb = $VERBOSE
$VERBOSE = nil
require 'rubygems'
Gem.use_paths(real_gems_path)
ensure
$VERBOSE = verb
end
end
end
# %%RUBYGEMS_SETUP_END%%
$LOAD_PATH << RUBY_LIB_LOCATION
$LOAD_PATH << VULTR_LOCATION
require 'vultr'
# Class covering Vultr functionality for Elastic driver
class VultrProvider
# Class constructor
#
# @param provider [OpenNebula::Provider] Provider information
# @param host [OpenNebula:Host] Host information
def initialize(provider, host)
connect = provider.body['connection']
@client = Vultr.new(connect['key'])
@deploy_id = host['TEMPLATE/PROVISION/DEPLOY_ID']
end
# Assign a reserved IP to the instance
#
# @param opts [Hash] opts[:vultr_ip_id] must contain reserved IP ID
#
# @return [Integer] 0 on success, 1 on error
def assign(_, _, opts = {})
rc = @client.attach_nic(@deploy_id, opts[:vultr_id])
if VultrError.error?(rc)
if rc.message == 'IP is already attached to a server'
return 0
else
OpenNebula.log_error("Error assiging #{rc.message}")
return 1
end
end
0
end
# Unassign a reserved IP from the instance
#
# @param opts [Hash] opts[:vultr_ip_id] must contain reserved IP ID
#
# @return [Integer] 0 on success, 1 on error
def unassign(_, _, opts = {})
rc = @client.detach_nic(@deploy_id, opts[:vultr_id])
if VultrError.error?(rc)
OpenNebula.log_error("Error unassiging #{rc.message}")
return 1
end
0
end
def activate(cmds, nic)
cmds.add :iptables,
"-t nat -A POSTROUTING -s #{nic[:ip]} -j SNAT " \
"--to-source #{nic[:external_ip]}"
cmds.add :iptables,
"-t nat -A PREROUTING -d #{nic[:external_ip]} -j DNAT " \
"--to-destination #{nic[:ip]}"
end
def deactivate(cmds, nic)
cmds.add :iptables,
"-t nat -D POSTROUTING -s #{nic[:ip]} -j SNAT " \
"--to-source #{nic[:external_ip]}"
cmds.add :iptables,
"-t nat -D PREROUTING -d #{nic[:external_ip]} -j DNAT " \
"--to-destination #{nic[:ip]}"
end
end