diff --git a/install.sh b/install.sh index a5e305b611..bfdf36159a 100755 --- a/install.sh +++ b/install.sh @@ -360,6 +360,7 @@ VAR_DIRS="$VAR_LOCATION/remotes \ $VAR_LOCATION/remotes/market/one \ $VAR_LOCATION/remotes/market/s3 \ $VAR_LOCATION/remotes/market/linuxcontainers \ + $VAR_LOCATION/remotes/market/turnkeylinux \ $VAR_LOCATION/remotes/datastore/iscsi_libvirt \ $VAR_LOCATION/remotes/auth \ $VAR_LOCATION/remotes/auth/plain \ @@ -511,6 +512,7 @@ INSTALL_FILES=( MARKETPLACE_DRIVER_ONE_SCRIPTS:$VAR_LOCATION/remotes/market/one MARKETPLACE_DRIVER_S3_SCRIPTS:$VAR_LOCATION/remotes/market/s3 MARKETPLACE_DRIVER_LXC_SCRIPTS:$VAR_LOCATION/remotes/market/linuxcontainers + MARKETPLACE_DRIVER_TK_SCRIPTS:$VAR_LOCATION/remotes/market/turnkeylinux IPAM_DRIVER_DUMMY_SCRIPTS:$VAR_LOCATION/remotes/ipam/dummy IPAM_DRIVER_PACKET_SCRIPTS:$VAR_LOCATION/remotes/ipam/packet NETWORK_FILES:$VAR_LOCATION/remotes/vnm @@ -1531,6 +1533,10 @@ MARKETPLACE_DRIVER_LXC_SCRIPTS="src/market_mad/remotes/linuxcontainers/import \ src/market_mad/remotes/linuxcontainers/delete \ src/market_mad/remotes/linuxcontainers/monitor" +MARKETPLACE_DRIVER_TK_SCRIPTS="src/market_mad/remotes/turnkeylinux/import \ + src/market_mad/remotes/turnkeylinux/delete \ + src/market_mad/remotes/turnkeylinux/monitor" + #------------------------------------------------------------------------------- # Migration scripts for onedb command, to be installed under $LIB_LOCATION #------------------------------------------------------------------------------- diff --git a/src/market_mad/remotes/turnkeylinux/delete b/src/market_mad/remotes/turnkeylinux/delete new file mode 100755 index 0000000000..a99937d4fa --- /dev/null +++ b/src/market_mad/remotes/turnkeylinux/delete @@ -0,0 +1,29 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2019, 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. # +# -------------------------------------------------------------------------- # + +if [ -z "${ONE_LOCATION}" ]; then + LIB_LOCATION=/usr/lib/one +else + LIB_LOCATION=$ONE_LOCATION/lib +fi + +. $LIB_LOCATION/sh/scripts_common.sh + +error_message "Cannot delete app from turnkey linux marketplace" + +exit -1 diff --git a/src/market_mad/remotes/turnkeylinux/import b/src/market_mad/remotes/turnkeylinux/import new file mode 100755 index 0000000000..3cdde480ec --- /dev/null +++ b/src/market_mad/remotes/turnkeylinux/import @@ -0,0 +1,29 @@ +#!/bin/bash + +# -------------------------------------------------------------------------- # +# Copyright 2002-2019, 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. # +# -------------------------------------------------------------------------- # + +if [ -z "${ONE_LOCATION}" ]; then + LIB_LOCATION=/usr/lib/one +else + LIB_LOCATION=$ONE_LOCATION/lib +fi + +. $LIB_LOCATION/sh/scripts_common.sh + +error_message "Cannot import app into turnkey linux marketplace" + +exit -1 diff --git a/src/market_mad/remotes/turnkeylinux/monitor b/src/market_mad/remotes/turnkeylinux/monitor new file mode 100755 index 0000000000..d5235414ed --- /dev/null +++ b/src/market_mad/remotes/turnkeylinux/monitor @@ -0,0 +1,226 @@ +#!/usr/bin/env ruby + +# -------------------------------------------------------------------------- # +# Copyright 2002-2019, 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 'net/http' +require 'uri' +require 'json' +require 'base64' +require 'rexml/document' +require 'nokogiri' +require 'digest/md5' + +def unindent(str) + m = str.match(/^(\s*)/) + spaces = m[1].size + str.gsub!(/^ {#{spaces}}/, '') +end + +#------------------------------------------------------------------------------- +# This class is used to query the TurnkeyLinux repository +#------------------------------------------------------------------------------- +class TurnkeyLinux + + #--------------------------------------------------------------------------- + # Default Configuration parameters for the Driver + #--------------------------------------------------------------------------- + DEFAULTS = { + :url => 'http://mirror.turnkeylinux.org', + :platform => '/turnkeylinux/images/proxmox/', + :sizemb => 5120, + :fs => 'ext4', + :format => 'raw', + :agent => 'OpenNebula' + } + + TEMPLATE = unindent(<<-EOS) + HYPERVISOR = \"lxd\" + CPU = \"1\" + MEMORY = \"768\" + LXD_SECURITY_PRIVILEGED = \"true\" + GRAPHICS = [ + LISTEN =\"0.0.0.0\", + TYPE =\"vnc\" + ] + CONTEXT = [ + NETWORK =\"YES\", + SSH_PUBLIC_KEY =\"$USER[SSH_PUBLIC_KEY]\", + SET_HOSTNAME =\"$NAME\" + ]" + EOS + + #--------------------------------------------------------------------------- + # Configuration varibales + # :url of linuxcontainers market place + # :sizemb default size for container images + # :fs filesystem for the image file + # :format for the image file, qcow2, raw + # :agent for HTTP client + #--------------------------------------------------------------------------- + def initialize(options = {}) + @options = DEFAULTS + @options.merge!(options) + + vp = File.dirname(__FILE__) + '/../../VERSION' + + @options[:agent] = "OpenNebula #{File.read(vp)}" if File.exist? vp + end + + #--------------------------------------------------------------------------- + # Fetch URL + #--------------------------------------------------------------------------- + def get(path) + # Get proxy params (needed for ruby 1.9.3) + http_proxy = ENV['http_proxy'] || ENV['HTTP_PROXY'] + + p_host = nil + p_port = nil + + if http_proxy + p_uri = URI(http_proxy) + p_host = p_uri.host + p_port = p_uri.port + end + + uri = URI(@options[:url] + path) + req = Net::HTTP::Get.new(uri.request_uri) + + req['User-Agent'] = @options[:agent] if @options[:agent] + + rc = Net::HTTP.start(uri.hostname, uri.port, p_host, p_port) do |http| + http.request(req) + end + + return [rc.code.to_i, rc.msg] unless rc.is_a? Net::HTTPSuccess + + [0, rc.body] + end + + #--------------------------------------------------------------------------- + # Get appliance list + #--------------------------------------------------------------------------- + def appliances + try = 0 + appstr = '' + apps = [] + + loop do + rc, body = get(@options[:platform]) + + return [rc, body] if rc != 0 + + parsed = Nokogiri::HTML.parse(body) + apps = parsed.css('pre').text.lines + + break unless apps.empty? + + try += 1 + + return [0, ''] if try > 5 + end + + # Line example + # debian-9-turnkey-zurmo_15.2-1_amd64.tar.gz.hash 2018-11-29 09:45 2.2K + apps.each do |l| + f = l.split + + next if f[0] =~ /\.hash$/ + + image = f[0].split('-') + time = f[1].split('-') + regt = Time.new(time[0], time[1], time[2]).to_i + + data = { + 'NAME' => "#{image[3]} - LXD", + 'SOURCE' => app_url(f[0]), + 'IMPORT_ID' => -1, + 'ORIGIN_ID' => -1, + 'TYPE' => 'IMAGE', + 'PUBLISHER' => 'turnkeylinux.org', + 'MD5' => md5(regt), + 'FORMAT' => 'raw', + 'VERSION' => '1.0', + 'TAGS' => '', + 'REGTIME' => regt, + 'SIZE' => @options[:sizemb], + 'DESCRIPTION' => "Based on #{image[0]}-#{image[1]}" + } + + tmpl = '' + data.each {|key, val| print_var(tmpl, key, val) } + + tmpl64 = '' + print_var(tmpl64, 'DRIVER', 'raw') + + data = { 'APPTEMPLATE64' => tmpl64, 'VMTEMPLATE64' => TEMPLATE } + data.each do |key, val| + print_var(tmpl, key, Base64.strict_encode64(val)) + end + + appstr << "APP=\"#{Base64.strict_encode64(tmpl)}\"\n" + end + + [0, appstr] + end + + def app_url(path) + "lxd://#{@options[:url]}/#{@options[:platform]}/#{path}?" \ + "size=#{@options[:sizemb]}&filesystem=#{@options[:fs]}&" \ + "format=#{@options[:format]}" + end + + def print_var(str, name, val) + return if val.nil? + return if val.class == String && val.empty? + + str << "#{name}=\"#{val}\"\n" + end + + # Returns an md5 from a combination of the @option hash and an input string + def md5(string) + Digest::MD5.hexdigest("#{@options} #{string}") + end + +end + +################################################################################ +# Main Program. Outpust the list of marketplace appliances +################################################################################ +def set_option(opt, doc, name, path) + opt[name] = doc.elements[path].text if doc.elements[path] +end + +begin + options = {} + drv_message = Base64.decode64(ARGV[0]) + + doc = REXML::Document.new(drv_message).root + + set_option(options, doc, :url, 'MARKETPLACE/TEMPLATE/ENDPOINT') + set_option(options, doc, :sizemb, 'MARKETPLACE/TEMPLATE/IMAGE_SIZE_MB') + set_option(options, doc, :fs, 'MARKETPLACE/TEMPLATE/FILESYSTEM') + set_option(options, doc, :format, 'MARKETPLACE/TEMPLATE/FORMAT') + + rc, str = TurnkeyLinux.new(options).appliances + + if rc != 0 + STDERR.puts str + exit(-1) + end + + puts str +end