Class: OpenNebula::Service
- Inherits:
-
DocumentJSON
- Object
- XMLElement
- PoolElement
- Document
- DocumentJSON
- OpenNebula::Service
- Defined in:
- lib/models/service.rb
Overview
Service class as wrapper of DocumentJSON
Constant Summary collapse
- DOCUMENT_TYPE =
100- STATE =
{ 'PENDING' => 0, 'DEPLOYING' => 1, 'RUNNING' => 2, 'UNDEPLOYING' => 3, 'WARNING' => 4, 'DONE' => 5, 'FAILED_UNDEPLOYING' => 6, 'FAILED_DEPLOYING' => 7, 'SCALING' => 8, 'FAILED_SCALING' => 9, 'COOLDOWN' => 10, 'DEPLOYING_NETS' => 11, 'UNDEPLOYING_NETS' => 12, 'FAILED_DEPLOYING_NETS' => 13, 'FAILED_UNDEPLOYING_NETS' => 14, 'HOLD' => 15 }
- STATE_STR =
[ 'PENDING', 'DEPLOYING', 'RUNNING', 'UNDEPLOYING', 'WARNING', 'DONE', 'FAILED_UNDEPLOYING', 'FAILED_DEPLOYING', 'SCALING', 'FAILED_SCALING', 'COOLDOWN', 'DEPLOYING_NETS', 'UNDEPLOYING_NETS', 'FAILED_DEPLOYING_NETS', 'FAILED_UNDEPLOYING_NETS', 'HOLD' ]
- TRANSIENT_STATES =
[ 'DEPLOYING', 'UNDEPLOYING', 'SCALING', 'COOLDOWN', 'DEPLOYING_NETS', 'UNDEPLOYING_NETS' ]
- FAILED_STATES =
[ 'FAILED_DEPLOYING', 'FAILED_UNDEPLOYING', 'FAILED_SCALING', 'FAILED_DEPLOYING_NETS', 'FAILED_UNDEPLOYING_NETS' ]
- RECOVER_DEPLOY_STATES =
[ 'FAILED_DEPLOYING', 'DEPLOYING', 'PENDING' ]
- RECOVER_UNDEPLOY_STATES =
[ 'FAILED_UNDEPLOYING', 'UNDEPLOYING', 'FAILED_UNDEPLOYING_NETS' ]
- RECOVER_SCALE_STATES =
[ 'FAILED_SCALING', 'SCALING' ]
- RECOVER_DEPLOY_NETS_STATES =
['DEPLOYING_NETS', 'FAILED_DEPLOYING_NETS']
- RECOVER_UNDEPLOY_NETS_STATES =
[ 'UNDEPLOYING_NETS', 'FAILED_UNDEPLOYING_NETS' ]
- IMMUTABLE_ATTRS =
List of attributes that can’t be changed in update operation
user_inputs: it only has sense when deploying, not in running user_inputs_values: it only has sense when deploying, not in running deployment: changing this, changes the undeploy operation log: this is just internal information, no sense to change it name: this has to be changed using rename operation networks: it only has sense when deploying, not in running networks_values: it only has sense when deploying, not in running ready_status_gate: it only has sense when deploying, not in running state: this is internal information managed by OneFlow server start_time: this is internal information managed by OneFlow server
[ 'user_inputs', 'user_inputs_values', 'deployment', 'log', 'name', 'networks', 'networks_values', 'ready_status_gate', 'state', 'start_time' ]
- LOG_COMP =
'SER'
Constants inherited from DocumentJSON
Constants inherited from Document
Instance Attribute Summary collapse
-
#client ⇒ Object
readonly
Returns the value of attribute client.
-
#roles ⇒ Object
readonly
Returns the value of attribute roles.
Instance Method Summary collapse
-
#add_role(template) ⇒ OpenNebula::Role
Adds a role to the service.
-
#all_roles_done? ⇒ true, false
Returns true if all the nodes are in done state.
-
#all_roles_hold? ⇒ true, false
Returns true if all the nodes are in hold state.
-
#all_roles_running? ⇒ true, false
Returns true if all the nodes are correctly deployed.
-
#allocate(template_json) ⇒ nil, OpenNebula::Error
Create a new service based on the template provided.
- #can_recover_deploy? ⇒ Boolean
- #can_recover_deploy_nets? ⇒ Boolean
- #can_recover_scale? ⇒ Boolean
- #can_recover_undeploy? ⇒ Boolean
- #can_recover_undeploy_nets? ⇒ Boolean
- #can_scale? ⇒ Boolean
-
#can_undeploy? ⇒ Boolean
Return true if the service can be undeployed.
-
#can_update? ⇒ Boolean
Return true if the service can be updated.
-
#check_new_template(template_json, append) ⇒ Boolean, String
Check that changes values are correct.
-
#check_role(role) ⇒ Boolean
Check if role is terminated or not.
-
#chown(uid, gid) ⇒ nil, OpenNebula::Error
Changes the owner/group.
- #delete_networks ⇒ Object
- #deploy_networks(deploy = true) ⇒ Object
-
#failed_state? ⇒ Boolean
Return true if the service is in failed state.
-
#fill_template ⇒ nil, OpenNebula::Error
Fills the service template with the provided values.
- #gid ⇒ Object
-
#info ⇒ nil, OpenNebula::Error
Retrieves the information of the Service and all its Nodes.
-
#info_roles ⇒ nil, OpenNebula::Error
Retrieves the information of the Service and all its Nodes.
-
#log_error(message) ⇒ Object
Add an error message in the service information that will be stored in OpenNebula.
-
#log_info(message) ⇒ Object
Add an info message in the service information that will be stored in OpenNebula.
-
#name ⇒ String
Returns the service name.
-
#networks(deploy) ⇒ Array
Returns virtual networks IDs.
-
#on_hold=(on_hold) ⇒ Object
Change the ‘on_hold` option value.
-
#on_hold? ⇒ true, false
Returns the on_hold service option.
-
#recover ⇒ nil, OpenNebula::Error
Recover a failed service.
-
#remove_role(name) ⇒ Object
Removes a role from the service.
-
#replace_client(owner_client) ⇒ Object
Replaces this object’s client with a new one.
-
#report_ready? ⇒ true, false
Returns the running_status_vm option.
-
#running? ⇒ Boolean
Return true if the service is running.
- #shutdown_action ⇒ Object
-
#state ⇒ Integer
Returns the service state.
-
#state=(state) ⇒ true, false
Sets a new state.
-
#state_str ⇒ Object
Returns the string representation of the service state.
-
#strategy ⇒ String
Returns the service strategy.
-
#transient_state? ⇒ Boolean
Returns true if the service is in transient state.
- #uid ⇒ Object
- #uname ⇒ Object
-
#update(template_json = nil, append = false) ⇒ nil, OpenNebula::Error
Replaces the template contents.
-
#update_raw(template_raw, append = false) ⇒ nil, OpenNebula::Error
Replaces the raw template contents.
-
#update_role(role_name, template_json) ⇒ nil, OpenNebula::Error
Updates a role.
Methods inherited from DocumentJSON
#allocate_xml, #build_template_xml, #load_body, #template_tag, #to_json
Methods inherited from Document
build_xml, #chmod, #chmod_octet, #clone, #delete, #document_type, #initialize, #owner_id, #public?, #rename
Methods inherited from PoolElement
#id, new_with_id, #replace, #to_str
Methods inherited from XMLElement
#[], #add_element, #attr, build_xml, #delete_element, #each, #each_xpath, #element_xml, #has_elements?, #initialize, #initialize_xml, #retrieve_elements, #retrieve_xmlelements, #set_content, #template_like_str, #template_str, #template_xml, #text, #to_hash, #to_xml, #xml_nil?
Constructor Details
This class inherits a constructor from OpenNebula::Document
Instance Attribute Details
#client ⇒ Object (readonly)
Returns the value of attribute client.
22 23 24 |
# File 'lib/models/service.rb', line 22 def client @client end |
#roles ⇒ Object (readonly)
Returns the value of attribute roles.
22 23 24 |
# File 'lib/models/service.rb', line 22 def roles @roles end |
Instance Method Details
#add_role(template) ⇒ OpenNebula::Role
Adds a role to the service
414 415 416 417 418 419 420 421 422 423 424 425 426 |
# File 'lib/models/service.rb', line 414 def add_role(template) template['state'] ||= Role::STATE['PENDING'] role = Role.for(template, self) if @roles[role.name] return OpenNebula::Error.new("Role #{role.name} already exists") end @roles[role.name] = role @body['roles'] << template if @body && @body['roles'] role end |
#all_roles_done? ⇒ true, false
Returns true if all the nodes are in done state
275 276 277 278 279 280 281 282 283 |
# File 'lib/models/service.rb', line 275 def all_roles_done? @roles.each do |_name, role| if role.state != Role::STATE['DONE'] return false end end true end |
#all_roles_hold? ⇒ true, false
Returns true if all the nodes are in hold state
287 288 289 290 291 292 293 294 295 |
# File 'lib/models/service.rb', line 287 def all_roles_hold? @roles.each do |_name, role| if role.state != Role::STATE['HOLD'] return false end end true end |
#all_roles_running? ⇒ true, false
Returns true if all the nodes are correctly deployed
263 264 265 266 267 268 269 270 271 |
# File 'lib/models/service.rb', line 263 def all_roles_running? @roles.each do |_name, role| if role.state != Role::STATE['RUNNING'] return false end end true end |
#allocate(template_json) ⇒ nil, OpenNebula::Error
Create a new service based on the template provided
319 320 321 322 323 324 325 326 327 328 329 330 331 332 |
# File 'lib/models/service.rb', line 319 def allocate(template_json) template = JSON.parse(template_json) template['state'] = STATE['PENDING'] if template['roles'] template['roles'].each do |elem| elem['state'] ||= Role::STATE['PENDING'] end end template['start_time'] = Integer(Time.now) super(template.to_json, template['name']) end |
#can_recover_deploy? ⇒ Boolean
187 188 189 |
# File 'lib/models/service.rb', line 187 def can_recover_deploy? RECOVER_DEPLOY_STATES.include? STATE_STR[state] end |
#can_recover_deploy_nets? ⇒ Boolean
199 200 201 |
# File 'lib/models/service.rb', line 199 def can_recover_deploy_nets? RECOVER_DEPLOY_NETS_STATES.include?(STATE_STR[state]) end |
#can_recover_scale? ⇒ Boolean
195 196 197 |
# File 'lib/models/service.rb', line 195 def can_recover_scale? RECOVER_SCALE_STATES.include? STATE_STR[state] end |
#can_recover_undeploy? ⇒ Boolean
191 192 193 |
# File 'lib/models/service.rb', line 191 def can_recover_undeploy? RECOVER_UNDEPLOY_STATES.include? STATE_STR[state] end |
#can_recover_undeploy_nets? ⇒ Boolean
203 204 205 |
# File 'lib/models/service.rb', line 203 def can_recover_undeploy_nets? RECOVER_UNDEPLOY_NETS_STATES.include?(STATE_STR[state]) end |
#can_scale? ⇒ Boolean
704 705 706 |
# File 'lib/models/service.rb', line 704 def can_scale? state == Service::STATE['RUNNING'] end |
#can_undeploy? ⇒ Boolean
Return true if the service can be undeployed
170 171 172 173 174 175 176 177 178 179 |
# File 'lib/models/service.rb', line 170 def can_undeploy? # rubocop:disable Style/IfWithBooleanLiteralBranches if (transient_state? && state != Service::STATE['UNDEPLOYING']) || state == Service::STATE['DONE'] || failed_state? false else true end # rubocop:enable Style/IfWithBooleanLiteralBranches end |
#can_update? ⇒ Boolean
Return true if the service can be updated
183 184 185 |
# File 'lib/models/service.rb', line 183 def can_update? !transient_state? && !failed_state? end |
#check_new_template(template_json, append) ⇒ Boolean, String
Check that changes values are correct
605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 |
# File 'lib/models/service.rb', line 605 def check_new_template(template_json, append) template = JSON.parse(template_json) if append IMMUTABLE_ATTRS.each do |attr| next if template[attr].nil? return [false, "service/#{attr}"] end else if template['roles'].size != @roles.size return [false, 'service/roles size'] end IMMUTABLE_ATTRS.each do |attr| next if template[attr] == @body[attr] return [false, "service/#{attr}"] end template['roles'].each do |role| # Role name can't be changed, if it is changed some problems # may appear, as name is used to reference roles return [false, 'name'] unless @roles[role['name']] rc = @roles[role['name']].check_new_template(role) return rc unless rc[0] end end [true, nil] end |
#check_role(role) ⇒ Boolean
Check if role is terminated or not
715 716 717 718 719 720 721 722 723 724 725 |
# File 'lib/models/service.rb', line 715 def check_role(role) return unless @body['automatic_deletion'] return unless role.nodes.empty? ret = true @body['roles'].each {|r| ret &= r['nodes'].empty? } ret end |
#chown(uid, gid) ⇒ nil, OpenNebula::Error
Changes the owner/group
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 |
# File 'lib/models/service.rb', line 478 def chown(uid, gid) old_uid = self['UID'].to_i old_gid = self['GID'].to_i rc = super(uid, gid) if OpenNebula.is_error?(rc) return rc end @roles.each do |_name, role| rc = role.chown(uid, gid) break if rc[0] == false end if rc[0] == false log_error('Chown operation failed, will try to rollback ' \ 'all VMs to the old user and group') update super(old_uid, old_gid) @roles.each do |_name, role| role.chown(old_uid, old_gid) end return OpenNebula::Error.new(rc[1]) end nil end |
#delete_networks ⇒ Object
682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 |
# File 'lib/models/service.rb', line 682 def delete_networks vnets = @body['networks_values'] vnets_failed = [] return if vnets.nil? vnets.each do |vnet| vnet.each do |_, net| next unless net.key?('template_id') || net.key?('reserve_from') rc = OpenNebula::VirtualNetwork.new_with_id( net['id'], @client ).delete vnets_failed << net['id'] if OpenNebula.is_error?(rc) end end vnets_failed end |
#deploy_networks(deploy = true) ⇒ Object
652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 |
# File 'lib/models/service.rb', line 652 def deploy_networks(deploy = true) body = if deploy JSON.parse(self['TEMPLATE/BODY']) else @body end return if body['networks_values'].nil? body['networks_values'].each do |vnet| vnet.each do |name, net| next if net.key?('id') if net.key?('template_id') rc = create_vnet(name, net) elsif net.key?('reserve_from') rc = reserve(name, net) end return rc if OpenNebula.is_error?(rc) net['id'] = rc end end if deploy # @body = template.to_hash update_body(body) end |
#failed_state? ⇒ Boolean
Return true if the service is in failed state
164 165 166 |
# File 'lib/models/service.rb', line 164 def failed_state? FAILED_STATES.include? STATE_STR[state] end |
#fill_template ⇒ nil, OpenNebula::Error
Fills the service template with the provided values.
This method replaces placeholders in the service template with corresponding values Placeholders are expected to be in the format $key.
645 646 647 648 649 650 |
# File 'lib/models/service.rb', line 645 def fill_template generate_template_contents rescue StandardError => e Log.error LOG_COMP, "Error generating VM template contents: #{e.}" return OpenNebula::Error.new('Error generating VM template contents') end |
#gid ⇒ Object
227 228 229 |
# File 'lib/models/service.rb', line 227 def gid self['GID'].to_i end |
#info ⇒ nil, OpenNebula::Error
Retrieves the information of the Service and all its Nodes.
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 |
# File 'lib/models/service.rb', line 390 def info rc = super if OpenNebula.is_error?(rc) return rc end @roles = {} if @body['roles'] @body['roles'].each do |elem| elem['state'] ||= Role::STATE['PENDING'] role = Role.for(elem, self) @roles[role.name] = role end end nil end |
#info_roles ⇒ nil, OpenNebula::Error
Retrieves the information of the Service and all its Nodes.
443 444 445 446 447 448 449 450 451 452 453 454 455 |
# File 'lib/models/service.rb', line 443 def info_roles @roles = {} if @body['roles'] @body['roles'].each do |elem| elem['state'] ||= Role::STATE['PENDING'] role = Role.for(elem, self) @roles[role.name] = role end end nil end |
#log_error(message) ⇒ Object
Add an error message in the service information that will be stored
in OpenNebula
467 468 469 |
# File 'lib/models/service.rb', line 467 def log_error() add_log(Logger::ERROR, ) end |
#log_info(message) ⇒ Object
Add an info message in the service information that will be stored
in OpenNebula
460 461 462 |
# File 'lib/models/service.rb', line 460 def log_info() add_log(Logger::INFO, ) end |
#name ⇒ String
Returns the service name
134 135 136 |
# File 'lib/models/service.rb', line 134 def name @body['name'] end |
#networks(deploy) ⇒ Array
Returns virtual networks IDs
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 |
# File 'lib/models/service.rb', line 299 def networks(deploy) ret = [] return ret unless @body['networks_values'] @body['networks_values'].each do |vnet| vnet.each do |_, net| next if net.key?('id') && !deploy ret << net['id'].to_i end end ret end |
#on_hold=(on_hold) ⇒ Object
Change the ‘on_hold` option value
238 239 240 |
# File 'lib/models/service.rb', line 238 def on_hold=(on_hold) @body['on_hold'] = on_hold end |
#on_hold? ⇒ true, false
Returns the on_hold service option
233 234 235 |
# File 'lib/models/service.rb', line 233 def on_hold? @body['on_hold'] end |
#recover ⇒ nil, OpenNebula::Error
Recover a failed service.
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 |
# File 'lib/models/service.rb', line 337 def recover if [Service::STATE['FAILED_DEPLOYING']].include?(state) @roles.each do |_name, role| if role.state == Role::STATE['FAILED_DEPLOYING'] role.state = Role::STATE['PENDING'] end end self.state = Service::STATE['DEPLOYING'] elsif state == Service::STATE['FAILED_SCALING'] @roles.each do |_name, role| if role.state == Role::STATE['FAILED_SCALING'] role.state = Role::STATE['SCALING'] end end self.state = Service::STATE['SCALING'] elsif state == Service::STATE['FAILED_UNDEPLOYING'] @roles.each do |_name, role| if role.state == Role::STATE['FAILED_UNDEPLOYING'] role.state = Role::STATE['RUNNING'] end end self.state = Service::STATE['UNDEPLOYING'] elsif state == Service::STATE['COOLDOWN'] @roles.each do |_name, role| if role.state == Role::STATE['COOLDOWN'] role.state = Role::STATE['RUNNING'] end end self.state = Service::STATE['RUNNING'] elsif state == Service::STATE['WARNING'] @roles.each do |_name, role| if role.state == Role::STATE['WARNING'] role.recover_warning end end else OpenNebula::Error.new('Action recover: Wrong state' \ " #{state_str}") end end |
#remove_role(name) ⇒ Object
Removes a role from the service
431 432 433 434 435 436 437 |
# File 'lib/models/service.rb', line 431 def remove_role(name) @roles.delete(name) @body['roles'].delete_if do |role| role['name'] == name end end |
#replace_client(owner_client) ⇒ Object
Replaces this object’s client with a new one
244 245 246 |
# File 'lib/models/service.rb', line 244 def replace_client(owner_client) @client = owner_client end |
#report_ready? ⇒ true, false
Returns the running_status_vm option
215 216 217 |
# File 'lib/models/service.rb', line 215 def report_ready? @body['ready_status_gate'] end |
#running? ⇒ Boolean
Return true if the service is running
209 210 211 |
# File 'lib/models/service.rb', line 209 def running? state_str == 'RUNNING' end |
#shutdown_action ⇒ Object
554 555 556 |
# File 'lib/models/service.rb', line 554 def shutdown_action @body['shutdown_action'] end |
#state ⇒ Integer
Returns the service state
140 141 142 |
# File 'lib/models/service.rb', line 140 def state @body['state'].to_i end |
#state=(state) ⇒ true, false
Sets a new state
251 252 253 254 255 256 257 258 259 |
# File 'lib/models/service.rb', line 251 def state=(state) return if state < 0 || state > STATE_STR.size @body['state'] = state.to_i msg = "New state: #{STATE_STR[state]}" Log.info LOG_COMP, msg, id log_info(msg) end |
#state_str ⇒ Object
Returns the string representation of the service state
152 153 154 |
# File 'lib/models/service.rb', line 152 def state_str STATE_STR[state] end |
#strategy ⇒ String
Returns the service strategy
146 147 148 |
# File 'lib/models/service.rb', line 146 def strategy @body['deployment'] end |
#transient_state? ⇒ Boolean
Returns true if the service is in transient state
158 159 160 |
# File 'lib/models/service.rb', line 158 def transient_state? TRANSIENT_STATES.include? STATE_STR[state] end |
#uid ⇒ Object
223 224 225 |
# File 'lib/models/service.rb', line 223 def uid self['UID'].to_i end |
#uname ⇒ Object
219 220 221 |
# File 'lib/models/service.rb', line 219 def uname self['UNAME'] end |
#update(template_json = nil, append = false) ⇒ nil, OpenNebula::Error
Replaces the template contents
566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 |
# File 'lib/models/service.rb', line 566 def update(template_json = nil, append = false) if template_json template = JSON.parse(template_json) if append rc = info if OpenNebula.is_error? rc return rc end template = @body.merge(template) end template_json = template.to_json end super(template_json, append) end |
#update_raw(template_raw, append = false) ⇒ nil, OpenNebula::Error
Replaces the raw template contents
594 595 596 |
# File 'lib/models/service.rb', line 594 def update_raw(template_raw, append = false) super(template_raw, append) end |
#update_role(role_name, template_json) ⇒ nil, OpenNebula::Error
Updates a role
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 |
# File 'lib/models/service.rb', line 517 def update_role(role_name, template_json) if ![Service::STATE['RUNNING'], Service::STATE['WARNING']] .include?(state) return OpenNebula::Error.new('Update role: Wrong state' \ " #{state_str}") end template = JSON.parse(template_json) # TODO: Validate template? role = @roles[role_name] if role.nil? return OpenNebula::Error.new("ROLE \"#{role_name}\" " \ 'does not exist') end rc = role.update(template) if OpenNebula.is_error?(rc) return rc end # TODO: The update may not change the cardinality, only # the max and min vms... role.state = Role::STATE['SCALING'] role.set_default_cooldown_duration self.state = Service::STATE['SCALING'] update end |