Compare commits
33 commits
Author | SHA1 | Date | |
---|---|---|---|
f75a672a12 | |||
d72da89cab | |||
5d644a53e3 | |||
8411d10d8d | |||
b15e2e0e4c | |||
3c727ab282 | |||
99f33f84e6 | |||
7a5f8d4571 | |||
758a535320 | |||
679529b5b5 | |||
cd5cc40cef | |||
49c86cd848 | |||
0d49bd53a3 | |||
d0dc43dd3b | |||
0697e7bf9a | |||
45d451f5c9 | |||
f7258c19d1 | |||
17f2e8b3eb | |||
c13a89807e | |||
0348a4ec86 | |||
873f63533b | |||
b98c50246f | |||
a53a103a1d | |||
ac8230e2df | |||
8d31a7a69c | |||
6d9a6078b3 | |||
856f047d16 | |||
3aef835b4b | |||
a88d51141f | |||
324ec9abc5 | |||
6186daad55 | |||
e6d494ab0c | |||
2e48c3f173 |
21 changed files with 698 additions and 23 deletions
95
.drone.yml
Normal file
95
.drone.yml
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
type: docker
|
||||||
|
name: "stage:build"
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
event:
|
||||||
|
- push
|
||||||
|
- pull_request
|
||||||
|
|
||||||
|
services:
|
||||||
|
- name: service:docker
|
||||||
|
image: docker:dind
|
||||||
|
privileged: true
|
||||||
|
volumes:
|
||||||
|
- name: dockersock
|
||||||
|
path: /var/run
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- name: crystal_cache
|
||||||
|
temp: {}
|
||||||
|
- name: docker_cache
|
||||||
|
temp: {}
|
||||||
|
- name: dockersock
|
||||||
|
temp: {}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: "build:prepare"
|
||||||
|
image: busybox
|
||||||
|
commands:
|
||||||
|
# Debug
|
||||||
|
- pwd
|
||||||
|
- mkdir -p _artifacts _cache
|
||||||
|
|
||||||
|
- name: "build:executable"
|
||||||
|
image: crystallang/crystal:1.5.0
|
||||||
|
volumes:
|
||||||
|
- name: crystal_cache
|
||||||
|
path: /drone/src/_cache
|
||||||
|
commands:
|
||||||
|
# Debug
|
||||||
|
- pwd
|
||||||
|
- crystal version
|
||||||
|
- shards version
|
||||||
|
# Build
|
||||||
|
- make build
|
||||||
|
|
||||||
|
- name: "build:docker-image"
|
||||||
|
image: docker:20.10.16-dind
|
||||||
|
volumes:
|
||||||
|
- name: dockersock
|
||||||
|
path: /var/run
|
||||||
|
- name: docker_cache
|
||||||
|
path: /drone/src/_cache
|
||||||
|
commands:
|
||||||
|
# Prepare
|
||||||
|
- apk add make
|
||||||
|
- test -f _cache/docker-image.tar && docker load < _cache/docker-image.tar
|
||||||
|
# Build
|
||||||
|
- make docker-build
|
||||||
|
- make docker-save > _artifacts/docker-image.tar
|
||||||
|
- make docker-save > _cache/docker-image.tar
|
||||||
|
|
||||||
|
- name: "publish:docker-image"
|
||||||
|
image: docker:20.10.16-dind
|
||||||
|
volumes:
|
||||||
|
- name: dockersock
|
||||||
|
path: /var/run
|
||||||
|
commands:
|
||||||
|
# Prepare
|
||||||
|
- test -f _artifacts/docker-image.tar
|
||||||
|
- apk add make
|
||||||
|
- make docker-load < _artifacts/docker-image.tar
|
||||||
|
# Build
|
||||||
|
- make docker-push
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
type: docker
|
||||||
|
name: "stage:deploy"
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
event:
|
||||||
|
- promote
|
||||||
|
target:
|
||||||
|
- production
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: "deploy:prepare"
|
||||||
|
image: busybox
|
||||||
|
commands:
|
||||||
|
# Debug
|
||||||
|
- echo "No op"
|
||||||
|
|
||||||
|
#
|
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1,2 +1,2 @@
|
||||||
lib
|
/lib
|
||||||
bin
|
/bin
|
||||||
|
|
|
@ -7,11 +7,59 @@
|
||||||
# Note that environment variables can be set in several places
|
# Note that environment variables can be set in several places
|
||||||
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
|
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
|
||||||
stages:
|
stages:
|
||||||
|
- build
|
||||||
- test
|
- test
|
||||||
|
- publish
|
||||||
|
|
||||||
|
build:executable:
|
||||||
|
stage: build
|
||||||
|
image: crystallang/crystal:1.5.0
|
||||||
|
script:
|
||||||
|
# Debug
|
||||||
|
- crystal version
|
||||||
|
- shards version
|
||||||
|
# Build
|
||||||
|
- make build
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- bin
|
||||||
|
cache:
|
||||||
|
paths:
|
||||||
|
- lib
|
||||||
|
|
||||||
|
build:docker-image:
|
||||||
|
stage: build
|
||||||
|
image: docker:20.10.16
|
||||||
|
services:
|
||||||
|
- docker:20.10.16-dind
|
||||||
|
needs:
|
||||||
|
- build:executable
|
||||||
|
script:
|
||||||
|
- apk install make
|
||||||
|
- make docker-build
|
||||||
|
- make docker-save > _artifacts/docker-image.tar
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- _artifacts
|
||||||
|
|
||||||
sast:
|
sast:
|
||||||
stage: test
|
stage: test
|
||||||
|
|
||||||
|
publish:docker-image:
|
||||||
|
stage: publish
|
||||||
|
needs:
|
||||||
|
- build:docker-image
|
||||||
|
image: docker:20.10.16
|
||||||
|
services:
|
||||||
|
- docker:20.10.16-dind
|
||||||
|
script:
|
||||||
|
- apk install make
|
||||||
|
- make docker-load < _artifacts/docker-image.tar
|
||||||
|
- make docker-push
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- bin
|
||||||
|
|
||||||
include:
|
include:
|
||||||
- template: Security/SAST.gitlab-ci.yml
|
- template: Security/SAST.gitlab-ci.yml
|
||||||
|
|
||||||
|
|
18
Makefile
18
Makefile
|
@ -1,15 +1,25 @@
|
||||||
|
|
||||||
|
DOCKER_IMAGE=glenux/openstack
|
||||||
|
|
||||||
|
all: build
|
||||||
|
|
||||||
build:
|
build:
|
||||||
shards build
|
shards install
|
||||||
|
shards build --error-trace
|
||||||
|
|
||||||
docker: docker-build docker-test docker-push
|
docker: docker-build docker-test docker-push
|
||||||
|
|
||||||
docker-build:
|
docker-build:
|
||||||
docker build -t glenux/openstack-arkisto .
|
docker build --file docker/Dockerfile -t $(DOCKER_IMAGE) .
|
||||||
|
|
||||||
docker-push:
|
docker-push:
|
||||||
docker push glenux/openstack-arkisto
|
docker push $(DOCKER_IMAGE)
|
||||||
|
|
||||||
docker-test:
|
docker-test:
|
||||||
docker run glenux/openstack-arkisto arkisto --version
|
docker run $(DOCKER_IMAGE) arkisto --version
|
||||||
|
|
||||||
|
docker-save:
|
||||||
|
docker save $(DOCKER_IMAGE)
|
||||||
|
|
||||||
|
docker-load:
|
||||||
|
docker load
|
||||||
|
|
36
README.md
36
README.md
|
@ -1,4 +1,38 @@
|
||||||
|
|
||||||
|
|
||||||
# Arkisto
|
# Arkisto
|
||||||
|
|
||||||
A simple tool to automate openstack snapshots
|
[![Build Status](https://cicd.apps.glenux.net/api/badges/glenux/arkisto/status.svg?ref=refs/heads/develop)](https://cicd.apps.glenux.net/glenux/arkisto)
|
||||||
|
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
|
||||||
|
[![Donate on patreon](https://img.shields.io/badge/patreon-donate-orange.svg)](https://patreon.com/glenux)
|
||||||
|
|
||||||
|
A simple tool to automate and manage openstack snapshots
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### With docker
|
||||||
|
|
||||||
|
Make sure you have Docker and Make installed. Then type
|
||||||
|
|
||||||
|
make docker-build
|
||||||
|
|
||||||
|
### Manual
|
||||||
|
|
||||||
|
Make sure you have installed the following software on your system:
|
||||||
|
|
||||||
|
* Crystal
|
||||||
|
* Make
|
||||||
|
* libevent-core-2.1-7
|
||||||
|
* python-openstackclient
|
||||||
|
|
||||||
|
Then type
|
||||||
|
|
||||||
|
make build
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
## Licence
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,27 +11,30 @@ FROM python:3.7-bullseye AS runner
|
||||||
|
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get -yq install \
|
&& apt-get -yq install \
|
||||||
libevent-core-2.1-7 \
|
gettext \
|
||||||
gettext \
|
jq \
|
||||||
jq \
|
libevent-core-2.1-7 \
|
||||||
python3-aodhclient \
|
zip \
|
||||||
python3-barbicanclient \
|
|
||||||
python3-ceilometerclient \
|
|
||||||
python3-cinderclient \
|
|
||||||
python3-cloudkittyclient \
|
|
||||||
python3-designateclient \
|
|
||||||
python3-gnocchiclient \
|
|
||||||
python3-octaviaclient \
|
|
||||||
python3-osc-placement \
|
|
||||||
python3-openstackclient \
|
|
||||||
python3-pankoclient \
|
|
||||||
zip \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN pip install \
|
||||||
|
aodhclient \
|
||||||
|
cinder \
|
||||||
|
gnocchiclient \
|
||||||
|
osc-placement \
|
||||||
|
panko \
|
||||||
|
python-barbicanclient \
|
||||||
|
python-ceilometerclient \
|
||||||
|
python-cloudkittyclient \
|
||||||
|
python-designateclient \
|
||||||
|
python-octaviaclient \
|
||||||
|
python-openstackclient
|
||||||
|
|
||||||
|
|
||||||
# RUN wget https://github.com/sapcc/cyclone/releases/download/v0.1.28/cyclone \
|
# RUN wget https://github.com/sapcc/cyclone/releases/download/v0.1.28/cyclone \
|
||||||
# -O /usr/bin/cyclone \
|
# -O /usr/bin/cyclone \
|
||||||
# && chmod +x /usr/bin/cyclone
|
# && chmod +x /usr/bin/cyclone
|
||||||
|
|
||||||
COPY --from=builder /app/bin/arkisto /usr/bin/arkisto
|
COPY --from=builder /app/bin/arkisto /usr/bin/arkisto
|
||||||
|
|
||||||
CMD /bin/bash
|
CMD ["/bin/bash"]
|
26
src/lib/actions.cr
Normal file
26
src/lib/actions.cr
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
require "tablo"
|
||||||
|
|
||||||
|
module Arkisto
|
||||||
|
class Action
|
||||||
|
def initialize(_config : ConfigModel, _options : ActionOptions)
|
||||||
|
# Do nothing by default
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
def perform
|
||||||
|
# Do nothing by default
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class ActionFactory
|
||||||
|
def self.build(action_type : Action.class, config, options)
|
||||||
|
action = action_type.new(config, options)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
require "./actions/*"
|
||||||
|
|
||||||
|
|
91
src/lib/actions/apply.cr
Normal file
91
src/lib/actions/apply.cr
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
|
||||||
|
require "../openstack"
|
||||||
|
require "../actions"
|
||||||
|
|
||||||
|
module Arkisto
|
||||||
|
class ApplyAction < Action
|
||||||
|
def initialize(config : ConfigModel, options : ActionOptions)
|
||||||
|
puts "action = Apply"
|
||||||
|
@config = config
|
||||||
|
end
|
||||||
|
|
||||||
|
# First create today's backup
|
||||||
|
# Then remove old backups
|
||||||
|
def perform
|
||||||
|
_create_backup_all
|
||||||
|
_delete_backup_all
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
def _create_backup_all
|
||||||
|
puts "_create_backup_all".colorize(:yellow)
|
||||||
|
os_volumes = OpenStack.volume_list
|
||||||
|
|
||||||
|
@config.targets.each do |config_volume_item|
|
||||||
|
os_volume_item =
|
||||||
|
os_volumes.select {|vol| vol.id == config_volume_item.volume_id }.first?
|
||||||
|
|
||||||
|
if os_volume_item.nil?
|
||||||
|
puts " ERROR: no volume found with this id".colorize(:red)
|
||||||
|
exit(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
_create_backup(config_volume_item, os_volume_item)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def _create_backup(config_item : TargetItemModel, volume_item : OSVolume::ListItemModel)
|
||||||
|
puts "_create_backup".colorize(:yellow)
|
||||||
|
puts "+ openstack volume snapshot #{config_item.name.colorize(:yellow)} {"
|
||||||
|
puts "+ volume_id #{config_item.volume_id}"
|
||||||
|
puts "+ name #{volume_item.name}"
|
||||||
|
puts "+ size #{volume_item.size}"
|
||||||
|
puts "+ }"
|
||||||
|
|
||||||
|
created_volume = OpenStack.volume_snapshot_create(volume_item, config_item.name)
|
||||||
|
end
|
||||||
|
|
||||||
|
def _delete_backup_all
|
||||||
|
puts "_delete_backup_all".colorize(:yellow)
|
||||||
|
os_volumes = OpenStack.volume_list
|
||||||
|
os_all_snapshots = OpenStack.volume_snapshot_list
|
||||||
|
|
||||||
|
@config.targets.each do |config_volume_item|
|
||||||
|
os_volume_item = os_volumes.select {|vol|
|
||||||
|
vol.id == config_volume_item.volume_id
|
||||||
|
}.try &.first
|
||||||
|
|
||||||
|
os_volume_snapshots = os_all_snapshots.select {|snap|
|
||||||
|
snap.volume == config_volume_item.volume_id
|
||||||
|
}
|
||||||
|
|
||||||
|
os_volume_snapshots.each do |snap_item|
|
||||||
|
_delete_backup(config_volume_item, snap_item)
|
||||||
|
pp snap_item
|
||||||
|
end
|
||||||
|
|
||||||
|
# _delete_backup(config_volume_item, os_volume_snapshot_item)
|
||||||
|
# volume_snapshots.each do |target_snapshot|
|
||||||
|
# os_volume_item =
|
||||||
|
# os_volumes.select {|vol| vol.id == config_volume_item.volume_id }.first
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def _delete_backup(config_item : TargetItemModel, snap_item : OSVolume::SnapshotListItemModel)
|
||||||
|
puts "_delete_backup".colorize(:yellow)
|
||||||
|
|
||||||
|
puts "- openstack volume snapshot #{config_item.name.colorize(:yellow)} {"
|
||||||
|
puts "- volume_id #{config_item.volume_id}"
|
||||||
|
puts "- created_at #{snap_item.created_at}"
|
||||||
|
puts "- snap_id #{snap_item.id}"
|
||||||
|
puts "- name #{snap_item.name}"
|
||||||
|
puts "- size #{snap_item.size}"
|
||||||
|
puts "- }"
|
||||||
|
|
||||||
|
pp config_item
|
||||||
|
pp snap_item
|
||||||
|
|
||||||
|
# FIXME: not implemented
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
17
src/lib/actions/none.cr
Normal file
17
src/lib/actions/none.cr
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
|
||||||
|
require "../actions"
|
||||||
|
|
||||||
|
module Arkisto
|
||||||
|
class NoneAction < Action
|
||||||
|
def initialize(config : ConfigModel, options : ActionOptions)
|
||||||
|
puts "action = None"
|
||||||
|
# @global_options = global_options
|
||||||
|
# @config = config
|
||||||
|
end
|
||||||
|
|
||||||
|
def perform
|
||||||
|
# Do nothing by default
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
21
src/lib/actions/plan.cr
Normal file
21
src/lib/actions/plan.cr
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
require "../actions"
|
||||||
|
|
||||||
|
module Arkisto
|
||||||
|
class PlanAction < Action
|
||||||
|
def initialize(config : ConfigModel, options : ActionOptions)
|
||||||
|
@config = config
|
||||||
|
puts "action = Plan"
|
||||||
|
end
|
||||||
|
|
||||||
|
def perform
|
||||||
|
@config.targets.each do |target|
|
||||||
|
puts "#{target.name}"
|
||||||
|
puts "- volume_id #{target.volume_id}"
|
||||||
|
# puts "- snapshot_prefix #{target.snapshot_prefix}"
|
||||||
|
puts ""
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
11
src/lib/models.cr
Normal file
11
src/lib/models.cr
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
require "yaml"
|
||||||
|
|
||||||
|
module Arkisto
|
||||||
|
class Model
|
||||||
|
include YAML::Serializable
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
require "./types"
|
||||||
|
require "./models/*"
|
11
src/lib/models/config.cr
Normal file
11
src/lib/models/config.cr
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
require "../models"
|
||||||
|
|
||||||
|
module Arkisto
|
||||||
|
class ConfigModel < Model
|
||||||
|
property version : String
|
||||||
|
property retention : RetentionModel
|
||||||
|
property targets : Array(TargetItemModel)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
74
src/lib/models/os_vol_list_item.cr
Normal file
74
src/lib/models/os_vol_list_item.cr
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
|
||||||
|
|
||||||
|
# - Attached to: []
|
||||||
|
# ID: 8c87c196-1dd6-4190-bff5-00b543965093
|
||||||
|
# Name: ovh-managed-kubernetes-e6j07m-pvc-9fad19b4-b32c-452a-9893-524fcdc3a4b1
|
||||||
|
# Size: 50
|
||||||
|
# Status: available
|
||||||
|
# - Attached to:
|
||||||
|
# - attached_at: '2022-06-27T17:38:53.000000'
|
||||||
|
# attachment_id: 88a7dfc4-5bdf-4864-b38d-c82169c37b9d
|
||||||
|
# device: /dev/sdc
|
||||||
|
# host_name: null
|
||||||
|
# id: c9b11fcb-a6a4-4387-b55b-34121f97dac4
|
||||||
|
# server_id: 37220c33-19e7-45cc-9c6a-ddf957be3c76
|
||||||
|
# volume_id: c9b11fcb-a6a4-4387-b55b-34121f97dac4
|
||||||
|
# ID: c9b11fcb-a6a4-4387-b55b-34121f97dac4
|
||||||
|
# Name: ovh-managed-kubernetes-e6j07m-pvc-13dcac68-71c9-4794-b0ab-d48e76d843ef
|
||||||
|
# Size: 5800
|
||||||
|
# Status: in-use
|
||||||
|
|
||||||
|
## LONG
|
||||||
|
|
||||||
|
# - Attached to:
|
||||||
|
# - attached_at: '2022-06-27T17:31:53.000000'
|
||||||
|
# attachment_id: 845a7ff2-ad54-4040-b69b-fce7fdfdece2
|
||||||
|
# device: /dev/sdb
|
||||||
|
# host_name: null
|
||||||
|
# id: 6d4492e5-6b38-4ad3-b9bf-27ba86e2506b
|
||||||
|
# server_id: 37220c33-19e7-45cc-9c6a-ddf957be3c76
|
||||||
|
# volume_id: 6d4492e5-6b38-4ad3-b9bf-27ba86e2506b
|
||||||
|
# Bootable: 'false'
|
||||||
|
# ID: 6d4492e5-6b38-4ad3-b9bf-27ba86e2506b
|
||||||
|
# Name: ovh-managed-kubernetes-e6j07m-pvc-7bf995bf-ac82-4f42-94ca-78cd9c78959d
|
||||||
|
# Properties:
|
||||||
|
# attached_mode: rw
|
||||||
|
# cinder.csi.openstack.org/cluster: kubernetes
|
||||||
|
# readonly: 'False'
|
||||||
|
# Size: 1
|
||||||
|
# Status: in-use
|
||||||
|
# Type: high-speed
|
||||||
|
|
||||||
|
|
||||||
|
require "../models"
|
||||||
|
|
||||||
|
module Arkisto
|
||||||
|
module OSVolume
|
||||||
|
class ListItemModel < Model
|
||||||
|
@[YAML::Field(key: "Attached to")]
|
||||||
|
property attached_to : Array(OSVolume::ListItemAttachment::ListItemModel)
|
||||||
|
|
||||||
|
@[YAML::Field(key: "Bootable")]
|
||||||
|
property bootable : String
|
||||||
|
|
||||||
|
@[YAML::Field(key: "ID")]
|
||||||
|
property id : String
|
||||||
|
|
||||||
|
@[YAML::Field(key: "Name")]
|
||||||
|
property name : String
|
||||||
|
|
||||||
|
@[YAML::Field(key: "Properties")]
|
||||||
|
property properties : YAML::Any
|
||||||
|
|
||||||
|
@[YAML::Field(key: "Size")]
|
||||||
|
property size : UInt16
|
||||||
|
|
||||||
|
@[YAML::Field(key: "Status")]
|
||||||
|
property status : String
|
||||||
|
|
||||||
|
@[YAML::Field(key: "Type")]
|
||||||
|
property type : String
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
20
src/lib/models/os_vol_list_item_attach_item.cr
Normal file
20
src/lib/models/os_vol_list_item_attach_item.cr
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
require "../models"
|
||||||
|
|
||||||
|
module Arkisto
|
||||||
|
module OSVolume
|
||||||
|
class ListItemAttachment
|
||||||
|
class ListItemModel < Model
|
||||||
|
property attached_at : String
|
||||||
|
property attachment_id : String
|
||||||
|
property device : String
|
||||||
|
property host_name : String
|
||||||
|
property id : String
|
||||||
|
property server_id : String
|
||||||
|
property volume_id : String
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
42
src/lib/models/os_vol_snap_create_item.cr
Normal file
42
src/lib/models/os_vol_snap_create_item.cr
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
|
||||||
|
# created_at: '2022-06-28T11:26:06.266927'
|
||||||
|
# description: null
|
||||||
|
# id: 52fa0022-3ed8-43bc-90d9-08d22597fb35
|
||||||
|
# name: pouet
|
||||||
|
# properties: {}
|
||||||
|
# size: 50
|
||||||
|
# status: creating
|
||||||
|
# updated_at: null
|
||||||
|
# volume_id: de7b118f-413b-4962-a028-a742df4bc4fc
|
||||||
|
|
||||||
|
require "../models"
|
||||||
|
|
||||||
|
module Arkisto
|
||||||
|
module OSVolume
|
||||||
|
class SnapshotCreateItemModel < Model
|
||||||
|
@[YAML::Field(key: "created_at")]
|
||||||
|
property created_at : String
|
||||||
|
|
||||||
|
@[YAML::Field(key: "description")]
|
||||||
|
property description : String
|
||||||
|
|
||||||
|
@[YAML::Field(key: "id")]
|
||||||
|
property id : String ## UUID
|
||||||
|
|
||||||
|
@[YAML::Field(key: "name")]
|
||||||
|
property name : String
|
||||||
|
|
||||||
|
@[YAML::Field(key: "properties")]
|
||||||
|
property properties : YAML::Any
|
||||||
|
|
||||||
|
@[YAML::Field(key: "size")]
|
||||||
|
property size : UInt16
|
||||||
|
|
||||||
|
@[YAML::Field(key: "status")]
|
||||||
|
property status : String
|
||||||
|
|
||||||
|
@[YAML::Field(key: "volume_id")]
|
||||||
|
property volume_id : String
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
51
src/lib/models/os_vol_snap_list_item.cr
Normal file
51
src/lib/models/os_vol_snap_list_item.cr
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
|
||||||
|
## volume snapshot list -f yaml
|
||||||
|
|
||||||
|
# - Description: null
|
||||||
|
# ID: 86367f4d-fbc2-4e09-b0e7-1b4b73f72baa
|
||||||
|
# Name: db-snapshot01
|
||||||
|
# Size: 50
|
||||||
|
# Status: available
|
||||||
|
|
||||||
|
## volume snapshot list --long -f yaml
|
||||||
|
|
||||||
|
# - Created At: '2022-06-27T14:09:47.000000'
|
||||||
|
# Description: null
|
||||||
|
# ID: 86367f4d-fbc2-4e09-b0e7-1b4b73f72baa
|
||||||
|
# Name: db-snapshot01
|
||||||
|
# Properties: {}
|
||||||
|
# Size: 50
|
||||||
|
# Status: available
|
||||||
|
# Volume: 8c87c196-1dd6-4190-bff5-00b543965093
|
||||||
|
|
||||||
|
require "../models"
|
||||||
|
|
||||||
|
module Arkisto
|
||||||
|
module OSVolume
|
||||||
|
class SnapshotListItemModel < Model
|
||||||
|
@[YAML::Field(key: "Created At")]
|
||||||
|
property created_at : String
|
||||||
|
|
||||||
|
@[YAML::Field(key: "Description")]
|
||||||
|
property description : String
|
||||||
|
|
||||||
|
@[YAML::Field(key: "ID")]
|
||||||
|
property id : String ## UUID
|
||||||
|
|
||||||
|
@[YAML::Field(key: "Name")]
|
||||||
|
property name : String
|
||||||
|
|
||||||
|
@[YAML::Field(key: "Properties")]
|
||||||
|
property properties : YAML::Any
|
||||||
|
|
||||||
|
@[YAML::Field(key: "Size")]
|
||||||
|
property size : UInt16
|
||||||
|
|
||||||
|
@[YAML::Field(key: "Status")]
|
||||||
|
property status : String
|
||||||
|
|
||||||
|
@[YAML::Field(key: "Volume")]
|
||||||
|
property volume : String
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
10
src/lib/models/retention.cr
Normal file
10
src/lib/models/retention.cr
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
require "../models"
|
||||||
|
|
||||||
|
module Arkisto
|
||||||
|
class RetentionModel < Model
|
||||||
|
property days : UInt8
|
||||||
|
property cycle : Bool
|
||||||
|
property max_items : UInt8
|
||||||
|
end
|
||||||
|
end
|
11
src/lib/models/target.cr
Normal file
11
src/lib/models/target.cr
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
require "../models"
|
||||||
|
|
||||||
|
module Arkisto
|
||||||
|
class TargetItemModel < Model
|
||||||
|
property name : String
|
||||||
|
property volume_id : String
|
||||||
|
# property snapshot_prefix : String
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
77
src/lib/openstack.cr
Normal file
77
src/lib/openstack.cr
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
|
||||||
|
module Arkisto
|
||||||
|
class OpenStack
|
||||||
|
#
|
||||||
|
# openstack volume list
|
||||||
|
#
|
||||||
|
def self.volume_list
|
||||||
|
cmd = "openstack"
|
||||||
|
args = [
|
||||||
|
"volume", "list",
|
||||||
|
"--long",
|
||||||
|
"--format", "yaml"
|
||||||
|
]
|
||||||
|
stdout = IO::Memory.new
|
||||||
|
stderr = IO::Memory.new
|
||||||
|
|
||||||
|
status = Process.run(cmd, args: args, output: stdout, error: stderr)
|
||||||
|
if ! status.success?
|
||||||
|
raise RuntimeError.new("command failed for: #{cmd} #{args.join(" ")}") # FIXME: improve message
|
||||||
|
end
|
||||||
|
|
||||||
|
return Array(OSVolume::ListItemModel).from_yaml(stdout.to_s)
|
||||||
|
rescue ex : RuntimeError
|
||||||
|
puts "ERROR: #{ex.message}".colorize(:red)
|
||||||
|
exit(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# openstack volume snapshot list
|
||||||
|
#
|
||||||
|
def self.volume_snapshot_list
|
||||||
|
cmd = "openstack"
|
||||||
|
args =[
|
||||||
|
"volume", "snapshot", "list",
|
||||||
|
"--long",
|
||||||
|
"--format", "yaml"
|
||||||
|
]
|
||||||
|
stdout = IO::Memory.new
|
||||||
|
stderr = IO::Memory.new
|
||||||
|
|
||||||
|
status = Process.run(cmd, args: args, output: stdout, error: stderr)
|
||||||
|
if ! status.success?
|
||||||
|
raise RuntimeError.new("command failed for: #{cmd} #{args.join(" ")}") # FIXME: improve message
|
||||||
|
end
|
||||||
|
|
||||||
|
return Array(OSVolume::SnapshotListItemModel).from_yaml(stdout.to_s)
|
||||||
|
rescue ex : RuntimeError
|
||||||
|
puts "ERROR: #{ex.message}".colorize(:red)
|
||||||
|
exit(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# openstack volume snapshot create --volume VOLUME_ID --force SNAPSHOT_NAME -f yaml
|
||||||
|
#
|
||||||
|
def self.volume_snapshot_create(target_volume, snap_name)
|
||||||
|
cmd = "openstack"
|
||||||
|
args = ["volume", "snapshot", "create",
|
||||||
|
"--volume", target_volume.id,
|
||||||
|
"--force",
|
||||||
|
snap_name,
|
||||||
|
"--format", "yaml"]
|
||||||
|
stdout = IO::Memory.new
|
||||||
|
stderr = IO::Memory.new
|
||||||
|
|
||||||
|
status = Process.run(cmd, args: args, output: stdout, error: stderr)
|
||||||
|
if ! status.success?
|
||||||
|
raise RuntimeError.new("#{cmd} #{args.join(" ")}\n#{stderr.to_s}") # FIXME: improve message
|
||||||
|
end
|
||||||
|
|
||||||
|
return OSVolume::SnapshotCreateItemModel.from_yaml(stdout.to_s)
|
||||||
|
|
||||||
|
rescue ex : RuntimeError
|
||||||
|
puts "ERROR: #{ex.message}".colorize(:red)
|
||||||
|
exit(1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
16
src/lib/types.cr
Normal file
16
src/lib/types.cr
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
|
||||||
|
require "./actions"
|
||||||
|
|
||||||
|
module Arkisto
|
||||||
|
alias GlobalOptions = {
|
||||||
|
action: Action.class,
|
||||||
|
verbose: Bool,
|
||||||
|
dry_run: Bool,
|
||||||
|
config_file: String
|
||||||
|
}
|
||||||
|
|
||||||
|
alias ActionOptions = {
|
||||||
|
verbose: Bool,
|
||||||
|
dry_run: Bool
|
||||||
|
}
|
||||||
|
end
|
7
src/lib/version.cr
Normal file
7
src/lib/version.cr
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
module Arkisto
|
||||||
|
class Version
|
||||||
|
PROGRAM_ARKISTOCTL = "arkistoctl"
|
||||||
|
VERSION = "0.1.0"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
Loading…
Reference in a new issue