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%> Project   Description system   The system project is used for all system processes and daemons. user.root   All root processes run in the user.root project. no.project   The noproject project is a special project for IP Quality of Service. You can savely ignore it for this tutorial default   When there isn´t a matching group, this is the catch-all. A user without an explicitly defined project is member of this project group.staff   The group.staff project is used for all users in the group staff </table>

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:

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:

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&
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>
Voila, the sleep runs within a different project.

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.