Statistics
| Branch: | Tag: | Revision:

one / src / scheduler / src / pool / VirtualMachineXML.cc @ 4697f1ee

History | View | Annotate | Download (12.8 KB)

1
/* -------------------------------------------------------------------------- */
2
/* Copyright 2002-2015, OpenNebula Project, OpenNebula Systems                */
3
/*                                                                            */
4
/* Licensed under the Apache License, Version 2.0 (the "License"); you may    */
5
/* not use this file except in compliance with the License. You may obtain    */
6
/* a copy of the License at                                                   */
7
/*                                                                            */
8
/* http://www.apache.org/licenses/LICENSE-2.0                                 */
9
/*                                                                            */
10
/* Unless required by applicable law or agreed to in writing, software        */
11
/* distributed under the License is distributed on an "AS IS" BASIS,          */
12
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   */
13
/* See the License for the specific language governing permissions and        */
14
/* limitations under the License.                                             */
15
/* -------------------------------------------------------------------------- */
16

    
17
#include <algorithm>
18

    
19
#include "VirtualMachineXML.h"
20
#include "DatastoreXML.h"
21
#include "DatastorePoolXML.h"
22
#include "NebulaUtil.h"
23
#include "History.h"
24

    
25
void VirtualMachineXML::init_attributes()
26
{
27
    vector<xmlNodePtr> nodes;
28

    
29
    int rc;
30
    int action;
31

    
32
    string automatic_requirements;
33
    string automatic_cluster_requirements;
34

    
35
    xpath(oid, "/VM/ID", -1);
36
    xpath(uid, "/VM/UID", -1);
37
    xpath(gid, "/VM/GID", -1);
38

    
39
    xpath(memory, "/VM/TEMPLATE/MEMORY", 0);
40
    xpath<float>(cpu, "/VM/TEMPLATE/CPU", 0);
41

    
42
    // ------------------------ RANK & DS_RANK ---------------------------------
43

    
44
    rc = xpath(rank, "/VM/USER_TEMPLATE/SCHED_RANK", "");
45

    
46
    if (rc != 0)
47
    {
48
        // Compatibility with previous versions
49
        xpath(rank, "/VM/USER_TEMPLATE/RANK", "");
50
    }
51

    
52
    xpath(ds_rank, "/VM/USER_TEMPLATE/SCHED_DS_RANK", "");
53

    
54
    // ------------------- HOST REQUIREMENTS -----------------------------------
55

    
56
    xpath(automatic_requirements, "/VM/TEMPLATE/AUTOMATIC_REQUIREMENTS", "");
57

    
58
    rc = xpath(requirements, "/VM/USER_TEMPLATE/SCHED_REQUIREMENTS", "");
59

    
60
    if (rc == 0)
61
    {
62
        if ( !automatic_requirements.empty() )
63
        {
64
            ostringstream oss;
65

    
66
            oss << automatic_requirements << " & ( " << requirements << " )";
67

    
68
            requirements = oss.str();
69
        }
70
    }
71
    else if ( !automatic_requirements.empty() )
72
    {
73
        requirements = automatic_requirements;
74
    }
75

    
76
    // ------------------- DS REQUIREMENTS -------------------------------------
77

    
78
    rc = xpath(ds_requirements, "/VM/USER_TEMPLATE/SCHED_DS_REQUIREMENTS", "");
79

    
80
    if (rc == 0)
81
    {
82
        if ( !automatic_requirements.empty() )
83
        {
84
            ostringstream oss;
85

    
86
            oss << automatic_requirements << " & ( " << ds_requirements << " )";
87

    
88
            ds_requirements = oss.str();
89
        }
90
    }
91
    else if ( !automatic_requirements.empty() )
92
    {
93
        ds_requirements = automatic_requirements;
94
    }
95

    
96
    // ------------------- CLUSTER REQUIREMENTS --------------------------------
97

    
98
    xpath(automatic_cluster_requirements, "/VM/TEMPLATE/AUTOMATIC_CLUSTER_REQUIREMENTS", "");
99

    
100
    rc = xpath(cluster_requirements, "/VM/USER_TEMPLATE/SCHED_CLUSTER_REQUIREMENTS", "");
101

    
102
    if (rc == 0)
103
    {
104
        if ( !automatic_cluster_requirements.empty() )
105
        {
106
            ostringstream oss;
107

    
108
            oss << automatic_cluster_requirements << " & ( " << cluster_requirements << " )";
109

    
110
            cluster_requirements = oss.str();
111
        }
112
    }
113
    else if ( !automatic_cluster_requirements.empty() )
114
    {
115
        cluster_requirements = automatic_cluster_requirements;
116
    }
117

    
118
    // ---------------- HISTORY HID, DSID, RESCHED & TEMPLATE ------------------
119

    
120
    xpath(hid,  "/VM/HISTORY_RECORDS/HISTORY/HID", -1);
121
    xpath(dsid, "/VM/HISTORY_RECORDS/HISTORY/DS_ID", -1);
122

    
123
    xpath(resched, "/VM/RESCHED", 0);
124

    
125
    xpath(action, "/VM/HISTORY_RECORDS/HISTORY/ACTION", -1);
126

    
127
    resume = (action == History::STOP_ACTION ||
128
              action == History::UNDEPLOY_ACTION ||
129
              action == History::UNDEPLOY_HARD_ACTION );
130

    
131
    if (get_nodes("/VM/TEMPLATE", nodes) > 0)
132
    {
133
        vm_template = new VirtualMachineTemplate;
134

    
135
        vm_template->from_xml_node(nodes[0]);
136

    
137
        free_nodes(nodes);
138
    }
139
    else
140
    {
141
        vm_template = 0;
142
    }
143

    
144
    nodes.clear();
145

    
146
    if (get_nodes("/VM/USER_TEMPLATE", nodes) > 0)
147
    {
148
        user_template = new VirtualMachineTemplate;
149

    
150
        user_template->from_xml_node(nodes[0]);
151

    
152
        free_nodes(nodes);
153
    }
154
    else
155
    {
156
        user_template = 0;
157
    }
158

    
159
    if (vm_template != 0)
160
    {
161
        init_storage_usage();
162
    }
163
    else
164
    {
165
        system_ds_usage = 0;
166
    }
167

    
168
    vector<VectorAttribute*> attrs;
169

    
170
    public_cloud = (user_template->get("PUBLIC_CLOUD", attrs) > 0);
171

    
172
    if (public_cloud == false)
173
    {
174
        attrs.clear();
175
        public_cloud = (user_template->get("EC2", attrs) > 0);
176
    }
177

    
178
    only_public_cloud = false;
179
}
180

    
181
/* -------------------------------------------------------------------------- */
182
/* -------------------------------------------------------------------------- */
183

    
184
ostream& operator<<(ostream& os, VirtualMachineXML& vm)
185
{
186
    const vector<Resource *> resources = vm.match_hosts.get_resources();
187

    
188
    vector<Resource *>::const_reverse_iterator  i;
189

    
190
    if (resources.empty())
191
    {
192
        return os;
193
    }
194

    
195
    os << "Virtual Machine: " << vm.oid << endl << endl;
196

    
197
    os << "\tPRI\tID - HOSTS"<< endl
198
       << "\t------------------------"  << endl;
199

    
200
    for (i = resources.rbegin(); i != resources.rend() ; i++)
201
    {
202
        os << "\t" << (*i)->priority << "\t" << (*i)->oid << endl;
203
    }
204

    
205
    os << endl;
206

    
207
    os << "\tPRI\tID - DATASTORES"<< endl
208
       << "\t------------------------"  << endl;
209

    
210
    const vector<Resource *> ds_resources = vm.match_datastores.get_resources();
211

    
212
    for (i = ds_resources.rbegin(); i != ds_resources.rend() ; i++)
213
    {
214
        os << "\t" << (*i)->priority << "\t" << (*i)->oid << endl;
215
    }
216

    
217
    os << endl;
218

    
219
    return os;
220
};
221

    
222
/* -------------------------------------------------------------------------- */
223
/* -------------------------------------------------------------------------- */
224

    
225
void VirtualMachineXML::get_requirements (int& cpu, int& memory,
226
    long long& disk, vector<VectorAttribute *> &pci)
227
{
228
    pci.clear();
229

    
230
    if (vm_template != 0)
231
    {
232
        vm_template->get("PCI", pci);
233
    }
234

    
235
    if (this->memory == 0 || this->cpu == 0)
236
    {
237
        cpu    = 0;
238
        memory = 0;
239
        disk   = 0;
240

    
241
        return;
242
    }
243

    
244
    cpu    = (int) (this->cpu * 100);//now in 100%
245
    memory = this->memory * 1024;    //now in Kilobytes
246
    disk   = this->system_ds_usage;  // MB
247
}
248

    
249
/* -------------------------------------------------------------------------- */
250
/* -------------------------------------------------------------------------- */
251

    
252
// TODO: use VirtualMachine::isVolatile(disk)
253
bool isVolatile(const VectorAttribute * disk)
254
{
255
    string type = disk->vector_value("TYPE");
256

    
257
    one_util::toupper(type);
258

    
259
    return ( type == "SWAP" || type == "FS");
260
}
261

    
262
map<int,long long> VirtualMachineXML::get_storage_usage()
263
{
264
    return ds_usage;
265
}
266

    
267
void VirtualMachineXML::init_storage_usage()
268
{
269
    vector<Attribute  *>            disks;
270
    vector<Attribute*>::iterator    it;
271

    
272
    long long   size;
273
    long long   snapshot_size;
274
    string      st;
275
    int         ds_id;
276
    bool        clone;
277

    
278
    system_ds_usage = 0;
279

    
280
    int num = vm_template->remove("DISK", disks);
281

    
282
    for (it=disks.begin(); it != disks.end(); it++)
283
    {
284
        const VectorAttribute * disk = dynamic_cast<const VectorAttribute*>(*it);
285

    
286
        if (disk == 0)
287
        {
288
            continue;
289
        }
290

    
291
        if (disk->vector_value("SIZE", size) != 0)
292
        {
293
            continue;
294
        }
295

    
296
        if (disk->vector_value("DISK_SNAPSHOT_TOTAL_SIZE", snapshot_size) == 0)
297
        {
298
            size += snapshot_size;
299
        }
300

    
301
        if (isVolatile(disk))
302
        {
303
            system_ds_usage += size;
304
        }
305
        else
306
        {
307
            if (disk->vector_value("DATASTORE_ID", ds_id) != 0)
308
            {
309
                continue;
310
            }
311

    
312
            if (ds_usage.count(ds_id) == 0)
313
            {
314
                ds_usage[ds_id] = 0;
315
            }
316

    
317
            if (disk->vector_value("CLONE", clone) != 0)
318
            {
319
                continue;
320
            }
321

    
322
            if (clone)
323
            {
324
                st = disk->vector_value("CLONE_TARGET");
325
            }
326
            else
327
            {
328
                st = disk->vector_value("LN_TARGET");
329
            }
330

    
331
            one_util::toupper(st);
332

    
333
            if (st == "SELF")
334
            {
335
                ds_usage[ds_id] += size;
336
            }
337
            else if (st == "SYSTEM")
338
            {
339
                system_ds_usage += size;
340
            } // else st == NONE
341
        }
342
    }
343

    
344
    for (int i = 0; i < num ; i++)
345
    {
346
        delete disks[i];
347
    }
348
}
349

    
350
/* -------------------------------------------------------------------------- */
351
/* -------------------------------------------------------------------------- */
352

    
353
void VirtualMachineXML::log(const string &st)
354
{
355
    if (user_template == 0 || st.empty())
356
    {
357
        return;
358
    }
359
    ostringstream oss;
360

    
361
    oss << one_util::log_time() << " : " << st;
362

    
363
    user_template->replace("SCHED_MESSAGE", oss.str());
364
}
365

    
366
/* -------------------------------------------------------------------------- */
367
/* -------------------------------------------------------------------------- */
368

    
369
bool VirtualMachineXML::clear_log()
370
{
371
    string st;
372

    
373
    if (user_template == 0)
374
    {
375
        return false;
376
    }
377

    
378
    user_template->get("SCHED_MESSAGE", st);
379

    
380
    if (st.empty())
381
    {
382
        return false;
383
    }
384

    
385
    user_template->erase("SCHED_MESSAGE");
386

    
387
    return true;
388
}
389

    
390
/* -------------------------------------------------------------------------- */
391
/* -------------------------------------------------------------------------- */
392

    
393
int VirtualMachineXML::parse_action_name(string& action_st)
394
{
395
    one_util::tolower(action_st);
396

    
397
    if (   action_st != "shutdown"
398
        && action_st != "shutdown-hard"
399
        && action_st != "undeploy"
400
        && action_st != "undeploy-hard"
401
        && action_st != "hold"
402
        && action_st != "release"
403
        && action_st != "stop"
404
        && action_st != "suspend"
405
        && action_st != "resume"
406
        && action_st != "delete"
407
        && action_st != "delete-recreate"
408
        && action_st != "reboot"
409
        && action_st != "reboot-hard"
410
        && action_st != "poweroff"
411
        && action_st != "poweroff-hard"
412
        && action_st != "snapshot-create")
413
    {
414
        return -1;
415
    }
416

    
417
    return 0;
418
};
419

    
420
/* -------------------------------------------------------------------------- */
421
/* -------------------------------------------------------------------------- */
422

    
423
bool VirtualMachineXML::test_image_datastore_capacity(
424
    ImageDatastorePoolXML * img_dspool, string & error_msg) const
425
{
426
    map<int,long long>::const_iterator ds_usage_it;
427
    DatastoreXML* ds;
428

    
429
    for (ds_usage_it = ds_usage.begin(); ds_usage_it != ds_usage.end(); ds_usage_it++)
430
    {
431
        ds = img_dspool->get(ds_usage_it->first);
432

    
433
        if (ds == 0 || !ds->test_capacity(ds_usage_it->second))
434
        {
435
            ostringstream oss;
436

    
437
            oss << "Image Datastore " << ds->get_oid()
438
                << " does not have enough capacity";
439

    
440
            error_msg = oss.str();
441
            return false;
442
        }
443
    }
444

    
445
    return true;
446
}
447

    
448
/* -------------------------------------------------------------------------- */
449
/* -------------------------------------------------------------------------- */
450

    
451
void VirtualMachineXML::add_image_datastore_capacity(
452
        ImageDatastorePoolXML * img_dspool)
453
{
454
    map<int,long long>::const_iterator ds_usage_it;
455

    
456
    DatastoreXML *ds;
457

    
458
    for (ds_usage_it = ds_usage.begin(); ds_usage_it != ds_usage.end(); ds_usage_it++)
459
    {
460
        ds = img_dspool->get(ds_usage_it->first);
461

    
462
        if (ds == 0) //Should never reach here
463
        {
464
            continue;
465
        }
466

    
467
        ds->add_capacity(ds_usage_it->second);
468
    }
469
}
470

    
471
/* -------------------------------------------------------------------------- */
472
/* -------------------------------------------------------------------------- */
473

    
474
void VirtualMachineXML::set_only_public_cloud()
475
{
476
    only_public_cloud = true;
477

    
478
    ostringstream oss;
479

    
480
    oss << "VM " << oid << ": Local Datastores do not have enough capacity. "
481
            << "This VM can be only deployed in a Public Cloud Host.";
482

    
483
    NebulaLog::log("SCHED",Log::INFO,oss);
484
}
485

    
486
/* -------------------------------------------------------------------------- */
487
/* -------------------------------------------------------------------------- */
488

    
489
bool VirtualMachineXML::is_only_public_cloud() const
490
{
491
    return only_public_cloud;
492
}