Compare commits

..

69 Commits

Author SHA1 Message Date
62700f65e1 rewrite db adapter to use single execute() method 2018-12-10 03:09:00 +03:00
57fdb62a5c impl paratemers to requests, impl support of task modifications 2018-03-26 00:13:20 +03:00
9f57f9db88 try to use params (broken) 2018-03-25 01:03:03 +03:00
ba9a1c5cdd use 100 symbols (2) 2018-01-06 17:12:23 +03:00
2b885ebee5 use 100 symbols 2018-01-06 17:10:28 +03:00
4f9e3d6639 implement support of new commands to clients 2017-11-30 02:23:39 +03:00
5f229b8ade implement support of plugin supinfo 2017-11-27 23:12:37 +03:00
9dd63fc77e do not allow get user and task properties w\o auth 2017-11-26 15:30:59 +03:00
bb0a3c43be implement auth for get option methods to hide sensetive settings 2017-11-24 11:24:04 +03:00
bfea1635f9 implement priority supprt for users 2017-11-24 09:33:10 +03:00
881abd4c51 some improvements
* add plugin tree
* add emailnotify plugin template
2017-11-17 00:28:15 +03:00
3717d1426e implement usage of native cgroups instead of systemd-run
* allow server to be started w\o daemon
* handle process childs
2017-11-10 01:33:23 +03:00
2bd72344ba Pretty result usage, try to split Core class to several 2017-10-28 12:28:05 +03:00
bdb1dd0101 massive api changes: replace public method results to Result<T, E> 2017-10-27 02:35:04 +03:00
de0653f038 add ability to reload without reinitialization 2017-10-13 23:13:00 +03:00
0d5e9a328e add cgadaptor template 2017-10-06 10:11:19 +03:00
49299af761 code cleanup 2017-09-14 23:21:44 +03:00
cdb05844ae small renaming 2017-09-13 02:02:51 +03:00
f68d607da8 merge changes 2017-04-10 00:25:29 +03:00
f56c937651 more actions, improve process manager, fix bugs with datetime in dbus response 2017-04-10 00:21:37 +03:00
baa20af363 some improvements 2017-04-07 00:28:49 +03:00
e0833f22a5 some server implementations 2017-04-06 03:27:20 +03:00
80689782de some server template improvements 2017-04-05 02:41:04 +03:00
511de6e2d0 add server proto 2017-03-29 03:46:42 +03:00
505c1e2b93 fix merge conflicts 2017-03-24 19:03:51 +03:00
793d833d55 add plugin interaction 2017-03-23 23:11:05 +03:00
5f52ae9b05 implement work with plugins 2017-03-21 01:03:02 +03:00
3ed3973f4d add cmake adds 2017-03-20 03:29:44 +03:00
9094e6f450 add some reports 2017-03-17 02:30:17 +03:00
69fbab45b2 more improvements of queuedctl 2017-03-16 01:58:50 +03:00
f59095dbb0 add task helper 2017-03-15 02:31:25 +03:00
9931204837 some work on queuedctl 2017-03-14 05:51:53 +03:00
80c6f977d7 start on queuedctl realization 2017-03-13 03:37:52 +03:00
a2872e7c23 add sighup catch to daemon 2017-03-12 05:15:40 +03:00
8031e60355 add debug information 2017-03-12 04:54:31 +03:00
b5839051e9 add interface adaptor 2017-03-12 04:34:03 +03:00
b1821507dc doxygen fixes 2017-03-11 06:30:09 +03:00
57281bbb88 massive fixes in logic 2017-03-11 05:27:54 +03:00
9000bf08a4 add proto for task run 2017-03-10 07:28:51 +03:00
2d8d501f02 integrate plugin engine 2017-03-10 06:38:54 +03:00
d177aa81af add template for plugin system 2017-03-09 04:07:01 +03:00
01d5d99e16 forgotten fixes 2017-03-08 05:44:59 +03:00
2701e44119 add control processes and so on 2017-03-08 05:33:52 +03:00
20578996b7 add DATABASE_VERSION field for future migrations if any 2017-03-07 01:50:51 +03:00
bd62bc8777 improve settings and limits 2017-03-06 00:07:01 +03:00
84b8632ae8 add demo application 2017-03-05 03:20:09 +03:00
6646400027 replace unsigned int to uint, add coreinterface class 2017-03-02 22:01:04 +03:00
de3d7c10c3 add authorization structure to core methods 2017-03-01 23:12:17 +03:00
dc46039a53 change doxygen configuration a bit 2017-02-28 00:32:40 +03:00
58787dc543 Library code changes
* change documenting to better l&f
* add custom exceptions header
* QueuedCore::init will now throw exception on library opening error
* add database cleanup functions
* use sql query to filter data b4 upload to workers
* add custom auth structure
2017-02-28 00:22:56 +03:00
8ab4eb155c core and processanager improvements 2017-02-27 00:40:37 +03:00
c2b92cd212 some limit improvements 2017-02-26 05:00:48 +03:00
5e9b2ad190 start working on QueuedCore 2017-02-25 17:09:54 +03:00
aa527d2975 add token and settigns managers 2017-02-24 15:35:27 +03:00
6ad0731a4a add user class, some improvements inside 2017-02-23 04:10:08 +03:00
74c7855713 more pretty schema control 2017-02-22 04:09:08 +03:00
8261f610f7 add database manager 2017-02-21 02:15:48 +03:00
6bc4668271 start working on C++ implementation 2017-02-20 03:09:21 +03:00
arcan1s
f745595174 readme update 2014-10-28 05:25:27 +03:00
arcan1s
293c8546b4 Edited readme 2013-12-24 00:51:54 +04:00
arcan1s
9f465170fe Edited readme 2013-12-24 00:44:34 +04:00
arcan1s
051e6df16b Release 1.2.0
+ edited man page and readme
2013-12-24 00:42:25 +04:00
arcan1s
74a95a57e5 Added add_queued 2013-12-24 00:38:40 +04:00
arcan1s
345dfd574f Added license to readme 2013-12-23 23:41:43 +04:00
arcan1s
9141a1fc12 Release 1.1.0
* edited install script
* edited README
+ added license
2013-12-23 23:39:07 +04:00
arcan1s
4a002e0d8b Added mans, edited readme 2013-12-23 23:09:51 +04:00
arcan1s
f11944394f Changes in daemon
* changes in cmd parametrs
* some refactoring
+ added sleeptime parametr
- bug with pgrep
2013-12-23 22:15:23 +04:00
arcan1s
d0672e76ce Added install scripts 2013-12-23 12:20:01 +04:00
arcan1s
c50b0a1bcd Prerelease 1.1.0
* fix bug with moving root (ooops)
* changes in work
2013-12-23 04:39:08 +04:00
151 changed files with 19610 additions and 921 deletions

47
.gitignore vendored Normal file
View File

@ -0,0 +1,47 @@
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
# cmake
CMakeCache.txt
CMakeFiles
CMakeScripts
Makefile
cmake_install.cmake
install_manifest.txt
# build directory
build
# archives
*src.tar.[gx]z
*pkg.tar.[gx]z
*.deb
# clion settings
.idea

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "sources/3rdparty/result"]
path = sources/3rdparty/result
url = https://github.com/arcan1s/result.git

695
COPYING
View File

@ -1,674 +1,21 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
queued
Copyright (C) 2013 Evgeniy Alekseev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
queued Copyright (C) 2013 Evgeniy Alekseev
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
MIT License
Copyright (c) 2016 Evgeniy Alekseev
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.

View File

@ -1,26 +0,0 @@
# Author: Evgeniy "arcanis" Alexeev <esalexeev@gmail.com>
# Maintainer: Evgeniy "arcanis" Alexeev <esalexeev@gmail.com>
pkgname=queued
pkgver=1.0.0
pkgrel=1
pkgdesc="Daemon for starting jobs to queue of calculations"
arch=('any')
url="https://github.com/arcan1s/queued"
license=("GPL")
makedeps=('git')
source=(https://github.com/arcan1s/queued/releases/download/V.${pkgver}/${pkgname}-${pkgver}.tar.xz)
md5sums=('d93c8cf20804b07b47645b0c43d45d3d')
backup=('etc/queued.conf')
package()
{
# daemon
install -D -m755 "${srcdir}/${pkgname}/usr/bin/queued" "${pkgdir}/usr/bin/queued"
# service
install -D -m644 "${srcdir}/${pkgname}/usr/lib/systemd/system/queued.service" \
"${pkgdir}/usr/lib/systemd/system/queued.service"
install -D -m644 "${srcdir}/${pkgname}/etc/queued.conf" \
"${pkgdir}/etc/queued.conf"
}

View File

@ -3,44 +3,72 @@ queued
Information
-----------
Daemon for starting jobs to queue of calculations. To start deamon just run `systemctl start queued` as root.
License
-------
GPLv3
help message
------------
queued [ -jd | --jobdir /var/lib/queued/job ] [ --priority 0 ] [ -q | --queuefile /var/lib/queued/queue ] [ -u | --user root ] [ -wd | --workdir /var/lib/queued/work ] [-v | --version ] [ -h | --help ]
Parametrs:
-jd --jobdir PATH - path to job directory. Default is '/var/lib/queued/job'
--priority NUM - defalut priority. Default is '0'
-q --queuefile PATH - path to queue file. Default is '/var/lib/queued/queue'
-u --user USERNAME - start jobs by user. Default is 'root'
-wd --workdir PATH - path to work directory. Default is '/var/lib/queued/work'
-v --version - show version and exit
-h --help - show this help and exit
* queued:
queued [ -c /etc/queued.conf ] [ -v | --version ] [ -h | --help ]
Parametrs:
-c PATH - path to configuration file. Default is `/etc/queued.conf`
-v --version - show version and exit
-h --help - show this help and exit
* add_queued:
add_queued [ -c /etc/queued.conf ] [ -p NUM ] [ -u USER ] [ -h | --help ] /path/to/script
Parameters:
-c PATH - path to configuration file. Default is '/etc/queued.conf'
-p NUM - job priority
-u USER - username
-h --help - show this help and exit
Configuration
-------------
All settings are stored in `/etc/queued.conf`. After edit them you must restart daemon (`systemctl restart queued`).
How-to run jobs
---------------
* create shell script with the command (it have a name `script.sh` for example)
* create priority file (`script.sh.pr`) with the job priority if it is needed
* create user file (`script.sh.user`) with the job username if it is needed
* copy files to `$WORKDIR`
Also you may use `add_queued`.
See also
--------
man 1 queued
man 1 add_queued
man 5 queued.conf
Instruction
===========
Dependencies
------------
* bash (sed, awk, etc)
* systemd
Installation
------------
* download sources
* copy source to `/`:
sudo cp ../queued/* /
* download sources
* run `install.sh` from source directory:
cd queued
sudo ./install.sh "/path/to/root"

Binary file not shown.

66
sources/.clang-format Normal file
View File

@ -0,0 +1,66 @@
---
Language: Cpp
AccessModifierOffset: -4
AlignAfterOpenBracket: true
AlignConsecutiveAssignments: false
AlignEscapedNewlinesLeft: false
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
BreakBeforeBinaryOperators: All
BreakBeforeBraces: Linux
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: true
ColumnLimit: 100
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IndentCaseLabels: false
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 2
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 8
UseTab: Never
...

1
sources/3rdparty/result vendored Submodule

@ -0,0 +1 @@
Subproject commit f1247cd01093f90dd57f581a4b0d778bf82020cd

63
sources/CMakeLists.txt Normal file
View File

@ -0,0 +1,63 @@
cmake_minimum_required(VERSION 2.8.12)
# some fucking magic
cmake_policy(SET CMP0011 NEW)
cmake_policy(SET CMP0015 NEW)
if (POLICY CMP0063)
cmake_policy(SET CMP0063 OLD)
endif ()
project(queued)
set(PROJECT_AUTHOR "Queued team")
set(PROJECT_CONTACT "esalexeev@gmail.com")
set(PROJECT_LICENSE "MIT")
set(PROJECT_VERSION_MAJOR "0")
set(PROJECT_VERSION_MINOR "9")
set(PROJECT_VERSION_PATCH "0")
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
# append git version if any
set(PROJECT_COMMIT_SHA "Commit hash" CACHE INTERNAL "")
include(checkgit.cmake)
string(TIMESTAMP CURRENT_DATE "%Y-%m-%d %H:%M" UTC)
string(TIMESTAMP CURRENT_YEAR "%Y")
message(STATUS "Project: ${PROJECT_NAME}")
message(STATUS "Version: ${PROJECT_VERSION}")
message(STATUS "Build date: ${CURRENT_DATE}")
# components
option(BUILD_PLUGINS "Build plugins" ON)
option(BUILD_DEB_PACKAGE "Build deb package" OFF)
option(BUILD_RPM_PACKAGE "Build rpm package" OFF)
# build details
option(BUILD_DOCS "Build Doxygen documentation" OFF)
option(BUILD_FUTURE "Build with the features which will be marked as stable later" OFF)
option(BUILD_LOAD "Build with additional load" OFF)
option(BUILD_TESTING "Build with additional test abilities" OFF)
set(PROJECT_TRDPARTY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty)
set(PROJECT_LIBRARY "queued")
set(PROJECT_LIBRARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_LIBRARY}")
include(compiler.cmake)
include(libraries.cmake)
include(clang-format.cmake)
include(cppcheck.cmake)
include(paths.cmake)
get_directory_property(CMAKE_DEFINITIONS COMPILE_DEFINITIONS)
configure_file("${CMAKE_SOURCE_DIR}/version.h.in" "${CMAKE_CURRENT_BINARY_DIR}/version.h")
add_subdirectory("queued")
add_subdirectory("queued-daemon")
add_subdirectory("queued-server")
add_subdirectory("queuedctl")
if (BUILD_PLUGINS)
add_subdirectory("plugins")
endif()
if (BUILD_TESTING)
enable_testing()
add_subdirectory("test")
endif ()

11
sources/checkgit.cmake Normal file
View File

@ -0,0 +1,11 @@
exec_program(
"git"
${CMAKE_CURRENT_SOURCE_DIR}
ARGS "log" "-1" "--format=\"%h\""
OUTPUT_VARIABLE COMMIT_SHA
RETURN_VALUE GIT_RETURN
)
if (${GIT_RETURN} EQUAL "0")
set(PROJECT_COMMIT_SHA "${COMMIT_SHA}")
endif ()

View File

@ -0,0 +1,19 @@
# additional target to perform clang-format run, requires clang-format
set(CLANGFORMAT_EXECUTABLE "/usr/bin/clang-format" CACHE STRING "Path to clang-format executable")
# get all project files
file(GLOB_RECURSE ALL_SOURCE_FILES *.cpp *.h *.h.in)
foreach (SOURCE_FILE ${ALL_SOURCE_FILES})
string(FIND ${SOURCE_FILE} ${PROJECT_TRDPARTY_DIR} PROJECT_TRDPARTY_DIR_FOUND)
if (NOT ${PROJECT_TRDPARTY_DIR_FOUND} EQUAL -1)
list(REMOVE_ITEM ALL_SOURCE_FILES ${SOURCE_FILE})
endif ()
endforeach ()
add_custom_target(
clangformat
COMMAND ${CLANGFORMAT_EXECUTABLE}
-style=file
-i
${ALL_SOURCE_FILES}
)

29
sources/compiler.cmake Normal file
View File

@ -0,0 +1,29 @@
# flags
if (CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "-Wall")
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0")
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
set(CMAKE_CXX_FLAGS_OPTIMIZATION "-Ofast -DNDEBUG")
# avoid newer gcc warnings
add_definitions(-D_DEFAULT_SOURCE)
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "-Wall")
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0")
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
set(CMAKE_CXX_FLAGS_OPTIMIZATION "-Ofast -DNDEBUG")
# linker flags
else ()
message(FATAL_ERROR "Unknown compiler")
endif ()
# some flags
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# verbose output for debug builds
if (CMAKE_BUILD_TYPE MATCHES Debug)
set(CMAKE_VERBOSE_MAKEFILE ON)
endif ()
# required by successfully coverity and cppcheck build
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

25
sources/cppcheck.cmake Normal file
View File

@ -0,0 +1,25 @@
# additional target to perform cppcheck run, requires cppcheck
set(CPPCHECK_EXECUTABLE "/usr/bin/cppcheck" CACHE STRING "Path to cppcheck executable")
# get all project files
# HACK this workaround is required to avoid qml files checking ^_^
file(GLOB_RECURSE ALL_SOURCE_FILES *.cpp *.h)
foreach (SOURCE_FILE ${ALL_SOURCE_FILES})
string(FIND ${SOURCE_FILE} ${PROJECT_TRDPARTY_DIR} PROJECT_TRDPARTY_DIR_FOUND)
if (NOT ${PROJECT_TRDPARTY_DIR_FOUND} EQUAL -1)
list(REMOVE_ITEM ALL_SOURCE_FILES ${SOURCE_FILE})
endif ()
endforeach ()
add_custom_target(
cppcheck
COMMAND ${CPPCHECK_EXECUTABLE}
--enable=warning,performance,portability,information,missingInclude
--std=c++11
--language=c++
--library=qt.cfg
--template="[{severity}][{id}] {message} {callstack} \(On {file}:{line}\)"
--verbose
--quiet
${ALL_SOURCE_FILES}
)

15
sources/libraries.cmake Normal file
View File

@ -0,0 +1,15 @@
# main qt libraries
find_package(Qt5 5.8.0 REQUIRED COMPONENTS Core DBus Network Sql Test)
add_definitions(
${Qt5Core_DEFINITIONS} ${Qt5DBus_DEFINITIONS} ${Qt5Network_DEFINITIONS}
${Qt5Sql_DEFINITIONS}
)
set(Qt_INCLUDE
${Qt5Core_INCLUDE_DIRS} ${Qt5DBus_INCLUDE_DIRS} ${Qt5Network_INCLUDE_PATH}
${Qt5Sql_INCLUDE_DIRS}
)
set(Qt_LIBRARIES
${Qt5Core_LIBRARIES} ${Qt5DBus_LIBRARIES} ${Qt5Network_LIBRARIES}
${Qt5Sql_LIBRARIES}
)

5
sources/paths.cmake Normal file
View File

@ -0,0 +1,5 @@
# paths
set(BIN_INSTALL_DIR "bin" CACHE STRING "Installation directory for executables")
set(DATA_INSTALL_DIR "share" CACHE STRING "Installation directory for data")
set(INCLUDE_INSTALL_DIR "include" CACHE STRING "Installation directory for headers")
set(LIB_INSTALL_DIR "lib" CACHE STRING "Installation directory for libraries")

View File

@ -0,0 +1,9 @@
set (SUBPROJECT "plugins")
message (STATUS "Subproject ${SUBPROJECT}")
include_directories("${CMAKE_BINARY_DIR}"
"${PROJECT_LIBRARY_DIR}/include" # required by moc
"${PROJECT_TRDPARTY_DIR}")
find_package(Queued PATHS "${CMAKE_CURRENT_SOURCE_DIR}" NO_DEFAULT_PATH)
queued_install_plugin("emailnotify" "emailnotify" curl)

View File

@ -0,0 +1,13 @@
set(QUEUED_DEFINITIONS "")
find_path(QUEUEDCORE_INCLUDE_DIR "queued/Queued.h" PATH_SUFFIXES "queued"
PATHS "${PROJECT_LIBRARY_DIR}/include" NO_DEFAULT_PATH)
set(QUEUED_INCLUDE_DIRS "${QUEUEDCORE_INCLUDE_DIR}")
set(QUEUED_LIBRARIES "${PROJECT_LIBRARY}")
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Queued DEFAULT_MSG
QUEUED_LIBRARIES QUEUED_INCLUDE_DIRS)
set(QUEUED_PLUGIN_ROOT "${DATA_INSTALL_DIR}/queued/plugins")
include("${PROJECT_LIBRARY_DIR}/QueuedLibraries.cmake")
include("${PROJECT_LIBRARY_DIR}/QueuedMacros.cmake")

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#include "QueuedEmailNotify.h"
#include <queued/Queued.h>
#include "QueuedEmailNotifyHelper.h"
void QueuedEmailNotify::init(const QVariantHash &_settings)
{
m_helper = new QueuedEmailNotifyHelper(this);
m_helper->setFrom(_settings.value("From", "mail@example.com").toString());
m_helper->setInsecureCurl(_settings.value("InsecureCurl", false).toBool());
m_helper->setPassword(_settings.value("Password", "").toString());
m_helper->setPort(_settings.value("Port", 465).toInt());
m_helper->setServer(_settings.value("Server", "smtp://smtp.example.com").toString());
m_helper->setSslEnabled(_settings.value("UseSSL", false).toBool());
m_helper->setUsername(_settings.value("Username", "").toString());
}
void QueuedEmailNotify::setToken(const QString &_token)
{
m_token = _token;
m_helper->setToken(_token);
}
void QueuedEmailNotify::setup(const QueuedPluginManagerInterface *_manager)
{
connect(_manager, SIGNAL(onStopTask(const long long)), m_helper,
SLOT(sendEmail(const long long)));
}
void QueuedEmailNotify::updateSettings(const QString &_key, const QVariant &_value)
{
qCDebug(LOG_PL) << "Update settings for" << _key;
if (!m_helper) {
qCWarning(LOG_PL) << "Helper is not initialized. Did you forget to call ::init()?";
return;
}
if (_key == "From") {
m_helper->setFrom(_value.toString());
} else if (_key == "Password") {
m_helper->setPassword(_value.toString());
} else if (_key == "Port") {
m_helper->setPort(_value.toInt());
} else if (_key == "Server") {
m_helper->setServer(_value.toString());
} else if (_key == "Username") {
m_helper->setUsername(_value.toString());
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#ifndef QUEUEDEMAILNOTIFY_H
#define QUEUEDEMAILNOTIFY_H
#include <queued/QueuedPluginInterface.h>
class QueuedEmailNotifyHelper;
class QueuedEmailNotify : public QObject, public QueuedPluginInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.queued.emailnotify/1.0")
Q_INTERFACES(QueuedPluginInterface)
public:
virtual ~QueuedEmailNotify() = default;
void init(const QVariantHash &_settings) override;
void setToken(const QString &_token) override;
void setup(const QueuedPluginManagerInterface *_manager) override;
void updateSettings(const QString &_key, const QVariant &_value) override;
private:
QueuedEmailNotifyHelper *m_helper = nullptr;
QString m_token;
};
#endif /* QUEUEDEMAILNOTIFY_H */

View File

@ -0,0 +1,256 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#include "QueuedEmailNotifyHelper.h"
#include <queued/Queued.h>
extern "C" {
#include <curl/curl.h>
}
QueuedEmailNotifyHelper::QueuedEmailNotifyHelper(QObject *_parent)
: QObject(_parent)
{
qCDebug(LOG_PL) << __PRETTY_FUNCTION__;
}
QString QueuedEmailNotifyHelper::curlEmail(const QString &_from)
{
qCDebug(LOG_PL) << "Convert email to curl format from" << _from;
return QString("<%1>").arg(_from);
}
char *QueuedEmailNotifyHelper::curlString(const QString &_source)
{
return strdup(_source.toStdString().c_str());
}
size_t QueuedEmailNotifyHelper::curlReadCallback(char *buffer, size_t size, size_t nitems,
void *instream)
{
// FIXME not really best choice to use here
auto text = reinterpret_cast<MailBody *>(instream);
// check sizes and whatever
if ((size == 0) || (nitems == 0) || ((size * nitems) < 1))
return 0;
if (text->text.count() <= text->currentLine)
return 0;
// get char* string from related qstring
auto data = curlString(text->text.at(text->currentLine));
size_t len = strlen(data);
memcpy(buffer, data, len);
text->currentLine++;
return len;
}
QString QueuedEmailNotifyHelper::from() const
{
return m_from;
}
bool QueuedEmailNotifyHelper::isInsecureCurl() const
{
return m_insecure;
}
bool QueuedEmailNotifyHelper::isSslEnabled() const
{
return m_ssl;
}
QString QueuedEmailNotifyHelper::password() const
{
return m_password;
}
int QueuedEmailNotifyHelper::port() const
{
return m_port;
}
QString QueuedEmailNotifyHelper::server() const
{
return m_server;
}
QString QueuedEmailNotifyHelper::token() const
{
return m_token;
}
QString QueuedEmailNotifyHelper::username() const
{
return m_username;
}
void QueuedEmailNotifyHelper::setFrom(const QString &_from)
{
qCDebug(LOG_PL) << "Set from" << _from;
m_from = _from;
}
void QueuedEmailNotifyHelper::setInsecureCurl(const bool _insecureCurl)
{
qCDebug(LOG_PL) << "Set insecure curl" << _insecureCurl;
m_insecure = _insecureCurl;
}
void QueuedEmailNotifyHelper::setPassword(const QString &_password)
{
qCDebug(LOG_PL) << "Set password";
m_password = _password;
}
void QueuedEmailNotifyHelper::setPort(const int &_port)
{
qCDebug(LOG_PL) << "Set port" << _port;
m_port = _port;
}
void QueuedEmailNotifyHelper::setServer(const QString &_server)
{
qCDebug(LOG_PL) << "Set server" << _server;
m_server = _server;
}
void QueuedEmailNotifyHelper::setSslEnabled(const bool _sslEnabled)
{
qCDebug(LOG_PL) << "Set ssl enabled" << _sslEnabled;
m_ssl = _sslEnabled;
}
void QueuedEmailNotifyHelper::setToken(const QString &_token)
{
m_token = _token;
}
void QueuedEmailNotifyHelper::setUsername(const QString &_username)
{
qCDebug(LOG_PL) << "Set username" << _username;
m_username = _username;
}
void QueuedEmailNotifyHelper::sendEmail(const long long _id)
{
auto rcpt = getEmail(_id);
if (rcpt.isEmpty())
return;
MailBody text = {getEmailText(_id, rcpt), 0};
CURL *curl = curl_easy_init();
QString url = QString("%1:%2").arg(server()).arg(port());
curl_easy_setopt(curl, CURLOPT_URL, curlString(url));
// ssl options
if (isSslEnabled())
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
if (isInsecureCurl())
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
// auth if applicable
if ((!username().isEmpty()) && (!password().isEmpty())) {
curl_easy_setopt(curl, CURLOPT_USERNAME, curlString(username()));
curl_easy_setopt(curl, CURLOPT_PASSWORD, curlString(password()));
}
// from & to
curl_easy_setopt(curl, CURLOPT_MAIL_FROM, curlString(curlEmail(from())));
curl_slist *recipients = nullptr;
recipients = curl_slist_append(recipients, curlString(curlEmail(rcpt)));
curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
// mail body
curl_easy_setopt(curl, CURLOPT_READFUNCTION, &QueuedEmailNotifyHelper::curlReadCallback);
curl_easy_setopt(curl, CURLOPT_READDATA, &text);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
// send
auto res = curl_easy_perform(curl);
if (res != CURLE_OK)
qCWarning(LOG_PL) << "Could not perform curl action" << curl_easy_strerror(res);
// cleanup
curl_slist_free_all(recipients);
curl_easy_cleanup(curl);
}
QString QueuedEmailNotifyHelper::getEmail(const long long _id) const
{
qCDebug(LOG_PL) << "Get email for task ID" << _id;
auto task = QueuedCoreAdaptor::getTask(_id, "user", token());
if (task.type() != Result::Content::Value) {
qCWarning(LOG_LIB) << "Could not get task information" << _id;
return "";
}
auto userId = task.get().toLongLong();
auto user = QueuedCoreAdaptor::getUser(userId, "email", token());
if (user.type() != Result::Content::Value) {
qCWarning(LOG_LIB) << "Could not get user information" << userId;
return "";
}
return user.get().toString();
}
QStringList QueuedEmailNotifyHelper::getEmailText(const long long _id, const QString &_to) const
{
qCDebug(LOG_PL) << "Get email text for user" << _to << "for task" << _id;
auto now = QDateTime::currentDateTimeUtc().toString(Qt::DateFormat::RFC2822Date);
return {QString("Date: %1\r\n").arg(now), QString("To: %1\r\n").arg(curlEmail(_to)),
QString("From: %1\r\n").arg(curlEmail(from())),
// message-id?
QString("Subject: %1\r\n").arg("Job %1 done").arg(_id), "\r\n",
QString("Job %1 done\r\n").arg(_id)};
}

View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#ifndef QUEUEDEMAILNOTIFYHELPER_H
#define QUEUEDEMAILNOTIFYHELPER_H
#include <QObject>
class QueuedEmailNotifyHelper : public QObject
{
Q_OBJECT
Q_PROPERTY(QString from READ from WRITE setFrom)
Q_PROPERTY(bool insecureCurl READ isInsecureCurl WRITE setInsecureCurl)
Q_PROPERTY(QString password READ password WRITE setPassword)
Q_PROPERTY(int port READ port WRITE setPort)
Q_PROPERTY(QString server READ server WRITE setServer)
Q_PROPERTY(bool ssl READ isSslEnabled WRITE setSslEnabled)
Q_PROPERTY(QString token READ token WRITE setToken)
Q_PROPERTY(QString username READ username WRITE setUsername)
public:
typedef struct {
QStringList text;
int currentLine = 0;
} MailBody;
explicit QueuedEmailNotifyHelper(QObject *_parent);
virtual ~QueuedEmailNotifyHelper() = default;
static QString curlEmail(const QString &_from);
static char *curlString(const QString &_source);
static size_t curlReadCallback(char *buffer, size_t size, size_t nitems, void *instream);
// properties
QString from() const;
bool isInsecureCurl() const;
bool isSslEnabled() const;
QString password() const;
int port() const;
QString server() const;
QString token() const;
QString username() const;
void setFrom(const QString &_from);
void setInsecureCurl(const bool _insecureCurl);
void setPassword(const QString &_password);
void setPort(const int &_port);
void setServer(const QString &_server);
void setSslEnabled(const bool _sslEnabled);
void setToken(const QString &_token);
void setUsername(const QString &_username);
public slots:
void sendEmail(const long long _id);
private:
QString getEmail(const long long _id) const;
QStringList getEmailText(const long long _id, const QString &_to) const;
QString m_from;
bool m_insecure = false;
QString m_password;
int m_port = 0;
QString m_server;
bool m_ssl = false;
QString m_token;
QString m_username;
};
#endif /* QUEUEDEMAILNOTIFYHELPER_H */

View File

@ -0,0 +1,44 @@
{
"author": "Queued team",
"description": "Send email on job updates",
"homepage": "https://github.com/arcan1s/queued",
"license": "MIT",
"options": {
"From": {
"default": "mail@example.com",
"description": "from email field",
"type": "string"
},
"InsecureCurl": {
"default": false,
"description": "ignore insecure warnings",
"type": "boolean"
},
"Password": {
"default": "",
"description": "email service auth password",
"type": "string"
},
"Port": {
"default": 465,
"description": "email service port",
"type": "integer"
},
"Server": {
"default": "smtp://smtp.example.com",
"description": "email server url",
"type": "string"
},
"UseSSL": {
"default": false,
"description": "use ssl for connection",
"type": "boolean"
},
"Username": {
"default": "",
"description": "email service auth username",
"type": "string"
}
}
}

View File

@ -1,184 +0,0 @@
#!/bin/bash
func_help() {
echo -e "Simple daemon written on BASH for starting jobs to queue of calculations"
echo -e "\nUsage: queued [ -jd | --jobdir /var/lib/queued/job ] [ --priority 0 ]"
echo -e " [ -q | --queuefile /var/lib/queued/queue ] [ -u | --user root ]"
echo -e " [ -wd | --workdir /var/lib/queued/work ] [ -v | --version ]"
echo -e " [ -h | --help ]"
echo -e "\nParametrs:"
echo -e " -jd --jobdir PATH - path to job directory. Default is '/var/lib/queued/job'"
echo -e " --priority NUM - defalut priority. Default is '0'"
echo -e " -q --queuefile PATH - path to queue file. Default is '/var/lib/queued/queue'"
echo -e " -u --user USERNAME - start jobs by user. Default is 'root'"
echo -e " -wd --workdir PATH - path to work directory. Default is '/var/lib/queued/work'"
echo -e "\n -v --version - show version and exit"
echo -e " -h --help - show this help and exit"
exit 0
}
func_ver() {
echo -e " queued "
echo -e "Simple daemon for starting jobs to queue of calculations"
echo -e "Version : 1.0.0 License : GPLv3"
echo -e "Author : Evgeniy Alexeev aka arcanis"
echo -e "E-mail : esalexeev (at) gmail.com"
exit 0
}
isnum () {
(t=$(( 0$1+0 ))) 2>/dev/null
}
# default values
JOBDIR="/var/lib/queued/job"
PRIORITY=0
QUEUEFILE="/var/lib/queued/queue"
STARTASUSER="root"
WORKDIR="/var/lib/queued/work"
# parametrs parsing
until [ -z $1 ]; do
if [ "$1" = "-h" ]; then
func_help; fi
if [ "$1" = "--help" ]; then
func_help; fi
if [ "$1" = "-v" ]; then
func_ver; fi
if [ "$1" = "--version" ]; then
func_ver; fi
if [ "$1" = "-jd" ]; then
JOBDIR="$2"
shift; fi
if [ "$1" = "--jobdir" ]; then
JOBDIR="$2"
shift; fi
if [ "$1" = "--priority" ]; then
PRIORITY="$2"
shift; fi
if [ "$1" = "-q" ]; then
QUEUEFILE="$2"
shift; fi
if [ "$1" = "--queuefile" ]; then
QUEUEFILE="$2"
shift; fi
if [ "$1" = "-u" ]; then
STARTASUSER="$2"
shift; fi
if [ "$1" = "--user" ]; then
STARTASUSER="$2"
shift; fi
if [ "$1" = "-wd" ]; then
WORKDIR="$2"
shift; fi
if [ "$1" = "--workdir" ]; then
WORKDIR="$2"
shift; fi
shift
done
# creating directories if doesn't exist
if [ ! -d "$JOBDIR" ]; then
if [ -e "$JOBDIR" ]; then
echo "[EE]: '$JOBDIR' is a file"
exit 1
fi
echo "[II]: Create directory '$JOBDIR'"
mkdir -m777 -p "$JOBDIR" || (echo "[EE] Unknown error"; exit 1)
fi
if [ ! -d "$WORKDIR" ]; then
if [ -e "$WORKDIR" ]; then
echo "[EE]: '$WORKDIR' is a file"
exit 1
fi
echo "[II]: Create directory '$WORKDIR'"
mkdir -m777 -p "$WORKDIR" || (echo "[EE] Unknown error"; exit 1)
fi
if [ ! -d "$(dirname "$QUEUEFILE")" ]; then
if [ -e "$(dirname "$QUEUEFILE")" ]; then
echo "[EE]: '$(dirname "$QUEUEFILE")' is a file"
exit 1
fi
echo "[II]: Create directory '$(dirname "$QUEUEFILE")'"
mkdir -m777 -p "$(dirname "$QUEUEFILE")" || (echo "[EE] Unknown error"; exit 1)
fi
# check priority
isnum "$PRIORITY" || (echo "[EE]: '$PRIORITY' isn't a number"; exit 1)
# work block
# change cwd
cd /
# output to /dev/null
< /dev/null > /dev/null 2>&1 &
# forking
(
while true; do
# check files
echo "[II] Check new files"
for FILE in $(ls "$WORKDIR/"); do
[ -d "$WORKDIR/$FILE" ] && continue
FILE_EXT="${FILE##*.}"
[ "$FILE_EXT" = "pr" ] && continue
[ "$FILE_EXT" = "user" ] && continue
[ -e "$QUEUEFILE" ] && grep --quiet "$WORKDIR/$FILE" "$QUEUEFILE" && continue
echo "[II] Adding file '$FILE' to list"
if [ -e "$WORKDIR/$FILE".pr ]; then
CURJOB_PRIOR=$(cat "$WORKDIR/$FILE".pr)
isnum "$CURJOB_PRIOR" || CURJOB_PRIOR="$PRIORITY"
else
CURJOB_PRIOR="$PRIORITY"
fi
echo "[II] Setting priority to '$CURJOB_PRIOR'"
if [ ! -e "$QUEUEFILE" ]; then
echo "$CURJOB_PRIOR==$WORKDIR/$FILE" > "$QUEUEFILE"
chmod 777 "$QUEUEFILE"
else
if [[ $(cat "$QUEUEFILE") = "" ]]; then
echo "$CURJOB_PRIOR==$WORKDIR/$FILE" >> "$QUEUEFILE"
else
LASTLINE=""
for JOB in $(cat "$QUEUEFILE"); do
JOB_PRIOR=$(echo "$JOB" | awk -F "==" '{print $1}')
if [[ $JOB_PRIOR < $CURJOB_PRIOR ]]; then
LASTLINE="$JOB"
continue
fi
if [ -z "$LASTLINE" ]; then
sed -i '1i '"$CURJOB_PRIOR==$WORKDIR/$FILE" "$QUEUEFILE"
else
sed -i '/'$LASTLINE'/a '"$CURJOB_PRIOR==$WORKDIR/$FILE" "$QUEUEFILE"
fi
break
done
grep --quiet "$WORKDIR/$FILE" "$QUEUEFILE" || echo "$CURJOB_PRIOR==$WORKDIR/$FILE" >> "$QUEUEFILE"
fi
fi
done
# check running job
CALC=0
for FILE in $(ls "$JOBDIR/"); do
[ -d "$JOBDIR/$FILE" ] && continue
pgrep "$JOBDIR/$FILE" &> /dev/null && CALC=$(($CALC+1))
done
# running job
if [ "$CALC" = "0" ]; then
(
CURJOB=$(tail -1 "$QUEUEFILE" | awk -F "==" '{print $2}')
[ -z "$CURJOB" ] && break
sed -i '$d' "$QUEUEFILE"
[ -e "$CURJOB".user ] && CUR_USER="$(cat "$CURJOB".user)" || CUR_USER="$STARTASUSER"
mv "$CURJOB"* "$JOBDIR/" 2> /dev/null || break
echo "[II] Running job '$CURJOB'"
su -c "/bin/sh "$JOBDIR/$(basename "$CURJOB")" &> "$JOBDIR/$(basename "$CURJOB")".log" $CUR_USER &
)
else
echo "[II] You have a running job"
fi
# wait for 60 seconds
sleep 60
done
) &

View File

@ -0,0 +1,13 @@
# set project name
set (SUBPROJECT "queued-daemon")
message (STATUS "Subproject ${SUBPROJECT}")
add_subdirectory ("src")
# build man
file (GLOB SUBPROJECT_MAN_IN "*.1")
file (RELATIVE_PATH SUBPROJECT_MAN "${CMAKE_SOURCE_DIR}" "${SUBPROJECT_MAN_IN}")
configure_file ("${SUBPROJECT_MAN_IN}" "${CMAKE_CURRENT_BINARY_DIR}/${SUBPROJECT_MAN}")
install (FILES "${CMAKE_CURRENT_BINARY_DIR}/${SUBPROJECT_MAN}" DESTINATION "${DATA_INSTALL_DIR}/man/man1")
install (FILES "bash-completions" DESTINATION "${DATA_INSTALL_DIR}/bash-completion/completions" RENAME "${SUBPROJECT}")
install (FILES "zsh-completions" DESTINATION "${DATA_INSTALL_DIR}/zsh/site-functions" RENAME "_${SUBPROJECT}")

View File

View File

@ -0,0 +1,28 @@
.TH queued-daemon 1 "@CURRENT_DATE@" "version @PROJECT_VERSION@"
.SH NAME
Daemon for starting jobs to queue of calculation
.SH SYNOPSIS
.B queued-daemon
[ options ]
.SH DESCRIPTION
Daemon for starting jobs to queue of calculation. Daemon to start application
.SH OPTIONS
.IP "-c, --config <config>"
path to configuration file, default is /etc/xdg/queued.ini
.IP "-d, --debug"
verbose output
.IP "--daemon"
start daemonize
.IP "-v, --version"
show version and exit
.IP "-i, --info"
show build information and exit
.IP "-h, --help"
show this help and exit
.SH SEE ALSO
.BR queuedctl (1)
.BR queued-server (1)
.SH AUTHOR
@PROJECT_AUTHOR@ <\fI@PROJECT_CONTACT@\fR>
.SH LICENSE
This software is licensed under @PROJECT_LICENSE@

View File

@ -0,0 +1,12 @@
[Administrator]
Username = root
Password = 9bc0798aa9d5de1f41e56ea4654cf86694dae080912d7df83cf293e7c7beb1b62e2811ed88bb24553a50d53f5cf85458928d25aea19aca5dc42fb316ba9c0e2c
Salt = suzMBxyKxtyQtu7c4vVfbQTB
[Database]
Driver = QSQLITE
Hostname =
Password =
Path = /tmp/queued.db
Port =
Username =

View File

@ -0,0 +1,18 @@
# set files
file (GLOB_RECURSE SUBPROJECT_SOURCES "*.cpp")
file (GLOB_RECURSE SUBPROJECT_HEADERS "*.h")
# include_path
include_directories ("${PROJECT_LIBRARY_DIR}/include"
"${CMAKE_CURRENT_BINARY_DIR}"
"${CMAKE_BINARY_DIR}"
"${PROJECT_TRDPARTY_DIR}"
"${Qt_INCLUDE}")
qt5_wrap_cpp (SUBPROJECT_MOC_SOURCES "${SUBPROJECT_HEADERS}")
add_executable ("${SUBPROJECT}" "${SUBPROJECT_HEADERS}" "${SUBPROJECT_SOURCES}"
"${SUBPROJECT_MOC_SOURCES}")
target_link_libraries ("${SUBPROJECT}" "${PROJECT_LIBRARY}" "${Qt_LIBRARIES}")
# install properties
install (TARGETS "${SUBPROJECT}" DESTINATION "${BIN_INSTALL_DIR}")

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#include "QueuedApplication.h"
#include <QDBusConnection>
#include <QDBusMessage>
#include <queued/Queued.h>
#include "QueuedApplicationInterface.h"
QueuedApplication::QueuedApplication(QObject *parent, const QVariantHash &args)
: QObject(parent)
, m_configuration(args)
{
qCDebug(LOG_APP) << __PRETTY_FUNCTION__;
m_core = new QueuedCore(this);
init();
initDBus();
}
QueuedApplication::~QueuedApplication()
{
qCDebug(LOG_APP) << __PRETTY_FUNCTION__;
QDBusConnection::sessionBus().unregisterObject(QueuedConfig::DBUS_APPLICATION_PATH);
m_core->deleteLater();
}
void QueuedApplication::init()
{
m_core->deinit();
m_core->init(m_configuration["config"].toString());
}
void QueuedApplication::initDBus()
{
QDBusConnection bus = QDBusConnection::systemBus();
if (!bus.registerObject(QueuedConfig::DBUS_APPLICATION_PATH,
new QueuedApplicationInterface(this),
QDBusConnection::ExportAllContents)) {
QString message
= QString("Could not register application object %1").arg(bus.lastError().message());
qCCritical(LOG_DBUS) << message;
throw QueuedDBusException(message);
}
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#ifndef QUEUEDAPPLICATION_H
#define QUEUEDAPPLICATION_H
#include <QObject>
#include <QVariant>
class QueuedCore;
class QueuedApplication : public QObject
{
Q_OBJECT
public:
explicit QueuedApplication(QObject *parent, const QVariantHash &args);
virtual ~QueuedApplication();
void init();
private:
// backend
void initDBus();
// library
QueuedCore *m_core = nullptr;
// configuration
QVariantHash m_configuration;
};
#endif /* QUEUEDAPPLICATION_H */

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#include "QueuedApplicationInterface.h"
#include <QCoreApplication>
#include <QDBusMetaType>
#include <queued/Queued.h>
#include "QueuedApplication.h"
extern "C" {
#include <unistd.h>
}
QueuedApplicationInterface::QueuedApplicationInterface(QueuedApplication *parent)
: QDBusAbstractAdaptor(parent)
, m_application(parent)
{
qCDebug(LOG_DBUS) << __PRETTY_FUNCTION__;
qRegisterMetaType<QueuedResult<QStringList>>("QueuedResult<QStringList>");
qDBusRegisterMetaType<QueuedResult<QStringList>>();
}
QueuedApplicationInterface::~QueuedApplicationInterface()
{
qCDebug(LOG_DBUS) << __PRETTY_FUNCTION__;
}
QDBusVariant QueuedApplicationInterface::Active() const
{
return QueuedCoreAdaptor::toDBusVariant(QueuedResult<bool>(true));
}
QDBusVariant QueuedApplicationInterface::UIDs() const
{
QStringList uids;
uids.append(QString::number(::getuid()));
uids.append(QString::number(::geteuid()));
return QueuedCoreAdaptor::toDBusVariant(QueuedResult<QStringList>(uids));
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#ifndef QUEUEDAPPLICATIONINTERFACE_H
#define QUEUEDAPPLICATIONINTERFACE_H
#include <QDBusAbstractAdaptor>
#include <QDBusVariant>
#include "QueuedConfig.h"
class QueuedApplication;
class QueuedApplicationInterface : public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", DBUS_SERVICE_NAME)
public:
explicit QueuedApplicationInterface(QueuedApplication *parent);
virtual ~QueuedApplicationInterface();
public slots:
QDBusVariant Active() const;
QDBusVariant UIDs() const;
private:
QueuedApplication *m_application = nullptr;
};
#endif /* QUEUEDAPPLICATIONINTERFACE_H */

View File

@ -0,0 +1,114 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#include <QCommandLineParser>
#include <QDBusConnection>
#include <queued/Queued.h>
#include <csignal>
#include <iostream>
#include "QueuedApplication.h"
#include "version.h"
extern "C" {
#include <unistd.h>
}
QueuedApplication *instance = nullptr;
bool existingSessionOperation(const QString &operation)
{
auto res = QueuedCoreAdaptor::sendRequest<bool>(
QueuedConfig::DBUS_SERVICE, QueuedConfig::DBUS_APPLICATION_PATH, QueuedConfig::DBUS_SERVICE,
operation, QVariantList());
return ((res.type() == Result::Content::Value) && res.get());
}
int main(int argc, char *argv[])
{
// HACK preparse arguments to find out if --daemon is set
for (int i = 0; i < argc; i++) {
if (std::string(argv[i]) != "--daemon")
continue;
::daemon(0, 0);
break;
}
QueuedDebug::applyLogFormat();
QCoreApplication app(argc, argv);
app.setApplicationName(NAME);
app.setApplicationVersion(VERSION);
// parser
QCommandLineParser parser;
parser.setApplicationDescription("Daemon for starting jobs to queue of calculations");
parser.addHelpOption();
parser.addVersionOption();
// info
QCommandLineOption infoOption({"i", "info"}, "Show additional info.");
parser.addOption(infoOption);
// configuration option
QCommandLineOption configOption({"c", "config"}, "Read initial configuration from file.",
"config", QueuedSettings::defaultPath());
parser.addOption(configOption);
// debug mode
QCommandLineOption debugOption({"d", "debug"}, "Print debug information.");
parser.addOption(debugOption);
// daemon mode
QCommandLineOption daemonOption("daemon", "Start detached.");
parser.addOption(daemonOption);
parser.process(app);
// show info and exit
if (parser.isSet(infoOption)) {
auto metadata = QueuedDebug::getBuildData();
for (auto &string : metadata)
std::cout << qPrintable(string) << std::endl;
return 0;
}
// check if exists
if (existingSessionOperation("Active")) {
qCWarning(LOG_APP) << "Another session is active";
return 1;
}
// enable debug
if (parser.isSet(debugOption))
QueuedDebug::enableDebug();
// build initial options hash
QVariantHash arguments = {{"config", parser.value(configOption)}};
// start application
instance = new QueuedApplication(nullptr, arguments);
// catch SIGHUP
signal(SIGHUP, [](int sig) -> void {
qCInfo(LOG_APP) << "Received SIGHUP signal, reinit components";
instance->init();
});
return app.exec();
}

View File

View File

@ -0,0 +1,13 @@
# set project name
set (SUBPROJECT "queued-server")
message (STATUS "Subproject ${SUBPROJECT}")
add_subdirectory ("src")
# build man
file (GLOB SUBPROJECT_MAN_IN "*.1")
file (RELATIVE_PATH SUBPROJECT_MAN "${CMAKE_SOURCE_DIR}" "${SUBPROJECT_MAN_IN}")
configure_file ("${SUBPROJECT_MAN_IN}" "${CMAKE_CURRENT_BINARY_DIR}/${SUBPROJECT_MAN}")
install (FILES "${CMAKE_CURRENT_BINARY_DIR}/${SUBPROJECT_MAN}" DESTINATION "${DATA_INSTALL_DIR}/man/man1")
install (FILES "bash-completions" DESTINATION "${DATA_INSTALL_DIR}/bash-completion/completions" RENAME "${SUBPROJECT}")
install (FILES "zsh-completions" DESTINATION "${DATA_INSTALL_DIR}/zsh/site-functions" RENAME "_${SUBPROJECT}")

View File

View File

@ -0,0 +1,27 @@
.TH queued-server 1 "@CURRENT_DATE@" "version @PROJECT_VERSION@"
.SH NAME
Daemon for starting jobs to queue of calculation
.SH SYNOPSIS
.B queued-server
[ options ]
.SH DESCRIPTION
Daemon for starting jobs to queue of calculation. Web server applicaiton which
provides interface to daemon
.SH OPTIONS
.IP "-d, --debug"
verbose output
.IP "--daemon"
start daemonize
.IP "-v, --version"
show version and exit
.IP "-i, --info"
show build information and exit
.IP "-h, --help"
show this help and exit
.SH SEE ALSO
.BR queuedctl (1)
.BR queued-daemon (1)
.SH AUTHOR
@PROJECT_AUTHOR@ <\fI@PROJECT_CONTACT@\fR>
.SH LICENSE
This software is licensed under @PROJECT_LICENSE@

View File

@ -0,0 +1,18 @@
# set files
file (GLOB_RECURSE SUBPROJECT_SOURCES "*.cpp")
file (GLOB_RECURSE SUBPROJECT_HEADERS "*.h")
# include_path
include_directories ("${PROJECT_LIBRARY_DIR}/include"
"${CMAKE_CURRENT_BINARY_DIR}"
"${CMAKE_BINARY_DIR}"
"${PROJECT_TRDPARTY_DIR}"
"${Qt_INCLUDE}")
qt5_wrap_cpp (SUBPROJECT_MOC_SOURCES "${SUBPROJECT_HEADERS}")
add_executable ("${SUBPROJECT}" "${SUBPROJECT_HEADERS}" "${SUBPROJECT_SOURCES}"
"${SUBPROJECT_MOC_SOURCES}")
target_link_libraries ("${SUBPROJECT}" "${PROJECT_LIBRARY}" "${Qt_LIBRARIES}")
# install properties
install (TARGETS "${SUBPROJECT}" DESTINATION "${BIN_INSTALL_DIR}")

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#include "QueuedServer.h"
#include <queued/Queued.h>
#include <QCoreApplication>
#include "QueuedTcpServer.h"
QueuedServer::QueuedServer(QObject *parent, const QVariantHash &args)
: QObject(parent)
, m_configuration(args)
{
qCDebug(LOG_SERV) << __PRETTY_FUNCTION__;
m_server = new QueuedTcpServer(this);
init();
}
QueuedServer::~QueuedServer()
{
qCDebug(LOG_SERV) << __PRETTY_FUNCTION__;
m_server->deleteLater();
}
void QueuedServer::init()
{
while (QueuedCoreAdaptor::getStatus().type() != Result::Content::Value) {
qCWarning(LOG_SERV) << "Daemon seems to be unavailable wait" << WAIT_FOR_DAEMON;
QTime timer = QTime::currentTime().addMSecs(WAIT_FOR_DAEMON);
while (QTime::currentTime() < timer)
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}
m_server->init(QueuedCoreAdaptor::getOption(QueuedConfig::QueuedSettings::ServerTimeout, "")
.get()
.toInt());
QString address = QueuedCoreAdaptor::getOption(QueuedConfig::QueuedSettings::ServerAddress, "")
.get()
.toString();
ushort port
= QueuedCoreAdaptor::getOption(QueuedConfig::QueuedSettings::ServerPort, "").get().toUInt();
m_server->listen(QHostAddress(address), port);
m_server->setMaxPendingConnections(
QueuedCoreAdaptor::getOption(QueuedConfig::QueuedSettings::ServerMaxConnections, "")
.get()
.toInt());
qCInfo(LOG_SERV) << "Server listen on" << m_server->serverAddress() << m_server->serverPort();
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#ifndef QUEUEDSERVER_H
#define QUEUEDSERVER_H
#include <QObject>
#include <QVariant>
class QueuedTcpServer;
class QueuedServer : public QObject
{
Q_OBJECT
public:
static const long WAIT_FOR_DAEMON = 30000;
explicit QueuedServer(QObject *parent, const QVariantHash &args);
virtual ~QueuedServer();
void init();
private:
// backend
QueuedTcpServer *m_server = nullptr;
// configuration
QVariantHash m_configuration;
};
#endif /* QUEUEDSERVER_H */

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#include "QueuedTcpServer.h"
#include <queued/Queued.h>
#include "QueuedTcpServerThread.h"
QueuedTcpServer::QueuedTcpServer(QObject *parent)
: QTcpServer(parent)
{
qCDebug(LOG_SERV) << __PRETTY_FUNCTION__;
}
QueuedTcpServer::~QueuedTcpServer()
{
qCDebug(LOG_SERV) << __PRETTY_FUNCTION__;
}
void QueuedTcpServer::init(const int timeout)
{
m_timeout = timeout;
}
void QueuedTcpServer::incomingConnection(qintptr socketDescriptor)
{
auto thread = new QueuedTcpServerThread(socketDescriptor, m_timeout, this);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#ifndef QUEUEDTCPSERVER_H
#define QUEUEDTCPSERVER_H
#include <QTcpServer>
class QueuedTcpServer : public QTcpServer
{
Q_OBJECT
public:
explicit QueuedTcpServer(QObject *parent);
virtual ~QueuedTcpServer();
void init(const int timeout);
protected:
void incomingConnection(qintptr socketDescriptor) override;
private:
int m_timeout = -1;
};
#endif /* QUEUEDTCPSERVER_H */

View File

@ -0,0 +1,103 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#include "QueuedTcpServerResponseHelper.h"
#include <QRegularExpression>
#include <queued/Queued.h>
#include "QueuedTcpServerResponseHelperApi1.h"
QVariantHash QueuedTcpServerResponseHelper::getData(const Request &_request,
const QVariantHash &_data,
const QString &_token)
{
qCDebug(LOG_SERV) << "Get data for request" << static_cast<int>(_request.path)
<< _request.apiVersion << _request.arg << "with data" << _data;
QVariantHash output;
if (_request.apiVersion == 1)
output = QueuedTcpServerResponseHelperApi1::getData(_request.path, _request.arg,
_request.type, _data, _token);
return output;
}
QueuedTcpServerResponseHelper::Request
QueuedTcpServerResponseHelper::parsePath(const QString &_path)
{
qCDebug(LOG_SERV) << "Parse path" << _path;
// /api/v1/request/arg or /api/v1/request
QRegularExpression regex("^\\/api\\/v(?<version>\\d+)\\/"
"(?<path>[\\d\\w]*)(\\/(?<arg>[\\d\\w]+))?$");
regex.setPatternOptions(QRegularExpression::DotMatchesEverythingOption);
Request request;
request.valid = false;
QRegularExpressionMatchIterator it = regex.globalMatch(_path);
while (it.hasNext()) {
QRegularExpressionMatch match = it.next();
request.apiVersion = match.captured("version").toUInt();
request.arg = match.captured("arg");
request.path = pathToEnum(match.captured("path"));
// check if request is valid
request.valid = (request.path != RequestPath::Unknown)
&& (std::find(std::begin(QueuedConfig::WEBAPI_VERSIONS),
std::end(QueuedConfig::WEBAPI_VERSIONS), request.apiVersion)
!= std::end(QueuedConfig::WEBAPI_VERSIONS));
}
return request;
}
QueuedTcpServerResponseHelper::RequestPath
QueuedTcpServerResponseHelper::pathToEnum(const QString &_path)
{
qCDebug(LOG_SERV) << "Convert path" << _path;
if (_path == "auth")
return RequestPath::Auth;
else if (_path == "option")
return RequestPath::Option;
else if (_path == "permissions")
return RequestPath::Permissions;
else if (_path == "plugin")
return RequestPath::Plugin;
else if (_path == "plugins")
return RequestPath::Plugins;
else if (_path == "reports")
return RequestPath::Reports;
else if (_path == "status")
return RequestPath::Status;
else if (_path == "task")
return RequestPath::Task;
else if (_path == "tasks")
return RequestPath::Tasks;
else if (_path == "user")
return RequestPath::User;
else if (_path == "users")
return RequestPath::Users;
return RequestPath::Unknown;
}

View File

@ -0,0 +1,92 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#ifndef QUEUEDTCPSERVERRESPONSEHELPER_H
#define QUEUEDTCPSERVERRESPONSEHELPER_H
#include <QVariant>
namespace QueuedTcpServerResponseHelper
{
enum class RequestPath {
Unknown,
Auth,
Option,
Permissions,
Plugin,
Plugins,
Reports,
Status,
Task,
Tasks,
User,
Users
};
typedef struct {
int apiVersion;
QString arg;
RequestPath path;
QString type;
bool valid;
} Request;
static const QHash<int, QByteArray> HTTPCodeMap = {{100, "Continue"},
{101, "Switching Protocols"},
{200, "OK"},
{201, "Created"},
{202, "Accepted"},
{203, "Non-Authoritative Information"},
{204, "No Content"},
{205, "Reset Content"},
{206, "Partial Content"},
{300, "Multiple Choices"},
{301, "Moved Permanently"},
{302, "Found"},
{303, "See Other"},
{304, "Not Modified"},
{305, "Use Proxy"},
{307, "Temporary Redirect"},
{400, "Bad Request"},
{401, "Unauthorized"},
{402, "Payment Required"},
{403, "Forbidden"},
{404, "Not Found"},
{405, "Method Not Allowed"},
{406, "Not Acceptable"},
{407, "Proxy Authentication Required"},
{408, "Request Time-out"},
{409, "Conflict"},
{410, "Gone"},
{411, "Length Required"},
{412, "Precondition Failed"},
{413, "Request Entity Too Large"},
{414, "Request-URI Too Large"},
{415, "Unsupported Media Type"},
{416, "Requested range not satisfiable"},
{417, "Expectation Failed"},
{500, "Internal Server Error"},
{501, "Not Implemented"},
{502, "Bad Gateway"},
{503, "Service Unavailable"},
{504, "Gateway Time-out"},
{505, "HTTP Version not supported"}};
QVariantHash getData(const Request &_request, const QVariantHash &_data, const QString &_token);
Request parsePath(const QString &_path);
RequestPath pathToEnum(const QString &_path);
}; // namespace QueuedTcpServerResponseHelper
#endif /* QUEUEDTCPSERVERRESPONSEHELPER_H */

View File

@ -0,0 +1,157 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#include "QueuedTcpServerResponseHelperApi1.h"
#include <queued/Queued.h>
#include "QueuedTcpServerResponseHelperAuth.h"
#include "QueuedTcpServerResponseHelperOption.h"
#include "QueuedTcpServerResponseHelperPermissions.h"
#include "QueuedTcpServerResponseHelperPlugins.h"
#include "QueuedTcpServerResponseHelperTask.h"
#include "QueuedTcpServerResponseHelperUser.h"
QVariantHash QueuedTcpServerResponseHelperApi1::getData(
const QueuedTcpServerResponseHelper::RequestPath _request, const QString &_arg,
const QString &_type, const QVariantHash &_data, const QString &_token)
{
qCDebug(LOG_SERV) << "Get data for" << static_cast<int>(_request) << "with arg" << _arg
<< "with data" << _data;
QVariantHash output;
if ((_request != QueuedTcpServerResponseHelper::RequestPath::Auth)
&& !QueuedTcpServerResponseHelperAuth::tryAuth(_token)) {
output = {{"code", 401}};
return output;
}
switch (_request) {
case QueuedTcpServerResponseHelper::RequestPath::Auth:
if (_type == "POST")
output = QueuedTcpServerResponseHelperAuth::auth(_data);
else
output = {{"code", 405}};
break;
case QueuedTcpServerResponseHelper::RequestPath::Option:
if (_type == "GET")
output = QueuedTcpServerResponseHelperOption::getOption(_arg, _token);
else if (_type == "POST")
output = QueuedTcpServerResponseHelperOption::setOption(_arg, _data, _token);
else
output = {{"code", 405}};
break;
case QueuedTcpServerResponseHelper::RequestPath::Permissions:
if (_type == "DELETE")
output = QueuedTcpServerResponseHelperPermissions::removePermission(_arg.toLongLong(),
_data, _token);
else if (_type == "POST")
output = QueuedTcpServerResponseHelperPermissions::addPermission(_arg.toLongLong(),
_data, _token);
else
output = {{"code", 405}};
break;
case QueuedTcpServerResponseHelper::RequestPath::Plugin:
if (_type == "GET")
output = QueuedTcpServerResponseHelperPlugins::getPlugin(_arg, _token);
else
output = {{"code", 405}};
break;
case QueuedTcpServerResponseHelper::RequestPath::Plugins:
if (_type == "DELETE")
output = QueuedTcpServerResponseHelperPlugins::removePlugin(_arg, _token);
else if (_type == "GET")
output = QueuedTcpServerResponseHelperPlugins::listPlugins();
else if (_type == "POST")
output = QueuedTcpServerResponseHelperPlugins::addPlugin(_arg, _token);
else
output = {{"code", 405}};
break;
case QueuedTcpServerResponseHelper::RequestPath::Reports:
if (_type == "GET")
output = QueuedTcpServerResponseHelperUser::getReport(_data, _token);
else
output = {{"code", 405}};
break;
case QueuedTcpServerResponseHelper::RequestPath::Status:
if (_type == "GET")
output = getStatus();
else
output = {{"code", 405}};
break;
case QueuedTcpServerResponseHelper::RequestPath::Task:
if (_type == "GET")
output = QueuedTcpServerResponseHelperTask::getTask(_arg.toLongLong(), _data, _token);
else if (_type == "POST")
output = QueuedTcpServerResponseHelperTask::addOrEditTask(_arg.toLongLong(), _data,
_token);
else if (_type == "PUT")
output = QueuedTcpServerResponseHelperTask::startOrStopTask(_arg.toLongLong(), _token);
else
output = {{"code", 405}};
break;
case QueuedTcpServerResponseHelper::RequestPath::Tasks:
if (_type == "GET")
output = QueuedTcpServerResponseHelperTask::getTasks(_data, _token);
else
output = {{"code", 405}};
break;
case QueuedTcpServerResponseHelper::RequestPath::User:
if (_type == "GET")
output = QueuedTcpServerResponseHelperUser::getUser(_arg, _data, _token);
else if (_type == "POST")
output = QueuedTcpServerResponseHelperUser::addOrEditUser(_arg, _data, _token);
else
output = {{"code", 405}};
break;
case QueuedTcpServerResponseHelper::RequestPath::Users:
if (_type == "GET")
output = QueuedTcpServerResponseHelperUser::getUsers(_data, _token);
else
output = {{"code", 405}};
break;
case QueuedTcpServerResponseHelper::RequestPath::Unknown:
output = {{"code", 404}};
break;
}
return output;
}
QVariantHash QueuedTcpServerResponseHelperApi1::getStatus()
{
QVariantHash output = {{"code", 200}};
auto res = QueuedCoreAdaptor::getStatus();
if (res.type() != Result::Content::Value)
return {};
auto data = res.get();
auto sections = data.keys();
sections.sort();
for (auto &section : sections) {
QVariantHash sectionData;
auto keys = data[section].keys();
keys.sort();
for (auto &key : keys)
sectionData[key] = data[section][key];
// append output
output[section] = sectionData;
}
return output;
}

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#ifndef QUEUEDTCPSERVERRESPONSEHELPERAPI1_H
#define QUEUEDTCPSERVERRESPONSEHELPERAPI1_H
#include <QVariant>
#include "QueuedTcpServerResponseHelper.h"
namespace QueuedTcpServerResponseHelperApi1
{
QVariantHash getData(const QueuedTcpServerResponseHelper::RequestPath _request, const QString &_arg,
const QString &_type, const QVariantHash &_data, const QString &_token);
QVariantHash getStatus();
}; // namespace QueuedTcpServerResponseHelperApi1
#endif /* QUEUEDTCPSERVERRESPONSEHELPERAPI1_H */

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#include "QueuedTcpServerResponseHelperAuth.h"
#include <queued/Queued.h>
QVariantHash QueuedTcpServerResponseHelperAuth::auth(const QVariantHash &_data)
{
qCDebug(LOG_SERV) << "Auth with data" << _data;
QVariantHash output;
if (_data.contains("user") && _data.contains("password")) {
auto res = QueuedCoreAdaptor::auth(_data["user"].toString(), _data["password"].toString());
res.match(
[&output](const QString &val) {
output = {{"code", 200}, {"token", val}};
},
[&output](const QueuedError &err) {
output = {{"code", 401}, {"message", err.message().c_str()}};
});
} else {
output = {{"code", 400}, {"message", "No required fields found"}};
}
return output;
}
bool QueuedTcpServerResponseHelperAuth::tryAuth(const QString &_token)
{
qCDebug(LOG_APP) << "Try auth with" << _token;
auto res = QueuedCoreAdaptor::auth(_token);
bool ret = true;
res.match([&ret](const bool val) { ret = val; },
[&ret](const QueuedError &err) { ret = false; });
return ret;
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#ifndef QUEUEDTCPSERVERRESPONSEHELPERAUTH_H
#define QUEUEDTCPSERVERRESPONSEHELPERAUTH_H
#include <QVariant>
namespace QueuedTcpServerResponseHelperAuth
{
QVariantHash auth(const QVariantHash &_payload);
bool tryAuth(const QString &_token);
}; // namespace QueuedTcpServerResponseHelperAuth
#endif /* QUEUEDTCPSERVERRESPONSEHELPERAUTH_H */

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#include "QueuedTcpServerResponseHelperOption.h"
#include <queued/Queued.h>
QVariantHash QueuedTcpServerResponseHelperOption::getOption(const QString &_option,
const QString &_token)
{
qCDebug(LOG_SERV) << "Get option" << _option;
auto res = QueuedCoreAdaptor::getOption(_option, _token);
QVariantHash output;
res.match(
[&output](const QVariant &val) {
QVariantHash opt = {{"_option", val}};
output = {{"code", 200}, {"properties", opt}};
},
[&output](const QueuedError &) {
output = {{"code", 404}, {"message", "Option not found"}};
});
return output;
}
QVariantHash QueuedTcpServerResponseHelperOption::setOption(const QString &_option,
const QVariantHash &_value,
const QString &_token)
{
qCDebug(LOG_SERV) << "Set option" << _option << "to" << _value;
if (!_value.contains("value"))
return {{"code", 400}, {"message", "No required fields found"}};
auto res = QueuedCoreAdaptor::sendOptionEdit(_option, _value["value"], _token);
QVariantHash output;
res.match(
[&output](const QVariant &) {
output = {{"code", 200}};
},
[&output](const QueuedError &err) {
output = {{"code", 500}, {"message", err.message().c_str()}};
});
return output;
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#ifndef QUEUEDTCPSERVERRESPONSEHELPEROPTION_H
#define QUEUEDTCPSERVERRESPONSEHELPEROPTION_H
#include <QVariant>
namespace QueuedTcpServerResponseHelperOption
{
QVariantHash getOption(const QString &_option, const QString &_token);
QVariantHash setOption(const QString &_option, const QVariantHash &_value, const QString &_token);
}; // namespace QueuedTcpServerResponseHelperOption
#endif /* QUEUEDTCPSERVERRESPONSEHELPEROPTION_H */

View File

@ -0,0 +1,75 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#include "QueuedTcpServerResponseHelperPermissions.h"
#include <queued/Queued.h>
QVariantHash QueuedTcpServerResponseHelperPermissions::addPermission(const long long _id,
const QVariantHash &_value,
const QString &_token)
{
qCDebug(LOG_SERV) << "Add permission for" << _id << _value;
if (!_value.contains("permission"))
return {{"code", 400}, {"message", "No required fields found"}};
auto permission = QueuedEnums::stringToPermission(_value["permission"].toString());
if (permission == QueuedEnums::Permission::Invalid)
return {{"code", 400}, {"message", "Invalid permission"}};
auto res = QueuedCoreAdaptor::sendUserPermissionAdd(_id, permission, _token);
QVariantHash output;
res.match(
[&output](const QVariant &) {
output = {{"code", 200}};
},
[&output](const QueuedError &err) {
output = {{"code", 500}, {"message", err.message().c_str()}};
});
return output;
}
QVariantHash QueuedTcpServerResponseHelperPermissions::removePermission(const long long _id,
const QVariantHash &_value,
const QString &_token)
{
qCDebug(LOG_SERV) << "Remove permission for" << _id << _value;
if (!_value.contains("permission"))
return {{"code", 400}, {"message", "No required fields found"}};
auto permission = QueuedEnums::stringToPermission(_value["permission"].toString());
if (permission == QueuedEnums::Permission::Invalid)
return {{"code", 400}, {"message", "Invalid permission"}};
auto res = QueuedCoreAdaptor::sendUserPermissionRemove(_id, permission, _token);
QVariantHash output;
res.match(
[&output](const QVariant &) {
output = {{"code", 200}};
},
[&output](const QueuedError &err) {
output = {{"code", 500}, {"message", err.message().c_str()}};
});
return output;
}

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#ifndef QUEUEDTCPSERVERRESPONSEHELPERPERMISSIONS_H
#define QUEUEDTCPSERVERRESPONSEHELPERPERMISSIONS_H
#include <QVariant>
namespace QueuedTcpServerResponseHelperPermissions
{
QVariantHash addPermission(const long long _id, const QVariantHash &_value, const QString &_token);
QVariantHash removePermission(const long long _id, const QVariantHash &_value,
const QString &_token);
}; // namespace QueuedTcpServerResponseHelperPermissions
#endif /* QUEUEDTCPSERVERRESPONSEHELPERPERMISSIONS_H */

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#include "QueuedTcpServerResponseHelperPlugins.h"
#include <queued/Queued.h>
QVariantHash QueuedTcpServerResponseHelperPlugins::addPlugin(const QString &_name,
const QString &_token)
{
qCDebug(LOG_SERV) << "Add plugin" << _name;
auto res = QueuedCoreAdaptor::sendPluginAdd(_name, _token);
QVariantHash output;
res.match(
[&output](const bool) {
output = {{"code", 200}};
},
[&output](const QueuedError &err) {
output = {{"code", 500}, {"message", err.message().c_str()}};
});
return output;
}
QVariantHash QueuedTcpServerResponseHelperPlugins::getPlugin(const QString &_name,
const QString &_token)
{
qCDebug(LOG_SERV) << "Get plugin" << _name;
auto res = QueuedCoreAdaptor::getPlugin(_name, _token);
QVariantHash output;
res.match(
[&output](const QueuedPluginSpecification::Plugin &val) {
auto dump = QueuedPluginSpecification::dumpSpecification(val);
QVariantList plugins = {dump};
output = {{"code", 200}, {"plugins", plugins}};
},
[&output](const QueuedError &err) {
output = {{"code", 500}, {"message", err.message().c_str()}};
});
return output;
}
QVariantHash QueuedTcpServerResponseHelperPlugins::listPlugins()
{
auto res = QueuedCoreAdaptor::getOption(QueuedConfig::QueuedSettings::Plugins, "");
QVariantHash output;
res.match(
[&output](const QVariant &val) {
output = {{"code", 200}, {"plugins", val.toStringList()}};
},
[&output](const QueuedError &err) {
output = {{"code", 500}, {"message", err.message().c_str()}};
});
return output;
}
QVariantHash QueuedTcpServerResponseHelperPlugins::removePlugin(const QString &_name,
const QString &_token)
{
qCDebug(LOG_SERV) << "Remove plugin" << _name;
auto res = QueuedCoreAdaptor::sendPluginRemove(_name, _token);
QVariantHash output;
res.match(
[&output](const bool) {
output = {{"code", 200}};
},
[&output](const QueuedError &err) {
output = {{"code", 500}, {"message", err.message().c_str()}};
});
return output;
}

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#ifndef QUEUEDTCPSERVERRESPONSEHELPLUGINS_H
#define QUEUEDTCPSERVERRESPONSEHELPLUGINS_H
#include <QVariant>
namespace QueuedTcpServerResponseHelperPlugins
{
QVariantHash addPlugin(const QString &_name, const QString &_token);
QVariantHash getPlugin(const QString &_name, const QString &_token);
QVariantHash listPlugins();
QVariantHash removePlugin(const QString &_name, const QString &_token);
}; // namespace QueuedTcpServerResponseHelperPlugins
#endif /* QUEUEDTCPSERVERRESPONSEHELPLUGINS_H */

View File

@ -0,0 +1,203 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#include "QueuedTcpServerResponseHelperTask.h"
#include <queued/Queued.h>
QVariantHash QueuedTcpServerResponseHelperTask::addOrEditTask(const long long _id,
const QVariantHash &_data,
const QString &_token)
{
qCDebug(LOG_SERV) << "Add or edit task" << _id << "with data" << _data;
auto defs = getDefinitions(_data);
QVariantHash output;
if (_id > 0) {
// edit existing task
auto res = QueuedCoreAdaptor::sendTaskEdit(_id, defs, _token);
res.match(
[&output](const bool val) {
output = {{"code", val ? 200 : 500}};
},
[&output](const QueuedError &err) {
output = {{"code", 500}, {"message", err.message().c_str()}};
});
} else {
// add new task
auto res = QueuedCoreAdaptor::sendTaskAdd(defs, _token);
res.match(
[&output](const long long val) {
output = {{"code", val ? 200 : 500}, {"id", val}};
},
[&output](const QueuedError &err) {
output = {{"code", 500}, {"message", err.message().c_str()}};
});
}
return output;
}
QueuedProcess::QueuedProcessDefinitions
QueuedTcpServerResponseHelperTask::getDefinitions(const QVariantHash &_data)
{
qCDebug(LOG_SERV) << "Get definitions from" << _data;
auto defs = QueuedProcess::QueuedProcessDefinitions();
auto args = _data["arguments"].toList();
for (auto &arg : args)
defs.arguments.append(arg.toString());
defs.command = _data["command"].toString();
defs.endTime = QDateTime::fromString(_data["end"].toString(), Qt::ISODateWithMs);
defs.gid = _data["gid"].toUInt();
defs.nice = _data["nice"].toUInt();
defs.startTime = QDateTime::fromString(_data["start"].toString(), Qt::ISODateWithMs);
defs.uid = _data["uid"].toUInt();
defs.user = _data["user"].toLongLong();
defs.workingDirectory = _data["workingDirectory"].toString();
// limits
QueuedLimits::Limits limits;
limits.cpu = _data["limitCpu"].toLongLong();
limits.gpu = _data["limitGpu"].toLongLong();
limits.memory = _data["limitMemory"].toLongLong();
limits.gpumemory = _data["limitGpumemory"].toLongLong();
limits.storage = _data["limitStorage"].toLongLong();
defs.limits = limits.toString();
return defs;
}
QVariantHash QueuedTcpServerResponseHelperTask::getTask(const long long _id,
const QVariantHash &_data,
const QString &_token)
{
qCDebug(LOG_SERV) << "Get task" << _id << _data;
auto property = _data["property"].toString();
QVariantHash output = {{"code", 200}};
if (property.isEmpty()) {
auto res = QueuedCoreAdaptor::getTask(_id, _token);
res.match([&output](const QVariantHash &val) { output["properties"] = val; },
[&output](const QueuedError &err) {
output = {{"code", 500}, {"message", err.message().c_str()}};
});
} else {
auto res = QueuedCoreAdaptor::getTask(_id, property, _token);
res.match(
[&output, &property](const QVariant &val) {
output["properties"] = {{property, val}};
},
[&output](const QueuedError &err) {
output = {{"code", 500}, {"message", err.message().c_str()}};
});
}
return output;
}
QVariantHash QueuedTcpServerResponseHelperTask::getTasks(const QVariantHash &_data,
const QString &_token)
{
qCDebug(LOG_SERV) << "Get tasks" << _data;
long long userId = _data.value("userId").toLongLong();
QDateTime start = QDateTime::fromString(_data["start"].toString(), Qt::ISODateWithMs);
QDateTime stop = QDateTime::fromString(_data["stop"].toString(), Qt::ISODateWithMs);
QVariantHash output;
// some conversion magic
QVariantList outputReport;
auto res = QueuedCoreAdaptor::getTasks(userId, start, stop, _token);
res.match(
[&output, &outputReport](const QList<QVariantHash> &val) {
for (auto &user : val)
outputReport += user;
output = {{"code", 200}, {"report", outputReport}};
},
[&output](const QueuedError &err) {
output = {{"code", 500}, {"message", err.message().c_str()}};
});
return output;
}
QVariantHash QueuedTcpServerResponseHelperTask::startOrStopTask(const long long _id,
const QString &_token)
{
qCDebug(LOG_SERV) << "Change task state" << _id;
auto res = QueuedCoreAdaptor::getTask(_id, _token);
QVariantHash output;
res.match(
[&output, &_id, &_token](const QVariantHash &val) {
if (val["startTime"].toString().isEmpty() || !val["endTime"].toString().isEmpty())
output = startTask(_id, _token);
else
output = stopTask(_id, _token);
},
[&output](const QueuedError &err) {
output = {{"code", 400}, {"message", err.message().c_str()}};
});
return output;
}
QVariantHash QueuedTcpServerResponseHelperTask::startTask(const long long _id,
const QString &_token)
{
qCDebug(LOG_SERV) << "Start task" << _id;
auto res = QueuedCoreAdaptor::sendTaskStart(_id, _token);
QVariantHash output;
res.match(
[&output](const bool val) {
output = {{"code", val ? 200 : 500}};
},
[&output](const QueuedError &err) {
output = {{"code", 500}, {"message", err.message().c_str()}};
});
return output;
}
QVariantHash QueuedTcpServerResponseHelperTask::stopTask(const long long _id, const QString &_token)
{
qCDebug(LOG_SERV) << "Stop task" << _id;
auto res = QueuedCoreAdaptor::sendTaskStop(_id, _token);
QVariantHash output;
res.match(
[&output](const bool val) {
output = {{"code", val ? 200 : 500}};
},
[&output](const QueuedError &err) {
output = {{"code", 500}, {"message", err.message().c_str()}};
});
return output;
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#ifndef QUEUEDTCPSERVERRESPONSEHELTASK_H
#define QUEUEDTCPSERVERRESPONSEHELTASK_H
#include <QVariant>
#include <queued/QueuedProcess.h>
namespace QueuedTcpServerResponseHelperTask
{
QVariantHash addOrEditTask(const long long _id, const QVariantHash &_data, const QString &_token);
QueuedProcess::QueuedProcessDefinitions getDefinitions(const QVariantHash &_data);
QVariantHash getTask(const long long _id, const QVariantHash &_data, const QString &_token);
QVariantHash getTasks(const QVariantHash &_data, const QString &_token);
QVariantHash startOrStopTask(const long long _id, const QString &_token);
QVariantHash startTask(const long long _id, const QString &_token);
QVariantHash stopTask(const long long _id, const QString &_token);
}; // namespace QueuedTcpServerResponseHelperTask
#endif /* QUEUEDTCPSERVERRESPONSEHELTASK_H */

View File

@ -0,0 +1,174 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#include "QueuedTcpServerResponseHelperUser.h"
#include <queued/Queued.h>
#include <queued/QueuedUser.h>
QVariantHash QueuedTcpServerResponseHelperUser::addOrEditUser(const QString &_user,
const QVariantHash &_data,
const QString &_token)
{
qCDebug(LOG_SERV) << "Add user" << _user << "with data" << _data;
// try define if user exists first
auto userIdRes = QueuedCoreAdaptor::getUserId(_user, _token);
long long userId = -1;
userIdRes.match([&userId](const long long val) { userId = val; },
[&userId](const QueuedError &) {});
auto defs = getDefinitions(_data);
defs.name = _user;
QVariantHash output;
if (userId > 0) {
// edit existing user
auto res = QueuedCoreAdaptor::sendUserEdit(userId, defs, _token);
res.match(
[&output](const bool val) {
output = {{"code", val ? 200 : 500}};
},
[&output](const QueuedError &err) {
output = {{"code", 500}, {"message", err.message().c_str()}};
});
} else {
// add new user
auto res = QueuedCoreAdaptor::sendUserAdd(defs, _token);
res.match(
[&output](const long long val) {
output = {{"code", val ? 200 : 500}, {"id", val}};
},
[&output](const QueuedError &err) {
output = {{"code", 500}, {"message", err.message().c_str()}};
});
}
return output;
}
QueuedUser::QueuedUserDefinitions
QueuedTcpServerResponseHelperUser::getDefinitions(const QVariantHash &_data)
{
qCDebug(LOG_SERV) << "Generate definitions from" << _data;
QueuedUser::QueuedUserDefinitions defs;
defs.email = _data["email"].toString();
auto res = QueuedCoreAdaptor::sendPasswordHash(_data["password"].toString());
res.match([&defs](const QString &val) { defs.password = val; }, [](const QueuedError &) {});
defs.permissions = _data["permissions"].toUInt();
defs.priority = _data["priority"].toUInt();
// limits
QueuedLimits::Limits limits;
limits.cpu = _data["limitCpu"].toLongLong();
limits.gpu = _data["limitGpu"].toLongLong();
limits.memory = _data["limitMemory"].toLongLong();
limits.gpumemory = _data["limitGpumemory"].toLongLong();
limits.storage = _data["limitStorage"].toLongLong();
defs.limits = limits.toString();
return defs;
}
QVariantHash QueuedTcpServerResponseHelperUser::getReport(const QVariantHash &_data,
const QString &_token)
{
qCDebug(LOG_SERV) << "Get report using payload" << _data;
QDateTime stop = QDateTime::fromString(_data["stop"].toString(), Qt::ISODateWithMs);
QDateTime start = QDateTime::fromString(_data["start"].toString(), Qt::ISODateWithMs);
QVariantHash output = {{"code", 200}};
// some conversion magic
QVariantList outputReport;
auto res = QueuedCoreAdaptor::getPerformance(start, stop, _token);
res.match(
[&output, &outputReport](const QList<QVariantHash> &val) {
for (auto &user : val)
outputReport += user;
output = {{"code", 200}, {"report", outputReport}};
},
[&output](const QueuedError &err) {
output = {{"code", 500}, {"message", err.message().c_str()}};
});
return output;
}
QVariantHash QueuedTcpServerResponseHelperUser::getUser(const QString &_user,
const QVariantHash &_data,
const QString &_token)
{
qCDebug(LOG_SERV) << "Get user data for" << _user << _data;
auto userIdRes = QueuedCoreAdaptor::getUserId(_user, _token);
long long userId = -1;
userIdRes.match([&userId](const long long val) { userId = val; }, [](const QueuedError &) {});
if (userId == -1)
return {{"code", 500}};
auto property = _data["property"].toString();
QVariantHash output = {{"code", 200}};
if (property.isEmpty()) {
auto res = QueuedCoreAdaptor::getUser(userId, _token);
res.match([&output](const QVariantHash &val) { output["properties"] = val; },
[&output](const QueuedError &err) {
output = {{"code", 500}, {"message", err.message().c_str()}};
});
} else {
auto res = QueuedCoreAdaptor::getUser(userId, property, _token);
res.match(
[&output, &property](const QVariant &val) {
output["properties"] = {{property, val}};
},
[&output](const QueuedError &err) {
output = {{"code", 500}, {"message", err.message().c_str()}};
});
}
return output;
}
QVariantHash QueuedTcpServerResponseHelperUser::getUsers(const QVariantHash &_data,
const QString &_token)
{
qCDebug(LOG_SERV) << "Get users" << _data;
QDateTime lastLogin = QDateTime::fromString(_data["lastLogged"].toString(), Qt::ISODateWithMs);
auto permission = QueuedEnums::stringToPermission(_data["permission"].toString());
QVariantHash output = {{"code", 200}};
// some conversion magic
QVariantList outputReport;
auto res = QueuedCoreAdaptor::getUsers(lastLogin, permission, _token);
res.match(
[&output, &outputReport](const QList<QVariantHash> &val) {
for (auto &user : val)
outputReport += user;
output = {{"code", 200}, {"report", outputReport}};
},
[&output](const QueuedError &err) {
output = {{"code", 500}, {"message", err.message().c_str()}};
});
return output;
}

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#ifndef QUEUEDTCPSERVERRESPONSEHELUSER_H
#define QUEUEDTCPSERVERRESPONSEHELUSER_H
#include <QVariant>
#include <queued/QueuedUser.h>
namespace QueuedTcpServerResponseHelperUser
{
QVariantHash addOrEditUser(const QString &_user, const QVariantHash &_data, const QString &_token);
QueuedUser::QueuedUserDefinitions getDefinitions(const QVariantHash &_data);
QVariantHash getReport(const QVariantHash &_data, const QString &_token);
QVariantHash getUser(const QString &_user, const QVariantHash &_data, const QString &_token);
QVariantHash getUsers(const QVariantHash &_data, const QString &_token);
}; // namespace QueuedTcpServerResponseHelperUser
#endif /* QUEUEDTCPSERVERRESPONSEHELUSER_H */

View File

@ -0,0 +1,220 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#include "QueuedTcpServerThread.h"
#include <QDataStream>
#include <QJsonDocument>
#include <QNetworkRequest>
#include <QTcpSocket>
#include <QUrlQuery>
#include <queued/Queued.h>
#include "QueuedTcpServerResponseHelper.h"
QueuedTcpServerThread::QueuedTcpServerThread(int socketDescriptor, const int timeout,
QObject *parent)
: QThread(parent)
, m_socketDescriptor(socketDescriptor)
, m_timeout(timeout)
{
qCDebug(LOG_SERV) << __PRETTY_FUNCTION__;
}
QueuedTcpServerThread::~QueuedTcpServerThread()
{
qCDebug(LOG_SERV) << __PRETTY_FUNCTION__;
if (m_socket)
m_socket->deleteLater();
}
QByteArrayList QueuedTcpServerThread::defaultResponse(const int code, const QVariantHash &json)
{
qCDebug(LOG_SERV) << "Build server response with code" << code << "and json";
QList<QByteArray> output;
output += "HTTP/1.1 " + QByteArray::number(code) + " "
+ QueuedTcpServerResponseHelper::HTTPCodeMap[code] + "\r\n";
output += "Server: QueuedServer/Qt" + QByteArray(qVersion()) + "\r\n";
output += "Date: "
+ QLocale::c()
.toString(QDateTime::currentDateTimeUtc(), "ddd, d MMM yyyy HH:mm:dd t")
.toUtf8()
+ "\r\n";
output += "Content-Type: application/json\r\n";
output += "\r\n";
// json response
if (!json.isEmpty()) {
auto jsonObj = QJsonObject::fromVariantHash(json);
auto jsonByte = QJsonDocument(jsonObj).toJson(QJsonDocument::JsonFormat::Compact);
output += jsonByte;
}
return output;
}
QueuedTcpServerThread::QueuedTcpServerHeaders
QueuedTcpServerThread::getHeaders(const QStringList &headers)
{
qCDebug(LOG_SERV) << "Get headers object from" << headers;
auto headersObj = QueuedTcpServerThread::QueuedTcpServerHeaders();
// metadata
auto protocolData = headers.first().split(' ');
if (protocolData.count() >= 3) {
headersObj.request = protocolData.takeFirst();
headersObj.protocol = protocolData.takeLast();
headersObj.query = protocolData.join(' ');
}
// headers
for (auto &header : headers.mid(1)) {
auto parsed = header.split(": ");
if (parsed.count() < 2)
continue;
headersObj.headers += QPair<QByteArray, QByteArray>(
{parsed.first().toUtf8().toLower(), parsed.mid(1).join(": ").toUtf8()});
}
return headersObj;
}
QueuedTcpServerThread::QueuedTcpServerRequest
QueuedTcpServerThread::getRequest(const QByteArray &body,
const QueuedTcpServerThread::QueuedTcpServerHeaders &headers)
{
qCDebug(LOG_SERV) << "Get request object from body" << body;
QueuedTcpServerThread::QueuedTcpServerRequest request;
request.headers = headers;
// body
auto error = QJsonParseError();
auto jsonDoc = QJsonDocument::fromJson(body, &error);
if (error.error == QJsonParseError::NoError)
request.data = jsonDoc.object().toVariantHash();
else
qCWarning(LOG_SERV) << "Parse error" << error.errorString();
// append from url if any
auto items = QUrlQuery(headers.query.query()).queryItems();
for (auto &item : items) {
auto key = item.first;
auto value = item.second;
QVariantList values;
switch (request.data[key].type()) {
case QVariant::List:
values = request.data[key].toList();
break;
case QVariant::Invalid:
break;
default:
values = QVariantList({request.data[key]});
break;
}
values.append(value);
request.data[key] = values.count() == 1 ? values.first() : values;
}
return request;
}
QueuedTcpServerThread::QueuedTcpServerResponse
QueuedTcpServerThread::response(const QueuedTcpServerRequest &request) const
{
qCDebug(LOG_SERV) << "Build response for request" << request.headers.query;
QueuedTcpServerThread::QueuedTcpServerResponse response;
// HACK additional workaround to parse content type header
QNetworkRequest netRequest;
for (auto &headers : request.headers.headers)
netRequest.setRawHeader(headers.first, headers.second);
// prepend code
if (netRequest.header(QNetworkRequest::KnownHeaders::ContentTypeHeader).toString()
!= "application/json")
response.code = 415;
else
response.code = 200;
QString token = netRequest.rawHeader(QueuedConfig::WEBAPI_TOKEN_HEADER);
// json data
if (response.code == 200) {
auto req = QueuedTcpServerResponseHelper::parsePath(request.headers.query.path());
req.type = request.headers.request;
if (req.valid) {
response.data = QueuedTcpServerResponseHelper::getData(req, request.data, token);
response.code = response.data["code"].toInt();
} else {
response.code = 404;
}
}
return response;
}
void QueuedTcpServerThread::run()
{
m_socket = new QTcpSocket(nullptr);
if (!m_socket->setSocketDescriptor(m_socketDescriptor)) {
qCWarning(LOG_SERV) << "Socket error" << m_socket->error();
return;
}
connect(m_socket, SIGNAL(readyRead()), this, SLOT(readyRead()), Qt::DirectConnection);
exec();
}
void QueuedTcpServerThread::readyRead()
{
QStringList headers;
while (m_socket->canReadLine())
headers += m_socket->readLine().simplified();
// request body
auto body = m_socket->readAll().simplified();
// get request object
auto headersObj = getHeaders(headers);
auto requestObj = getRequest(body, headersObj);
auto responseObj = response(requestObj);
auto responseList = defaultResponse(responseObj.code, responseObj.data);
for (auto &resp : responseList)
m_socket->write(resp);
m_socket->flush();
// TODO use timeouts?
if (m_socket->state() != QAbstractSocket::UnconnectedState)
m_socket->waitForBytesWritten(m_timeout);
m_socket->disconnectFromHost();
if (m_socket->state() != QAbstractSocket::UnconnectedState)
m_socket->waitForDisconnected();
exit(0);
}

View File

@ -0,0 +1,66 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#ifndef QUEUEDTCPSERVERTHREAD_H
#define QUEUEDTCPSERVERTHREAD_H
#include <QThread>
#include <QUrl>
#include <QVariant>
class QTcpSocket;
class QueuedTcpServerThread : public QThread
{
Q_OBJECT
public:
typedef struct {
QList<QPair<QByteArray, QByteArray>> headers;
QString protocol;
QUrl query;
QString request;
} QueuedTcpServerHeaders;
typedef struct {
QueuedTcpServerHeaders headers;
QVariantHash data;
} QueuedTcpServerRequest;
typedef struct {
int code;
QVariantHash data;
} QueuedTcpServerResponse;
explicit QueuedTcpServerThread(int socketDescriptor, const int timeout, QObject *parent);
virtual ~QueuedTcpServerThread();
static QByteArrayList defaultResponse(const int code, const QVariantHash &json);
static QueuedTcpServerHeaders getHeaders(const QStringList &headers);
static QueuedTcpServerRequest getRequest(const QByteArray &body,
const QueuedTcpServerHeaders &headers);
QueuedTcpServerResponse response(const QueuedTcpServerRequest &request) const;
void run() override;
private slots:
void readyRead();
private:
QTcpSocket *m_socket = nullptr;
int m_socketDescriptor;
int m_timeout = -1;
};
#endif /* QUEUEDTCPSERVERTHREAD_H */

View File

@ -0,0 +1,92 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
#include <QCommandLineParser>
#include <QDBusConnection>
#include <queued/Queued.h>
#include <csignal>
#include <iostream>
#include "QueuedServer.h"
#include "version.h"
extern "C" {
#include <unistd.h>
}
QueuedServer *instance = nullptr;
int main(int argc, char *argv[])
{
// HACK preparse arguments to find out if --daemon is set
for (int i = 0; i < argc; i++) {
if (std::string(argv[i]) != "--daemon")
continue;
::daemon(0, 0);
break;
}
QueuedDebug::applyLogFormat();
QCoreApplication app(argc, argv);
app.setApplicationName(NAME);
app.setApplicationVersion(VERSION);
// parser
QCommandLineParser parser;
parser.setApplicationDescription("Daemon for starting jobs to queue of calculations");
parser.addHelpOption();
parser.addVersionOption();
// info
QCommandLineOption infoOption({"i", "info"}, "Show additional info.");
parser.addOption(infoOption);
// debug mode
QCommandLineOption debugOption({"d", "debug"}, "Print debug information.");
parser.addOption(debugOption);
// daemon mode
QCommandLineOption daemonOption("daemon", "Start detached.");
parser.addOption(daemonOption);
parser.process(app);
// show info and exit
if (parser.isSet(infoOption)) {
auto metadata = QueuedDebug::getBuildData();
for (auto &string : metadata)
std::cout << qPrintable(string) << std::endl;
return 0;
}
// enable debug
if (parser.isSet(debugOption))
QueuedDebug::enableDebug();
QVariantHash arguments;
// start application
instance = new QueuedServer(nullptr, arguments);
// catch SIGHUP
signal(SIGHUP, [](int sig) -> void {
qCInfo(LOG_SERV) << "Received SIGHUP signal, reinit components";
instance->init();
});
return app.exec();
}

View File

View File

@ -1,14 +0,0 @@
## Configuration file for queued
## Paths
# path to directory with source jobs
WORKDIR=/home/arcanis/qdwork
# path to directory with running jobs
JOBDIR=/home/arcanis/qdjob
# path to file with queue list
QUEUEFILE=/home/arcanis/qdlist
## Additional parametrs
# default priority
PRIORITY=0
# start as user
STARTASUSER=arcanis

View File

@ -1,11 +0,0 @@
[Unit]
Description=Queue daemon
[Service]
EnvironmentFile=/etc/queued.conf
Type=forking
ExecStart=/usr/bin/queued -jd $JOBDIR --priority $PRIORITY -q $QUEUEFILE -u $STARTASUSER -wd $WORKDIR
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,14 @@
set (SUBPROJECT "queued")
message (STATUS "Subproject ${SUBPROJECT}")
configure_file ("QueuedConfig.h.in" "${CMAKE_BINARY_DIR}/QueuedConfig.h")
include("adds.cmake")
add_subdirectory ("src")
# headers
install (DIRECTORY "include/${SUBPROJECT}" DESTINATION "${INCLUDE_INSTALL_DIR}")
install (FILES "${CMAKE_BINARY_DIR}/QueuedConfig.h" DESTINATION "${INCLUDE_INSTALL_DIR}/${SUBPROJECT}")
# documentation
if (BUILD_DOCS)
include ("docs.cmake")
endif ()

View File

@ -0,0 +1,58 @@
#
# Copyright (c) 2017 Queued team
#
# 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.
##
# @file QueuedConfig.cmake
# Additional file of queued library
# @author Queued team
# @copyright MIT
# @bug https://github.com/arcan1s/queued/issues
##
##
# @brief try to find queued libraries
##
##
# @def QUEUED_DEFINITIONS
# optional cmake definitions
##
set(QUEUED_DEFINITIONS "")
##
# @def QUEUED_INCLUDE_DIRS
# path to root include directory
##
find_path(QUEUEDCORE_INCLUDE_DIR "queued/Queued.h" PATH_SUFFIXES "queued")
set(QUEUED_INCLUDE_DIRS "${QUEUEDCORE_INCLUDE_DIR}")
##
# @def QUEUED_LIBRARIES
# queued library name
##
find_library(QUEUEDCORE_LIBRARY NAMES "queued" "libqueued"
PATH_SUFFIXES "queued")
set(QUEUED_LIBRARIES "${QUEUEDCORE_LIBRARY}")
##
# @def QUEUED_FOUND
# boolean, true if library has been found
##
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Queued DEFAULT_MSG
QUEUED_LIBRARIES QUEUED_INCLUDE_DIRS)
##
# @brief additional defined macros
##
include("${CMAKE_CURRENT_LIST_DIR}/QueuedPaths.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/QueuedLibraries.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/QueuedMacros.cmake")

View File

@ -0,0 +1,125 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedConfig.h
* Source code of queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDCONFIG_H
#define QUEUEDCONFIG_H
/**
* @addtogroup QueuedConfig
* @brief Queued configuration constants
*/
namespace QueuedConfig
{
// dbus configuration
/**
* @brief DBus service name for library and application
* @remark required by Qt macro
*/
#define DBUS_SERVICE_NAME "org.queued.core"
/**
* @brief DBus service name for library and application
*/
static const char DBUS_SERVICE[] = DBUS_SERVICE_NAME;
/**
* @brief DBus object path for application
*/
static const char DBUS_APPLICATION_PATH[] = "/application";
/**
* @brief DBus object path for library
*/
static const char DBUS_OBJECT_PATH[] = "/queued";
/**
* @brief DBus properties path for properties library
*/
static const char DBUS_PROPERTY_PATH[] = "/property";
/**
* @brief DBus properties path for reports library
*/
static const char DBUS_REPORTS_PATH[] = "/report";
// path configuration
// common paths
/**
* @brief installation directory for executables
*/
static const char BIN_INSTALL_DIR[] = "@BIN_INSTALL_DIR@";
/**
* @brief installation directory for data
*/
static const char DATA_INSTALL_DIR[] = "@DATA_INSTALL_DIR@";
/**
* @brief installation directory for headers
*/
static const char INCLUDE_INSTALL_DIR[] = "@INCLUDE_INSTALL_DIR@";
/**
* @brief installation directory for libraries
*/
static const char LIB_INSTALL_DIR[] = "@LIB_INSTALL_DIR@";
/**
* @brief the same as CMAKE_INSTALL_PREFIX
*/
static const char ROOT_INSTALL_DIR[] = "@CMAKE_INSTALL_PREFIX@";
// application specific
/**
* @brief path to queued home directory
*/
static const char HOME_PATH[] = "queued";
/**
* @brief path to plugins inside @ref HOME_PATH
*/
static const char PLUGIN_PATH[] = "plugins";
// internal configuration
/**
* @brief version of internal storage
*/
static const int DATABASE_VERSION = 1;
/**
* @brief header name for token
*/
static const char WEBAPI_TOKEN_HEADER[] = "x-queued-token";
/**
* @brief supported web server API versions
*/
static const int WEBAPI_VERSIONS[] = {1};
// cgroups configuration
/**
* @brief path to root directory of cgroups
*/
static const char CG_FS_PATH[] = "/sys/fs/cgroup";
// plugin interfaces
/**
* @brief plugin interface name
* @remark required by Qt macro
*/
#define PLUGIN_INTERFACE_NAME "org.queued.plugin/@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@"
/**
* @brief plugin interface name
*/
static const char PLUGIN_INTERFACE[] = PLUGIN_INTERFACE_NAME;
} // namespace QueuedConfig
#endif /* QUEUEDCONFIG_H */

View File

@ -0,0 +1,50 @@
#
# Copyright (c) 2017 Queued team
#
# 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.
##
# @file QueuedLibraries.cmake
# Additional file of queued library
# @author Queued team
# @copyright MIT
# @bug https://github.com/arcan1s/queued/issues
##
##
# @brief Queued common libraries
##
find_package(Qt5 5.8.0 REQUIRED COMPONENTS Core DBus Network Sql)
##
# @brief add Qt definitions
##
add_definitions(
${Qt5Core_DEFINITIONS} ${Qt5DBus_DEFINITIONS} ${Qt5Network_DEFINITIONS}
${Qt5Sql_DEFINITIONS}
)
##
# @def Qt_INCLUDE
# Qt include paths
##
set(Qt_INCLUDE
${Qt5Core_INCLUDE_DIRS} ${Qt5DBus_INCLUDE_DIRS}
${Qt5Network_INCLUDE_DIRS} ${Qt5Sql_INCLUDE_DIRS}
)
##
# @def Qt_LIBRARIES
# Qt libraries
##
set(Qt_LIBRARIES
${Qt5Core_LIBRARIES} ${Qt5DBus_LIBRARIES} ${Qt5Network_LIBRARIES}
${Qt5Sql_LIBRARIES}
)

View File

@ -0,0 +1,63 @@
#
# Copyright (c) 2017 Queued team
#
# 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.
##
# @file QueuedMacros.cmake
# Additional file of queued library
# @author Queued team
# @copyright MIT
# @bug https://github.com/arcan1s/queued/issues
##
##
# @brief additional macros for queued
##
##
# @fn queued_install_plugin root [name] [libraries]
# @brief build and install plugin
# @param PLUGIN_ROOT
# plugin root directory
# @param PLUGIN
# plugin name (optional). Will be assigned from path if empty
# @param ADDS_LIBRARIES
# additional libraries (optional)
##
macro(queued_install_plugin PLUGIN_ROOT)
set(PLUGIN "${ARGV1}")
if (NOT PLUGIN)
set(PLUGIN "${PLUGIN_ROOT}")
endif()
set(ADDS_LIBRARIES "${ARGV2}")
message (STATUS "Plugin ${PLUGIN}")
# get sources
file (GLOB_RECURSE ${PLUGIN}_SOURCES "${PLUGIN_ROOT}/*.cpp")
file (GLOB_RECURSE ${PLUGIN}_HEADERS "${PLUGIN_ROOT}/*.h")
qt5_wrap_cpp (${PLUGIN}_MOC_SOURCES "${${PLUGIN}_HEADERS}")
# include directories
include_directories ("${CMAKE_CURRENT_BINARY_DIR}"
"${Qt_INCLUDE}" "${QUEUED_INCLUDE_DIRS}")
# build
add_library ("${PLUGIN}" MODULE "${${PLUGIN}_SOURCES}"
"${${PLUGIN}_HEADERS}" "${${PLUGIN}_MOC_SOURCES}")
target_link_libraries ("${PLUGIN}" "${QUEUED_LIBRARIES}" "${Qt_LIBRARIES}"
"${ADDS_LIBRARIES}")
# install
install (TARGETS "${PLUGIN}" DESTINATION "${QUEUED_PLUGIN_ROOT}")
install (FILES "${PLUGIN_ROOT}/${PLUGIN}.json" DESTINATION
"${QUEUED_PLUGIN_ROOT}")
endmacro()

View File

@ -0,0 +1,56 @@
#
# Copyright (c) 2017 Queued team
#
# 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.
##
# @file QueuedPaths.cmake
# Additional file of queued library
# @author Queued team
# @copyright MIT
# @bug https://github.com/arcan1s/queued/issues
##
##
# @brief Queued common paths
##
##
# @def BIN_INSTALL_DIR
# installation directory for executables
##
set(BIN_INSTALL_DIR "@BIN_INSTALL_DIR@")
##
# @def DATA_INSTALL_DIR
# installation directory for data
##
set(DATA_INSTALL_DIR "@DATA_INSTALL_DIR@")
##
# @def INCLUDE_INSTALL_DIR
# installation directory for headers
##
set(INCLUDE_INSTALL_DIR "@INCLUDE_INSTALL_DIR@")
##
# @def LIB_INSTALL_DIR
# installation directory for libraries
##
set(LIB_INSTALL_DIR "@LIB_INSTALL_DIR@")
##
# @def QUEUED_ROOT
# queued root directory
##
set(QUEUED_ROOT "${DATA_INSTALL_DIR}/queued")
##
# @def QUEUED_PLUGIN_ROOT
# queued plugins root directory
##
set(QUEUED_PLUGIN_ROOT "${QUEUED_ROOT}/plugins")

View File

@ -0,0 +1,8 @@
# configure paths
configure_file ("QueuedPaths.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/QueuedPaths.cmake" @ONLY)
# additional files
install (FILES "QueuedConfig.cmake" DESTINATION "${LIB_INSTALL_DIR}/cmake/Queued")
install (FILES "QueuedLibraries.cmake" DESTINATION "${LIB_INSTALL_DIR}/cmake/Queued")
install (FILES "QueuedMacros.cmake" DESTINATION "${LIB_INSTALL_DIR}/cmake/Queued")
install (FILES "${CMAKE_CURRENT_BINARY_DIR}/QueuedPaths.cmake" DESTINATION "${LIB_INSTALL_DIR}/cmake/Queued")
install (FILES "${PROJECT_TRDPARTY_DIR}/result/result.hpp" DESTINATION "${INCLUDE_INSTALL_DIR}/${SUBPROJECT}/result")

View File

@ -0,0 +1,8 @@
# doxygen documentation
find_package (Doxygen)
configure_file ("doxygen.conf.in" "${CMAKE_CURRENT_BINARY_DIR}/doxygen.conf")
add_custom_target ("docs" ALL COMMAND "${DOXYGEN_EXECUTABLE}" "${CMAKE_CURRENT_BINARY_DIR}/doxygen.conf")
# html docs
install (DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/docs/html" DESTINATION "${DATA_INSTALL_DIR}/doc/${SUBPROJECT}")

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file Queued.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUED_H
#define QUEUED_H
#include "QueuedAdvancedSettings.h"
#include "QueuedControlGroupsAdaptor.h"
#include "QueuedCore.h"
#include "QueuedCoreAdaptor.h"
#include "QueuedCoreInterface.h"
#include "QueuedDatabase.h"
#include "QueuedDatabaseManager.h"
#include "QueuedDebug.h"
#include "QueuedEnums.h"
#include "QueuedExceptions.h"
#include "QueuedLimits.h"
#include "QueuedPluginInterface.h"
#include "QueuedPluginManager.h"
#include "QueuedPluginManagerInterface.h"
#include "QueuedPluginSpecification.h"
#include "QueuedProcess.h"
#include "QueuedProcessManager.h"
#include "QueuedPropertyInterface.h"
#include "QueuedReportInterface.h"
#include "QueuedReportManager.h"
#include "QueuedResult.h"
#include "QueuedSettings.h"
#include "QueuedStaticConfig.h"
#include "QueuedSystemInfo.h"
#include "QueuedTokenManager.h"
#include "QueuedUser.h"
#include "QueuedUserManager.h"
#endif /* QUEUED_H */

View File

@ -0,0 +1,148 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedAdvancedSettings.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDADVANCEDSETTINGS_H
#define QUEUEDADVANCEDSETTINGS_H
#include <QObject>
#include <QVariant>
namespace QueuedConfig
{
enum class QueuedSettings;
}
/**
* @brief implementation over database stored settings
*/
class QueuedAdvancedSettings : public QObject
{
Q_OBJECT
public:
/**
* @brief QueuedAdvancedSettings class constructor
* @param parent
* pointer to parent item
*/
explicit QueuedAdvancedSettings(QObject *parent);
/**
* @brief QueuedAdvancedSettings class destructor
*/
virtual ~QueuedAdvancedSettings();
/**
* @brief check database version
* @return true if no version update required, otherwise return false
*/
bool checkDatabaseVersion() const;
/**
* @brief get value
* @param _key
* key to search in
* @return value by key if found
*/
QVariant get(const QString &_key) const;
/**
* @brief get value
* @param _key
* key to search in
* @return value by key if found
*/
QVariant get(const QueuedConfig::QueuedSettings _key) const;
/**
* @brief get database value ID
* @param _key
* key to search in
* @return database id or -1 if not found
*/
long long id(const QString &_key) const;
/**
* @brief get internal ID by given string key
* @param _key
* string key
* @return ID in settings representation
*/
static QString internalId(const QString &_key);
/**
* @brief get internal ID by given string key
* @param _key
* string key
* @return ID in settings representation
*/
static QString internalId(const QueuedConfig::QueuedSettings _key);
/**
* @brief check whether requested option is admin only
* @param _key
* key to search in
* @return true if this value is hidden for non-admins
*/
bool isAdmin(const QString &_key) const;
/**
* @brief check whether requested option is admin only
* @param _key
* key to search in
* @return true if this value is hidden for non-admins
*/
bool isAdmin(const QueuedConfig::QueuedSettings &_key) const;
/**
* @brief set value
* @param _key
* key to change
* @param _value
* value to change
*/
void set(const QString &_key, const QVariant &_value);
/**
* @brief upload configuration from database in to internal format
* @param _values
* configuration values from database
*/
void set(const QList<QVariantHash> &_values);
signals:
/**
* @brief emits on each value update
* @param _id
* internal key id
* @param _key
* changed key
* @param _value
* changed value
*/
void valueUpdated(const QueuedConfig::QueuedSettings _id, const QString &_key,
const QVariant &_value);
private:
/**
* @brief stored values
*/
QVariantHash m_values;
/**
* @brief ids of values
*/
QHash<QString, long long> m_ids;
};
#endif /* QUEUEDADVANCEDSETTINGS_H */

View File

@ -0,0 +1,165 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedControlGroupsAdaptor.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDCONTROLGROUPSADAPTOR_H
#define QUEUEDCONTROLGROUPSADAPTOR_H
#include <QObject>
/**
* @brief adaptor to control processes by using control groups
*/
class QueuedControlGroupsAdaptor : public QObject
{
Q_OBJECT
// static
Q_PROPERTY(QStringList controlPaths READ controlPaths)
Q_PROPERTY(QString cpuPath READ cpuPath)
Q_PROPERTY(QString memoryPath READ memoryPath)
// dynamic
Q_PROPERTY(QString name READ name)
Q_PROPERTY(long long cpuLimit READ cpuLimit WRITE setCpuLimit)
Q_PROPERTY(long long memoryLimit READ memoryLimit WRITE setMemoryLimit)
public:
// constants
/**
* @brief name of file contains cpu limit
*/
const char *CG_CPU_LIMIT = "cpu.cfs_quota_us";
/**
* @brief name of file contains memory limit
*/
const char *CG_MEMORY_LIMIT = "memory.limit_in_bytes";
/**
* @brief name of file contains notify status
*/
const char *CG_NOTIFY_ON_RELEASE_FILE = "notify_on_release";
/**
* @brief name of file contains processes list
*/
const char *CG_PROC_FILE = "cgroup.procs";
/**
* @brief name of file contains release command
*/
const char *CG_RELEASE_FILE = "release_agent";
/**
* @brief QueuedControlGroupsAdaptor class constructor
* @param _parent
* pointer to parent object
* @param _name
* control group name
*/
explicit QueuedControlGroupsAdaptor(QObject *_parent, QString _name);
/**
* @brief QueuedControlGroupsAdaptor class destructor
*/
virtual ~QueuedControlGroupsAdaptor();
/**
* @brief build group path for specific base directory
* @param _base
* full path to base directory
* @return full path to group properties
*/
QString groupPath(const QString &_base) const;
// static properties
/**
* @brief paths to all control directories
* @return full paths to all known control directories
*/
static QStringList controlPaths();
/**
* @brief path to CPU control
* @return full path to CPU control directory
*/
static QString cpuPath();
/**
* @brief path to memory control
* @return full path to memory control directory
*/
static QString memoryPath();
// instance depended properties
/**
* @brief CPU limit
* @return current CPU limit level
*/
long long cpuLimit() const;
/**
* @brief memory limit
* @return current memory limit level
*/
long long memoryLimit() const;
/**
* @brief control group name
* @return control group name
*/
QString name() const;
/**
* @brief set CPU limit
* @param _value
* new CPU limit level
*/
void setCpuLimit(const long long _value);
/**
* @brief set memory limit
* @param _value
* new memory limit level
*/
void setMemoryLimit(const long long _value);
// methods
/**
* @brief assign control group to process
* @param _pid
* process ID
* @param _name
* control group name
* @return process assignment status
*/
bool addProcess(const uint _pid);
/**
* @brief create empty group
* @param _name
* control group name
* @return group creation status
*/
bool createGroup();
/**
* @brief remove control group
* @param _name
* control group name
* @return group removal status
*/
bool removeGroup();
private:
// properties
/**
* @brief control group name
*/
QString m_name;
};
#endif /* QUEUEDCONTROLGROUPSADAPTOR_H */

View File

@ -0,0 +1,345 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedCore.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDCORE_H
#define QUEUEDCORE_H
#include <QObject>
#include "QueuedResult.h"
class QueuedCorePrivate;
class QueuedProcess;
class QueuedUser;
namespace QueuedEnums
{
enum class Permission;
};
namespace QueuedLimits
{
struct Limits;
}
namespace QueuedPluginSpecification
{
struct Plugin;
}
/**
* @brief aggregator of queued classes
*/
class QueuedCore : public QObject
{
Q_OBJECT
public:
/**
* @brief QueuedCore class constructor
* @param _parent
* pointer to parent item
*/
explicit QueuedCore(QObject *_parent);
/**
* @brief QueuedCore class destructor
*/
virtual ~QueuedCore();
/**
* @brief add plugin to autoload and load it now
* @param _plugin
* plugin name
* @param _token
* user auth token
* @return true on successfully addition
*/
QueuedResult<bool> addPlugin(const QString &_plugin, const QString &_token);
/**
* @brief add new task
* @param _command
* command line
* @param _arguments
* command arguments
* @param _workingDirectory
* working directory
* @param _userId
* task owner user ID
* @param _nice
* task nice level
* @param _limits
* task defined limits
* @param _token
* user auth token
* @return task ID or -1 if no task added
*/
QueuedResult<long long> addTask(const QString &_command, const QStringList &_arguments,
const QString &_workingDirectory, const long long _userId,
const uint _nice, const QueuedLimits::Limits &_limits,
const QString &_token);
/**
* @brief add new user
* @param _name
* user name
* @param _email
* user email
* @param _password
* user password
* @param _permissions
* user permissions
* @param _priority
* user priority
* @param _limits
* user limits
* @param _token
* user auth token
* @return user ID or -1 if no user created
*/
QueuedResult<long long> addUser(const QString &_name, const QString &_email,
const QString &_password, const uint _permissions,
const uint _priority, const QueuedLimits::Limits &_limits,
const QString &_token);
/**
* @brief try to authorize by given token
* @param _token
* token ID
* @return true if token is valid
*/
QueuedResult<bool> authorization(const QString &_token);
/**
* @brief authorize and create new token for user
* @param _name
* user name
* @param _password
* user password
* @return token. It will be empty if authorization error occurs
*/
QueuedResult<QString> authorization(const QString &_name, const QString &_password);
/**
* @brief edit advanced settings
* @param _key
* advanced settings key
* @param _value
* advanced settings value
* @param _token
* user auth token
* @return true on successful option edition
*/
QueuedResult<bool> editOption(const QString &_key, const QVariant &_value,
const QString &_token);
/**
* @brief edit task
* @param _id
* task ID to edit
* @param _taskData
* task data to edit
* @param _token
* user auth token
* @remark _taskData should contain only fields defined in schema, any other
* fields will be ignored. No need to pass all properties here
* @return true on successful task edition
*/
QueuedResult<bool> editTask(const long long _id, const QVariantHash &_taskData,
const QString &_token);
/**
* @brief edit user
* @param _id
* user ID to edit
* @param _userData
* user data to edit
* @param _token
* user auth token
* @remark _userData should contain only fields defined in schema, any other
* fields will be ignored. No need to pass all properties here
* @return true on successful user edition
*/
QueuedResult<bool> editUser(const long long _id, const QVariantHash &_userData,
const QString &_token);
/**
* @brief edit user permissions
* @param _id
* user ID to edit
* @param _permission
* permission to add or remove
* @param _add
* indicates whether it should be added or removed
* @param _token
* user auth token
* @return true on successful user permission edition
*/
QueuedResult<bool> editUserPermission(const long long _id,
const QueuedEnums::Permission &_permission,
const bool _add, const QString &_token);
/**
* @brief hash password
* @param _password
* user password as plain text
* @return hashed password with applied salt
*/
QueuedResult<QString> hashFromPassword(const QString &_password);
/**
* @brief get value from advanced settings
* @param _key
* key string
* @param _token
* user auth token
* @return option value or empty QVariant
*/
QueuedResult<QVariant> option(const QString &_key, const QString &_token);
/**
* @brief usage report
* @param _from
* start report date
* @param _to
* stop report date
* @param _token
* user auth token
* @return performance table
*/
QueuedResult<QList<QVariantHash>>
performanceReport(const QDateTime &_from, const QDateTime &_to, const QString &_token) const;
/**
* @brief get plugin description
* @param _plugin
* plugin name
* @param _token
* user auth token
* @return dictionary of PluginSpecification representation
*/
QueuedResult<QueuedPluginSpecification::Plugin> plugin(const QString &_plugin,
const QString &_token);
/**
* @brief get plugin settings
* @param _plugin
* plugin name
* @param _token
* user auth token
* @return hash of plugin settings
*/
QueuedResult<QVariantHash> pluginSettings(const QString &_plugin, const QString &_token);
/**
* @brief remove plugin from autoload and unload it now
* @param _plugin
* plugin name
* @param _token
* user auth token
* @return true on successful plugin removal
*/
QueuedResult<bool> removePlugin(const QString &_plugin, const QString &_token);
/**
* @brief force start task
* @param _id
* task ID
* @param _token
* user auth token
* @return true on successful task start
*/
QueuedResult<bool> startTask(const long long _id, const QString &_token);
/**
* @brief force stop task
* @param _id
* task ID
* @param _token
* user auth token
* @return true on successful task stop
*/
QueuedResult<bool> stopTask(const long long _id, const QString &_token);
/**
* @brief get task by ID
* @param _id
* task ID
* @param _token
* user auth token
* @return task object or nullptr if no task found
*/
const QueuedProcess *task(const long long _id, const QString &_token) const;
/**
* list of tasks which match criteria
* @param _user
* task user ID filter
* @param _from
* minimal start time
* @param _to
* maximal end time
* @param _token
* user auth token
* @return list of tasks in database format
*/
QueuedResult<QList<QVariantHash>> taskReport(const long long _user, const QDateTime &_from,
const QDateTime &_to, const QString &_token) const;
/**
* @brief get user by ID
* @param _id
* user ID
* @param _token
* user auth token
* @return user object or nullptr if no user found
*/
const QueuedUser *user(const long long _id, const QString &_token) const;
/**
* @brief get user by name
* @param _name
* user name
* @param _token
* user auth token
* @return user object or nullptr if no user found
*/
const QueuedUser *user(const QString &_name, const QString &_token) const;
/**
* list of users which match criteria
* @param _lastLogged
* last logged minimal date
* @param _permission
* user permission filter
* @param _token
* user auth token
* @return list of users in database format
*/
QueuedResult<QList<QVariantHash>> userReport(const QDateTime &_lastLogged,
const QueuedEnums::Permission _permission,
const QString &_token) const;
// control methods
/**
* @brief deinit subclasses
*/
void deinit();
/**
* @brief init subclasses
* @param _configuration
* path to configuration file
* @throw QueuedDatabaseException
* @throw QueuedDBusException
*/
void init(const QString &_configuration);
private:
/**
* @brief pointer to private implementation
*/
QueuedCorePrivate *m_impl = nullptr;
/**
* @brief init DBus interface
* @throw QueuedDBusException
*/
void initDBus();
};
#endif /* QUEUEDCORE_H */

View File

@ -0,0 +1,387 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedCoreAdaptor.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDCOREADAPTOR_H
#define QUEUEDCOREADAPTOR_H
#include <QDBusConnection>
#include <QDBusReply>
#include "QueuedProcess.h"
#include "QueuedUser.h"
namespace QueuedPluginSpecification
{
struct Plugin;
};
/**
* @addtogroup QueuedCoreAdaptor
* @brief adaptor to DBus methods
*/
namespace QueuedCoreAdaptor
{
// specific methods for control interface
/**
* @brief send TryAuth
* @param _token
* token ID
* @return true if token is valid
*/
QueuedResult<bool> auth(const QString &_token);
/**
* @brief send auth method
* @param _name
* user name
* @param _password
* user password
* @return generated token ID or empty string in case of invalid password
*/
QueuedResult<QString> auth(const QString &_name, const QString &_password);
/**
* @brief send OptionEdit
* @param _key
* option key to edit
* @param _value
* option value to edit
* @param _token
* auth user token
* @return true on successful option edition
*/
QueuedResult<bool> sendOptionEdit(const QString &_key, const QVariant &_value,
const QString &_token);
/**
* @brief send PasswordHash
* @param _password
* user password
* @return hashed password with applied salt
*/
QueuedResult<QString> sendPasswordHash(const QString &_password);
/**
* @brief send PluginAdd
* @param _plugin
* plugin name
* @param _token
* auth user token
* @return true on successful plugin addition
*/
QueuedResult<bool> sendPluginAdd(const QString &_plugin, const QString &_token);
/**
* @brief send PluginRemove
* @param _plugin
* plugin name
* @param _token
* auth user token
* @return true on successful plugin removal
*/
QueuedResult<bool> sendPluginRemove(const QString &_plugin, const QString &_token);
/**
* @brief send TaskAdd
* @param _definitions
* process definitions
* @param _token
* auth user token
* @return task ID or {0, -1} if no task added
*/
QueuedResult<long long> sendTaskAdd(const QueuedProcess::QueuedProcessDefinitions &_definitions,
const QString &_token);
/**
* @brief send TaskEdit
* @param _id
* task ID to edit
* @param _definitions
* process definitions
* @param _token
* auth user token
* @return true on successful task edition
*/
QueuedResult<bool> sendTaskEdit(const long long _id,
const QueuedProcess::QueuedProcessDefinitions &_definitions,
const QString &_token);
/**
* @brief send TaskStart
* @param _id
* task ID
* @param _token
* auth user token
* @return true on successful task start
*/
QueuedResult<bool> sendTaskStart(const long long _id, const QString &_token);
/**
* @brief send TaskStop
* @param _id
* task ID
* @param _token
* auth user token
* @return true on successful task stop
*/
QueuedResult<bool> sendTaskStop(const long long _id, const QString &_token);
/**
* @brief send UserAdd
* @param _definitions
* user definitions
* @param _token
* auth user token
* @return user ID or -1 if no user added
*/
QueuedResult<long long> sendUserAdd(const QueuedUser::QueuedUserDefinitions &_definitions,
const QString &_token);
/**
* @brief send UserEdit
* @param _id
* user ID to edit
* @param _definitions
* user definitions
* @param _token
* auth user token
* @return true on successful user edition
*/
QueuedResult<bool> sendUserEdit(const long long _id,
const QueuedUser::QueuedUserDefinitions &_definitions,
const QString &_token);
/**
* @brief send UserPermissionsAdd
* @param _id
* user ID
* @param _permission
* permission to add
* @param _token
* auth user token
* @return true on successful permission addition
*/
QueuedResult<bool> sendUserPermissionAdd(const long long _id,
const QueuedEnums::Permission _permission,
const QString &_token);
/**
* @brief send sendUserPermissionRemove
* @param _id
* user ID
* @param _permission
* permission to remove
* @param _token
* auth user token
* @return true on successful permission removal
*/
QueuedResult<bool> sendUserPermissionRemove(const long long _id,
const QueuedEnums::Permission _permission,
const QString &_token);
// specific methods for properties
/**
* @brief get plugin
* @param _plugin
* plugin name
* @param _token
* user auth token
* @return plugin specification body
*/
QueuedResult<QueuedPluginSpecification::Plugin> getPlugin(const QString &_plugin,
const QString &_token);
/**
* @brief get plugin options
* @param _plugin
* plugin name
* @param _token
* user auth token
* @return plugin options dictionary
*/
QueuedResult<QVariantHash> getPluginOptions(const QString &_plugin, const QString &_token);
/**
* @brief get option
* @param _property
* option name
* @param _token
* user auth token
* @return option value
*/
QueuedResult<QVariant> getOption(const QString &_property, const QString &_token);
/**
* @brief get option
* @param _property
* option name
* @param _token
* user auth token
* @return option value
*/
QueuedResult<QVariant> getOption(const QueuedConfig::QueuedSettings _property,
const QString &_token);
/**
* @brief performance report
* @param _from
* minimal start task time
* @param _to
* maximal stop task time
* @param _token
* user auth token
* @return list of user with used resources
*/
QueuedResult<QList<QVariantHash>> getPerformance(const QDateTime &_from, const QDateTime &_to,
const QString &_token);
/**
* @brief server status
* @return server status information
*/
QueuedResult<QueuedStatusMap> getStatus();
/**
* @brief get all task properties
* @param _id
* task ID
* @param _token
* user auth token
* @return task properties
*/
QueuedResult<QVariantHash> getTask(const long long _id, const QString &_token);
/**
* @brief get task property
* @param _id
* task id
* @param _property
* task property name
* @param _token
* user auth token
* @return task property value
*/
QueuedResult<QVariant> getTask(const long long _id, const QString &_property,
const QString &_token);
/**
* @brief get tasks list
* @param _user
* task user ID
* @param _from
* minimal start time
* @param _to
* maximal end time
* @param _token
* user auth token
* @return list of task in database representation
*/
QueuedResult<QList<QVariantHash>> getTasks(const long long _user, const QDateTime &_from,
const QDateTime &_to, const QString &_token);
/**
* @brief get user properties
* @param _id
* user id
* @param _token
* user auth token
* @return user properties
*/
QueuedResult<QVariantHash> getUser(const long long _id, const QString &_token);
/**
* @brief get user property
* @param _id
* user id
* @param _property
* user property name
* @param _token
* user auth token
* @return user property value
*/
QueuedResult<QVariant> getUser(const long long _id, const QString &_property,
const QString &_token);
/**
* @brief get user ID
* @param _name
* user name
* @param _token
* user auth token
* @return user ID or {0, -1} if no user found. If _name is numeric value it
* returns converted one
*/
QueuedResult<long long> getUserId(const QString &_name, const QString &_token);
/**
* @brief get users list
* @param _lastLogged
* minimal last logged in time
* @param _permission
* permission to search
* @param _token
* user auth token
* @return list of users in database representation
*/
QueuedResult<QList<QVariantHash>> getUsers(const QDateTime &_lastLogged,
const QueuedEnums::Permission _permission,
const QString &_token);
// common methods
/**
* @brief additional method to avoid conversion from QueuedResult to
* QDBusVariant
* @tparam T
* QueuedResult payload class
* @param _data
* input data
* @return converted data to QDBusVariant
*/
template <class T> QDBusVariant toDBusVariant(const QueuedResult<T> &_data)
{
return QDBusVariant(QVariant::fromValue<QueuedResult<T>>(_data));
};
/**
* @brief additional method to avoid conversion from QVariant to
* QueuedResult
* @tparam T
* QueuedResult payload class
* @param _data
* input data
* @return converted data to QueuedResult
*/
template <class T> QueuedResult<T> toResult(const QVariant &_data)
{
return qdbus_cast<QueuedResult<T>>(_data.value<QDBusArgument>());
};
/**
* @brief common DBus request
* @param _service
* DBus service name
* @param _path
* DBus object path
* @param _interface
* DBus interface name
* @param _cmd
* command which will be sent to DBus
* @param _args
* command arguments
* @return reply object from DBus request
*/
template <typename T>
QueuedResult<T> sendRequest(const QString &_service, const QString &_path,
const QString &_interface, const QString &_cmd,
const QVariantList &_args)
{
QDBusConnection bus = QDBusConnection::systemBus();
QDBusMessage request = QDBusMessage::createMethodCall(_service, _path, _interface, _cmd);
if (!_args.isEmpty())
request.setArguments(_args);
QDBusReply<QDBusVariant> dbusResponse = bus.call(request, QDBus::BlockWithGui);
if (dbusResponse.isValid()) {
auto response = dbusResponse.value();
return toResult<T>(response.variant());
} else {
return QueuedError(dbusResponse.error().message().toStdString());
}
};
} // namespace QueuedCoreAdaptor
#endif /* QUEUEDCOREADAPTOR_H */

View File

@ -0,0 +1,283 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedCoreInterface.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDCOREINTERFACE_H
#define QUEUEDCOREINTERFACE_H
#include <QDBusAbstractAdaptor>
#include <QDBusVariant>
#include "QueuedConfig.h"
class QueuedCore;
/**
* @brief DBus interface for QueuedCore class
*/
class QueuedCoreInterface : public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", DBUS_SERVICE_NAME)
public:
/**
* @brief QueuedCoreInterface class constructor
* @param parent
* pointer to QueuedCore object
*/
explicit QueuedCoreInterface(QueuedCore *parent);
/**
* @brief QueuedCoreInterface class destructor
*/
virtual ~QueuedCoreInterface();
public slots:
/**
* @brief auth user by password
* @param name
* user name
* @param password
* user password
* @return generated token ID or empty string in case of invalid password
*/
QDBusVariant Auth(const QString &name, const QString &password);
/**
* @brief edit option
* @param key
* option key to edit
* @param value
* option value to edit
* @param token
* auth user token
* @return true on successful option edition
*/
QDBusVariant OptionEdit(const QString &key, const QDBusVariant &value, const QString &token);
/**
* @brief get password hash
* @param password
* user password as plain text
* @return hashed password
*/
QDBusVariant PasswordHash(const QString &password);
/**
* @brief add plugin
* @param plugin
* plugin name
* @param token
* auth user token
* @return true on successful plugin addition
*/
QDBusVariant PluginAdd(const QString &plugin, const QString &token);
/**
* @brief remove plugin
* @param plugin
* plugin name
* @param token
* auth user token
* @return true on successful plugin removal
*/
QDBusVariant PluginRemove(const QString &plugin, const QString &token);
/**
* @brief add new task
* @param command
* command line
* @param arguments
* command line arguments
* @param workingDirectory
* working directory
* @param user
* user ID
* @param nice
* nice level
* @param cpu
* limit by CPU cores
* @param gpu
* limit by GPU cores
* @param memory
* limit by memory
* @param gpumemory
* limit by GPU memory
* @param storage
* limit by storage
* @param token
* auth user token
* @return task ID or -1 if no task added
*/
QDBusVariant TaskAdd(const QString &command, const QStringList &arguments,
const QString &workingDirectory, const qlonglong user, const uint nice,
const qlonglong cpu, const qlonglong gpu, const qlonglong memory,
const qlonglong gpumemory, const qlonglong storage, const QString &token);
/**
* @brief edit task
* @param id
* task ID
* @param command
* new command or empty
* @param arguments
* command line arguments or empty
* @param directory
* working directory or empty
* @param nice
* nice level or 0
* @param uid
* new uid or 0
* @param gid
* new gid or 0
* @param user
* new user ID or 0
* @param cpu
* new limit by CPU cores or -1
* @param gpu
* limit by GPU cores or -1
* @param memory
* new limit by memory or -1
* @param gpumemory
* new limit by GPU memory or -1
* @param storage
* new limit by storage or -1
* @param token
* auth user token
* @return true on successful task edition
*/
QDBusVariant TaskEdit(const qlonglong id, const QString &command, const QStringList &arguments,
const QString &directory, const uint nice, const uint uid, const uint gid,
const qlonglong user, const qlonglong cpu, const qlonglong gpu,
const qlonglong memory, const qlonglong gpumemory,
const qlonglong storage, const QString &token);
/**
* @brief force start task
* @param id
* task ID
* @param token
* auth user token
* @return true on successful task start
*/
QDBusVariant TaskStart(const qlonglong id, const QString &token);
/**
* @brief force stop task
* @param id
* task ID
* @param token
* auth user token
* @return true on successful task stop
*/
QDBusVariant TaskStop(const qlonglong id, const QString &token);
/**
* @brief try auth by token
* @param token
* token ID
* @return true if token is valid
*/
QDBusVariant TryAuth(const QString &token);
/**
* @brief add new user
* @param name
* user name
* @param email
* user email
* @param password
* user password
* @param permissions
* user permissions
* @param priority
* user permissions
* @param cpu
* limit by CPU cores
* @param gpu
* limit by GPU cores
* @param memory
* limit by memory
* @param gpumemory
* limit by GPU memory
* @param storage
* limit by storage
* @param token
* auth user token
* @return user ID or -1 if no user found
*/
QDBusVariant UserAdd(const QString &name, const QString &email, const QString &password,
const uint permissions, const uint priority, const qlonglong cpu,
const qlonglong gpu, const qlonglong memory, const qlonglong gpumemory,
const qlonglong storage, const QString &token);
/**
* @brief edit user
* @param id
* user ID
* @param name
* new user name or empty
* @param password
* new user password or empty
* @param email
* new user email or empty
* @param cpu
* new limit by CPU cores or -1
* @param gpu
* limit by GPU cores or -1
* @param memory
* new limit by memory or -1
* @param gpumemory
* new limit by GPU memory or -1
* @param storage
* new limit by storage or -1
* @param token
* auth user token
* @return true on successful user edition
*/
QDBusVariant UserEdit(const qlonglong id, const QString &name, const QString &password,
const QString &email, const qlonglong cpu, const qlonglong gpu,
const qlonglong memory, const qlonglong gpumemory,
const qlonglong storage, const QString &token);
/**
* @brief add permission to user
* @param id
* user ID
* @param permission
* permission to add
* @param token
* auth user token
* @return true on successful permission addition
*/
QDBusVariant UserPermissionAdd(const qlonglong id, const uint permission, const QString &token);
/**
* @brief remove permission from user
* @param id
* user ID
* @param permission
* permission to remove
* @param token
* auth user token
* @return true on successful permission removal
*/
QDBusVariant UserPermissionRemove(const qlonglong id, const uint permission,
const QString &token);
private:
/**
* @brief pointer to database object
*/
QueuedCore *m_core = nullptr;
};
#endif /* QUEUEDCOREINTERFACE_H */

View File

@ -0,0 +1,219 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedDatabase.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDDATABASE_H
#define QUEUEDDATABASE_H
#include <QHash>
#include <QObject>
#include <QSqlDatabase>
#include <QVariant>
/**
* @brief queued adaptor to databases
*/
class QueuedDatabase : public QObject
{
Q_OBJECT
Q_PROPERTY(QString path READ path)
public:
/**
* @brief QueuedDatabase class constructor
* @param parent
* pointer to parent item
* @param path
* path to database
* @param driver
* database driver
*/
explicit QueuedDatabase(QObject *parent, const QString path, const QString driver);
/**
* @brief QueuedDatabase class destructor
*/
virtual ~QueuedDatabase();
/**
* @brief check and create database
*/
void checkDatabase();
/**
* @brief close database connection
*/
void close();
/**
* @brief check and create queued administrator if missing
* @param _user
* administrator username
* @param _password
* administrator password SHA512
*/
void createAdministrator(const QString &_user, const QString &_password);
/**
* @brief create or update actual schema in table
* @param _table
* table name
*/
void createSchema(const QString &_table);
/**
* @brief create given table
* @param _table
* table name
*/
void createTable(const QString &_table);
/**
* @brief execute arbitrary query
* @throw QueuedDatabaseException
* in case if error occurs
* @param _query
* sql query
* @param _params
* sql query parameters
* @return query result
*/
QList<QVariantHash> execute(const QString &_query, const QVariantHash &_params);
/**
* @brief get all records from table
* @param _table
* table name
* @param _condition
* optional condition string
* @param _params
* optional condition parameters
* @return list of records from table
*/
QList<QVariantHash> get(const QString &_table, const QString &_condition = "",
const QVariantHash &_params = QVariantHash());
/**
* @brief get record from table with given id
* @param _table
* table name
* @param _id
* record id
* @return variant map from table
*/
QVariantHash get(const QString &_table, const long long _id);
/**
* @brief open database
* @param _hostname
* hostname to connect, may be empty
* @param _port
* port to connect, may be 0
* @param _username
* username to connect, may be empty
* @param _password
* password to connect, will be ignored if _username is empty
* @return true on successful opening
*/
bool open(const QString &_hostname, const int _port, const QString &_username,
const QString &_password);
/**
* @brief path to database
* @return path to used database
*/
QString path() const;
public slots:
/**
* @brief add record to database
* @param _table
* table name
* @param _value
* value to insert
* @return index of inserted record or -1 if no insertion
*/
long long add(const QString &_table, const QVariantHash &_value);
/**
* @brief modify record in table
* @param _table
* table name
* @param _id
* id for search
* @param _value
* value to update
* @return true on successfully modification
*/
bool modify(const QString &_table, const long long _id, const QVariantHash &_value);
/**
* @brief remove record in table by ID
* @param _table
* table name
* @param _id
* id to remove
* @return true on successfully removal
*/
bool remove(const QString &_table, const long long _id);
/**
* @brief remove ended task
* @param _endTime
* last task end time
*/
void removeTasks(const QDateTime &_endTime);
/**
* @brief remove unused tokens
*/
void removeTokens();
/**
* @brief remove user which where not logged into system
* @param _lastLogin
* last user login
*/
void removeUsers(const QDateTime &_lastLogin);
private:
/**
* @brief database
*/
QSqlDatabase m_database;
/**
* @brief database path
*/
QString m_path;
/**
* @brief additional function to get column numbers from table
* @param _record
* SQL record from query
* @return list of columns in table
*/
QStringList getColumnsInRecord(const QSqlRecord &_record) const;
/**
* @brief last insertion ID
* @param _table
* table name
* @return last insertion id from table
*/
long long lastInsertionId(const QString &_table);
/**
* @brief additional function to get payload for query
* @param _table
* table name for search
* @param _value
* value to build payload
* @return list of keys and list of values
*/
QHash<QString, QString> getQueryPayload(const QString &_table,
const QVariantHash &_value) const;
};
#endif /* QUEUEDDATABASE_H */

View File

@ -0,0 +1,130 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedDatabaseManager.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDDATABASEMANAGER_H
#define QUEUEDDATABASEMANAGER_H
#include <QObject>
#include <QTimer>
class QueuedDatabase;
/**
* @brief additional methods over database manager
*/
class QueuedDatabaseManager : public QObject
{
Q_OBJECT
Q_PROPERTY(long long interval READ interval WRITE setInterval)
Q_PROPERTY(long long keepTasks READ keepTasks WRITE setKeepTasks)
Q_PROPERTY(long long keepUsers READ keepUsers WRITE setKeepUsers)
public:
/**
* @brief additional constant to store msecs in day count
*/
const long long MSEC_IN_DAY = 86400000;
/**
* @brief QueuedDatabaseManager class constructor
* @param parent
* pointer to parent item
* @param database
* pointer to database object
*/
explicit QueuedDatabaseManager(QObject *parent, QueuedDatabase *database);
/**
* @brief QueuedDatabaseManager class destructor
*/
virtual ~QueuedDatabaseManager();
/**
* @brief start timer
*/
void startWorker();
// properties
/**
* @brief database actions interval
* @return interval in milliseconds
*/
long long interval() const;
/**
* @brief keep ended tasks
* @return interval for keeping tasks in milliseconds
*/
long long keepTasks() const;
/**
* @brief keep users last logged in
* @return interval for keeping users in milliseconds
*/
long long keepUsers() const;
/**
* @brief set database actions interval
* @param _interval
* interval in milliseconds
*/
void setInterval(const long long _interval);
/**
* @brief keep interval for tasks
* @param _keepInterval
* interval in milliseconds
*/
void setKeepTasks(const long long _keepInterval);
/**
* @brief keep interval for users
* @param _keepInterval
* interval in milliseconds
*/
void setKeepUsers(const long long _keepInterval);
public slots:
/**
* @brief cleanup database
*/
void cleanup();
private:
/**
* @brief pointer to database object
*/
QueuedDatabase *m_database = nullptr;
/**
* @brief database actions interval
*/
long long m_interval = MSEC_IN_DAY;
/**
* @brief ended task interval
*/
long long m_keepTasks = 0;
/**
* @brief user last logged in interval
*/
long long m_keepUsers = 0;
/**
* @brief timer object
*/
QTimer m_timer;
};
#endif /* QUEUEDDATABASEMANAGER_H */

View File

@ -0,0 +1,122 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedDatabaseSchema.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDDATABASESCHEMA_H
#define QUEUEDDATABASESCHEMA_H
#include <QHash>
#include <QVariant>
/**
* @addtogroup QueuedDB
* @brief Queued database related constants
*/
namespace QueuedDB
{
/**
* @brief settings table name
*/
static const char SETTINGS_TABLE[] = "settings";
/**
* @brief tasks modifications table name
*/
static const char TASKS_MODS_TABLE[] = "tasks_modifications";
/**
* @brief tasks table name
*/
static const char TASKS_TABLE[] = "tasks";
/**
* @brief tokens table name
*/
static const char TOKENS_TABLE[] = "tokens";
/**
* @brief users table name
*/
static const char USERS_TABLE[] = "users";
/**
* @struct QueuedDBField
* @brief describes database column
* @var QueuedDBField::name
* column name
* @var QueuedDBField::sqlDescription
* description to create column
* @var QueuedDBField::type
* Qt type of column for cast
* @var QueuedDBField::adminField
* is admin permissions required to edit or not
*/
typedef struct {
QString name;
QString sqlDescription;
QVariant::Type type;
bool adminField;
} QueuedDBField;
/**
* @typedef QueuedDBSchema
* custom map for database schemas descriptions
*/
typedef QHash<QString, QHash<QString, QueuedDBField>> QueuedDBSchema;
/**
* @brief database schema
*/
static const QueuedDBSchema DBSchema
= {{SETTINGS_TABLE,
{{"_id", {"_id", "INT PRIMARY KEY AUTOINCREMENT UNIQUE", QVariant::LongLong, true}},
{"key", {"key", "TEXT NOT NULL DEFAULT '0'", QVariant::String, true}},
{"value", {"value", "TEXT", QVariant::String, true}}}},
{TASKS_MODS_TABLE,
{{"_id", {"_id", "INT PRIMARY KEY AUTOINCREMENT UNIQUE", QVariant::LongLong, true}},
{"task", {"task", "INT NOT NULL DEFAULT 0", QVariant::LongLong, true}},
{"time", {"time", "TEXT", QVariant::String, true}},
{"user", {"user", "INT NOT NULL DEFAULT 0", QVariant::LongLong, true}},
{"value", {"value", "TEXT", QVariant::String, true}}}},
{TASKS_TABLE,
{{"_id", {"_id", "INT PRIMARY KEY AUTOINCREMENT UNIQUE", QVariant::LongLong, true}},
{"user", {"user", "INT NOT NULL DEFAULT 0", QVariant::LongLong, true}},
{"command", {"command", "TEXT", QVariant::String, false}},
{"commandArguments", {"commandArguments", "TEXT", QVariant::String, false}},
{"workDirectory", {"workDirectory", "TEXT", QVariant::String, false}},
{"nice", {"nice", "INT NOT NULL DEFAULT 0", QVariant::UInt, true}},
{"uid", {"uid", "INT", QVariant::UInt, true}},
{"gid", {"gid", "INT", QVariant::UInt, true}},
{"limits", {"limits", "TEXT", QVariant::String, false}},
{"startTime", {"startTime", "TEXT", QVariant::String, true}},
{"endTime", {"endTime", "TEXT", QVariant::String, true}}}},
{TOKENS_TABLE,
{{"_id", {"_id", "INT PRIMARY KEY AUTOINCREMENT UNIQUE", QVariant::LongLong, true}},
{"token", {"token", "TEXT NOT NULL DEFAULT '0'", QVariant::String, true}},
{"user", {"user", "TEXT NOT NULL DEFAULT '0'", QVariant::String, true}},
{"validUntil", {"validUntil", "TEXT NOT NULL DEFAULT '0'", QVariant::String, true}}}},
{USERS_TABLE,
{{"_id", {"_id", "INT PRIMARY KEY AUTOINCREMENT UNIQUE", QVariant::LongLong, true}},
{"name", {"name", "TEXT NOT NULL DEFAULT '0'", QVariant::String, true}},
{"password", {"password", "TEXT", QVariant::String, false}},
{"email", {"email", "TEXT", QVariant::String, false}},
{"lastLogin", {"lastLogin", "TEXT", QVariant::String, true}},
{"limits", {"limits", "TEXT", QVariant::String, true}},
{"permissions", {"permissions", "INT", QVariant::UInt, true}},
{"priotiry", {"priority", "INT", QVariant::UInt, true}}}}};
}; // namespace QueuedDB
#endif /* QUEUEDDATABASESCHEMA_H */

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedDebug.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDDEBUG_H
#define QUEUEDDEBUG_H
#include <QHash>
#include <QLoggingCategory>
/**
* @brief daemon logging category
*/
Q_DECLARE_LOGGING_CATEGORY(LOG_APP)
/**
* @brief control application logging category
*/
Q_DECLARE_LOGGING_CATEGORY(LOG_CTL)
/**
* @brief DBus logging category
*/
Q_DECLARE_LOGGING_CATEGORY(LOG_DBUS)
/**
* @brief library logging category
*/
Q_DECLARE_LOGGING_CATEGORY(LOG_LIB)
/**
* @brief plugin logging category
*/
Q_DECLARE_LOGGING_CATEGORY(LOG_PL)
/**
* @brief server logging category
*/
Q_DECLARE_LOGGING_CATEGORY(LOG_SERV)
/**
* @addtogroup QueuedDebug
* @brief Queued debug functions
*/
namespace QueuedDebug
{
/**
* @brief default log format
*/
static const char LOG_FORMAT[] = "[%{time "
"process}][%{if-debug}DD%{endif}%{if-info}II%{endif}%"
"{if-warning}WW%{endif}%{if-critical}CC%{endif}%{if-"
"fatal}FF%{endif}][%{category}][%{function}] "
"%{message}";
/**
* @brief method to apply log format
*/
void applyLogFormat();
/**
* @brief method to enable debug messages
*/
void enableDebug();
/**
* @brief additional method to get build details declared in version.h
*/
QStringList getBuildData();
/**
* @brief additional method to get build details declared in version.h
*/
QHash<QString, QHash<QString, QString>> getBuildMetaData();
} // namespace QueuedDebug
#endif /* QUEUEDDEBUG_H */

View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedEnums.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDENUMS_H
#define QUEUEDENUMS_H
#include <QHash>
/**
* @addtogroup QueuedEnums
* @brief Queued enumerations
*/
namespace QueuedEnums
{
/**
* @enum Permission
* @brief available user permissions
* @var Permission::Invalid
* invalid permission
* @var Permission::SuperAdmin
* "allow all" permissions
* @var Permission::Admin
* administrative permissions
* @var Permission::Job
* job related permissions
* @var Permission::Reports
* access to reports
*/
enum class Permission {
Invalid = 1 << 0,
SuperAdmin = 1 << 1,
Admin = 1 << 2,
Job = 1 << 3,
Reports = 1 << 4
};
Q_DECLARE_FLAGS(Permissions, Permission)
Q_DECLARE_OPERATORS_FOR_FLAGS(Permissions)
static const QHash<QString, Permission> PermissionMap = {
{"superadmin", Permission::SuperAdmin},
{"admin", Permission::Admin},
{"job", Permission::Job},
{"reports", Permission::Reports},
};
/**
* @brief converts string to permission enum
* @param _permission
* permission string
* @return related Permission value
*/
inline Permission stringToPermission(const QString &_permission)
{
return PermissionMap.contains(_permission.toLower())
? PermissionMap.value(_permission.toLower())
: Permission::Invalid;
};
/**
* @enum ExitAction
* @brief action with child process on destruction
* @var ExitAction::Terminate
* send SIGTERM on exit
* @var ExitAction::Kill
* send SIGKILL on exit
*/
enum class ExitAction { Terminate = 1 << 1, Kill = 1 << 2 };
/**
* @enum ReturnStatus
* @brief DBus response status
* @var ReturnStatus::OK
* no errors in report
* @var ReturnStatus::Error
* generic error occurs
* @var ReturnStatus::InsufficientPermissions
* insufficient user permissions
*/
enum class ReturnStatus {
Error = 1 << 1,
InvalidArgument = 1 << 2,
InsufficientPermissions = 1 << 3,
InvalidToken = 1 << 4,
InvalidPassword = 1 << 5
};
}; // namespace QueuedEnums
#endif /* QUEUEDENUMS_H */

View File

@ -0,0 +1,116 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedExceptions.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDEXCEPTIONS_H
#define QUEUEDEXCEPTIONS_H
#include <QException>
/**
* @brief generic exception class
*/
class QueuedException : public QException
{
public:
/**
* @brief QueuedException class constructor
* @param message
* exception message
*/
explicit QueuedException(QString message)
: QException()
{
m_message = std::move(message);
};
/**
* @brief clone QueuedException
*/
QueuedException *clone() const override { return new QueuedException(*this); };
/**
* @brief message of this exception
* @return message for logging, etc
*/
QString message() const { return m_message; };
/**
* @brief raise QueuedException
*/
void raise() const override { throw *this; }
private:
/**
* @brief exception message
*/
QString m_message;
};
/**
* @brief configuration related exception
*/
class QueuedConfigurationException : public QueuedException
{
public:
/**
* @brief QueuedConfigurationException class constructor
* @param message
* exception message
*/
explicit QueuedConfigurationException(const QString &message)
: QueuedException(message){};
};
/**
* @brief database operation exception
*/
class QueuedDatabaseException : public QueuedException
{
public:
/**
* @brief QueuedDatabaseException class constructor
* @param message
* exception message
*/
explicit QueuedDatabaseException(const QString &message)
: QueuedException(message){};
};
/**
* @brief DBus operation exception
*/
class QueuedDBusException : public QueuedException
{
public:
/**
* @brief QueuedDBusException class constructor
* @param message
* exception message
*/
explicit QueuedDBusException(const QString &message)
: QueuedException(message){};
};
#endif /* QUEUEDEXCEPTIONS_H */

View File

@ -0,0 +1,170 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedLimits.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDLIMITS_H
#define QUEUEDLIMITS_H
#include <QString>
/**
* @addtogroup QueuedLimits
* @brief Queued limits
*/
namespace QueuedLimits
{
/**
* @struct Limits
* @var Limits::cpu
* limit by CPU
* @var Limits::gpu
* limit by GPU
* @var Limits::memory
* limit by memory
* @var Limits::gpumemory
* limit by GPU memory
* @var Limits::storage
* limit by storage
* @var Limits::valid
* is this permissions default generated or not
*/
struct Limits {
long long cpu;
long long gpu;
long long memory;
long long gpumemory;
long long storage;
bool valid;
// structure methods
/**
* @brief limits to string conversion
* @return string representation of limits
*/
QString toString() const
{
return QString("%1\n%2\n%3\n%4\n%5")
.arg(cpu)
.arg(gpu)
.arg(memory)
.arg(gpumemory)
.arg(storage);
};
/**
* @brief default structure constructor
*/
Limits()
: cpu(0)
, gpu(0)
, memory(0)
, gpumemory(0)
, storage(0)
, valid(false){};
/**
* @brief structure constructor from string representation
* @param _stringLimits
* limits string representation
*/
explicit Limits(const QString &_stringLimits)
: Limits()
{
QStringList limits = _stringLimits.split('\n');
while (limits.count() < 5)
limits.append("0");
cpu = limits.at(0).toLongLong();
gpu = limits.at(1).toLongLong();
memory = limits.at(2).toLongLong();
gpumemory = limits.at(3).toLongLong();
storage = limits.at(4).toLongLong();
valid = true;
};
/**
* @brief structure constructor from fields
* @param _cpu
* limit by CPU cores
* @param _gpu
* limit by GPU cores
* @param _memory
* limit by memory
* @param _gpumemory
* limit by GPU memory
* @param _storage
* limit by storage
*/
Limits(const long long _cpu, const long long _gpu, const long long _memory,
const long long _gpumemory, const long long _storage)
: cpu(_cpu)
, gpu(_gpu)
, memory(_memory)
, gpumemory(_gpumemory)
, storage(_storage)
, valid(true){};
/**
* @brief *= operator overload
* @param _count
* multiplier
* @return multiplied values
*/
Limits &operator*=(const long long _count)
{
cpu *= _count;
gpu *= _count;
memory *= _count;
gpumemory *= _count;
return *this;
};
};
/**
* @brief convert QString memory value to integer
* @param _value
* value to convert
* @param _status
* conversion status
* @return converted integer
*/
long long convertMemory(QString _value, bool *_status = nullptr);
/**
* @brief compare two limits
* @param _first
* first limit
* @param _second
* second limit
* @return true if first limit is less than second
*/
bool limitCompare(const long long _first, const long long _second);
/**
* @brief get minimal limits from given
* @param _task
* task defined limits
* @param _user
* user defined limit
* @param _default
* default limits if anu
* @return minimal limits from given
*/
Limits minimalLimits(const Limits &_task, const Limits &_user, const Limits &_default);
}; // namespace QueuedLimits
#endif /* QUEUEDLIMITS_H */

View File

@ -0,0 +1,78 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedPluginInterface.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDPLUGININTERFACE_H
#define QUEUEDPLUGININTERFACE_H
#include <QtPlugin>
#include "QueuedConfig.h"
class QueuedPluginManagerInterface;
/**
* @brief plugin interface for queued
*/
class QueuedPluginInterface
{
public:
/**
* @brief QueuedPluginInterface class destructor
*/
virtual ~QueuedPluginInterface(){};
/**
* @brief plugin initialization method
* @param _settings
* plugin settings structure from database
* @remark plugin settings will be stored as "plugin.name.Key"
*/
virtual void init(const QVariantHash &_settings) = 0;
/**
* @brief set plugin token
* @remark this method may be safety ignored if plugin does not use methods
* require auth
* @param _token
* new token ID
*/
virtual void setToken(const QString &_token) = 0;
/**
* @brief will be emitted to map interface signals to plugin slots
* @param _manager
* pointer to manager interface object
*/
virtual void setup(const QueuedPluginManagerInterface *_manager) = 0;
/**
* @brief method which will be called on option update
* @param _key
* option key
* @param _value
* option value
*/
virtual void updateSettings(const QString &_key, const QVariant &_value) = 0;
};
Q_DECLARE_INTERFACE(QueuedPluginInterface, PLUGIN_INTERFACE_NAME)
#endif /* QUEUEDPLUGININTERFACE_H */

View File

@ -0,0 +1,132 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedPluginManager.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDPLUGINMANAGER_H
#define QUEUEDPLUGINMANAGER_H
#include <QHash>
#include <QObject>
#include <QPair>
class QueuedPluginInterface;
class QueuedPluginManagerInterface;
namespace QueuedPluginSpecification
{
struct Plugin;
};
/**
* @brief report manager for queued
*/
class QueuedPluginManager : public QObject
{
Q_OBJECT
public:
/**
* @typedef QueuedPluginMap
* map of names to QueuedPluginInterface pointers
*/
typedef QHash<QString, QueuedPluginInterface *> QueuedPluginMap;
/**
* @brief QueuedPluginManager class constructor
* @param parent
* pointer to parent item
* @param token
* plugin auth token
*/
explicit QueuedPluginManager(QObject *parent, const QString &token);
/**
* @brief QueuedPluginManager class destructor
*/
virtual ~QueuedPluginManager();
/**
* @brief get option name from database format
* @param _key
* option key
* @return plugin name and option key in plugin format
*/
static QPair<QString, QString> convertOptionName(const QString &_key);
/**
* @brief plugin manager interface
* @return pointer to plugin manager interface
*/
QueuedPluginManagerInterface *interface();
/**
* @brief load plugin
* @param _name
* plugin name
* @param _settings
* plugin settings
* @return true on success load otherwise return false
*/
bool loadPlugin(const QString &_name, const QVariantHash &_settings);
/**
* @brief load plugin specification
* @param _name
* plugin name
* @return plugin specification object
*/
QueuedPluginSpecification::Plugin loadSpecification(const QString &_name);
/**
* @brief path to plugin location
* @return full path to plugin location
*/
static QStringList pluginLocations();
/**
* @brief unload plugin
* @param _name
* plugin name
* @return true on success unload otherwise return false
*/
bool unloadPlugin(const QString &_name);
public slots:
/**
* @brief notifies plugin about option changes
* @param _key
* database option key
* @param _value
* option value
*/
void optionChanged(const QString &_key, const QVariant &_value);
private:
/**
* @brief pointer to database object
*/
QueuedPluginManagerInterface *m_interface = nullptr;
/**
* @brief loaded plugins
*/
QueuedPluginMap m_plugins;
/**
* @brief plugin auth token
*/
QString m_token;
};
#endif /* QUEUEDPLUGINMANAGER_H */

View File

@ -0,0 +1,119 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedPluginManagerInterface.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDPLUGINMANAGERINTERFACE_H
#define QUEUEDPLUGINMANAGERINTERFACE_H
#include <QObject>
/**
* @brief signal interface for plugin manager
*/
class QueuedPluginManagerInterface : public QObject
{
Q_OBJECT
public:
/**
* @brief QueuedPluginManagerInterface class constructor
*/
explicit QueuedPluginManagerInterface()
: QObject(nullptr){};
/**
* @brief QueuedPluginManagerInterface class destructor
*/
virtual ~QueuedPluginManagerInterface() = default;
;
signals:
/**
* @brief signal which emits on plugin addition
* @param _plugin
* plugin name
*/
void onAddPlugin(const QString &_plugin);
/**
* @brief signal which emits on task addition
* @param _id
* generated task ID
*/
void onAddTask(const long long _id);
/**
* @brief signal which emits on user addition
* @param _id
* generated user ID
*/
void onAddUser(const long long _id);
/**
* @brief signal which emits on user authorization
* @param _user
* user name
*/
void onAuthorization(const QString &_user);
/**
* @brief signal which emits on option edition
* @param _option
* option name
* @param _value
* option value
*/
void onEditOption(const QString &_option, const QVariant &_value);
/**
* @brief signal which emits on task edition
* @param _id
* task ID
* @param _taskData
* new task data
*/
void onEditTask(const long long _id, const QVariantHash &_taskData);
/**
* @brief signal which emits on user edition
* @param _id
* user ID
* @param _userData
* new user data
*/
void onEditUser(const long long _id, const QVariantHash &_userData);
/**
* @brief signal which emits on plugin removal
* @param _plugin
* plugin name
*/
void onRemovePlugin(const QString &_plugin);
/**
* @brief signal which emits on task starting
* @param _id
* started task ID
*/
void onStartTask(const long long _id);
/**
* @brief signal which emits on task stoping
* @param _id
* stopped task ID
*/
void onStopTask(const long long _id);
};
#endif /* QUEUEDPLUGINMANAGERINTERFACE_H */

View File

@ -0,0 +1,181 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedPluginSpecification.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDPLUGINSPECIFICATION_H
#define QUEUEDPLUGINSPECIFICATION_H
#include <QDebug>
#include <QString>
/**
* @addtogroup QueuedPluginSpecification
* @brief plugin specification representation
*/
namespace QueuedPluginSpecification
{
/**
* @struct PluginOption
* @brief plugin option structure
* @var PluginOption::defaultValue
* option default value
* @var PluginOption::description
* option description
* @var PluginOption::name
* option name
* @var PluginOption::type
* option type
*/
struct PluginOption {
QVariant defaultValue;
QString description;
QString name;
QString type;
};
/**
* @brief DBus marshalling method
* @param _argument
* output DBus argument
* @param _arg
* input variant object
* @return appended argument body
*/
inline QDBusArgument &operator<<(QDBusArgument &_argument, const PluginOption &_arg)
{
_argument.beginStructure();
_argument << QDBusVariant(_arg.defaultValue.isValid() ? _arg.defaultValue : "");
_argument << _arg.description;
_argument << _arg.name;
_argument << _arg.type;
_argument.endStructure();
return _argument;
};
/**
* @brief DBus un-marshalling method
* @param _argument
* input DBus argument
* @param _arg
* output variant object
* @return source DBus argument
*/
inline const QDBusArgument &operator>>(const QDBusArgument &_argument, PluginOption &_arg)
{
QDBusVariant variant;
_argument.beginStructure();
_argument >> variant;
_arg.defaultValue = variant.variant();
_argument >> _arg.description;
_argument >> _arg.name;
_argument >> _arg.type;
_argument.endStructure();
return _argument;
};
/**
* @struct Plugin
* @brief plugin specification structure
* @var Plugin::author
* plugin author
* @var Plugin::description
* plugin description
* @var Plugin::homepage
* plugin license
* @var Plugin::license
* plugin license
* @param Plugin::options
* plugin options
*/
struct Plugin {
QString author;
QString description;
QString homepage;
QString license;
QList<PluginOption> options;
};
/**
* @brief DBus marshalling method
* @param _argument
* output DBus argument
* @param _arg
* input variant object
* @return appended argument body
*/
inline QDBusArgument &operator<<(QDBusArgument &_argument, const Plugin &_arg)
{
_argument.beginStructure();
_argument << _arg.author;
_argument << _arg.description;
_argument << _arg.homepage;
_argument << _arg.license;
_argument << _arg.options;
_argument.endStructure();
return _argument;
};
/**
* @brief DBus un-marshalling method
* @param _argument
* input DBus argument
* @param _arg
* output variant object
* @return source DBus argument
*/
inline const QDBusArgument &operator>>(const QDBusArgument &_argument, Plugin &_arg)
{
_argument.beginStructure();
_argument >> _arg.author;
_argument >> _arg.description;
_argument >> _arg.homepage;
_argument >> _arg.license;
_argument >> _arg.options;
_argument.endStructure();
return _argument;
};
/**
* @brief dump specification to map
* @param _plugin
* plugin object
* @return specification dump
*/
QVariantHash dumpSpecification(const Plugin &_plugin);
/**
* @brief init specification from file
* @param _path
* path to specification file
* @return initialized object
*/
Plugin readSpecification(const QString &_path);
/**
* @brief init specification from map
* @param _map
* specification map
* @return initialized object
*/
Plugin readSpecification(const QVariantHash &_map);
}; // namespace QueuedPluginSpecification
#endif /* QUEUEDPLUGINSPECIFICATION_H */

View File

@ -0,0 +1,299 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedProcess.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDPROCESS_H
#define QUEUEDPROCESS_H
#include <QDateTime>
#include <QProcess>
#include <QVariant>
class QueuedControlGroupsAdaptor;
namespace QueuedLimits
{
struct Limits;
};
/**
* @brief implementation over QProcess to run processes
*/
class QueuedProcess : public QProcess
{
Q_OBJECT
Q_PROPERTY(QList<Q_PID> childrenPids READ childrenPids)
Q_PROPERTY(long long index READ index)
Q_PROPERTY(QString name READ name)
// mutable properties
Q_PROPERTY(QDateTime endTime READ endTime WRITE setEndTime)
Q_PROPERTY(uint gid READ uid WRITE setGid)
Q_PROPERTY(QString limits READ limits WRITE setLimits)
Q_PROPERTY(QString logError READ logError WRITE setLogError)
Q_PROPERTY(QString logOutput READ logOutput WRITE setLogOutput)
Q_PROPERTY(uint nice READ nice WRITE setNice)
Q_PROPERTY(QDateTime startTime READ startTime WRITE setStartTime)
Q_PROPERTY(uint uid READ uid WRITE setUid)
Q_PROPERTY(long long user READ user WRITE setUser)
Q_PROPERTY(QString workDirectory READ workDirectory WRITE setWorkDirectory)
public:
/**
* @struct QueuedProcessModDefinitions
* @brief structure to define process modifications
* @var QueuedProcessModDefinitions::field
* field name
* @var QueuedProcessModDefinitions::value
* new field value
* @var QueuedProcessModDefinitions::task
* task ID
* @var QueuedProcessModDefinitions::time
* modification time
* @var QueuedProcessModDefinitions::user
* user ID, who modified the task
*/
struct QueuedProcessModDefinitions {
QString field;
QVariant value;
long long task = 0;
QDateTime time;
long long user = 0;
};
/**
* @struct QueuedProcessDefinition
* @brief structure to define process
* @var QueuedProcessDefinitions::command
* command line
* @var QueuedProcessDefinitions::arguments
* command line arguments
* @var QueuedProcessDefinitions::workingDirectory
* path to working directory
* @var QueuedProcessDefinitions::uid
* UID of process
* @var QueuedProcessDefinitions::gid
* GID of process
* @var QueuedProcessDefinitions::nice
* nice level of process
* @var QueuedProcessDefinitions::startTime
* process start time
* @var QueuedProcessDefinitions::endTime
* process end time
* @var QueuedProcessDefinitions::user
* task owner ID
* @var QueuedProcessDefinitions::limits
* task limits
*/
struct QueuedProcessDefinitions {
QString command;
QStringList arguments;
QString workingDirectory;
uint uid = 0;
uint gid = 0;
uint nice = 0;
QDateTime startTime;
QDateTime endTime;
long long user = 0;
QString limits;
QList<QueuedProcessModDefinitions> modifications;
};
/**
* @brief QueuedProcess class constructor
* @param _parent
* pointer to parent item
* @param definitions
* definitions of process
* @param index
* index of process
*/
explicit QueuedProcess(QObject *_parent, const QueuedProcessDefinitions &definitions,
const long long index);
/**
* @brief QueuedProcess class destructor
*/
virtual ~QueuedProcess();
/**
* @brief force kill ald children
*/
void killChildren();
// properties
/**
* @brief children processes
* @return list of pids of children processes
*/
QList<Q_PID> childrenPids() const;
/**
* @brief index of process
* @return assigned index of process
*/
long long index() const;
/**
* @brief name of process
* @return generated name of process
*/
QString name() const;
// mutable properties
/**
* @brief process end time
* @return process end time
*/
QDateTime endTime() const;
/**
* @brief process GID
* @return process GID
*/
uint gid() const;
/**
* @brief process limits
* @return process defined limits
*/
QString limits() const;
/**
* @brief process error log
* @return path to process error log
*/
QString logError() const;
/**
* @brief process output log
* @return path to process output log
*/
QString logOutput() const;
/**
* @brief process limits
* @return process defined limits in native format
*/
QueuedLimits::Limits nativeLimits() const;
/**
* @brief process nice
* @return process nice
*/
uint nice() const;
/**
* @brief process start time
* @return process start time
*/
QDateTime startTime() const;
/**
* @brief process UID
* @return process UID
*/
uint uid() const;
/**
* @brief user
* @return process owner ID
*/
long long user() const;
/**
* @brief working directory
* @return process working directory
*/
QString workDirectory() const;
/**
* @brief set end time
* @param _time
* process end time
*/
void setEndTime(const QDateTime &_time);
/**
* @brief set process GID
* @param _gid
* new process GID
*/
void setGid(const uint _gid);
/**
* @brief set process limits
* @param _limits
* new process limits
*/
void setLimits(const QString &_limits);
/**
* @brief set process error log
*/
void setLogError(const QString &);
/**
* @brief set process output log
*/
void setLogOutput(const QString &);
/**
* @brief set process nice
* @param _nice
* new process nice
*/
void setNice(const uint _nice);
/**
* @brief set start time
* @param _time
* process start time
*/
void setStartTime(const QDateTime &_time);
/**
* @brief set process UID
* @param _uid
* new process UID
*/
void setUid(const uint _uid);
/**
* @brief set user ID
* @param _user
* new user ID
*/
void setUser(const long long _user);
/**
* @brief set working directory
* @param _workDirectory
* new process working directory
*/
void setWorkDirectory(const QString &_workDirectory);
/**
* @brief equal operator implementation
* @param _other
* other object
* @return true if objects are equal
*/
bool operator==(const QueuedProcess &_other);
public slots:
/**
* @brief method which will be called to apply cgroup after start
*/
void applyCGroup();
protected:
/**
* @brief apply child process properties
*/
void setupChildProcess();
private:
QueuedControlGroupsAdaptor *m_cgroup = nullptr;
/**
* @brief process definitions
*/
QueuedProcessDefinitions m_definitions;
/**
* @brief index of process
*/
long long m_index = -1;
};
#endif /* QUEUEDPROCESS_H */

View File

@ -0,0 +1,201 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedProcessManager.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDPROCESSMANAGER_H
#define QUEUEDPROCESSMANAGER_H
#include <QDateTime>
#include <QHash>
#include <QObject>
#include "QueuedProcess.h"
class QueuedPluginManagerInterface;
namespace QueuedEnums
{
enum class ExitAction;
};
/**
* @brief implementation over QProcess to run processes
*/
class QueuedProcessManager : public QObject
{
Q_OBJECT
Q_PROPERTY(QueuedEnums::ExitAction onExit READ onExit WRITE setExitAction)
public:
/**
* @typedef QueuedProcessMap
* map of indices to QueuedProcess pointers
*/
typedef QHash<long long, QueuedProcess *> QueuedProcessMap;
/**
* @typedef QueuedProcessConnectionMap
* map of indices to related QMetaObject::Connection
*/
typedef QHash<long long, QMetaObject::Connection> QueuedProcessConnectionMap;
/**
* @brief QueuedProcessManager class constructor
* @param _parent
* pointer to parent item
*/
explicit QueuedProcessManager(QObject *_parent);
/**
* @brief QueuedProcessManager class destructor
*/
virtual ~QueuedProcessManager();
/**
* @brief parse task definitions from table data
* @param _properties
* map of task properties
* @param _modifications
* list of task modifications
* @return data mapped to internal format
*/
static QueuedProcess::QueuedProcessDefinitions
parseDefinitions(const QVariantHash &_properties, const QList<QVariantHash> &_modifications);
/**
* @brief add task
* @param _properties
* task properties from database
* @param _modifications
* list of task modifications
* @param _index
* task index
* @return pointer to created task
*/
QueuedProcess *add(const QVariantHash &_properties, const QList<QVariantHash> &_modifications,
const long long _index);
/**
* @brief add task
* @param _definitions
* process definitions
* @param _index
* task index
* @return pointer to created task
*/
QueuedProcess *add(const QueuedProcess::QueuedProcessDefinitions &_definitions,
const long long _index);
/**
* @brief task
* @param _index
* task index
* @return task found by index or nullptr
*/
QueuedProcess *process(const long long _index);
/**
* @brief all tasks
* @return list of all tasks
*/
QueuedProcessMap processes();
/**
* @brief remove task from list
* @param _index
* task index
*/
void remove(const long long _index);
/**
* @brief select and start task automatically
*/
void start();
/**
* @brief force start task
* @param _index
* task index
*/
void start(const long long _index);
/**
* @brief force stop task
* @param _index
* task index
*/
void stop(const long long _index);
// properties
/**
* @brief default action on exit
* @return default action from possible ones
*/
QueuedEnums::ExitAction onExit() const;
/**
* @brief set on exit action
* @param _action
* new on exit action
*/
void setExitAction(const QueuedEnums::ExitAction _action);
/**
* @brief get used limits
* @return used system limits
*/
QueuedLimits::Limits usedLimits();
signals:
/**
* @brief signal which will be called on task start
* @param _index
* task index
* @param _time
* task start time
*/
void taskStartTimeReceived(const long long _index, const QDateTime &_time);
/**
* @brief signal which will be called on task end
* @param _index
* task index
* @param _time
* task stop time
*/
void taskStopTimeReceived(const long long _index, const QDateTime &_time);
private slots:
/**
* @brief slot for catching finished tasks
* @param _exitCode
* exit code of finished task
* @param _exitStatus
* exit status of finished task
* @param _index
* index of finished task
*/
void taskFinished(const int _exitCode, const QProcess::ExitStatus _exitStatus,
const long long _index);
private:
/**
* @brief connection map
*/
QueuedProcessConnectionMap m_connections;
/**
* @brief action on exit
*/
QueuedEnums::ExitAction m_onExit;
/**
* @brief processes list
*/
QueuedProcessMap m_processes;
};
#endif /* QUEUEDPROCESS_H */

View File

@ -0,0 +1,132 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedPropertyInterface.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDPROPERTYINTERFACE_H
#define QUEUEDPROPERTYINTERFACE_H
#include <QDBusAbstractAdaptor>
#include <QDBusVariant>
#include "QueuedConfig.h"
class QueuedCore;
/**
* @brief DBus interface for QueuedCore class
*/
class QueuedPropertyInterface : public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", DBUS_SERVICE_NAME)
public:
/**
* @brief QueuedPropertyInterface class constructor
* @param parent
* pointer to QueuedCore object
*/
explicit QueuedPropertyInterface(QueuedCore *parent);
/**
* @brief QueuedPropertyInterface class destructor
*/
virtual ~QueuedPropertyInterface();
public slots:
/**
* @brief get plugin description
* @param plugin
* plugin name
* @param token
* user auth token
* @return plugin properties
*/
QDBusVariant Plugin(const QString &plugin, const QString &token);
/**
* @brief get plugin options
* @param plugin
* plugin name
* @param token
* user auth token
* @return list of plugin options and their values
*/
QDBusVariant PluginOptions(const QString &plugin, const QString &token);
/**
* @brief get advanced option
* @param property
* property name
* @param token
* user auth token
* @return property value or empty if property not found
*/
QDBusVariant Option(const QString &property, const QString &token);
/**
* @brief get task property
* @param id
* task ID
* @param property
* property name
* @param token
* user auth token
* @remark if property is empty it return map of all properties
* @return property value or empty if task or property not found
*/
QDBusVariant Task(const long long id, const QString &property, const QString &token);
/**
* @brief get user property
* @param id
* user ID
* @param property
* property name
* @param token
* user auth token
* @remark if property is empty it return map of all properties
* @return property value or empty if user or property not found
*/
QDBusVariant User(const long long id, const QString &property, const QString &token);
/**
* @brief get user ID by name
* @param name
* user name
* @param token
* user auth token
* @return user ID or -1 if no user found
*/
QDBusVariant UserIdByName(const QString &name, const QString &token);
private:
/**
* @brief pointer to database object
*/
QueuedCore *m_core = nullptr;
/**
* @brief get all properties
* @param _object
* pointer to object
* @return map of properties
*/
QVariantHash getProperties(const QObject *_object);
};
#endif /* QUEUEDPROPERTYINTERFACE_H */

View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedReportInterface.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDREPORTINTERFACE_H
#define QUEUEDREPORTINTERFACE_H
#include <QDBusAbstractAdaptor>
#include <QDBusVariant>
#include "QueuedConfig.h"
class QueuedCore;
/**
* @brief DBus interface for QueuedReportManager class
*/
class QueuedReportInterface : public QDBusAbstractAdaptor
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", DBUS_SERVICE_NAME)
public:
/**
* @brief QueuedReportInterface class constructor
* @param parent
* pointer to QueuedCore object
*/
explicit QueuedReportInterface(QueuedCore *parent);
/**
* @brief QueuedReportInterface class destructor
*/
virtual ~QueuedReportInterface();
public slots:
/**
* @brief performance report
* @param from
* start report date
* @param to
* stop report date
* @param token
* user auth token
* @return
*/
QDBusVariant Performance(const QString &from, const QString &to, const QString &token);
/**
* @brief server status
* @return server status
*/
QDBusVariant Status();
/**
* @brief tasks list
* @param user
* user ID to select
* @param from
* minimal task start time
* @param to
* maximal task end time
* @param token
* user auth token
* @return list of tasks match to query
*/
QDBusVariant Tasks(const qlonglong user, const QString &from, const QString &to,
const QString &token);
/**
* @brief users list
* @param lastLogged
* minimal last logged
* @param permission
* permission to search
* @param token
* user auth token
* @return list of users match to query
*/
QDBusVariant Users(const QString &lastLogged, const uint permission, const QString &token);
private:
/**
* @brief pointer to database object
*/
QueuedCore *m_core = nullptr;
};
#endif /* QUEUEDREPORTINTERFACE_H */

View File

@ -0,0 +1,107 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedReportManager.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDREPORTMANAGER_H
#define QUEUEDREPORTMANAGER_H
#include <QDateTime>
#include <QObject>
#include "QueuedEnums.h"
class QueuedCore;
class QueuedDatabase;
/**
* @brief report manager for queued
*/
class QueuedReportManager : public QObject
{
Q_OBJECT
public:
/**
* @brief QueuedReportManager class constructor
* @param _parent
* pointer to parent item
* @param _database
* pointer to database object
* @param _token
* user auth token
*/
explicit QueuedReportManager(QObject *_parent, QueuedDatabase *_database,
const QString &_token);
/**
* @brief QueuedReportManager class destructor
*/
virtual ~QueuedReportManager();
/**
* @brief usage report
* @param _from
* start report date
* @param _to
* stop report date
* @param _core
* pointer to core object
* @return performance table
*/
QList<QVariantHash> performance(const QueuedCore *_core, const QDateTime &_from = QDateTime(),
const QDateTime &_to = QDateTime()) const;
/**
* list of tasks which match criteria
* @param _user
* task user ID filter
* @param _from
* minimal start time
* @param _to
* maximal end time
* @return list of tasks in database format
*/
QList<QVariantHash> tasks(const long long _user = -1, const QDateTime &_from = QDateTime(),
const QDateTime &_to = QDateTime()) const;
/**
* list of users which match criteria
* @param _lastLogged
* last logged minimal date
* @param _permission
* user permission filter
* @return list of users in database format
*/
QList<QVariantHash> users(const QDateTime &_lastLogged = QDateTime(),
const QueuedEnums::Permission _permission
= QueuedEnums::Permission::Invalid) const;
private:
/**
* @brief pointer to database object
*/
QueuedDatabase *m_database = nullptr;
/**
* @brief object token
*/
QString m_token;
};
#endif /* QUEUEDREPORTMANAGER_H */

View File

@ -0,0 +1,206 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedResult.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDRESULT_H
#define QUEUEDRESULT_H
#include <QDBusArgument>
#include <result/result.hpp>
#include "QueuedPluginSpecification.h"
namespace QueuedEnums
{
enum class ReturnStatus;
};
/**
* @typedef QueuedError
* custom result error implementation
*/
typedef Result::Error<QueuedEnums::ReturnStatus> QueuedError;
/**
* @brief DBus marshalling method
* @param _argument
* output DBus argument
* @param _arg
* input error class
* @return appended argument body
*/
inline QDBusArgument &operator<<(QDBusArgument &_argument, const QueuedError &_arg)
{
_argument.beginStructure();
_argument << QString(_arg.message().c_str());
_argument << static_cast<long long>(_arg.code());
_argument.endStructure();
return _argument;
};
/**
* @brief DBus un-marshalling method
* @param _argument
* input DBus argument
* @param _arg
* output object
* @return source DBus argument
*/
inline const QDBusArgument &operator>>(const QDBusArgument &_argument, QueuedError &_arg)
{
QString message;
long long code;
_argument.beginStructure();
_argument >> message;
_argument >> code;
_argument.endStructure();
_arg = QueuedError(message.toStdString(), static_cast<QueuedEnums::ReturnStatus>(code));
return _argument;
};
/**
* @typedef QueuedStatusMap
* status report representation
*/
typedef QHash<QString, QHash<QString, QString>> QueuedStatusMap;
/**
* @typedef QueuedResult
* @tparam T
* result value payload class
* custom Result<T, E> implementation
*/
template <class T> using QueuedResult = Result::Result<T, QueuedEnums::ReturnStatus>;
Q_DECLARE_METATYPE(QueuedResult<bool>)
Q_DECLARE_METATYPE(QueuedResult<long long>)
Q_DECLARE_METATYPE(QueuedResult<QString>)
Q_DECLARE_METATYPE(QueuedResult<QStringList>)
Q_DECLARE_METATYPE(QueuedResult<QVariant>)
Q_DECLARE_METATYPE(QueuedResult<QList<QVariantHash>>)
Q_DECLARE_METATYPE(QueuedResult<QVariantHash>)
Q_DECLARE_METATYPE(QueuedResult<QueuedPluginSpecification::Plugin>)
Q_DECLARE_METATYPE(QueuedResult<QueuedPluginSpecification::PluginOption>)
Q_DECLARE_METATYPE(QueuedResult<QueuedStatusMap>)
Q_DECLARE_METATYPE(QueuedPluginSpecification::Plugin)
Q_DECLARE_METATYPE(QueuedPluginSpecification::PluginOption)
/**
* @brief DBus marshalling method
* @param _argument
* output DBus argument
* @param _arg
* input variant object
* @return appended argument body
*/
inline QDBusArgument &operator<<(QDBusArgument &_argument, const QVariant &_arg)
{
return _argument << QDBusVariant(_arg.isValid() ? _arg : "");
};
/**
* @brief DBus un-marshalling method
* @param _argument
* input DBus argument
* @param _arg
* output variant object
* @return source DBus argument
*/
inline const QDBusArgument &operator>>(const QDBusArgument &_argument, QVariant &_arg)
{
QDBusVariant variant;
_argument >> variant;
_arg = variant.variant();
return _argument;
};
/**
* @brief DBus marshalling method
* @tparam T
* result value payload class
* @param _argument
* output DBus argument
* @param _arg
* input result object
* @return appended argument body
*/
template <class T>
inline QDBusArgument &operator<<(QDBusArgument &_argument, const QueuedResult<T> &_arg)
{
// HACK we are using explicit cast to QString here to make sure of valid
// marshalling
_argument.beginStructure();
switch (_arg.type()) {
case Result::Content::Value:
_argument << QString("v");
_argument << _arg.get();
_argument << QueuedError();
break;
case Result::Content::Error:
_argument << QString("e");
_argument << T();
_argument << _arg.error();
break;
case Result::Content::Empty:
_argument << QString("n");
_argument << T();
_argument << QueuedError();
break;
}
_argument.endStructure();
return _argument;
};
/**
* @brief DBus un-marshalling method
* @tparam T
* result value payload class
* @param _argument
* input DBus argument
* @param _arg
* output result object
* @return source DBus argument
*/
template <class T>
inline const QDBusArgument &operator>>(const QDBusArgument &_argument, QueuedResult<T> &_arg)
{
QString type;
T value;
QueuedError error;
_argument.beginStructure();
_argument >> type;
_argument >> value;
_argument >> error;
_argument.endStructure();
if (type == "v")
_arg = value;
else if (type == "e")
_arg = error;
else if (type == "n")
_arg = QueuedResult<T>();
return _argument;
};
#endif /* QUEUEDRESULT_H */

View File

@ -0,0 +1,104 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedSettings.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDSETTINGS_H
#define QUEUEDSETTINGS_H
#include <QObject>
#include "QueuedStaticConfig.h"
/**
* @brief implementation over QSettings
*/
class QueuedSettings : public QObject
{
Q_OBJECT
Q_PROPERTY(QString path READ path)
Q_PROPERTY(QueuedConfig::QueuedAdminSetup admin READ admin)
Q_PROPERTY(QueuedConfig::QueuedDBSetup db READ db)
public:
/**
* @brief QueuedSettings class constructor
* @param _parent
* pointer to parent item
* @param _path
* path to configuration file
*/
explicit QueuedSettings(QObject *_parent, const QString _path);
/**
* @brief QueuedSettings class destructor
*/
virtual ~QueuedSettings();
/**
* @brief administrator settings
* @return QueuedAdminSetup structure
*/
QueuedConfig::QueuedAdminSetup admin() const;
/**
* @brief database settings
* @return QueuedDBSetup structure
*/
QueuedConfig::QueuedDBSetup db() const;
/**
* @brief default path to configuration
* @return default path to configuration file
*/
static QString defaultPath();
/**
* @brief default path to cached token
* @return default path to cached token file
* @return
*/
static QString defaultTokenPath();
/**
* @brief path to database
* @return path to used database
*/
QString path() const;
public slots:
/**
* @brief read configuration from file
*/
void readConfiguration();
private:
/**
* @brief admin configuration
*/
QueuedConfig::QueuedAdminSetup m_cfgAdmin;
/**
* @brief database configuration
*/
QueuedConfig::QueuedDBSetup m_cfgDB;
/**
* @brief path to configuration
*/
QString m_path;
};
#endif /* QUEUEDSETTINGS_H */

View File

@ -0,0 +1,162 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedStaticConfig.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDCONFIGURATION_H
#define QUEUEDCONFIGURATION_H
#include <QHash>
#include <QString>
#include <QVariant>
#include "QueuedConfig.h"
/**
* @addtogroup QueuedConfig
* @brief Queued configuration related types
*/
namespace QueuedConfig
{
/**
* @struct QueuedAdminSetup
* @brief structure to define administrator user
* @var QueuedAdminSetup::name
* administrator user name
* @var QueuedAdminSetup::password
* administrator user password
* @var QueuedAdminSetup::salt
* user passwords salt
*/
struct QueuedAdminSetup {
QString name;
QString password;
QString salt;
};
/**
* @struct QueuedDBSetup
* @brief structure to define database setup
* @var QueuedDBSetup::driver
* driver name
* @var QueuedDBSetup::hostname
* hostname to connect
* @var QueuedDBSetup::password
* password to connect if any
* @var QueuedDBSetup::path
* path to database
* @var QueuedDBSetup::port
* port to connect
* @var QueuedDBSetup::username
* username to connect if any
*/
struct QueuedDBSetup {
QString driver;
QString hostname;
QString password;
QString path;
int port;
QString username;
};
/**
* @enum QueuedSettings
* @brief settings keys enum
* @var QueuedSettings::Invalid
* unknown key
* @var QueuedSettings::DatabaseInterval
* database actions interval in msecs
* @var QueuedSettings::DatabaseVersion
* internal field to control current database version
* @var QueuedSettings::DefaultLimits
* default limits value
* @var QueuedSettings::KeepTasks
* keep ended tasks in msecs
* @var QueuedSettings::KeepUsers
* keep users last logged in msecs
* @var QueuedSettings::OnExitAction
* on queued exit action enum
* @var QueuedSettings::Plugins
* plugin list
* @var QueuedSettings::ServerAddress
* queued server bind address
* @var QueuedSettings::ServerMaxConnections
* queued server max connections
* @var QueuedSettings::ServerPort
* queued server bind port
* @var QueuedSettings::ServerTimeout
* server thread timeout
* @var QueuedSettings::TokenExpiration
* token expiration value in days
*/
enum class QueuedSettings {
Invalid,
DatabaseInterval,
DatabaseVersion,
DefaultLimits,
KeepTasks,
KeepUsers,
OnExitAction,
Plugins,
ServerAddress,
ServerMaxConnections,
ServerPort,
ServerTimeout,
TokenExpiration
};
/**
* @struct QueuedSettingsField
* @brief structure to define advanced settings field
* @var QueuedSettingsField::id
* interval field ID
* @var QueuedSettingsField::defaultValue
* settings default value
*/
struct QueuedSettingsField {
QueuedSettings id;
QVariant defaultValue;
bool isAdmin = true;
};
/**
* @typedef QueuedSettingsDefaultMap
* map of settings indices to related values
*/
typedef QHash<QString, QueuedSettingsField> QueuedSettingsDefaultMap;
/**
* @brief default settings map
*/
static const QueuedSettingsDefaultMap QueuedSettingsDefaults = {
{"", {QueuedSettings::Invalid, QVariant(), false}},
{"DatabaseInterval", {QueuedSettings::DatabaseInterval, 86400000, true}},
{"DatabaseVersion", {QueuedSettings::DatabaseVersion, QueuedConfig::DATABASE_VERSION, true}},
{"DefaultLimits", {QueuedSettings::DefaultLimits, "0\n0\n0\n0\n0", false}},
{"KeepTasks", {QueuedSettings::KeepTasks, 0, false}},
{"KeepUsers", {QueuedSettings::KeepUsers, 0, false}},
{"OnExitAction", {QueuedSettings::OnExitAction, 2, false}},
{"Plugins", {QueuedSettings::Plugins, "", false}},
{"ServerAddress", {QueuedSettings::ServerAddress, "", false}},
{"ServerMaxConnections", {QueuedSettings::ServerMaxConnections, 30, false}},
{"ServerPort", {QueuedSettings::ServerPort, 8080, false}},
{"ServerTimeout", {QueuedSettings::ServerTimeout, -1, false}},
{"TokenExpiration", {QueuedSettings::TokenExpiration, 30, false}},
};
}; // namespace QueuedConfig
#endif /* QUEUEDCONFIGURATION_H */

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedSystemInfo.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDSYSTEMINFO_H
#define QUEUEDSYSTEMINFO_H
/**
* @addtogroup QueuedSystemInfo
* @brief system information methods
*/
namespace QueuedSystemInfo
{
/**
* @brief system CPU count
* @return system CPU count
*/
long long cpuCount();
/**
* @brief weight of specified CPU count
* @param _cpu
* CPU count to get weight
* @return weight as proportion
*/
double cpuWeight(const long long _cpu);
/**
* @brief system memory count
* @return system memory count in bytes
*/
long long memoryCount();
/**
* @brief weight of specified memory count
* @param _memory
* memory in bytes to get weight
* @return weight as proportion
*/
double memoryWeight(const long long _memory);
} // namespace QueuedSystemInfo
#endif /* QUEUEDSYSTEMINFO_H */

View File

@ -0,0 +1,126 @@
/*
* Copyright (c) 2017 Queued team
*
* 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.
*/
/**
* @file QueuedTokenManager.h
* Header of Queued library
* @author Queued team
* @copyright MIT
* @bug https://github.com/arcan1s/queued/issues
*/
#ifndef QUEUEDTOKENMANAGER_H
#define QUEUEDTOKENMANAGER_H
#include <QDateTime>
#include <QObject>
/**
* @brief token management system
*/
class QueuedTokenManager : public QObject
{
Q_OBJECT
public:
/**
* @struct QueuedTokenDefinitions
* @brief structure to define token
* @var QueuedTokenDefinitions::token
* token ID
* @var QueuedTokenDefinitions::user
* token owner user
* @var QueuedTokenDefinitions::validUntil
* valid until
*/
typedef struct {
QString token;
QString user;
QDateTime validUntil;
} QueuedTokenDefinitions;
/**
* @brief QueuedTokenManager class constructor
* @param _parent
* pointer to parent item
*/
explicit QueuedTokenManager(QObject *_parent);
/**
* @brief QueuedTokenManager class destructor
*/
virtual ~QueuedTokenManager();
/**
* @brief check if token is valid
* @param _token
* token ID
* @return token user if token is valid otherwise return empty string
*/
QString isTokenValid(const QString &_token) const;
/**
* @brief load token
* @param _definitions
* token definitions
*/
void loadToken(const QueuedTokenManager::QueuedTokenDefinitions &_definitions);
/**
* @brief upload tokens from database
* @param _values
* tokens from database
*/
void loadTokens(const QList<QVariantHash> &_values);
/**
* @brief register new token
* @param _user
* token user
* @param _validUntil
* token valid until
* @return new generated token
*/
QString registerToken(const QString &_user, const QDateTime &_validUntil);
/**
* @brief token expiration
* @param _token
* token ID
* @return token expiration if token found, otherwise return default
* QDateTime constructor
*/
QDateTime tokenExpiration(const QString &_token) const;
public slots:
/**
* @brief method which will be called on token expiring
* @param _token
* expired token ID
*/
void expireToken(const QString &_token);
signals:
/**
* @brief signal which will be emitted on token expiration
* @param _token
* token ID
*/
void tokenExpired(const QString &_token);
private:
/**
* @brief token storage
*/
QHash<QString, QueuedTokenDefinitions> m_tokens;
};
#endif /* QUEUEDTOKENMANAGER_H */

Some files were not shown because too many files have changed in this diff Show More