def configure(self, server): """Add the EIP to the server just after it has booted. """ _logger.info('Associating IP number %s with server %s', self.parameter, server) server.cnx.associate_address( server.instance.id, self.parameter) server.eip = self.parameter
def stop(self): """Stop the server, but do not terminate it. """ self.instance.stop() while self.instance.state != 'stopped': _logger.info("Wating 10s for instance to stop...") time.sleep(10) self.instance.update() _logger.info("Instance state now %s", self.instance.state)
def restart(self): """Ask the server instance to restart from a stopped state. """ self.instance.start() while self.instance.state != 'running': _logger.info("Wating 10s for instance to restart...") time.sleep(10) self.instance.update() _logger.info("Instance state now %s", self.instance.state)
def terminate(self): """Terminate the server waiting for it to shut down. """ self.instance.terminate() while self.instance.state != 'terminated': _logger.info("Wating 10s for instance to terminate...") time.sleep(10) self.instance.update() _logger.info("Instance state now %s", self.instance.state)
def install_packages(self, *packages): """Install the specified packages on the machine. """ # The decorator requires this to be an instance method # pylint: disable=R0201 if packages: package_names = " ".join(packages) _logger.info("Making sure the following packages are installed: %s", package_names) sudo("apt-get install -y %s" % package_names)
def install_packages(self, *packages): """Install the specified packages on the machine. """ # The decorator requires this to be an instance method # pylint: disable=R0201 if packages: package_names = ' '.join(packages) _logger.info("Making sure the following packages are installed: %s", package_names) sudo('apt-get install -y %s' % package_names)
def create(cls, server, size): """Create a new volume on the provided connection. """ _logger.info("Creating volume size %dGB on %s", size, server.instance.placement) device = cls.get_volume(server.get_volumes()) volume = cls(server, server.cnx.create_volume( size, server.instance.placement), device) cls.attach_volume(server.insatance.id, volume, device) return volume
def get_volumes(self): """Return all of the volumes attached to this server. """ volumes = [] all_volumes = self.cnx.get_all_volumes() for volume in all_volumes: if volume.attach_data.instance_id == self.instance.id: found = Volume(self, volume, volume.attach_data.device, volume.attach_data.status == "attached") _logger.info("Found volume %s on %s", found.volume.id, found.device) volumes.append(found) return volumes
def creat_from_snapshot(cls, server, snapshot): """Create a new volume from snapshot. """ _logger.info("Creating volume size 200GB from snapshot id %s", snapshot.id) device = cls.get_device(server.get_volumes()) _loger.info("Used device %s on this server", device) volume = cls(server, snapshot.create_volume( server.instance.placement), device) cls.attach_volume(server.instance.id, volume, device) return volume
def get_volumes(self): """Return all of the volumes attached to this server. """ volumes = [] all_volumes = self.cnx.get_all_volumes() for volume in all_volumes: if volume.attach_data.instance_id == self.instance.id: found = Volume(self, volume, volume.attach_data.device, volume.attach_data.status == 'attached') _logger.info("Found volume %s on %s", found.volume.id, found.device) volumes.append(found) return volumes
def dist_upgrade(self): """Perform a dist-upgrade and make sure the base packages are installed. """ _logger.info("First ensure all keys are on server") key_file = "~/.ssh/authorized_keys" authorized_keys = run("cat %s" % key_file) for key in self.config.ssh.ubuntu: if key.split()[2] not in authorized_keys: append(key_file, key) _logger.info("Starting dist-upgrade sequence for %s", self.instance) sudo("apt-get update") sudo("apt-get dist-upgrade -y") self.reboot() self.install_packages("byobu", "update-notifier-common", "python-software-properties")
def configure(self, server): """Add the node configuration to the server, and the server configuration on the node. """ _logger.info("Configuring node %s", server) put(_template(MUNIN_NODE_CONFIG), "/etc/munin/munin-node.conf", use_sudo=True) sudo("service munin-node restart") with settings(host_string=self.parameter): _logger.info("Configuring server %s", self.parameter) put(_template(MUNIN_SERVER_CONFIG), "/etc/munin/munin-conf.d/%s" % self.parameter, use_sudo=True) run("sudo -u munin /usr/bin/munin-cron")
def dist_upgrade(self): """Perform a dist-upgrade and make sure the base packages are installed. """ _logger.info("First ensure all keys are on server") key_file = '~/.ssh/authorized_keys' authorized_keys = run('cat %s' % key_file) for key in self.config.ssh.ubuntu: if key.split()[2] not in authorized_keys: append(key_file, key) _logger.info("Starting dist-upgrade sequence for %s", self.instance) sudo('apt-get update') sudo('apt-get dist-upgrade -y') self.reboot() self.install_packages('byobu', 'update-notifier-common', 'python-software-properties')
def get_all_reservations(config): """Return all reservations known to this connection. """ reservations = [] region_list = regions(aws_access_key_id=config.keys.api, aws_secret_access_key=config.keys.secret) for region in region_list: _logger.info("Searching %s", region) cnx = region.connect(aws_access_key_id=config.keys.api, aws_secret_access_key=config.keys.secret) for reservation in cnx.get_all_instances(): _logger.info("Found %s %s", reservation, [str(i.id) for i in reservation.instances]) reservations.append(reservation) return reservations
def connect(cls, client, hostname): """Connect to a given server by the provided hostname. If a matching server cannot be found then return None. """ servers = Server.get_all(client) try: ips = set([sockaddr[0] for (_, _, _, _, sockaddr) in getaddrinfo(hostname, 22)]) except gaierror: ips = set() for server in servers: instance = server.instance _logger.info("instance %s...", instance.dns_name) if instance.ip_address in ips or server.reservation.id == hostname: _logger.info("Found %s", instance) return server return None
def connect(cls, client, hostname): """Connect to a given server by the provided hostname. If a matching server cannot be found then return None. """ servers = Server.get_all(client) try: ips = set([sockaddr[0] for (_, _, _, _, sockaddr) in getaddrinfo(hostname, 22)]) except gaierror: ips = set() for server in servers: instance = server.instance _logger.info("instance %s...", instance.dns_name) if instance.ip_address in ips or \ server.reservation.id == hostname: _logger.info("Found %s", instance) return server return None
def get_private_key_filename(config, cnx): """Fetch the key filename for this configuration and connection. """ hostname = socket.gethostname() foldername = os.path.expanduser('~/.profab/%s/%s' % ( config.client, cnx.region.name)) pathname = '%s/%s.pem' % (foldername, hostname) if not os.access(foldername, os.F_OK): os.mkdir(foldername) keys = cnx.get_all_key_pairs() for key in keys: if key.name == hostname: _logger.debug("Already found key on EC2 for hostname %s", hostname) return pathname _logger.info("No key pair found for host %s on EC2." " Creating new key pair.", hostname) pem = cnx.create_key_pair(hostname) pem.save(foldername) return pathname
def get_private_key_filename(config, cnx): """Fetch the key filename for this configuration and connection. """ hostname = socket.gethostname() foldername = os.path.expanduser('~/.profab/%s/%s' % (config.client, cnx.region.name)) pathname = '%s/%s.pem' % (foldername, hostname) if not os.access(foldername, os.F_OK): os.mkdir(foldername) keys = cnx.get_all_key_pairs() for key in keys: if key.name == hostname: _logger.debug("Already found key on EC2 for hostname %s", hostname) return pathname _logger.info( "No key pair found for host %s on EC2." " Creating new key pair.", hostname) pem = cnx.create_key_pair(hostname) pem.save(foldername) return pathname
def start(cls, client, *roles): """Start a server for the specified client with the given roles and connect the requested services. Roles are passed as either a name or a tuple (name, parameter). """ config = Configuration(client) _logger.info("New server for %s on %s with roles %s", config.client, config.host, roles) roles = [("bits", None)] + list(roles) role_adders = cls.get_role_adders(*roles) # Work out the correct region to use and connect to it region = config.region for role_adder in role_adders: region = role_adder.region() or region cnx = ec2_connect(config, region) # Work out the machine size to launch and set default run args run_args = {"key_name": get_keyname(config, cnx), "instance_type": "t1.micro"} for role_adder in role_adders: run_args["instance_type"] = role_adder.size() or run_args["instance_type"] # Calculate how many bits the AMI should be using bits = None for role_adder in role_adders: bits = role_adder.bits(run_args["instance_type"]) or bits # Find the AMI to use ami = None for role_adder in role_adders: ami = role_adder.ami(region, bits, run_args["instance_type"]) or ami # Work out the other run arguments we need for role_adder in role_adders: run_args = role_adder.run_kwargs(run_args) # Start the machine image = cnx.get_all_images(ami)[0] reservation = image.run(**run_args) _logger.debug("Have reservation %s for new server with instances %s", reservation, reservation.instances) # Now we can make the server instance and add the roles server = cls(config, reservation, reservation.instances[0]) for role in role_adders: role.started(server) # Wait for it to start up while server.instance.state == "pending": _logger.info("Waiting 10s for instance to start...") time.sleep(10) server.instance.update() _logger.info("Instance state now %s with name %s.", server.instance.state, server.instance.dns_name) # Upgrade it and configure it server.dist_upgrade() server.add_roles(role_adders) return server
def create(cls, server, size): """Create a new volume on the provided connection. """ _logger.info("Creating volume size %dGB on %s", size, server.instance.placement) volumes = server.get_volumes() used = [v.device for v in volumes] devices = [d for d in cls.DEVICES if d not in used] _logger.info("Unused devices on this server are %s", devices) device = devices[0] volume = cls(server, server.cnx.create_volume( size, server.instance.placement), device) _logger.info("Attaching volume %s to %s as %s", volume.volume, server.instance, device) volume.attached = volume.volume.attach(server.instance.id, device) return volume
def create(cls, server, size): """Create a new volume on the provided connection. """ _logger.info("Creating volume size %dGB on %s", size, server.instance.placement) volumes = server.get_volumes() used = [v.device for v in volumes] devices = [d for d in cls.DEVICES if d not in used] _logger.info("Unused devices on this server are %s", devices) device = devices[0] volume = cls(server, server.cnx.create_volume(size, server.instance.placement), device) _logger.info("Attaching volume %s to %s as %s", volume.volume, server.instance, device) volume.attached = volume.volume.attach(server.instance.id, device) return volume
def configure(self, server): """Adds the Munin web site to Apache. """ if exists("/etc/apache2/sites-enabled/000-default"): _logger.warning("Removing Apache2 default site") sudo("a2dissite 000-default") _logger.info("Replace the Munin configuration file") put(_template(MUNIN_CONFIG), "/etc/munin/munin.conf", use_sudo=True) _logger.info("Configure Apache2 for Munin") put(_template(APACHE_CONFIG), "/etc/apache2/sites-available/munin.conf", use_sudo=True) sudo('a2ensite munin.conf') _logger.info("Finally we can restart Apache") sudo('service apache2 reload')
""" _logger.info("Creating volume size 200GB from snapshot id %s", snapshot.id) device = cls.get_device(server.get_volumes()) _loger.info("Used device %s on this server", device) volume = cls(server, snapshot.create_volume( server.instance.placement), device) cls.attach_volume(server.instance.id, volume, device) return volume @classmethod def get_device(cls, volumes) used = [v.device for v in volumes] devices = [d for d in cls.DEVICES if d not in used] _logger.info("Unused devices on this server are %s", devices) return devices[0] @classmethod def attach_volume(cls, server, volume, device) #Wait for create volume while volume.volume.status == 'creating': _logger.info("Waiting 10s for volume to create...") time.sleep(10) volume.volume.update() _logger.info("Volume state now %s with name %s", volume.volume.volume_state(), volume.volume) _logger.info("Attaching volume %s to %s as %s", volume.volume, server, device) volume.attached = volume.volume.attach(server, device)
def start(cls, client, *roles): """Start a server for the specified client with the given roles and connect the requested services. Roles are passed as either a name or a tuple (name, parameter). """ config = Configuration(client) _logger.info("New server for %s on %s with roles %s", config.client, config.host, roles) roles = [('ami.lucid', None), ('bits', None)] + list(roles) role_adders = cls.get_role_adders(*roles) # Work out the correct region to use and connect to it region = config.region for role_adder in role_adders: region = role_adder.region() or region cnx = ec2_connect(config, region) # Work out the machine size to launch and set default run args run_args = { 'key_name': get_keyname(config, cnx), 'instance_type': 't1.micro', } for role_adder in role_adders: run_args['instance_type'] = role_adder.size() or \ run_args['instance_type'] # Calculate how many bits the AMI should be using bits = None for role_adder in role_adders: bits = role_adder.bits(run_args['instance_type']) or bits # Find the AMI to use ami = None for role_adder in role_adders: ami = role_adder.ami(region, bits, run_args['instance_type']) or ami # Work out the other run arguments we need for role_adder in role_adders: run_args = role_adder.run_kwargs(run_args) # Start the machine image = cnx.get_all_images(ami)[0] reservation = image.run(**run_args) _logger.debug("Have reservation %s for new server with instances %s", reservation, reservation.instances) # Now we can make the server instance and add the roles server = cls(config, reservation, reservation.instances[0]) for role in role_adders: role.started(server) # Wait for it to start up while server.instance.state == 'pending': _logger.info("Waiting 10s for instance to start...") time.sleep(10) server.instance.update() _logger.info("Instance state now %s with name %s.", server.instance.state, server.instance.dns_name) # Upgrade it and configure it server.dist_upgrade() server.add_roles(role_adders) return server