Skip to content
Snippets Groups Projects
Commit 97e15c11 authored by garciaale's avatar garciaale
Browse files

Adds packages for test SA-05


Signed-off-by: default avatargarciaale <agarcia@whitestack.com>
parent 3aa99d92
No related branches found
No related tags found
1 merge request!76SA-05_packages
Showing
with 966 additions and 0 deletions
# Copyright 2014-2016 Canonical Limited.
#
# This file is part of layer-basic, the reactive base layer for Juju.
#
# charm-helpers is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License version 3 as
# published by the Free Software Foundation.
#
# charm-helpers is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
# This module may only import from the Python standard library.
import os
import sys
import subprocess
import time
'''
execd/preinstall
Read the layer-basic docs for more info on how to use this feature.
https://charmsreactive.readthedocs.io/en/latest/layer-basic.html#exec-d-support
'''
def default_execd_dir():
return os.path.join(os.environ['JUJU_CHARM_DIR'], 'exec.d')
def execd_module_paths(execd_dir=None):
"""Generate a list of full paths to modules within execd_dir."""
if not execd_dir:
execd_dir = default_execd_dir()
if not os.path.exists(execd_dir):
return
for subpath in os.listdir(execd_dir):
module = os.path.join(execd_dir, subpath)
if os.path.isdir(module):
yield module
def execd_submodule_paths(command, execd_dir=None):
"""Generate a list of full paths to the specified command within exec_dir.
"""
for module_path in execd_module_paths(execd_dir):
path = os.path.join(module_path, command)
if os.access(path, os.X_OK) and os.path.isfile(path):
yield path
def execd_sentinel_path(submodule_path):
module_path = os.path.dirname(submodule_path)
execd_path = os.path.dirname(module_path)
module_name = os.path.basename(module_path)
submodule_name = os.path.basename(submodule_path)
return os.path.join(execd_path,
'.{}_{}.done'.format(module_name, submodule_name))
def execd_run(command, execd_dir=None, stop_on_error=True, stderr=None):
"""Run command for each module within execd_dir which defines it."""
if stderr is None:
stderr = sys.stdout
for submodule_path in execd_submodule_paths(command, execd_dir):
# Only run each execd once. We cannot simply run them in the
# install hook, as potentially storage hooks are run before that.
# We cannot rely on them being idempotent.
sentinel = execd_sentinel_path(submodule_path)
if os.path.exists(sentinel):
continue
try:
subprocess.check_call([submodule_path], stderr=stderr,
universal_newlines=True)
with open(sentinel, 'w') as f:
f.write('{} ran successfully {}\n'.format(submodule_path,
time.ctime()))
f.write('Removing this file will cause it to be run again\n')
except subprocess.CalledProcessError as e:
# Logs get the details. We can't use juju-log, as the
# output may be substantial and exceed command line
# length limits.
print("ERROR ({}) running {}".format(e.returncode, e.cmd),
file=stderr)
print("STDOUT<<EOM", file=stderr)
print(e.output, file=stderr)
print("EOM", file=stderr)
# Unit workload status gets a shorter fail message.
short_path = os.path.relpath(submodule_path)
block_msg = "Error ({}) running {}".format(e.returncode,
short_path)
try:
subprocess.check_call(['status-set', 'blocked', block_msg],
universal_newlines=True)
if stop_on_error:
sys.exit(0) # Leave unit in blocked state.
except Exception:
pass # We care about the exec.d/* failure, not status-set.
if stop_on_error:
sys.exit(e.returncode or 1) # Error state for pre-1.24 Juju
def execd_preinstall(execd_dir=None):
"""Run charm-pre-install for each module within execd_dir."""
execd_run('charm-pre-install', execd_dir=execd_dir)
import os
from pathlib import Path
import yaml
_CHARM_PATH = Path(os.environ.get('JUJU_CHARM_DIR', '.'))
_DEFAULT_FILE = _CHARM_PATH / 'layer.yaml'
_CACHE = {}
def get(section=None, option=None, layer_file=_DEFAULT_FILE):
if option and not section:
raise ValueError('Cannot specify option without section')
layer_file = (_CHARM_PATH / layer_file).resolve()
if layer_file not in _CACHE:
with layer_file.open() as fp:
_CACHE[layer_file] = yaml.safe_load(fp.read())
data = _CACHE[layer_file].get('options', {})
if section:
data = data.get(section, {})
if option:
data = data.get(option)
return data
"""Module to help with executing commands over SSH."""
##
# Copyright 2016 Canonical Ltd.
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
##
from charmhelpers.core import unitdata
import io
import ipaddress
import paramiko
import os
import socket
import shlex
from subprocess import (
Popen,
CalledProcessError,
PIPE,
)
def get_config():
"""Get the current charm configuration.
Get the "live" kv store every time we need to access the charm config, in
case it has recently been changed by a config-changed event.
"""
db = unitdata.kv()
return db.get('config')
def get_host_ip():
"""Get the IP address for the ssh host.
HACK: This function was added to work around an issue where the
ssh-hostname was passed in the format of a.b.c.d;a.b.c.d, where the first
is the floating ip, and the second the non-floating ip, for an Openstack
instance.
"""
cfg = get_config()
return cfg['ssh-hostname'].split(';')[0]
def is_valid_hostname(hostname):
"""Validate the ssh-hostname."""
if hostname == "0.0.0.0":
return False
try:
ipaddress.ip_address(hostname)
except ValueError:
return False
return True
def verify_ssh_credentials():
"""Verify the ssh credentials have been installed to the VNF.
Attempts to run a stock command - `hostname` on the remote host.
"""
verified = False
status = ''
cfg = get_config()
try:
host = get_host_ip()
if is_valid_hostname(host):
if len(cfg['ssh-hostname']) and len(cfg['ssh-username']):
cmd = 'hostname'
status, err = _run(cmd)
if len(err) == 0:
verified = True
else:
status = "Invalid IP address."
except CalledProcessError as e:
status = 'Command failed: {} ({})'.format(
' '.join(e.cmd),
str(e.output)
)
except paramiko.ssh_exception.AuthenticationException as e:
status = '{}.'.format(e)
except paramiko.ssh_exception.BadAuthenticationType as e:
status = '{}'.format(e.explanation)
except paramiko.ssh_exception.BadHostKeyException as e:
status = 'Host key mismatch: expected {} but got {}.'.format(
e.expected_key,
e.got_key,
)
except (TimeoutError, socket.timeout):
status = "Timeout attempting to reach {}".format(cfg['ssh-hostname'])
except Exception as error:
status = 'Unhandled exception: {}'.format(error)
return (verified, status)
def charm_dir():
"""Return the root directory of the current charm."""
d = os.environ.get('JUJU_CHARM_DIR')
if d is not None:
return d
return os.environ.get('CHARM_DIR')
def run_local(cmd, env=None):
"""Run a command locally."""
if isinstance(cmd, str):
cmd = shlex.split(cmd) if ' ' in cmd else [cmd]
if type(cmd) is not list:
cmd = [cmd]
p = Popen(cmd,
env=env,
shell=True,
stdout=PIPE,
stderr=PIPE)
stdout, stderr = p.communicate()
retcode = p.poll()
if retcode > 0:
raise CalledProcessError(returncode=retcode,
cmd=cmd,
output=stderr.decode("utf-8").strip())
return (stdout.decode('utf-8').strip(), stderr.decode('utf-8').strip())
def _run(cmd, env=None):
"""Run a command remotely via SSH.
Note: The previous behavior was to run the command locally if SSH wasn't
configured, but that can lead to cases where execution succeeds when you'd
expect it not to.
"""
if isinstance(cmd, str):
cmd = shlex.split(cmd)
if type(cmd) is not list:
cmd = [cmd]
cfg = get_config()
if cfg:
if all(k in cfg for k in ['ssh-hostname', 'ssh-username',
'ssh-password', 'ssh-private-key']):
host = get_host_ip()
user = cfg['ssh-username']
passwd = cfg['ssh-password']
key = cfg['ssh-private-key'] # DEPRECATED
if host and user:
return ssh(cmd, host, user, passwd, key)
raise Exception("Invalid SSH credentials.")
def get_ssh_client(host, user, password=None, key=None):
"""Return a connected Paramiko ssh object."""
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
pkey = None
# Check for the DEPRECATED private-key
if key:
f = io.StringIO(key)
pkey = paramiko.RSAKey.from_private_key(f)
else:
# Otherwise, check for the auto-generated private key
if os.path.exists('/root/.ssh/id_juju_sshproxy'):
with open('/root/.ssh/id_juju_sshproxy', 'r') as f:
pkey = paramiko.RSAKey.from_private_key(f)
###########################################################################
# There is a bug in some versions of OpenSSH 4.3 (CentOS/RHEL 5) where #
# the server may not send the SSH_MSG_USERAUTH_BANNER message except when #
# responding to an auth_none request. For example, paramiko will attempt #
# to use password authentication when a password is set, but the server #
# could deny that, instead requesting keyboard-interactive. The hack to #
# workaround this is to attempt a reconnect, which will receive the right #
# banner, and authentication can proceed. See the following for more info #
# https://github.com/paramiko/paramiko/issues/432 #
# https://github.com/paramiko/paramiko/pull/438 #
###########################################################################
try:
client.connect(host, port=22, username=user,
password=password, pkey=pkey)
except paramiko.ssh_exception.SSHException as e:
if 'Error reading SSH protocol banner' == str(e):
# Once more, with feeling
client.connect(host, port=22, username=user,
password=password, pkey=pkey)
else:
# Reraise the original exception
raise e
return client
def sftp(local_file, remote_file, host, user, password=None, key=None):
"""Copy a local file to a remote host."""
client = get_ssh_client(host, user, password, key)
# Create an sftp connection from the underlying transport
sftp = paramiko.SFTPClient.from_transport(client.get_transport())
sftp.put(local_file, remote_file)
client.close()
def ssh(cmd, host, user, password=None, key=None):
"""Run an arbitrary command over SSH."""
client = get_ssh_client(host, user, password, key)
cmds = ' '.join(cmd)
stdin, stdout, stderr = client.exec_command(cmds, get_pty=True)
retcode = stdout.channel.recv_exit_status()
client.close() # @TODO re-use connections
if retcode > 0:
output = stderr.read().strip()
raise CalledProcessError(returncode=retcode, cmd=cmd,
output=output)
return (
stdout.read().decode('utf-8').strip(),
stderr.read().decode('utf-8').strip()
)
"name": "testmetrics"
"summary": "extends the ubuntuvnf charm with sayhello primitive to support basic metrics"
"maintainer": "Gianpietro Lavado <glavado@whitestack.com>"
"description": |
Extends the ubuntuvnf charm with sayhello primitive to support basic metrics
"tags":
# Replace "misc" with one or more whitelisted tags from this list:
# https://jujucharms.com/docs/stable/authors-charm-metadata
- "misc"
- "osm"
- "vnf"
"series":
- "xenial"
- "trusty"
"subordinate": !!bool "false"
metrics:
users:
type: gauge
description: "# of users"
command: who|wc -l
load:
type: gauge
description: "5 minute load average"
command: cat /proc/loadavg |awk '{print $1}'
load_pct:
type: gauge
description: "1 minute load average percent"
command: cat /proc/loadavg | awk '{load_pct=$1*100.00} END {print load_pct}'
\ No newline at end of file
##
# Copyright 2016 Canonical Ltd.
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
##
from charmhelpers.core import unitdata
from charmhelpers.core.hookenv import (
action_fail,
action_get,
action_set,
config,
log,
status_set,
DEBUG,
)
from charms.reactive.flags import register_trigger
from charms.reactive import (
clear_flag,
set_flag,
when,
when_not,
when_any,
)
import charms.sshproxy
import os
import subprocess
# Register a trigger so that we can respond to config.changed, even if
# it's being cleared by another handler
register_trigger(when='config.changed',
set_flag='sshproxy.reconfigure')
@when_any('config.changed', 'sshproxy.reconfigure')
def ssh_configured():
"""Check if charm is properly configured.
Check to see if the charm is configured with SSH credentials. If so,
set a state flag that can be used to execute ssh-only actions.
For example:
@when('sshproxy.configured')
def run_remote_command(cmd):
...
@when_not('sshproxy.configured')
def run_local_command(cmd):
...
"""
log("Checking sshproxy configuration", DEBUG)
cfg = config()
ssh_keys = ['ssh-hostname', 'ssh-username',
'ssh-password', 'ssh-private-key']
if all(k in cfg for k in ssh_keys):
# Store config in unitdata so it's accessible to sshproxy
db = unitdata.kv()
db.set('config', cfg)
# Explicitly flush the kv so it's immediately available
db.flush()
log("Verifying ssh credentials...", DEBUG)
(verified, output) = charms.sshproxy.verify_ssh_credentials()
if verified:
log("SSH credentials verified.", DEBUG)
set_flag('sshproxy.configured')
status_set('active', 'Ready!')
else:
clear_flag('sshproxy.configured')
status_set('blocked', "Verification failed: {}".format(output))
else:
log("No ssh credentials configured", DEBUG)
clear_flag('sshproxy.configured')
status_set('blocked', 'Invalid SSH credentials.')
def generate_ssh_key():
"""Generate a new 4096-bit rsa keypair.
If there is an existing keypair for this unit, it will be overwritten.
"""
cfg = config()
if all(k in cfg for k in ['ssh-key-type', 'ssh-key-bits']):
keytype = cfg['ssh-key-type']
bits = str(cfg['ssh-key-bits'])
privatekey = '/root/.ssh/id_juju_sshproxy'
publickey = "{}.pub".format(privatekey)
if os.path.exists(privatekey):
os.remove(privatekey)
if os.path.exists(publickey):
os.remove(publickey)
cmd = "ssh-keygen -t {} -b {} -N '' -f {}".format(
keytype,
bits,
privatekey
)
output, err = charms.sshproxy.run_local([cmd])
if len(err) == 0:
return True
return False
@when('actions.generate-ssh-key')
def action_generate_ssh_key():
"""Generate a new 4096-bit rsa keypair.
If there is an existing keypair for this unit, it will be overwritten.
"""
try:
if not generate_ssh_key():
action_fail('Unable to generate ssh key.')
except subprocess.CalledProcessError as e:
action_fail('Command failed: %s (%s)' %
(' '.join(e.cmd), str(e.output)))
finally:
clear_flag('actions.generate-ssh-key')
def get_ssh_public_key():
"""Get the public SSH key of this unit."""
publickey_path = '/root/.ssh/id_juju_sshproxy.pub'
publickey = None
if os.path.exists(publickey_path):
with open(publickey_path, 'r') as f:
publickey = f.read()
return publickey
@when('actions.get-ssh-public-key')
def action_get_ssh_public_key():
"""Get the public SSH key of this unit."""
try:
action_set({'pubkey': get_ssh_public_key()})
except subprocess.CalledProcessError as e:
action_fail('Command failed: %s (%s)' %
(' '.join(e.cmd), str(e.output)))
finally:
clear_flag('actions.get-ssh-public-key')
@when('actions.verify-ssh-credentials')
def action_verify_ssh_credentials():
"""Verify the ssh credentials have been installed to the VNF.
Attempts to run a stock command - `hostname` on the remote host.
"""
try:
(verified, output) = charms.sshproxy.verify_ssh_credentials()
action_set({
'output': output,
'verified': verified,
})
if not verified:
action_fail("Verification failed: {}".format(
output,
))
finally:
clear_flag('actions.verify-ssh-credentials')
@when('actions.run')
def run_command():
"""Run an arbitrary command.
Run an arbitrary command, either locally or over SSH with the configured
credentials.
"""
try:
cmd = action_get('command')
output, err = charms.sshproxy._run(cmd)
if len(err):
action_fail("Command '{}' returned error code {}".format(cmd, err))
else:
action_set({'output': output})
except subprocess.CalledProcessError as e:
action_fail('Command failed: %s (%s)' %
(' '.join(e.cmd), str(e.output)))
finally:
clear_flag('actions.run')
@when_not('sshproxy.installed')
def install_vnf_ubuntu_proxy():
"""Install and Configure SSH Proxy."""
log("Generating SSH key...", DEBUG)
generate_ssh_key()
set_flag('sshproxy.installed')
from charmhelpers.core.hookenv import (
action_get,
action_fail,
action_set,
config,
status_set,
)
from charms.reactive import (
remove_state as remove_flag,
set_state as set_flag,
when,
when_not,
)
import charms.sshproxy
from subprocess import (
Popen,
CalledProcessError,
PIPE,
)
import time
@when_not('testmetrics.installed')
def install_testmetrics():
# Do your setup here.
#
# If your charm has other dependencies before it can install,
# add those as @when() clauses above., or as additional @when()
# decorated handlers below
#
# See the following for information about reactive charms:
#
# * https://jujucharms.com/docs/devel/developer-getting-started
# * https://github.com/juju-solutions/layer-basic#overview
#
status_set('blocked', 'Waiting for SSH credentials.')
set_flag('testmetrics.installed')
# say-hello sample action
# two when clauses work like an AND
@when('testmetrics.installed')
@when('actions.say-hello')
def say_hello():
err = ''
## Gets the name parameter that the descriptor passed, otherwise the defined by default in actions.yaml
param1 = "Hello " + action_get("name")
try:
# Put the code here that you want to execute, it includes parameters
# Parameters should be defined in both actions.yaml and the VNF descriptor
## Define the command to run
cmd = "sudo wall -n " + param1
## Run the command through SSH
result, err = charms.sshproxy._run(cmd)
except:
# In case it fails, throw an exception
action_fail('command failed:' + err)
else:
# In case it suceeds, return the output
action_set({'output': result})
finally:
# Finally, end the action by removing the flag
remove_flag('actions.say-hello')
from charmhelpers.core.hookenv import (
action_fail,
action_set,
)
from charms.reactive import (
when,
clear_flag,
)
import charms.sshproxy
@when('actions.reboot')
def reboot():
err = ''
try:
result, err = charms.sshproxy._run("reboot")
except:
action_fail('command failed:' + err)
else:
action_set({'outout': result})
finally:
clear_flag('actions.reboot')
###############################################################################
# Below is an example implementation of the start/stop/restart actions. #
# To use this, copy the below code into your layer and add the appropriate #
# command(s) necessary to perform the action. #
###############################################################################
# @when('actions.start')
# def start():
# err = ''
# try:
# cmd = "service myname start"
# result, err = charms.sshproxy._run(cmd)
# except:
# action_fail('command failed:' + err)
# else:
# action_set({'outout': result})
# finally:
# clear_flag('actions.start')
#
#
# @when('actions.stop')
# def stop():
# err = ''
# try:
# # Enter the command to stop your service(s)
# cmd = "service myname stop"
# result, err = charms.sshproxy._run(cmd)
# except:
# action_fail('command failed:' + err)
# else:
# action_set({'outout': result})
# finally:
# clear_flag('actions.stop')
#
#
# @when('actions.restart')
# def restart():
# err = ''
# try:
# # Enter the command to restart your service(s)
# cmd = "service myname restart"
# result, err = charms.sshproxy._run(cmd)
# except:
# action_fail('command failed:' + err)
# else:
# action_set({'outout': result})
# finally:
# clear_flag('actions.restart')
#
#
# @when('actions.upgrade')
# def upgrade_vnf():
# err = ''
# try:
# # Add the command(s) to perform a VNF software upgrade
# cmd = ''
# result, err = charms.sshproxy._run(cmd)
# except:
# action_fail('command failed:' + err)
# else:
# action_set({'outout': result})
# finally:
# clear_flag('actions.upgrade')
#
flake8
pytest
#!/bin/bash
sudo add-apt-repository ppa:juju/stable -y
sudo apt-get update
sudo apt-get install amulet python-requests -y
#!/usr/bin/python3
import amulet
import requests
import unittest
class TestCharm(unittest.TestCase):
def setUp(self):
self.d = amulet.Deployment()
self.d.add('testmetrics')
self.d.expose('testmetrics')
self.d.setup(timeout=900)
self.d.sentry.wait()
self.unit = self.d.sentry['testmetrics'][0]
def test_service(self):
# test we can access over http
page = requests.get('http://{}'.format(self.unit.info['public-address']))
self.assertEqual(page.status_code, 200)
# Now you can use self.d.sentry[SERVICE][UNIT] to address each of the units and perform
# more in-depth steps. Each self.d.sentry[SERVICE][UNIT] has the following methods:
# - .info - An array of the information of that unit from Juju
# - .file(PATH) - Get the details of a file on that unit
# - .file_contents(PATH) - Get plain text output of PATH file from that unit
# - .directory(PATH) - Get details of directory
# - .directory_contents(PATH) - List files and folders in PATH on that unit
# - .relation(relation, service:rel) - Get relation data from return service
if __name__ == '__main__':
unittest.main()
[tox]
skipsdist=True
envlist = py34, py35
skip_missing_interpreters = True
[testenv]
# This is not pretty, but pytest will return 0 if all tests worked and 5 if no tests are found.
# We want to consider no tests as an indication of success.
commands = /bin/bash -c 'py.test -v || if [[ $? == 5 ]]; then true; else false; fi'
deps =
-r{toxinidir}/requirements.txt
[flake8]
exclude=docs
File added
#cloud-config
hostname: ubuntuvnf
password: osm2018
chpasswd: { expire: False }
ssh_pwauth: True
vnfd-catalog:
vnfd:
- id: ubuntuvm_vnfmetric_autoscale_vnf
name: ubuntuvm_vnfmetric_autoscale_vnf
short-name: ubuntuvm_vnfmetric_autoscale_vnf
description: Ubuntu VM with VNF metrics and load-based autoscaling
connection-point:
- name: vdu1_mgmt
type: VPORT
- name: vdu2_mgmt
type: VPORT
internal-vld:
- id: internal
internal-connection-point:
- id-ref: vdu1_internal
- id-ref: vdu2_internal
name: internal
short-name: internal
type: ELAN
mgmt-interface:
cp: vdu1_mgmt
vdu:
- cloud-init-file: cloud_init
count: 1
description: ubuntuvnfvdu1
id: ubuntuvnfvdu1
image: ubuntu
interface:
- external-connection-point-ref: vdu1_mgmt
mgmt-interface: true
name: vdu1_eth0
position: 1
type: EXTERNAL
virtual-interface:
type: VIRTIO
- internal-connection-point-ref: vdu1_internal
name: vdu1_eth1
position: 2
type: INTERNAL
virtual-interface:
type: VIRTIO
internal-connection-point:
- id: vdu1_internal
name: vdu1_internal
short-name: vdu1_internal
type: VPORT
name: ubuntuvnfvdu1
vm-flavor:
memory-mb: 2048
storage-gb: 10
vcpu-count: 1
- cloud-init-file: cloud_init
count: 1
description: ubuntuvdu2
id: ubuntuvdu2
image: ubuntu
interface:
- external-connection-point-ref: vdu2_mgmt
mgmt-interface: true
name: vdu2_eth0
position: 1
type: EXTERNAL
virtual-interface:
type: VIRTIO
- internal-connection-point-ref: vdu2_internal
name: vdu2_eth1
position: 2
type: INTERNAL
virtual-interface:
type: VIRTIO
internal-connection-point:
- id: vdu2_internal
name: vdu2_internal
short-name: vdu2_internal
type: VPORT
name: ubuntuvdu2
vm-flavor:
memory-mb: 2048
storage-gb: 10
vcpu-count: 1
vendor: Whitestack
version: '2.0'
vnf-configuration:
initial-config-primitive:
- name: config
parameter:
- name: ssh-hostname
value: <rw_mgmt_ip>
- name: ssh-username
value: ubuntu
- name: ssh-password
value: osm2018
seq: 1
juju:
charm: testmetrics
proxy: true
metrics:
- name: users
- name: load
- name: load_pct
scaling-group-descriptor:
- name: "ubuntuvnf_autoscale"
min-instance-count: 0
max-instance-count: 3
scaling-policy:
- name: "ubuntuvdu_load_pct_above_threshold"
scaling-type: "automatic"
threshold-time: 10
cooldown-time: 180
scaling-criteria:
- name: "ubuntuvdu_load_pct_above_threshold"
scale-in-threshold: 20
scale-in-relational-operation: "LT"
scale-out-threshold: 80
scale-out-relational-operation: "GT"
vnf-monitoring-param-ref: "ubuntuvdu_load_pct"
vdu:
- vdu-id-ref: ubuntuvnfvdu1
count: 1
monitoring-param:
- id: "ubuntuvdu_users"
name: "ubuntuvdu_users"
aggregation-type: AVERAGE
vnf-metric:
vnf-metric-name-ref: "users"
- id: "ubuntuvdu_load"
name: "ubuntuvdu_load"
aggregation-type: AVERAGE
vnf-metric:
vnf-metric-name-ref: "load"
- id: "ubuntuvdu_load_pct"
name: "ubuntuvdu_load_pct"
aggregation-type: AVERAGE
vnf-metric:
vnf-metric-name-ref: "load_pct"
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment