on
Less known Solaris Features: Resource Management - Part 2: How to work with Tasks and Projects
Even when you never heard of constructs like tasks and projects you already use them, as there are a few projects installed per default. For example whenever you log into your system as a regular user, all you do is part of the project default
because your user is member of this project:
# su jmoekamp<br />
# id -p<br />
uid=100(jmoekamp) gid=1(other) projid=3(default)
When you assume the privileges of the root user you work as a member of the user.root project.
$ su root<br />
Password:<br />
# id -p<br />
uid=0(root) gid=0(root) projid=1(user.root)
Let´s have another look at the alread running processes of your system.
# ps -ef -o pid,user,zone,project,taskid,args<br />
# ps -ef -o pid,user,zone,project,taskid,args<br />
PID USER ZONE PROJECT TASKID COMMAND<br />
0 root global system 0 sched<br />
[...]<br />
126 daemon global system 22 /usr/lib/crypto/kcfd<br />
646 jmoekamp global default 73 /usr/lib/ssh/sshd<br />
[...]<br />
413 root global user.root 72 -sh<br />
647 jmoekamp global default 73 -sh<br />
[...]<br />
655 root global user.root 74 ps -ef -o pid,user,zone,project,taskid,args<br />
651 root global user.root 74 sh<br />
As you see from the output of ps
you already use some projects, that are default on every Solaris system. And even the concept of task is in use right now. Whenever a user log into a Solaris system, a new task is opened. Furthermore you will see, that all your services started by the Service management facility have their own own task id. The SMF starts every service as a new task.
# ps -ef -o pid,user,zone,project,taskid,args | grep " 74 "<br />
653 root global user.root 74 bash<br />
656 root global user.root 74 ps -ef -o pid,user,zone,project,taskid,args<br />
657 root global user.root 74 bash<br />
651 root global user.root 74 sh</blockquote>
</code>The projects are stored in a file per default, but you can use LDAP or NIS for a common project database on all your systems:
<blockquote><code># cat /etc/project<br />
system:0::::<br />
user.root:1::::<br />
noproject:2::::<br />
default:3::::<br />
group.staff:10::::
A freshly installed system has already this pre-defined projects:
<table width=70%>
Okay, but how do we create our own projects? It´s really easy:
[root@theoden:~]$ projadd -p 1000 testproject<br />
[root@theoden:~]$ projmod -c "Testserver project" testproject<br />
[root@theoden:~]$ projdel testproject
We created the project testproject
with the project id 1000
. Then we modified it by adding informations to the comment field. After this, we´ve deleted the project.
A practical example
Okay, i will use a practical example, now. We working as an administrator at the Unseen University. We´ve got a new system and want to create the users.
# useradd alice<br />
# useradd bob<br />
# useradd mike<br />
# useradd laura
Looks familiar? I´ve omitted to set the password here. But of course you have to set one. Now we create some projects for two classes:
# projadd class2005<br />
# projadd class2006
Okay. This projects have no users. We assign the project to our users.
# usermod -K project=class2005 alice<br />
# usermod -K project=class2005 bob<br />
# usermod -K project=class2006 mike<br />
# usermod -K project=class2006 laura
Like roles this assignments are stored in the file /etc/user_attr
:
alice::::type=normal;project=class2005<br />
bob::::type=normal;project=class2005<br />
mike::::type=normal;project=class2006<br />
laura::::type=normal;project=class2006
Okay, let´s su
to the user alice and check for the project assignment:
bash-3.2$ su alice<br />
Password:<br />
$ id -p<br />
uid=2005(alice) gid=1(other) projid=100(class2005)
As configured the user alice
is assigned to the project class2005
. When we look into the process table, we can check the forth columns. All processes owned by alice are assigned to the correct project.
# ps -ef -o pid,user,zone,project,taskid,args | grep "class2005"<br />
752 alice global class2005 76 sh<br />
758 alice global class2005 76 sleep 10
Okay, obviously our teachers want their own projects: You can configure this on two ways. You can can configure it by hand, or create a project beginning with user.
and ending with the username. We use the second method in this example.
# useradd einstein<br />
# projadd user.einstein<br />
# passwd einstein<br />
New Password:<br />
Re-enter new Password:<br />
passwd: password successfully changed for einstein
Now we check for the project:
$ su einstein<br />
Password:<br />
$ id -p<br />
uid=2009(einstein) gid=1(other) projid=102(user.einstein)<br />
$ sleep 100 &<br />
$ ps -ef -o pid,user,zone,project,taskid,args | grep "user.einstein"<br />
777 einstein global user.einstein 78 sh<br />
782 einstein global user.einstein 78 sleep 100<br />
788 einstein global user.einstein 78 grep user.einstein<br />
789 einstein global user.einstein 78 ps -ef -o pid,user,zone,project,taskid,args
Et voila! We don´t have to assign the project explicitly. It´s done automagically by the system. The logic behind the automatic assigning of the project to a user is simple:
- If the name of the project is defined by adding the
project
user attribute, use the assigned project as the default for the user. - If it´s not defined with the user, look for a project beginning with
user.
and ending with the name of the user and use it as default project. For example:user.root
oruser.jmoekamp
- If there no such project, search for a project beginning with
group.
and ending with the name of the group of a user and use it as default project. For example:group.staff
- If there´s no group with this name, use the project "default" as the default project.
But how do you create a task? You don´t have to configure tasks! A task is created automatically by the system in certain events. Those events are:
- login
- cron
- newtask
- setproject
- su
Okay, let´s start a sleep in a new task:
$ newtask sleep 10 &<br />
761
Okay, when you look at the process table now, you will see the different taskid in the fifth column:
# ps -ef -o pid,user,zone,project,taskid,args | grep "class2005"<br />
752 alice global class2005 76 sh<br />
761 alice global class2005 77 sleep 10
But you can use the newtask command to assign a different project, too. At first we create another project. We work at the Large Hadron Collider project, thus we call it lhcproject
$ newtask -p lhcproject sleep 100 &<br />
802<br />
$ newtask: user "einstein" is not a member of project "lhcproject"
Hey, not this fast! You have to be a member of the project to add a task to a project. Without this hurdle it would be too easy to use the resources of different project ;) Okay, let´s add the user einstein
to the group lhcproject again.
# projmod -U einstein lhcproject
Now we can try it again:
$ newtask -p lhcproject sleep 1000&
Voila, the sleep runs within a different project.
817
$ ps -ef -o pid,user,zone,project,taskid,args | grep "einstein"
777 einstein global user.einstein 78 sh
817 einstein global lhcproject 80 sleep 1000
819 einstein global user.einstein 78 ps -ef -o pid,user,zone,project,taskid,args
818 einstein global user.einstein 78 grep einstein
$ </blockquote>Why do i need all this stuff?
But why is all this stuff important for Resource Management? While it´s possible to put resource management onto a single process, this isn´t a sensible choise most of the time. Your workload consists out of multiple services out of multiple processes and it would be more complex to configure resource managment to each of this processes. With the concepts of projects and tasks you can assign those limits to a group of processes.