Skip to content
Snippets Groups Projects
Commit 42660e4a authored by Mark Beierl's avatar Mark Beierl
Browse files

Merge branch 'beierlm-virtual-pc' into 'master'

Virtual PC Descriptor

See merge request !118

(cherry picked from commit 74517831)

93f1539f Virtual PC Descriptor
a3376cdc Update hackfest_virtual-pc_vnfd/virtual-pc_vnfd.yaml
15bccf2b Deleted hackfest_virtual-pc_vnfd/charms/virtual-pc/hooks/install,...
5074ce34 Adding built charm
4e56134b Virtual PC NS Descriptor
a7fcf52d Fix no indicators on virtual-pc charm
a819702e Merge branch 'fix-virtual-pc-no-indicators' into 'beierlm-virtual-pc'
parent 6f202ff8
No related branches found
No related tags found
1 merge request!130Virtual PC for Hackfest
Pipeline #250 passed with stage
in 1 minute and 32 seconds
Showing
with 421 additions and 0 deletions
# Copyright 2020 ETSI OSM Contributors
# See LICENSE file for licensing details.
#
# This is only an example, and you should edit to suit your needs.
# If you don't need actions, you can remove the file entirely.
# It ties in to the example _on_fortune_action handler in src/charm.py
# Copyright 2020 ETSI OSM Contributors
# See LICENSE file for licensing details.
#
# This is only an example, and you should edit to suit your needs.
# If you don't need config, you can remove the file entirely.
options:
#!/bin/sh
JUJU_DISPATCH_PATH="${JUJU_DISPATCH_PATH:-$0}" PYTHONPATH=lib:venv ./src/charm.py
../dispatch
\ No newline at end of file
../dispatch
\ No newline at end of file
../dispatch
\ No newline at end of file
# Copyright 2020 David Garcia
# See LICENSE file for licensing details.
name: virtual-pc
description: |
TODO: fill out the charm's description
summary: |
TODO: fill out the charm's summary
series:
- focal
-r requirements.txt
flake8
charmcraft
\ No newline at end of file
ops
#!/bin/sh -e
# Copyright 2020 David Garcia
# See LICENSE file for licensing details.
if [ -z "$VIRTUAL_ENV" -a -d venv/ ]; then
. venv/bin/activate
fi
if [ -z "$PYTHONPATH" ]; then
export PYTHONPATH=src
else
export PYTHONPATH="src:$PYTHONPATH"
fi
flake8
python3 -m unittest -v "$@"
#!/usr/bin/env python3
# Copyright 2020 David Garcia
# See LICENSE file for licensing details.
from apt.progress.base import InstallProgress
import logging
import os
import shutil
from jinja2 import Template
from ops.charm import CharmBase
from ops.framework import StoredState
from ops.main import main
from ops.model import (
MaintenanceStatus,
ActiveStatus,
# BlockedStatus,
)
from utils import (
service_stop,
service_restart,
install_apt,
shell,
)
# from typing import Dict, Any
logger = logging.getLogger(__name__)
APT_REQUIREMENTS = [
"firefox",
"mate-desktop", # 469 packages
"mate-applets",
"mate-applet-brisk-menu",
"mate-indicator-applet",
"mate-session-manager",
"indicator-applet-session",
"mate-terminal",
"xrdp",
]
SNAP_INSTALLS = [
"code --classic",
]
POLKIT_TEMPLATE = "./templates/color.pkla"
POLKIT_PATH = "/etc/polkit-1/localauthority/50-local.d/color.pkla"
STARTWM_TEMPLATE = "./templates/startwm.sh"
STARTWM_PATH = "/etc/xrdp/startwm.sh"
# WM_COMMAND = "startxfce4" # xubuntu-desktop
# WM_COMMAND = "budgie-desktop" # budgie-desktop-environment
WM_COMMAND = "mate-session" # mate-desktop
class VirtualPCCharm(CharmBase, InstallProgress):
_stored = StoredState()
def __init__(self, *args):
super().__init__(*args)
InstallProgress.__init__(self)
self._stored.set_default()
# Basic hooks
self.framework.observe(self.on.install, self._on_install)
self.framework.observe(self.on.start, self._on_start)
self.framework.observe(self.on.stop, self._on_stop)
self.framework.observe(self.on.config_changed, self._on_config_changed)
self.framework.observe(self.on.update_status, self._on_update_status)
# Actions hooks
# Relations hooks
# Override InstallProgress to update our status
def status_change(self, pkg, percent, status):
message = str(int(percent)) + "% " + status
self.unit.status = MaintenanceStatus(message)
# Basic hooks
def _on_install(self, _):
self.unit.status = MaintenanceStatus("Installing apt packages")
install_apt(packages=APT_REQUIREMENTS, update=True, progress=self)
service_stop('xrdp')
self.unit.status = MaintenanceStatus("Installing snaps")
for snap in SNAP_INSTALLS:
shell("sudo snap install " + snap)
self.unit.status = MaintenanceStatus("Setting default display manager")
shell("echo /usr/sbin/lightdm | sudo tee /etc/X11/default-display-manager")
self.unit.status = MaintenanceStatus("Adding XRDP to ssl-cert group")
shell("sudo adduser xrdp ssl-cert")
self.unit.status = MaintenanceStatus("Generating Window Manager startup script")
with open(STARTWM_TEMPLATE, "r") as template:
content = Template(template.read()).render(command=WM_COMMAND)
with open(STARTWM_PATH, "w") as startwm:
startwm.write(content)
self.unit.status = MaintenanceStatus("Generating Polkit files")
with open(POLKIT_TEMPLATE, "r") as template:
content = Template(template.read()).render()
with open(POLKIT_PATH, "w") as polkit:
polkit.write(content)
self._stored.installed = True
def _on_start(self, _):
self.unit.status = MaintenanceStatus("Starting XRDP server")
service_restart('xrdp')
self._stored.started = True
self.unit.status = self._get_current_status()
def _on_stop(self, _):
service_stop('xrdp')
self._stored.started = False
self.unit.status = self._get_current_status()
def _on_config_changed(self, _):
self.unit.status = self._get_current_status()
def _on_update_status(self, _):
self.unit.status = self._get_current_status()
# Action hooks
# Relation hooks
# Private functions
def _get_current_status(self):
status_type = ActiveStatus
status_msg = ""
if self._stored.installed:
status_msg = "Ready"
return status_type(status_msg)
if __name__ == "__main__":
main(VirtualPCCharm)
from apt.progress.base import InstallProgress
from utils import (
install_apt,
)
class Progress(InstallProgress):
def status_change(self, pkg, percent, status):
print("status change\n")
#print(str(int(percent)) + "% \n")
True
if __name__ == "__main__":
install_apt(packages=["mate-backgrounds"], update=True, progress=Progress())
import apt
from apt.progress.base import OpProgress
import shutil
import subprocess
from typing import Dict, List, NoReturn
def service_active(service_name: str):
result = subprocess.run(
["systemctl", "is-active", service_name],
stdout=subprocess.PIPE,
encoding="utf-8",
)
return result.stdout == "active\n"
def all_values_set(dictionary: Dict[str, str]) -> bool:
return not any(v is None for v in dictionary.values())
def install_apt(packages: List, update: bool = False, progress=None) -> NoReturn:
cache = apt.cache.Cache()
if update:
cache.update()
cache.open()
for package in packages:
pkg = cache[package]
if not pkg.is_installed:
pkg.mark_install()
cache.commit(install_progress=progress)
def remove_apt(packages: List, update: bool = False) -> NoReturn:
cache = apt.cache.Cache()
if update:
cache.update()
cache.open()
for package in packages:
pkg = cache[package]
if not pkg.is_installed:
pkg.mark_delete()
cache.commit()
def shell(command: str) -> NoReturn:
subprocess.run(command, shell=True).check_returncode()
def copy_files(origin: Dict[str, str], destination: Dict[str, str]) -> NoReturn:
for config, origin_path in origin.items():
destination_path = destination[config]
shutil.copy(origin_path, destination_path)
# Service functions
def _systemctl(action: str, service_name: str) -> NoReturn:
subprocess.run(["systemctl", action, service_name]).check_returncode()
def service_start(service_name: str) -> NoReturn:
_systemctl("start", service_name)
def service_restart(service_name: str) -> NoReturn:
_systemctl("restart", service_name)
def service_stop(service_name: str) -> NoReturn:
_systemctl("stop", service_name)
def service_enable(service_name: str) -> NoReturn:
_systemctl("enable", service_name)
def systemctl_daemon_reload():
subprocess.run(["systemctl", "daemon-reload"]).check_returncode()
[Allow colord for all users]
Identity=unix-user:*
Action=org.freedesktop.color-manager.create-device;org.freedesktop.color-manager.create-profile;org.freedesktop.color-manager.delete-device;org.freedesktop.color-manager.delete-profile;org.freedesktop.color-manager.modify-device;org.freedesktop.color-manager.modify-profile
ResultAny=yes
ResultInactive=yes
ResultActive=yes
\ No newline at end of file
#!/bin/sh
# xrdp X session start script (c) 2015, 2017 mirabilos
# published under The MirOS Licence
if test -r /etc/profile; then
. /etc/profile
fi
if test -r /etc/default/locale; then
. /etc/default/locale
test -z "${LANG+x}" || export LANG
test -z "${LANGUAGE+x}" || export LANGUAGE
test -z "${LC_ADDRESS+x}" || export LC_ADDRESS
test -z "${LC_ALL+x}" || export LC_ALL
test -z "${LC_COLLATE+x}" || export LC_COLLATE
test -z "${LC_CTYPE+x}" || export LC_CTYPE
test -z "${LC_IDENTIFICATION+x}" || export LC_IDENTIFICATION
test -z "${LC_MEASUREMENT+x}" || export LC_MEASUREMENT
test -z "${LC_MESSAGES+x}" || export LC_MESSAGES
test -z "${LC_MONETARY+x}" || export LC_MONETARY
test -z "${LC_NAME+x}" || export LC_NAME
test -z "${LC_NUMERIC+x}" || export LC_NUMERIC
test -z "${LC_PAPER+x}" || export LC_PAPER
test -z "${LC_TELEPHONE+x}" || export LC_TELEPHONE
test -z "${LC_TIME+x}" || export LC_TIME
test -z "${LOCPATH+x}" || export LOCPATH
fi
if test -r /etc/profile; then
. /etc/profile
fi
{{ command }}
# Copyright 2020 David Garcia
# See LICENSE file for licensing details.
import unittest
from unittest.mock import Mock
from ops.testing import Harness
from charm import SrsLteCharm
class TestCharm(unittest.TestCase):
def test_config_changed(self):
harness = Harness(SrsLteCharm)
self.addCleanup(harness.cleanup)
harness.begin()
self.assertEqual(list(harness.charm._stored.things), [])
harness.update_config({"thing": "foo"})
self.assertEqual(list(harness.charm._stored.things), ["foo"])
def test_action(self):
harness = Harness(SrsLteCharm)
harness.begin()
# the harness doesn't (yet!) help much with actions themselves
action_event = Mock(params={"fail": ""})
harness.charm._on_fortune_action(action_event)
self.assertTrue(action_event.set_results.called)
def test_action_fail(self):
harness = Harness(SrsLteCharm)
harness.begin()
action_event = Mock(params={"fail": "fail this"})
harness.charm._on_fortune_action(action_event)
self.assertEqual(action_event.fail.call_args, [("fail this",)])
Copyright (c) 2017-2021 Ingy döt Net
Copyright (c) 2006-2016 Kirill Simonov
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Metadata-Version: 2.1
Name: PyYAML
Version: 5.4.1
Summary: YAML parser and emitter for Python
Home-page: https://pyyaml.org/
Author: Kirill Simonov
Author-email: xi@resolvent.net
License: MIT
Download-URL: https://pypi.org/project/PyYAML/
Project-URL: Bug Tracker, https://github.com/yaml/pyyaml/issues
Project-URL: CI, https://github.com/yaml/pyyaml/actions
Project-URL: Documentation, https://pyyaml.org/wiki/PyYAMLDocumentation
Project-URL: Mailing lists, http://lists.sourceforge.net/lists/listinfo/yaml-core
Project-URL: Source Code, https://github.com/yaml/pyyaml
Platform: Any
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Cython
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Text Processing :: Markup
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*
YAML is a data serialization format designed for human readability
and interaction with scripting languages. PyYAML is a YAML parser
and emitter for Python.
PyYAML features a complete YAML 1.1 parser, Unicode support, pickle
support, capable extension API, and sensible error messages. PyYAML
supports standard YAML tags and provides Python-specific tags that
allow to represent an arbitrary Python object.
PyYAML is applicable for a broad range of tasks from complex
configuration files to object serialization and persistence.
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