Commit 6117a375 authored by Anton Joubert's avatar Anton Joubert
Browse files

Merge branch 'SAR-190_adr25_rename_package' into 'master'

SAR-190 Rename ska.base to ska_tango_base as per ADR-25

See merge request ska-telescope/lmc-base-classes!40
parents 93c0a5aa 3f701fbb
......@@ -26,7 +26,7 @@ ifeq ($(strip $(DOCKER_REGISTRY_HOST)),)
endif
ifeq ($(strip $(DOCKER_REGISTRY_USER)),)
DOCKER_REGISTRY_USER = tango-example
DOCKER_REGISTRY_USER = ska-telescope
endif
IMAGE=$(DOCKER_REGISTRY_HOST)/$(DOCKER_REGISTRY_USER)/$(NAME)
......@@ -53,7 +53,7 @@ pre-push:
post-push:
docker-build: .release
docker build $(DOCKER_BUILD_ARGS) -t $(IMAGE):$(VERSION) $(DOCKER_BUILD_CONTEXT) -f $(DOCKER_FILE_PATH) --build-arg DOCKER_REGISTRY_HOST=$(DOCKER_REGISTRY_HOST) --build-arg DOCKER_REGISTRY_USER=$(DOCKER_REGISTRY_USER)
docker build $(DOCKER_BUILD_ARGS) -t $(IMAGE):$(VERSION) $(DOCKER_BUILD_CONTEXT) -f $(DOCKER_FILE_PATH) --build-arg DOCKER_REGISTRY_HOST=$(DOCKER_REGISTRY_HOST) --build-arg DOCKER_REGISTRY_USER=$(DOCKER_REGISTRY_USER) --build-arg IMAGE_VERSION=$(VERSION)
@DOCKER_MAJOR=$(shell docker -v | sed -e 's/.*version //' -e 's/,.*//' | cut -d\. -f1) ; \
DOCKER_MINOR=$(shell docker -v | sed -e 's/.*version //' -e 's/,.*//' | cut -d\. -f2) ; \
if [ $$DOCKER_MAJOR -eq 1 ] && [ $$DOCKER_MINOR -lt 10 ] ; then \
......
release=0.8.1
tag=lmcbaseclasses-0.8.1
release=0.9.0
tag=ska_tango_base-0.9.0
......@@ -2,6 +2,18 @@
FROM nexus.engageska-portugal.pt/ska-docker/ska-python-buildenv:9.3.3.1 AS buildenv
FROM nexus.engageska-portugal.pt/ska-docker/ska-python-runtime:9.3.3.1 AS runtime
ARG IMAGE_VERSION=0.0.1
LABEL \
author="SKA India and SARAO and CSIRO and INAF" \
description="A set of generic base devices for SKA Telescope" \
license="BSD-3-Clause" \
registry="nexus.engageska-portugal.pt/ska-telescope/ska_tango_base" \
vendor="SKA Telescope" \
org.skatelescope.team="NCRA, Karoo, MCCS, CREAM" \
org.skatelescope.version="${IMAGE_VERSION}" \
org.skatelescope.website="https://gitlab.com/ska-telescope/ska-tango-base/"
# create ipython profile to so that itango doesn't fail if ipython hasn't run yet
RUN ipython profile create
......
#
# Project makefile for a LMC Base Classes project. You should normally only need to modify
# Project makefile for a SKA Tango Base project. You should normally only need to modify
# DOCKER_REGISTRY_USER and PROJECT below.
# Use bash shell with pipefail option enabled so that the return status of a
......@@ -13,10 +13,10 @@ SHELL = /bin/bash
# the Docker tag for this project. The definition below inherits the standard
# value for DOCKER_REGISTRY_HOST (=rnexus.engageska-portugal.pt) and overwrites
# DOCKER_REGISTRY_USER and PROJECT to give a final Docker tag of
# nexus.engageska-portugal.pt/tango-example/dishmaster
# nexus.engageska-portugal.pt/ska-telescope/ska_tango_base
#
DOCKER_REGISTRY_USER:=tango-example
PROJECT = lmcbaseclasses
DOCKER_REGISTRY_USER:=ska-telescope
PROJECT = ska_tango_base
IMAGE_FOR_DIAGRAMS = nexus.engageska-portugal.pt/ska-docker/ska-python-buildenv:9.3.3.1
#
# include makefile to pick up the standard Make targets, e.g., 'make build'
......@@ -27,16 +27,16 @@ include .make/Makefile.mk
.DEFAULT_GOAL := help
test: ## test lmcbaseclasses Python code
test: ## test ska_tango_base Python code
mkdir -p build/reports
python3 setup.py test | tee build/setup_py_test.stdout
lint: ## lint lmcbaseclasses Python code
lint: ## lint ska_tango_base Python code
python3 -m pip install -U pylint==2.4.4
python3 -m pip install pylint2junit
mkdir -p build/reports
pylint --output-format=parseable src/ska | tee build/code_analysis.stdout
pylint --output-format=pylint2junit.JunitReporter src/ska > build/reports/linting.xml
pylint --output-format=parseable src/ska_tango_base | tee build/code_analysis.stdout
pylint --output-format=pylint2junit.JunitReporter src/ska_tango_base > build/reports/linting.xml
test-in-docker: build ## Build the docker image and run tests inside it.
@docker run --rm $(IMAGE):$(VERSION) make test
......
# lmc-base-classes
# SKA Tango Base Classes and Utilities
[![Documentation Status](https://readthedocs.org/projects/lmc-base-classes/badge/?version=latest)](https://developerskatelescopeorg.readthedocs.io/projects/lmc-base-classes/en/latest/?badge=latest)
[![Documentation Status](https://readthedocs.org/projects/ska-tango-base/badge/?version=latest)](https://developerskatelescopeorg.readthedocs.io/projects/ska-tango-base/en/latest/?badge=latest)
## About
A shared repository for the Local Monitoring and Control (LMC) Base Classes. The goal is to create a Software Development Kit for the Control System of the [Square Kilometre Array](http://skatelescope.org/) (SKA) radio telescope project. The Telescope Manager provides the Central Control System and each _Element_ provides a Local Control System that all work together as the Control System for the instrument. In the SKA case _Elements_ are subsystems such as the Central Signal Processor (CSP), Science Data Processor (SDP), Dishes (DSH), Low-Frequency Apperture Array (LFAA) etc. Control is implement using the distributed control system, [TANGO](http://www.tango-controls.org), which is accessed from Python using the [PyTango](https://github.com/tango-controls/pytango) package.
A shared repository for the Local Monitoring and Control (LMC) Tango Base Classes. The goal is to create a Software Development Kit for the Control System of the [Square Kilometre Array](http://skatelescope.org/) (SKA) radio telescope project. The Telescope Manager provides the Central Control System and each _Element_ provides a Local Control System that all work together as the Control System for the instrument. In the SKA case _Elements_ are subsystems such as the Central Signal Processor (CSP), Science Data Processor (SDP), Dishes (DSH), Low-Frequency Apperture Array (LFAA) etc. Control is implement using the distributed control system, [TANGO](http://www.tango-controls.org), which is accessed from Python using the [PyTango](https://gitlab.com/tango-controls/pytango) package.
Early work in this repo was done as part of the LMC Base Classes Evolutionary Prototype (LEvPro) project, under the INDO-SA collaboration program.
The lmc-base-classe repository contains set of eight classes as mentioned in SKA Control systems guidelines. Following is the list of base classes
The ska-tango-base repository includes a set of eight classes as mentioned in SKA Control systems guidelines. Following is the list of base classes
- SKABaseDevice: This is generic class that includes common attributes, commands and properties that are required for any SKA tango device.
- SKACapability: This is generic base class for any element to provide common functionality of a capability of an SKA device.
- SKAAlarmHandler: This is the generic class meant to handle the alarms and alerts.
......@@ -25,6 +25,12 @@ The lmc-base-classe repository contains set of eight classes as mentioned in SKA
## Version History
#### 0.9.0
- Breaking change: Package rename
- Installable package name changed from `lmcbaseclasses` to `ska_tango_base`.
- Package import `ska.base` has been changed to `ska_tango_base`. For example, instead of
`from ska.base import SKABaseDevice` use `from ska_tango_base import SKABaseDevice`.
#### 0.8.1
- Fix broken docs
......@@ -125,13 +131,13 @@ than only EMPTY obsState.
No change to usage.
#### 0.5.0
- Breaking change: Major restructuring of the package to simplify imports and reduce confusion.
- Breaking change: Major restructuring of the package to simplify imports and reduce confusion.
- The single word `skabase` module has now changed to two words: `ska.base`.
- Instead of `from skabase.SKABaseDevice.SKABaseDevice import SKABaseDevice` to import the
class, just use `from ska.base import SKABaseDevice`.
class, just use `from ska.base import SKABaseDevice`.
- Instead of `skabase.control_model` use `ska.base.control_model`.
- The `SKATestDevice` was removed. Note that this class was only intended
for internal use in lmc-base-classes and is no longer needed.
for internal use and is no longer needed.
- Removed unused scripts and modules.
- Removed `TangoLoggingLevel` which was deprecated in 0.4.0. Use `ska.base.control_model.LoggingLevel`
instead.
......@@ -214,9 +220,9 @@ The requirements for testing are:
3. Run 'python3 -m pip install . --extra-index-url https://nexus.engageska-portugal.pt/repository/pypi/simple'
## Testing
The LMC base classes can be tested locally my invoking *make CI_JOB_ID=some_id test* command.
This invokes a chain of commands from the makefile which builds the lmc base classes
python package, creates a docker image with lmc base classes, instantiates separate
The project can be tested locally my invoking *make CI_JOB_ID=some_id test* command.
This invokes a chain of commands from the makefile which builds the project's
python package, creates a docker image with the project, instantiates separate
container for each of the base class and runs unit test cases of each class. Additionally,
code analysis is also done and code coverage report is prepared.
After testing is done, the containers are taken down.
......@@ -429,7 +435,7 @@ to the Tango Logging Service:
### Where are the logs from the admin device (dserver)?
PyTango is wrapper around the C++ Tango library, and the admin device is implemented in C++.
PyTango is wrapper around the C++ Tango library, and the admin device is implemented in C++.
The admin device does not inherit from the SKABaseDevice and we cannot override its behaviour
from the Python layer. Its logs can only be seen by configuring the TLS appropriately.
......@@ -472,10 +478,10 @@ In future, it would be useful to override the property with the command line opt
### PyCharm
The Docker integration is recommended. For development, use the
`nexus.engageska-portugal.pt/tango-example/lmcbaseclasses:latest` image
`nexus.engageska-portugal.pt/ska-telescope/ska_tango_base:latest` image
as the Python Interpreter for the project. Note that if `make` is
run with targets like `build`, `up`, or `test`, that image will be
rebuilt by Docker using the local code, and tagged as `latest`.
rebuilt by Docker using the local code, and tagged as `latest`.
As this project uses a `src` [folder structure](https://blog.ionelmc.ro/2014/05/25/python-packaging/#the-structure),
so under _Preferences > Project Structure_, the `src` folder needs to be marked as "Sources". That will
......@@ -484,7 +490,7 @@ When adding Run/Debug configurations, make sure "Add content roots to PYTHONPATH
"Add source roots to PYTHONPATH" are checked.
## Docs
- Online: [Read The Docs](https://developerskatelescopeorg.readthedocs.io/projects/lmc-base-classes/en/latest)
- Online: [Read The Docs](https://developerskatelescopeorg.readthedocs.io/projects/ska-tango-base/en/latest)
- SKA Control System guidelines: [Google docs folder](https://drive.google.com/drive/folders/0B8fhAW5QnZQWQ2ZlcjhVS0NmRms)
- Old LEvPro work area: [Google docs folder](https://drive.google.com/drive/folders/0B8fhAW5QnZQWVHVFVGVXT2Via28)
......
......@@ -85,17 +85,17 @@ qthelp:
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/LMCBaseClasses.qhcp"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/SKA_TangoBase.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/LMCBaseClasses.qhc"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/SKA_TangoBase.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/LMCBaseClasses"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/LMCBaseClasses"
@echo "# mkdir -p $$HOME/.local/share/devhelp/SKA_TangoBase"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/SKA_TangoBase"
@echo "# devhelp"
epub:
......
......@@ -5,7 +5,7 @@ SKA Commands
.. toctree::
:maxdepth: 2
.. automodule:: ska.base.commands
.. automodule:: ska_tango_base.commands
:members:
:undoc-members:
.. LMC Base Classes documentation master file, created by
.. SKA Tango Base documentation master file, created by
sphinx-quickstart on Fri Jan 11 10:03:42 2019.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
......@@ -9,7 +9,7 @@ SKA Control Model
.. toctree::
:maxdepth: 2
.. automodule:: ska.base.control_model
.. automodule:: ska_tango_base.control_model
:members:
:undoc-members:
.. LMC Base Classes documentation master file, created by
.. SKA Tango Base documentation master file, created by
sphinx-quickstart on Fri Jan 11 10:03:42 2019.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
......@@ -10,7 +10,7 @@ This module implements a general Master device for a CSP Sub-element.
.. toctree::
:maxdepth: 2
.. automodule:: ska.base.csp_subelement_master
.. autoclass:: ska.base.CspSubElementMaster
.. automodule:: ska_tango_base.csp_subelement_master
.. autoclass:: ska_tango_base.CspSubElementMaster
:members:
:undoc-members:
.. LMC Base Classes documentation master file, created by
.. SKA Tango Base documentation master file, created by
sphinx-quickstart on Fri Jan 11 10:03:42 2019.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
......@@ -13,8 +13,8 @@ SKA CSP Sub-element ObsDevice
.. toctree::
:maxdepth: 2
.. automodule:: ska.base.csp_subelement_obsdevice
.. autoclass:: ska.base.CspSubElementObsDevice
.. automodule:: ska_tango_base.csp_subelement_obsdevice
.. autoclass:: ska_tango_base.CspSubElementObsDevice
:members:
:undoc-members:
......@@ -27,9 +27,9 @@ Here it is reported the list of the *instance attributes*. |br|
The scan ID is passed as argument of the *Scan* command. |br|
The attribute value is reported via TANGO attribute *scanID*.
* ``_sdp_addresses``: a python dictionary with the SDP destination addresses for the output
* ``_sdp_addresses``: a python dictionary with the SDP destination addresses for the output
products. |br|
Depending on the sub-element (CBF, PSS, PST) this attribute can specify more than one destination address,
Depending on the sub-element (CBF, PSS, PST) this attribute can specify more than one destination address,
as for example in CBF sub-element. |br|
The SDP destination addresses are specified at configuration.
An SDP address specifies the MAC address, IP address and port of the endpoint. |br|
......@@ -44,7 +44,7 @@ Here it is reported the list of the *instance attributes*. |br|
}
The value of this attribute is reported via the TANGO *sdpDestionationAddresses* attribute.
.. note:: Not all the Sub-element observing devices are connected to the SDP (for example Mid VCCs).
......@@ -53,12 +53,12 @@ Here it is reported the list of the *instance attributes*. |br|
* ``_sdp_links_capacity``: this attribute records the capacity in GB/s of the SDP link.
* ``_config_id``: it stores the unique identificator associated to a JSON scan configuration. |br|
* ``_config_id``: it stores the unique identificator associated to a JSON scan configuration. |br|
The value of this attribute is reported via the TANGO attriute *configID*.
* ``_last_scan_configuration``: this attribute stores the last configuration successully programmed. |br|
The value is reported via the TANGO attribute *lastScanConfiguration*.
* ``_health_failure_msg``:
* ``_health_failure_msg``:
The value is reported via the TANGO attribute *healthFailureMesssage*.
.. LMC Base Classes documentation master file, created by
.. SKA Tango Base documentation master file, created by
sphinx-quickstart on Fri Jan 11 10:03:42 2019.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
......@@ -6,14 +6,14 @@
SKA CSP Sub-element Subarray
============================================
This module implements a generic Subarray device for a CSP Sub-element.
The scope of this module is to provide a uniform access to a CSP Sub-element
The scope of this module is to provide a uniform access to a CSP Sub-element
subarray from the CSP.LMC side.
.. toctree::
:maxdepth: 2
.. automodule:: ska.base.csp_subelement_subarray
.. autoclass:: ska.base.CspSubElementSubarray
.. automodule:: ska_tango_base.csp_subelement_subarray
.. autoclass:: ska_tango_base.CspSubElementSubarray
:members:
:undoc-members:
.. LMC Base Classes documentation master file, created by
.. SKA Tango Base documentation master file, created by
sphinx-quickstart on Fri Jan 11 10:03:42 2019.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
......@@ -9,7 +9,7 @@ SKA AlarmHandler
.. toctree::
:maxdepth: 2
.. automodule:: ska.base.alarm_handler_device
.. autoclass:: ska.base.SKAAlarmHandler
.. automodule:: ska_tango_base.alarm_handler_device
.. autoclass:: ska_tango_base.SKAAlarmHandler
:members:
:undoc-members:
.. LMC Base Classes documentation master file, created by
.. SKA Tango Base documentation master file, created by
sphinx-quickstart on Fri Jan 11 10:03:42 2019.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
......@@ -9,12 +9,12 @@ SKA BaseDevice
.. toctree::
:maxdepth: 2
.. automodule:: ska.base.base_device
.. automodule:: ska_tango_base.base_device
.. autoclass:: ska.base.DeviceStateModel
.. autoclass:: ska_tango_base.DeviceStateModel
:members:
:undoc-members:
.. autoclass:: ska.base.SKABaseDevice
.. autoclass:: ska_tango_base.SKABaseDevice
:members:
:undoc-members:
.. LMC Base Classes documentation master file, created by
.. SKA Tango Base documentation master file, created by
sphinx-quickstart on Fri Jan 11 10:03:42 2019.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
......@@ -9,7 +9,7 @@ SKA Capability
.. toctree::
:maxdepth: 2
.. automodule:: ska.base.capability_device
.. autoclass:: ska.base.SKACapability
.. automodule:: ska_tango_base.capability_device
.. autoclass:: ska_tango_base.SKACapability
:members:
:undoc-members:
.. LMC Base Classes documentation master file, created by
.. SKA Tango Base documentation master file, created by
sphinx-quickstart on Fri Jan 11 10:03:42 2019.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
......@@ -9,7 +9,7 @@ SKA Logger
.. toctree::
:maxdepth: 2
.. automodule:: ska.base.logger_device
.. autoclass:: ska.base.SKALogger
.. automodule:: ska_tango_base.logger_device
.. autoclass:: ska_tango_base.SKALogger
:members:
:undoc-members:
.. LMC Base Classes documentation master file, created by
.. SKA Tango Base documentation master file, created by
sphinx-quickstart on Fri Jan 11 10:03:42 2019.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
......@@ -9,7 +9,7 @@ SKA Master
.. toctree::
:maxdepth: 2
.. automodule:: ska.base.master_device
.. autoclass:: ska.base.SKAMaster
.. automodule:: ska_tango_base.master_device
.. autoclass:: ska_tango_base.SKAMaster
:members:
:undoc-members:
.. LMC Base Classes documentation master file, created by
.. SKA Tango Base documentation master file, created by
sphinx-quickstart on Fri Jan 11 10:03:42 2019.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
......@@ -9,7 +9,7 @@ SKA ObsDevice
.. toctree::
:maxdepth: 2
.. automodule:: ska.base.obs_device
.. autoclass:: ska.base.SKAObsDevice
.. automodule:: ska_tango_base.obs_device
.. autoclass:: ska_tango_base.SKAObsDevice
:members:
:undoc-members:
.. LMC Base Classes documentation master file, created by
.. SKA Tango Base documentation master file, created by
sphinx-quickstart on Fri Jan 11 10:03:42 2019.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
......@@ -9,7 +9,7 @@ SKA Subarray
.. toctree::
:maxdepth: 2
.. automodule:: ska.base.subarray_device
.. autoclass:: ska.base.SKASubarray
.. automodule:: ska_tango_base.subarray_device
.. autoclass:: ska_tango_base.SKASubarray
:members:
:undoc-members:
.. LMC Base Classes documentation master file, created by
.. SKA Tango Base documentation master file, created by
sphinx-quickstart on Fri Jan 11 10:03:42 2019.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
......@@ -9,7 +9,7 @@ SKA TelState
.. toctree::
:maxdepth: 2
.. automodule:: ska.base.tel_state_device
.. autoclass:: ska.base.SKATelState
.. automodule:: ska_tango_base.tel_state_device
.. autoclass:: ska_tango_base.SKATelState
:members:
:undoc-members:
......@@ -99,7 +99,7 @@ state state machine by
* three extra states: INIT_ADMIN, FAULT_ADMIN and DISABLED_ADMIN
* two extra transition triggers: "admin_on" and "admin_off", which allow
for transition between INIT and INIT_ADMIN; FAULT and FAULT_ADMIN; and
DISABLE and DISABLE_ADMIN.
DISABLE and DISABLE_ADMIN.
This implementation minimises the coupling between admin mode and
operational state, allowing the two machines to be conceptualised almost
......@@ -133,7 +133,7 @@ observations (currently only subarray devices).
:width: 80%
:alt: Diagram of the observation state machine, as decided and
published in ADR-8.
Diagram of the observation state machine, as decided and published in
ADR-8.
......@@ -142,7 +142,7 @@ observations (currently only subarray devices).
:width: 80%
:alt: Diagram of the observation state machine, automatically
generated from the implementation
Diagram of the observation state machine, automatically generated from
the implementation. The equivalance of this diagram to the diagram
previous demonstrates that the machine has been implemented in
......@@ -153,14 +153,14 @@ CSP SubElement ObsDevice state machine
This state machine is implemented for the CSP SubElement devices, different
from the subarrays, that manage observations.
Compared to the SKA Observation State Machine, it implements a smaller number
Compared to the SKA Observation State Machine, it implements a smaller number
of states, number that can be further descreased depending on the necessities of the different
sub-elements.
The implemented states for the current state machine are:
* IDLE: this is the observing state after the device intialization.
* CONFIGURING: transitional state to report the device configuration is in progress.
* CONFIGURING: transitional state to report the device configuration is in progress.
*Need to understand if this state is really required by the observing devices of any
CSP sub-element.*
* READY: the device is configured and is ready to perform observations
......@@ -168,7 +168,7 @@ The implemented states for the current state machine are:
* ABORTING: the device is processing an abort.
Need to understand if this state is really required by the observing devices of any
CSP sub-element.
* ABORTED: the device has completed the abort request.
* ABORTED: the device has completed the abort request.
* FAULT: the device has experienced an error from which it can be recovered only via
manual intervention invoking a reset command that force the device to the base
state (IDLE).
......@@ -184,7 +184,7 @@ The implemented states for the current state machine are:
API
---
.. automodule:: ska.base.state_machine
.. automodule:: ska_tango_base.state_machine
:members:
:undoc-members:
......@@ -197,7 +197,7 @@ API
.. autoclass:: ObservationStateMachine
:members:
.. automodule:: ska.base.csp_subelement_state_machine
.. automodule:: ska_tango_base.csp_subelement_state_machine
:members:
:undoc-members:
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment