Attached is my OS::Linux::Fedora module. (The ASF license is mentioned in the header)
As I said, I was able to capture the image, but the network interfaces (as I recall) kept getting renamed: Fedora doesn’t use eth0, eth1, etc. So there was some issue with binding sshd to one or both of those interfaces on startup. I am not actually using this module, since CentOS and Ubuntu ended up being much easier to deal with. In any case, I hope this helps. Aaron C. On Mar 14, 2014, at 9:11 AM, Aaron Peeler <[email protected]> wrote: > Aaron, > Anything you have might help and is appreciated. > -A > > On Thu, Mar 13, 2014 at 2:02 PM, Aaron Coburn <[email protected]> wrote: >> Last summer I tried getting Fedora 19 to work with the VCL but was never >> entirely successful (I haven't tried working with Fedora 20). The main issue >> related to network configurations: Fedora has its own way of organizing >> network interfaces, and certain commands (e.g. ifconfig) produce output in a >> format different than what is expected by the standard OS::Linux module. I >> ended up writing a custom module (OS::Linux::Fedora), and was able to >> successfully capture images. When new instances were provisioned, there was >> something I had to do manually to make sure that sshd started up properly, >> and then, a user could connect to the reservation. But at that point I gave >> up on Fedora and told my colleagues that they could have CentOS and Ubuntu >> (but not Fedora), both of which work great in the VCL. If you'd like to see >> the semi-functional OS::Linux::Fedora module, let me know. >> >> Aaron Coburn >> >> >> >> >> -- >> Aaron Coburn >> System Administrator / Programmer >> Web Services, Amherst College >> >> >> >> >> On Mar 13, 2014, at 1:37 PM, Aaron Peeler <[email protected]> wrote: >> >> I've not. So far I ran into issues with ssh logins a fresh install of >> Fedora20, it looked like identity exchange errors. Then got side >> tracked before I could finish trouble shooting the issue. >> >> I'll try again soon. >> Aaron >> >> >> On Thu, Mar 13, 2014 at 1:32 PM, António Aragão <[email protected]> >> wrote: >> >> Josh, >> >> thanks for the information. I will do it. Does anyone made Fedora Core >> 20 image successful ? >> >> Thanks. >> >> 2014-03-13 17:16 GMT+00:00 Josh Thompson <[email protected]>: >> >> -----BEGIN PGP SIGNED MESSAGE----- >> Hash: SHA1 >> >> Aarago, >> >> Junaid provided some great info. You can remove the affiliations as he >> explained. However, you may just want to remove the ability to use them for >> logging in from the conf.php file so that you maintain the entry for any >> users >> that had the affiliation. If you do remove the entries from the affiliation >> table, you'll need to handle any users that had the affiliation. You can >> either just change their affiliation to something else that you keep an >> entry >> for, or you can remove the users. If you remove the users, you'll want to >> make sure they are not assigned as the owner of any resources. You also may >> want to delete all of their records from the log tables. >> >> Josh >> >> On Thursday, March 13, 2014 9:48:18 AM Junaid Ali wrote: >> >> Hello Aarago, >> The images can be managed from the web interface using "Manage images" >> menu on the left (when logged in as Administrator account). You need to >> use "Edit image Profiles" option and then you can delete the images that >> are published within the system. You need to make sure that you don't have >> any current reservations which are using those reservations otherwise the >> image will not be deleted. >> The above steps only removes the image from being available in the >> reservation system. To delete the actual image files you will need to >> delete the image folder from each of the VMHost server and finally from >> the shared image repository. >> >> Regarding, affiliations they are added and removed from the database >> manually. The table you need to edit is named "affiliations". Please make >> sure to remove the user groups for that affiliation before you remove the >> actual database entry. If you also have the web authentication configured >> you will need to update the web configuration file accordingly. For more >> details refer >> http://vcl.apache.org/docs/ldapauth.html#adding-ldap-authentication-to-the >> -web-code >> >> VCL Gurus, >> Please correct me if I missed anything. >> >> Thanks. >> Junaid Ali >> >> >> -----Original Message----- >> From: [email protected] [mailto:[email protected]] On Behalf >> Of António Aragão >> Sent: Thursday, March 13, 2014 6:20 AM >> To: [email protected] >> Subject: Some tips >> >> Hi, >> >> i need to purge old images and affiliations. How can I do that ? >> >> -- >> http://www.di.uminho.pt/~apa/email/cartao_virtual_email_aaragao.png >> >> - -- >> - ------------------------------- >> Josh Thompson >> VCL Developer >> North Carolina State University >> >> my GPG/PGP key can be found at pgp.mit.edu >> >> All electronic mail messages in connection with State business which >> are sent to or received by this account are subject to the NC Public >> Records Law and may be disclosed to third parties. >> -----BEGIN PGP SIGNATURE----- >> Version: GnuPG v2.0.22 (GNU/Linux) >> >> iEYEARECAAYFAlMh5/MACgkQV/LQcNdtPQOmoACfXPeQ/TFjepYKLUrrevflARYI >> h1kAmgIZRzsKJSADYP5p0FxFe8YxP6xH >> =iBEJ >> -----END PGP SIGNATURE----- >> >> >> >> >> -- >> http://www.di.uminho.pt/~apa/email/cartao_virtual_email_aaragao.png >> >> >> >> >> -- >> Aaron Peeler >> Program Manager >> Virtual Computing Lab >> NC State University >> >> All electronic mail messages in connection with State business which >> are sent to or received by this account are subject to the NC Public >> Records Law and may be disclosed to third parties. >> >> > > > > -- > Aaron Peeler > Program Manager > Virtual Computing Lab > NC State University > > All electronic mail messages in connection with State business which > are sent to or received by this account are subject to the NC Public > Records Law and may be disclosed to third parties.
#!/usr/bin/perl -w ############################################################################### # $Id: $ ############################################################################### # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ############################################################################### =head1 NAME VCL::Module::OS::Fedora.pm - VCL module to support Ubuntu operating systems =head1 SYNOPSIS Needs to be written =head1 DESCRIPTION This module provides VCL support for Fedora operating systems. =cut ############################################################################## package VCL::Module::OS::Linux::Fedora; # Specify the lib path using FindBin use FindBin; use lib "$FindBin::Bin/../../../.."; # Configure inheritance use base qw(VCL::Module::OS::Linux); # Specify the version of this module our $VERSION = '2.3.2'; # Specify the version of Perl to use use 5.008000; use strict; use warnings; use diagnostics; no warnings 'redefine'; use VCL::utils; ############################################################################## =head1 OBJECT METHODS =cut #///////////////////////////////////////////////////////////////////////////// sub get_network_configuration { my $self = shift; if (ref($self) !~ /VCL::Module/i) { notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method"); return; } # Check if the network configuration has already been retrieved and saved in this object return $self->{network_configuration} if ($self->{network_configuration}); # Run ipconfig my $ifconfig_command = "/sbin/ifconfig -a"; my ($ifconfig_exit_status, $ifconfig_output) = $self->execute($ifconfig_command); if (!defined($ifconfig_output)) { notify($ERRORS{'WARNING'}, 0, "failed to run command to retrieve network configuration: $ifconfig_command"); return; } # Loop through the ifconfig output lines my $network_configuration; my $interface_name; for my $ifconfig_line (@$ifconfig_output) { # Extract the interface name from the Link line: # ens33: flags=...<UP,BROADCAST,RUNNING,MULTICAST> if ($ifconfig_line =~ /^([^\s:]+):.*BROADCAST/) { $interface_name = $1; $network_configuration->{$interface_name}{name} = $interface_name; } # Skip to the next line if the interface name has not been determined yet next if !$interface_name; # Parse the HWaddr line: # ether 00:50:56:07:A1:1D if ($ifconfig_line =~ /ether\s+([\w:]+)/) { $network_configuration->{$interface_name}{physical_address} = lc($1); } # Parse the IP address line: # inet 148.85.12.38 netmask 255.255.0.0 broadcast 148.85.255.255 # inet addr:10.10.4.35 Bcast:10.10.15.255 Mask:255.255.240.0 if ($ifconfig_line =~ /inet\s+([\d\.]+)\s+netmask\s([\d\.]+)\s+broadcast\s([\d\.]+)/) { $network_configuration->{$interface_name}{ip_address}{$1} = $2; $network_configuration->{$interface_name}{broadcast_address} = $3; } } # Run route my $route_command = "/sbin/route -n"; my ($route_exit_status, $route_output) = $self->execute($route_command); if (!defined($route_output)) { notify($ERRORS{'WARNING'}, 0, "failed to run command to retrieve routing configuration: $route_command"); return; } # Loop through the route output lines for my $route_line (@$route_output) { my ($default_gateway, $interface_name) = $route_line =~ /^0\.0\.0\.0\s+([\d\.]+).*\s([^\s]+)$/g; if (!defined($interface_name) || !defined($default_gateway)) { notify($ERRORS{'DEBUG'}, 0, "route output line does not contain a default gateway: '$route_line'"); } elsif (!defined($network_configuration->{$interface_name})) { notify($ERRORS{'WARNING'}, 0, "found default gateway for '$interface_name' interface but the network configuration for '$interface_name' was not previously retrieved, route output:\n" . join("\n", @$route_output) . "\nnetwork configuation:\n" . format_data($network_configuration)); } elsif (defined($network_configuration->{$interface_name}{default_gateway})) { notify($ERRORS{'WARNING'}, 0, "multiple default gateway are configured for '$interface_name' interface, route output:\n" . join("\n", @$route_output)); } else { $network_configuration->{$interface_name}{default_gateway} = $default_gateway; notify($ERRORS{'DEBUG'}, 0, "found default route configured for '$interface_name' interface: $default_gateway"); } } $self->{network_configuration} = $network_configuration; notify($ERRORS{'DEBUG'}, 0, "retrieved network configuration:\n" . format_data($self->{network_configuration})); return $self->{network_configuration}; } #///////////////////////////////////////////////////////////////////////////// =head2 generate_rc_local Parameters : none Returns : boolean Description : Generate a rc.local file locally, copy to node and make executable. =cut sub generate_rc_local { my $self = shift; if (ref($self) !~ /linux/i) { notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method"); return 0; } my $request_id = $self->data->get_request_id(); my $management_node_keys = $self->data->get_management_node_keys(); my $computer_short_name = $self->data->get_computer_short_name(); my $computer_node_name = $self->data->get_computer_node_name(); # Determine if /etc/rc.local is a symlink or not my $command = "file /etc/rc.local"; my $symlink = 0; my $rc_local_path; my ($echo_exit_status, $echo_output) = $self->execute($command, 1); if (!defined($echo_output)) { notify($ERRORS{'WARNING'}, 0, "failed to run command to check file of /etc/rc.local"); } elsif (grep(/symbolic/, @$echo_output)) { notify($ERRORS{'OK'}, 0, "confirmed /etc/rc.local is symbolic link \n" . join("\n", @$echo_output)); $symlink = 1; } if(!$symlink) { #my $symlink_command = "mv /etc/rc.local /etc/_orig.rc.local ; ln -s /etc/rc.d/rc.local /etc/rc.local"; #my ($sym_exit_status, $sym_output) = $self->execute($symlink_command, 1); #if (!defined($sym_output)) { # notify($ERRORS{'WARNING'}, 0, "failed to run symlink_command $symlink_command on node $computer_node_name"); #} #else { # notify($ERRORS{'OK'}, 0, "successfully ran $symlink_command on $computer_node_name"); #} $rc_local_path = "/etc/rc.local"; } else { $rc_local_path = "/etc/rc.d/rc.local"; } my @array2print; push(@array2print, '#!/bin/sh' . "\n"); push(@array2print, '#' . "\n"); push(@array2print, '# This script will be executed after all the other init scripts.' . "\n"); push(@array2print, '#' . "\n"); push(@array2print, '# WARNING --- VCL IMAGE CREATORS --- WARNING' . "\n"); push(@array2print, '#' . "\n"); push(@array2print, '# This file will get overwritten during image capture. Any customizations' . "\n"); push(@array2print, '# should be put into /etc/init.d/vcl_post_reserve or /etc/init.d/vcl_post_load' . "\n"); push(@array2print, '# Note these files do not exist by default.' . "\n"); push(@array2print, "\n"); push(@array2print, "#Use the /root/.vclcontrol/vcl_exclude_list to prevent vcld from updating this file."); push(@array2print, "\n"); push(@array2print, 'touch /var/lock/subsys/local' . "\n"); push(@array2print, "\n"); push(@array2print, 'IP0=$(ifconfig ens33 | grep \'inet \' | awk \'{print $2}\')' . "\n"); push(@array2print, 'IP1=$(ifconfig ens34 | grep \'inet \' | awk \'{print $2}\')' . "\n"); push(@array2print, 'sed -i -e \'/.*AllowUsers .*$/d\' /etc/ssh/sshd_config' . "\n"); push(@array2print, 'sed -i -e \'/.*ListenAddress .*/d\' /etc/ssh/sshd_config' . "\n"); push(@array2print, 'sed -i -e \'/.*ListenAddress .*/d\' /etc/ssh/external_sshd_config' . "\n"); push(@array2print, 'echo "AllowUsers root" >> /etc/ssh/sshd_config' . "\n"); push(@array2print, 'echo "ListenAddress $IP0" >> /etc/ssh/sshd_config' . "\n"); push(@array2print, 'echo "ListenAddress $IP1" >> /etc/ssh/external_sshd_config' . "\n"); push(@array2print, 'service ext_sshd stop' . "\n"); push(@array2print, 'service sshd restart' . "\n"); push(@array2print, 'sleep 2' . "\n"); #push(@array2print, 'service sshd start' . "\n"); push(@array2print, 'service ext_sshd start' . "\n"); #write to tmpfile my $tmpfile = "/tmp/$request_id.rc.local"; if (open(TMP, ">$tmpfile")) { print TMP @array2print; close(TMP); } else { #print "could not write $tmpfile $!\n"; notify($ERRORS{'OK'}, 0, "could not write $tmpfile $!"); return 0; } #copy to node if (run_scp_command($tmpfile, "$computer_node_name:$rc_local_path", $management_node_keys)) { } else{ return 0; } # Assemble the command my $chmod_command = "chmod +rx $rc_local_path"; # Execute the command my ($exit_status, $output) = run_ssh_command($computer_node_name, $management_node_keys, $chmod_command, '', '', 1); if (defined($exit_status) && $exit_status == 0) { notify($ERRORS{'OK'}, 0, "executed $chmod_command, exit status: $exit_status"); } elsif (defined($exit_status)) { notify($ERRORS{'WARNING'}, 0, "setting rx on $rc_local_path returned a non-zero exit status: $exit_status"); return; } else { notify($ERRORS{'WARNING'}, 0, "failed to run SSH command to execute $chmod_command"); return 0; } unlink($tmpfile); # If systemd managed; confirm rc-local.service is enabled if($self->file_exists("/bin/systemctl") ) { if(!$self->generate_rc_local_systemd() ) { return 0; } } else { #Re-run rc.local my ($rclocal_exit_status, $rclocal_output) = $self->execute("$rc_local_path"); if (!defined($rclocal_exit_status)) { notify($ERRORS{'WARNING'}, 0, "failed to run $rc_local_path on node $computer_node_name"); } else { notify($ERRORS{'OK'}, 0, "successfully ran $rc_local_path"); } } return 1; } #///////////////////////////////////////////////////////////////////////////// =head2 update_public_hostname Parameters : none Returns : boolean Description : Retrieves the public IP address being used on the Linux computer. Runs ipcalc locally on the management node to determine the registered hostname for that IP address. If unable to determine the hostname by running ipcalc on the management node, an attempt is made to run ipcalc on the Linux computer. Once the hostname is determined, the hostname command is run to set the hostname on the Linux computer. =cut sub update_public_hostname { my $self = shift; unless (ref($self) && $self->isa('VCL::Module')) { notify($ERRORS{'CRITICAL'}, 0, "subroutine can only be called as a VCL::Module module object method"); return; } my $management_node_keys = $self->data->get_management_node_keys(); my $computer_node_name = $self->data->get_computer_node_name(); # Get the IP address of the public adapter my $public_ip_address = $self->get_public_ip_address(); if (!$public_ip_address) { notify($ERRORS{'WARNING'}, 0, "hostname cannot be set, unable to determine public IP address"); return; } notify($ERRORS{'DEBUG'}, 0, "retrieved public IP address of $computer_node_name: $public_ip_address"); # Get the hostname for the public IP address my $ipcalc_command = "/bin/ipcalc --hostname $public_ip_address"; my ($ipcalc_exit_status, $ipcalc_output) = run_command($ipcalc_command); if (!defined($ipcalc_output)) { notify($ERRORS{'WARNING'}, 0, "failed to run ipcalc command on management node to determine public hostname of $computer_node_name, command: '$ipcalc_command'"); return; } my ($public_hostname) = ("@$ipcalc_output" =~ /HOSTNAME=(.*)/i); if ($public_hostname) { notify($ERRORS{'DEBUG'}, 0, "determined registered public hostname of $computer_node_name ($public_ip_address) by running ipcalc on the management node: '$public_hostname'"); } else { notify($ERRORS{'DEBUG'}, 0, "failed to determine registered public hostname of $computer_node_name ($public_ip_address), command: '$ipcalc_command', output:\n" . join("\n", @$ipcalc_output)); # Attempt to run the host command on the host my $host_command = "host $public_ip_address"; my ($host_exit_status, $host_output) = run_ssh_command($computer_node_name, $management_node_keys, $host_command); if (!defined($host_output)) { notify($ERRORS{'WARNING'}, 0, "failed to run host command on $computer_node_name to determine its public hostname, command: '$host_command'"); return; } ($public_hostname) = $5 if ("@$host_output" =~ /([-\.0-9a-z]*)\s([a-z]*)\s([a-z]*)\s([a-z]*)\s(.*)\.$/); if ($public_hostname) { notify($ERRORS{'DEBUG'}, 0, "determined registered public hostname of $computer_node_name ($public_ip_address) by running host on $computer_node_name: '$public_hostname'"); } else { notify($ERRORS{'WARNING'}, 0, "failed to determine registered public hostname of $computer_node_name ($public_ip_address) by running host on either the management node or $computer_node_name, command: '$host_command', output:\n" . join("\n", @$host_output)); return; } } # Set the node's hostname to public hostname my $hostname_command = "hostname $public_hostname"; my ($hostname_exit_status, $hostname_output) = run_ssh_command($computer_node_name, $management_node_keys, $hostname_command); if (!defined($hostname_output)) { notify($ERRORS{'WARNING'}, 0, "failed to SSH command to set hostname on $computer_node_name to $public_hostname, command: '$hostname_command'"); return; } elsif ($hostname_exit_status == 0) { notify($ERRORS{'OK'}, 0, "set public hostname on $computer_node_name to $public_hostname"); return 1; } else { notify($ERRORS{'WARNING'}, 0, "failed to set public hostname on $computer_node_name to $public_hostname, exit status: $hostname_exit_status, output:\n" . join("\n", @$hostname_output)); return 0; } } #///////////////////////////////////////////////////////////////////////////// =head2 sync_date Parameters : called as an object Returns : 1 - success , 0 - failure Description : updates and sets date on node =cut sub sync_date { my $self = shift; if (ref($self) !~ /linux/i) { notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method"); return 0; } my $computer_node_name = $self->data->get_computer_node_name(); #get Throttle source value from database if set my $time_source; my $variable_name = "timesource|" . $self->data->get_management_node_hostname(); my $variable_name_global = "timesource|global"; if($self->data->is_variable_set($variable_name)){ #fetch variable $time_source = $self->data->get_variable($variable_name); notify($ERRORS{'DEBUG'}, 0, "time_source is $time_source set for $variable_name"); } elsif($self->data->is_variable_set($variable_name_global) ) { #fetch variable $time_source = $self->data->get_variable($variable_name_global); notify($ERRORS{'DEBUG'}, 0, "time_source is $time_source set for $variable_name"); } else { notify($ERRORS{'DEBUG'}, 0, "time_source is not set for $variable_name or $variable_name_global not able update time"); return ; } # Keep only the first host $time_source =~ s/,.+$//g; # Assemble the time command my $time_command = "rdate -s $time_source"; my ($exit_status, $output) = $self->execute($time_command, 1, 180); #update ntpservers file my @time_array = split(/ /,$time_source); my $ntp_command = "cp /dev/null /etc/ntp/ntpservers;"; foreach my $i (@time_array) { $ntp_command .= "echo $i >> /etc/ntp/ntpservers; "; } $ntp_command .= "/bin/systemctl restart ntpd.service"; ($exit_status, $output) = $self->execute($ntp_command, 1, 180); return 1; } #///////////////////////////////////////////////////////////////////////////// =head2 clean_iptables Parameters : Returns : 0 , 1 Description : Deletes rules with any leftover -s addresses =cut sub clean_iptables { my $self = shift; if (ref($self) !~ /linux/i) { notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method"); return; } # Check to see if this distro has iptables # If not return 1 so it does not fail if (!($self->service_exists("iptables"))) { notify($ERRORS{'WARNING'}, 0, "iptables does not exist on this OS"); return 1; } my $computer_node_name = $self->data->get_computer_node_name(); my $reservation_id = $self->data->get_reservation_id(); my $management_node_keys = $self->data->get_management_node_keys(); # Retrieve the firewall configuration my $INPUT_CHAIN = "INPUT"; # Retrieve the iptables file to work on locally my $tmpfile = "/tmp/" . $reservation_id . "_iptables"; my $source_file_path = "/etc/sysconfig/iptables"; if (run_scp_command("$computer_node_name:\"$source_file_path\"", $tmpfile, $management_node_keys)) { my @lines; if(open(IPTAB_TMPFILE, $tmpfile)){ @lines = <IPTAB_TMPFILE>; close(IPTAB_TMPFILE); } foreach my $line (@lines){ if ($line =~ s/-A INPUT -s .*\n//) { } } #Rewrite array to tmpfile if(open(IPTAB_TMPFILE, ">$tmpfile")){ print IPTAB_TMPFILE @lines; close (IPTAB_TMPFILE); } # Copy iptables file back to node if (run_scp_command($tmpfile, "$computer_node_name:\"$source_file_path\"", $management_node_keys)) { notify($ERRORS{'DEBUG'}, 0, "copied $tmpfile to $computer_node_name $source_file_path"); } } #my $command = "sed -i -e '/-A INPUT -s */d' /etc/sysconfig/iptables"; #my ($status, $output) = $self->execute($command); #if (defined $status && $status == 0) { # notify($ERRORS{'DEBUG'}, 0, "executed command $command on $computer_node_name"); #} #else { # notify($ERRORS{'WARNING'}, 0, "output from iptables:" . join("\n", @$output)); #} #restart iptables my $command = "/bin/systemctl restart iptables.service"; my ($status_iptables,$output_iptables) = $self->execute($command); if (defined $status_iptables && $status_iptables == 0) { notify($ERRORS{'DEBUG'}, 0, "executed command $command on $computer_node_name"); } else { notify($ERRORS{'WARNING'}, 0, "output from iptables:" . join("\n", @$output_iptables)); } if ($self->wait_for_ssh(0)) { return 1; } else { notify($ERRORS{'CRITICAL'}, 0, "not able to login via ssh after cleaning_iptables"); return 0; } }
