Solaris Resource Manager
Resource Management is an rather old feature in Solaris, albeit it got more mind share since it got a really important part of the Solaris Zones. But this tutorial doesn’t focus on the usage of Resource Management in conjunction with the zone configuration. I want to go to the basics, because at the end the zone configuration just uses this facilities to control the resource consumption of zones. Secondly you can use this knowledge to limit resource usage in a zone itself.
Resource Management was introduced to solve one important question. You can run multiple programs and services at once in a single instance of the operating system, but how do I limit the consumption of resources of a single application? How do I prevent a single program from consuming all the resources leaving nothing to others? Resource Management in Solaris solves this class of problems.
Why do you need Resource Management?
Unix systems were capable to execute a multitude of independent services on one system since its introduction many years ago. But there was a problem: What happens in case of a process running amok? A user eating away resources of the system? You have to control the allocation of this resources. How many CPU does a process get? How many file descriptors are allocated to a user? The Solaris Resource Management is capable to put other processes under the control of an user configurable ruleset. Thus you can prevent a situation where your system is down, because a single process takes all resources.
With such an ability, the usage of a single system for a multitude of services becomes more manageable and thus more feasible.
Definitions
Okay, as usual, this technology has its own jargon. So I have to define some of it at first:
-
Tasks: A task is a group of processes. For example when you log into a system and do some work all the steps you’ve done are an task until you logout or open a new task. Another example would be a webserver. It consists out of a multitude of processes, but they are all part of the same task. The database server on the same machine may have a completely different task id.
-
Projects: A project is a group of tasks. For example you have a webserver. It consists out of the processes of the database task and the webserver task.
-
Zones: From the perspective of the resource management, a Solaris Zone is just a group of one or more projects.
The basic idea of Solaris Resource Management
The basic idea of resource management is to use the grouping of processes and to impose limits on a group on processes defined by one of the above entities. A limit on the zone would limit all projects in a zone. A limit on the project would limit all tasks grouped by the project. A limit on a task would limit all processes grouped by the tasks.
Let’s take an example: There is a resource control called max-lwps. It controls the amount of processes. This control exists as task.max-lwps, project.max-lwps and zone.max-lwps. With this control you can define limits for the number of processes in a group of processes defined by one of the entities mentioned above.
You want to ensure, that you have 1000 processes at maximum in your zone webserver. You can define it by using zone.max-lwps for the zone webserver. You want to ensure, that the www.c0t0d0s0.org webserver project consisting out of mysql and apache processes uses 250 processes at maximum. You use the project.max-lwps for the project webserver-c0t0d0s0. You want to limit the httpd-server itself to 100 processes. You impose this limit by using the task.max-lwps control.
How do you configure this? This will be the topic of this tutorial. It sounds complex, but it isn’t, once you’ve understand the entities.
How to work with projects and tasks
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
# id -p
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
Password:
# id -p
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
PID USER ZONE PROJECT TASKID COMMAND
0 root global system 0 sched
[...]
126 daemon global system 22 /usr/lib/crypto/kcfd
646 jmoekamp global default 73 /usr/lib/ssh/sshd
[...]
413 root global user.root 72 -sh
647 jmoekamp global default 73 -sh
[...]
655 root global user.root 74 ps -ef -o pid,user,zone,project,taskid,args
651 root global user.root 74 sh
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 task id. The SMF starts every service as a new task.
# ps -ef -o pid,user,zone,project,taskid,args | grep " 74 "
653 root global user.root 74 bash
656 root global user.root 74 ps -ef -o pid,user,zone,project,taskid,args
657 root global user.root 74 bash
651 root global user.root 74 sh
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:
# cat /etc/project
system:0::::
user.root:1::::
noproject:2::::
default:3::::
group.staff:10::::
A freshly installed system has already this pre-defined projects:
- ::: center
- ::: {#default}
- [Project]{.smallcaps} [Description]{.smallcaps}
- ———————– ———————————————————————————————————————————-
- 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
-
Factory-configured project in Solaris ::: :::
[]{#default label=”default”}
Okay, but how do we create our own projects? It’s really easy:
[root@theoden:~]$ projadd -p 1000 testproject
[root@theoden:~]$ projmod -c "Testserver project" testproject
[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
# useradd bob
# useradd mike
# 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
# projadd class2006
Okay. This projects have no users. We assign the project to our users.
# usermod -K project=class2005 alice
# usermod -K project=class2005 bob
# usermod -K project=class2006 mike
# usermod -K project=class2006 laura
Like roles this assignments are stored in the file /etc/user_attr:
alice::::type=normal;project=class2005
bob::::type=normal;project=class2005
mike::::type=normal;project=class2006
laura::::type=normal;project=class2006
Okay, let’s su to the user alice and check for the project assignment:
bash-3.2$ su alice
Password:
$ id -p
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"
752 alice global class2005 76 sh
758 alice global class2005 76 sleep 10
Okay, obviously our teachers want their own projects: You can configure this on two ways. You 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
# projadd user.einstein
# passwd einstein
New Password:
Re-enter new Password:
passwd: password successfully changed for einstein
Now we check for the project:
$ su einstein
Password:
$ id -p
uid=2009(einstein) gid=1(other) projid=102(user.einstein)
$ sleep 100 &
$ ps -ef -o pid,user,zone,project,taskid,args | grep "user.einstein"
777 einstein global user.einstein 78 sh
782 einstein global user.einstein 78 sleep 100
788 einstein global user.einstein 78 grep user.einstein
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
projectuser 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.rootoruser.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 &
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"
752 alice global class2005 76 sh
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 &
802
$ 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
$
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 choice most of the time. Your workload consists out of multiple services out of multiple processes and it would be more complex to configure resource management to each of this processes. With the concepts of projects and tasks you can assign those limits to a group of processes.
Limiting operating environment resources
The kernel of an operating system provides a huge amount of resources to the processes running on it. Such resources are file descriptors, shared memory segments or the process tables. Albeit hard to fill up this resources with modern operating systems it’s not impossible. When a resource is consumed by a single malicious or erroneous application, all other can’t run as well when they need more resources from the operating system.
Let’s assume this scenario: There is an course "Perl Scripting for beginners" at the Unseen University and in the last year the lesson "About fork" ended in chaos as some of your students coded forkbombs as they though this would be funny (as the class before, and the one before ...)
#!/usr/bin/perl
fork while 1
I’ve stored this little script at /opt/bombs/forkbomb.pl. A few seconds after starting such a script, the system is toast because of the hundreds of forked processes. Don’t try this without resource management. Okay, but this year, you’ve migrated to Solaris. You can impose resource management.
Okay, we have to modify our project configuration:
# projmod -K "task.max-lwps=(privileged,10,deny)" class2005
Now we have configured a resource limit. A single task in the class2005 cant have more than 9 processes. The tenth attempt to fork will be denied. Okay, do you remember the reasons, why the system starts a new task? One of it is "login". Thus every login of a user gives him 10 threads to work with. And this is exactly the behavior we want.
Let’s assume Alice starts her forkbomb:
# ps -ef | grep "alice"
alice 685 682 0 14:58:12 ? 0:00 /usr/lib/ssh/sshd
alice 693 686 14 14:58:42 pts/1 0:38 /usr/bin/perl /opt/bombs/forkbomb.pl
alice 686 685 0 14:58:12 pts/1 0:00 -sh
alice 694 693 15 14:58:42 pts/1 0:38 /usr/bin/perl /opt/bombs/forkbomb.pl
alice 695 694 14 14:58:42 pts/1 0:37 /usr/bin/perl /opt/bombs/forkbomb.pl
alice 696 695 14 14:58:42 pts/1 0:37 /usr/bin/perl /opt/bombs/forkbomb.pl
alice 697 696 14 14:58:42 pts/1 0:37 /usr/bin/perl /opt/bombs/forkbomb.pl
alice 698 697 14 14:58:42 pts/1 0:39 /usr/bin/perl /opt/bombs/forkbomb.pl
alice 699 698 14 14:58:42 pts/1 0:38 /usr/bin/perl /opt/bombs/forkbomb.pl
# ps -ef | grep "alice" | wc -l
9
After forking away 7 forkbomb.pl processes, any further fork is denied by the system. The load of the system goes up (as there are hundreds of denied forks) but the system stays usable.
Alice sends her script to Bob. He tries it, too:
# ps -ef | grep "alice"
alice 685 682 0 14:58:12 ? 0:00 /usr/lib/ssh/sshd
alice 28520 28519 6 15:15:08 pts/1 0:03 /usr/bin/perl /opt/bombs/forkbomb.pl
alice 686 685 0 14:58:12 pts/1 0:00 -sh
alice 28521 28520 6 15:15:08 pts/1 0:03 /usr/bin/perl /opt/bombs/forkbomb.pl
alice 28519 686 6 15:15:08 pts/1 0:02 /usr/bin/perl /opt/bombs/forkbomb.pl
alice 28522 28521 6 15:15:08 pts/1 0:03 /usr/bin/perl /opt/bombs/forkbomb.pl
alice 28524 28523 6 15:15:08 pts/1 0:03 /usr/bin/perl /opt/bombs/forkbomb.pl
alice 28523 28522 6 15:15:08 pts/1 0:03 /usr/bin/perl /opt/bombs/forkbomb.pl
alice 28525 28524 6 15:15:08 pts/1 0:02 /usr/bin/perl /opt/bombs/forkbomb.pl
# ps -ef | grep "bob"
bob 28514 28511 0 15:14:47 ? 0:00 /usr/lib/ssh/sshd
bob 28515 28514 0 15:14:47 pts/3 0:00 -sh
bob 2789 2502 6 15:15:10 pts/3 0:03 /usr/bin/perl /opt/bombs/forkbomb.pl
bob 2791 2790 6 15:15:10 pts/3 0:03 /usr/bin/perl /opt/bombs/forkbomb.pl
bob 2502 28515 6 15:15:10 pts/3 0:03 /usr/bin/perl /opt/bombs/forkbomb.pl
bob 2790 2789 6 15:15:10 pts/3 0:03 /usr/bin/perl /opt/bombs/forkbomb.pl
bob 2792 2791 6 15:15:10 pts/3 0:03 /usr/bin/perl /opt/bombs/forkbomb.pl
bob 2793 2792 6 15:15:10 pts/3 0:02 /usr/bin/perl /opt/bombs/forkbomb.pl
bob 2794 2793 6 15:15:10 pts/3 0:03 /usr/bin/perl /opt/bombs/forkbomb.pl
This is still no problem for the system. After a few forks of the forkbomb, the system denies further forks. And the system stays usable. The limitation of the number of processes is only one example. You can limit other resources. You can find a list of all controls at the man page of resource_controls
Limiting CPU resources
Okay, but your system wasn’t purchased for students at night. You’ve bought it for computational science at night. The Large Hadron Collider project spend 75% of the costs, and the Small Hadron Collider project spend 25%. Thus the compute power should be distributed in a similar manner.
Without Resource Management
But when you start two compute intensive processes, both get roundabout 50 percent of processor. Okay, we have an super-duper simulation script called /opt/bombs/cpuhog.pl:
#! /usr/bin/perl
while (1) { my $res = ( 3.3333 / 3.14 ) }
Let’s login as user einstein:
# su einstein
Password:
$ /opt/bombs/cpuhog.pl &
$ /opt/bombs/cpuhog.pl &
After a few moments the system will stabilize at aprox. 50% CPU resources for both processes. Just look at the first column:
bash-3.2$ ps -o pcpu,project,args
%CPU PROJECT COMMAND
0.0 user.einstein -sh
0.3 user.einstein bash
47.3 user.einstein /usr/bin/perl /opt/bombs/cpuhog.pl
48.0 user.einstein /usr/bin/perl /opt/bombs/cpuhog.pl
0.2 user.einstein ps -o pcpu,project,args
This isn’t the intended behavior.
Using the Fair Share Scheduler
Solaris can solve this problem. There is something called Fair Share Scheduler in Solaris. This scheduler is capable to distribute the compute power of the system based on a configuration. The FFS isn’t activated by default. You have to login as root to activate it:
# dispadmin -d FSS
There are ways to enable this scheduler with a running system, but it’s easier to reboot the system now.
When the system has started, we get root privileges by using su. At first we create an additional project for the SHC project. We created the other project (lhcproject) before:
# projadd shcproject
#projmod -U einstein shcproject
Now we configure an resource limit on the projects.
# projmod -K "project.cpu-shares=(privileged,150,none)" lhcproject
# projmod -K "project.cpu-shares=(privileged,50,none)" shcproject
We’ve used the resource control project.cpu-shares. With this control we can assign an amount of CPU power to an project. We’ve defined an privileged limit, thus only root can change this limit later on.
Shares
Okay, what is the meaning of these numbers 150 and 50 in the last commands ? Where are the 25% and the 75%? Well, the resource management isn’t configured with percentages, it’s configured in a unit called shares.
It’s like with stocks. The person with the most stocks owns most of the company. The project with the most shares owns most of the CPU. In our example we divided the CPU in 200 shares. Every share represents 1/200 of the CPU. Project shcproject owns 50 shares. Project lhcproject owns 150. I think, you already saw it: 150 is 75% of 200 and 50 is 25% of 200. Here we find our planed partitioning of the CPU we’ve planed before. By the way: I deliberately choose 150/50 instead of 75/25 to show you that these share definitions are not scaled in percent.
Okay, but what happens when you add a third project and you give this project 200 shares (For example because a new project gave money for buying another processor board). Then the percentages are different. In total you have 400 shares on the system. The 200 shares of the new project are 50%, thus the project gets 50% of the compute power. The 150 shares of the lhcproject are 37.5 percent. This project gets 37.5 of the computing power. And the 50 shares of the shcproject are now 12.5 percent and thus the project get this part of the CPU power.
Behavior of processes with Resource Management
Okay, now let’s start a process under the control of the new resource limitation. Login as user einstein and type the following command:
$ newtask -p shcproject /opt/bombs/cpuhog.pl &
We start at first only one of the cpuhog.pl processes .
bash-3.2$ ps -o pcpu,project,args
%CPU PROJECT COMMAND^
0.0 user.einstein -sh
0.3 user.einstein bash
0.2 user.einstein ps -o pcpu,project,args
95.9 shcproject /usr/bin/perl /opt/bombs/cpuhog.pl
Wait ... the process gets 95.9 percent? An error ? No. It makes no sense to slow down the process, when there is no other process needing the compute power.
Now we start the second process, this time as a task in the lhcproject:
bash-3.2$ newtask -p lhcproject /opt/bombs/cpuhog.pl &
[2] 784
We look in the process table again.
bash-3.2$ ps -o pcpu,project,args
%CPU PROJECT COMMAND
0.0 user.einstein -sh
0.1 user.einstein bash
72.5 lhcproject /usr/bin/perl /opt/bombs/cpuhog.pl
25.6 shcproject /usr/bin/perl /opt/bombs/cpuhog.pl
0.2 user.einstein ps -o pcpu,project,args
Voila, each of our compute processes get their configured part of the compute power. It isn’t exactly 75%/25% all the time but in average the distribution will be this way.
A few days later, the Dean of the department comes into the office and tells you that we need the results of the SHC project earlier, as important persons want to see them soon to spend more money. So you have to change the ratio of the shares. We can do this without restarting the processes at runtime. But as we’ve defined the limits as privileged before, we have to login as root:
# prctl -n project.cpu-shares -r -v 150 -i project shcproject
# prctl -n project.cpu-shares -r -v 50 -i project lhcproject
Let’s look after the processes again after a few moments:
bash-3.2$ ps -o pcpu,project,args
%CPU PROJECT COMMAND
0.0 user.einstein -sh
0.1 user.einstein bash
25.7 lhcproject /usr/bin/perl /opt/bombs/cpuhog.pl
72.9 shcproject /usr/bin/perl /opt/bombs/cpuhog.pl
0.2 user.einstein ps -o pcpu,project,args
The ratio has changed to new settings. It’s important to know that only the settings in /etc/projects is boot-persistent. Everything you set via prctl is lost at the boot.
Limiting memory resources
So far we configured limits on the usage of operating system resources and the CPU. Let’s get back to the class room example used before. A different course at the unseen university is "Memory Management for beginners". And at start our students have problem with severe memory leaks. It would be useful to impose resource management to the memory management.
Without memory resource management
Bob wrote a little script within Perl that eats a large amount of the available memory.
#!/usr/bin/perl
for ($i=0;$i<10;$i++) {
push @_,"x"x(1*1024*1024);
sleep(5);
}
sleep(30);
for ($i=0;$i<10;$i++) {
push @_,"x"x(1*1024*1024);
sleep(5);
}
When we start this script, it will allocate memory by pushing blocks of 1 Megabyte of x chars onto a stack.
# ps -ef -o pid,user,vsz,rss,project,args | grep "bob" | grep -v "grep"
1015 bob 8728 892 class2005 /usr/lib/ssh/sshd
1362 bob 26148 24256 class2005 /usr/bin/perl ./memoryhog.pl
1016 bob 1624 184 class2005 -sh
1031 bob 3260 1336 class2005 bash
When you look in the forth column you see the resident set size. The resident set is the amount of data of a process in the real memory. After a short moment the process ./memoryhog.pl uses 24 MB of our precious memory (20 times 1 MB plus the perl interpreter minus some shared stuff).
With memory resource management
It would be nice to control the amount of data, that resides in the real memory. Solaris has such a capability. At first we have to activate the resource cap enforcement daemon. You have to login as root to do so:
# rcapadm -E
The rcapd daemon enforces resource caps on a group of processes. The rcapd supports caps on projects and zones at the moment. When the resident set size of a group of processes exceeds the defined cap. To reduce the resource consumption of a process group, the daemon can page out infrequently uses pages of memory to swap.
For testing purposes we configure the daemon in such a way, that it scans every second for new processes in projects with a resource cap. Furthermore we configure it to sample the resident set size every 1 second, too. Additionally the pageout statistics of the rcapd will be updated every second, too.
# rcapadm -i scan=1,sample=1,report=1
For testing purposes we define a new project called mmgntcourse and add the user bob to this project:
# projadd mmgntcourse
# projmod -U bob mmgntcourse
Now we set an resource cap for the resident set size of 5 Megabytes for this project:
# projmod -K rcap.max-rss=5242880 mmgntcourse
Okay, now get back to the window with the login of user <code>bob</code>. Let’s start the memoryhog.pl in the mmgntcourse:
$ newtask -p mmgntcourse ./memoryhog.pl
Okay, get back to a different window and login as root. With the rcapstat you can observe the activities of the rcapd. In our example we tell rcapstat to print the statistics every 5 seconds:
# rcapstat 5
id project nproc vm rss cap at avgat pg avgpg
105 mmgntcourse - 2352K 3876K 5120K 0K 0K 0K 0K
105 mmgntcourse - 3376K 4900K 5120K 0K 0K 0K 0K
105 mmgntcourse 1 4400K 5924K 5120K 812K 812K 804K 804K
105 mmgntcourse 1 5424K 6408K 5120K 3380K 1126K 3380K 1126K
105 mmgntcourse - 6448K 4856K 5120K 0K 0K 0K 0K
105 mmgntcourse 1 7472K 5880K 5120K 760K 760K 760K 760K
105 mmgntcourse 1 8496K 5384K 5120K 1024K 512K 1024K 512K
105 mmgntcourse 1 9520K 6144K 5120K 1024K 1024K 1024K 1024K
105 mmgntcourse 1 10M 5120K 5120K 1024K 1024K 1024K 1024K
105 mmgntcourse 1 11M 6144K 5120K 1024K 1024K 1024K 1024K
105 mmgntcourse 1 11M 4096K 5120K 1024K 1024K 1024K 1024K
105 mmgntcourse - 11M 4096K 5120K 0K 0K 0K 0K
[...]
105 mmgntcourse - 11M 4096K 5120K 0K 0K 0K 0K
105 mmgntcourse 1 14M 5892K 5120K 2820K 940K 2820K 940K
105 mmgntcourse 1 15M 5628K 5120K 1280K 640K 1280K 640K
105 mmgntcourse 1 16M 6144K 5120K 1024K 1024K 1024K 1024K
105 mmgntcourse 1 17M 6144K 5120K 1024K 1024K 1024K 1024K
105 mmgntcourse 1 18M 5120K 5120K 1024K 1024K 1024K 1024K
105 mmgntcourse - 18M 5120K 5120K 0K 0K 0K 0K
105 mmgntcourse 1 20M 5120K 5120K 2048K 1024K 2048K 1024K
105 mmgntcourse - 20M 5120K 5120K 0K 0K 0K 0K
105 mmgntcourse 1 22M 5120K 5120K 2048K 1024K 2048K 1024K
As you see, the resident set size stays at approx. 5 Megabyte. The RSS may increase above the configured size, as the applications may allocate memory between the RSS sampling intervals. But at the next sampling size the rcap starts to force the page out of this exceeding pages. After a few seconds the resident set size is enforced, again. You can observe this behaviour in column 5 of the rcapstat printout.
Resource Management and SMF
A few days ago, I wrote about the Service Management Facility, a framework to manage services in Solaris. This framework enables Solaris to start services in a more intelligent manner. Albeit almost all services started by SMF are member of the project <code>system</code> it doesn’t have to be this way. You can specify the project used for a service.
Assigning a project to an already running service
This method is described in the SMF FAQ[^2]. I will use an practical example. You run a server in the internet, but it’s under high load from spam bot. You’ve already created a project sendmail and configured the resource management.
At the moment, the sendmail runs in the system project:
# ps -o pid,project,args -ef | grep "sendmail" | grep -v "grep"
648 system /usr/lib/sendmail -Ac -q15m
647 system /usr/lib/sendmail -bd -q15m -C /etc/mail/local.cf
How do you start it as a part of a different project? Okay, check for an already configured project.
# svcprop -p start/project smtp:sendmail
svcprop: Couldn't find property `start/project' for instance `svc:/network/smtp:sendmail'.
Okay, nothing defined ... this makes it a little bit harder, because we can’t set the project only at the moment, as there is a bug in the restarter daemon. You need a fully populated start method. If the svcprop run delivers you the name of a project, you can ignore the next block of commands:
svccfg -s sendmail setprop start/user = astring: root
svccfg -s sendmail setprop start/group = astring: :default
svccfg -s sendmail setprop start/working_directory = astring: :default
svccfg -s sendmail setprop start/resource_pool = astring: :default
svccfg -s sendmail setprop start/supp_groups = astring: :default
svccfg -s sendmail setprop start/privileges = astring: :default
svccfg -s sendmail setprop start/limit_privileges = astring: :default
svccfg -s sendmail setprop start/use_profile = boolean: false
Okay, now we can set the project property of the start method:
svccfg -s smtp/sendmail setprop start/project = astring: sendmail
\end{lstlsting}
Now we have to refresh the configuration of the service. After refreshing the service we can check the property:
\begin{lstlisting}
# svcadm refresh sendmail
# svcprop -p start/project sendmail
sendmail
Okay, the new properties are active. Now restart the service:
# svcadm restart sendmail
Let’s check for the result:
# ps -o pid,project,args -ef | grep "sendmail" | grep -v "grep"
1539 sendmail /usr/lib/sendmail -bd -q15m -C /etc/mail/local.cf
1540 sendmail /usr/lib/sendmail -Ac -q15m
Configuring the project in a SMF manifest
Okay, you have written your own application and want to run it under the control of the SMF. You can define the project for the service in the manifest. You have to define the project in the start method of the manifest:
<exec_method type='method' name='start' exec='/path/to/method start' timeout_seconds='0' >
<method_context project=projectname'>
<method_credential user='someuser'>
</method_context>
</exec_method>
That’s all. The important part is the second row of the fragment. We define the project as a part of the startup method context. The rest is done as described in the SMF tutorial[^3]
Conclusion
The Solaris Resource Management is an powerful tool to partition the resources of a single instance of an operating system. By using Solaris Resource Management you can use a single operating system for a multitude of services but still ensuring the availability of resources to them. I hope, this tutorial gave you an good insights into the basics of resource management.
Do you want to learn more?
Documentation
System Administration Guide: Solaris Containers-Resource Management and Solaris Zones
man page for resource_controls(5)
man page for the Fair Share Scheduler
Misc. links
Zones and Containers FAQ - Section 3: Resource Management, Performance